File size: 3,973 Bytes
4344b33
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# src/data/core_parser.py — FuseSoC .core file parser

from __future__ import annotations

from typing import Any, Dict, List, Optional

import yaml

from src.data.preprocessor import SpecPreprocessor


class CoreParser:
    """Parses FuseSoC .core files into the internal DesignSpec-compatible dict.

    The .core format (YAML) describes IP cores with:
      - name / version / description
      - parameters
      - interfaces (each with signals, type, bus standard)
      - registers (address, access, fields with bit positions)
      - clock_reset
      - filesets, targets
    """

    ACCESS_MAP = {
        "ro": "read-only",
        "wo": "write-only",
        "rw": "read-write",
        "rc": "read-clear",
        "rs": "read-set",
        "w1c": "write-1-to-clear",
    }

    def parse(self, content: str) -> Dict[str, Any]:
        raw = yaml.safe_load(content)
        spec: Dict[str, Any] = {}

        spec["design_name"] = self._extract_name(raw)
        spec["clock_reset"] = self._extract_clock_reset(raw)
        spec["interfaces"] = self._extract_interfaces(raw)
        spec["registers"] = self._extract_registers(raw)
        spec["parameters"] = self._extract_parameters(raw)

        return SpecPreprocessor().preprocess(spec)

    @staticmethod
    def _extract_name(raw: Dict[str, Any]) -> str:
        name = raw.get("name", "unknown")
        if isinstance(name, str):
            return name.strip().lower()
        return "unknown"

    @staticmethod
    def _extract_clock_reset(raw: Dict[str, Any]) -> Dict[str, Any]:
        cr = raw.get("clock_reset")
        if cr:
            return {
                "clock": cr.get("clock", "clk"),
                "reset": cr.get("reset", "rst_n"),
                "reset_active": cr.get("reset_active", 0),
            }
        return {"clock": "clk", "reset": "rst_n", "reset_active": 0}

    @staticmethod
    def _extract_interfaces(raw: Dict[str, Any]) -> List[Dict[str, Any]]:
        interfaces = raw.get("interfaces", [])
        result: List[Dict[str, Any]] = []
        for iface in interfaces:
            entry: Dict[str, Any] = {
                "name": iface.get("name", "bus"),
                "signals": [],
            }
            for sig in iface.get("signals", []):
                entry["signals"].append({
                    "name": sig.get("name", "sig"),
                    "direction": sig.get("direction", "input"),
                    "width": sig.get("width", 1),
                })
            result.append(entry)
        return result

    @staticmethod
    def _extract_registers(raw: Dict[str, Any]) -> List[Dict[str, Any]]:
        registers = raw.get("registers", [])
        result: List[Dict[str, Any]] = []
        seen = set()
        for reg in registers:
            name = reg.get("name", f"reg_{len(result)}")
            if name in seen:
                name = f"{name}_{len(result)}"
            seen.add(name)

            entry: Dict[str, Any] = {
                "name": name,
                "address": reg.get("address", "0x00"),
                "description": reg.get("description", ""),
                "access": reg.get("access", "rw"),
                "fields": [],
            }
            for fld in reg.get("fields", []):
                entry["fields"].append({
                    "name": fld.get("name", "field"),
                    "bits": fld.get("bits", "0"),
                    "description": fld.get("description", ""),
                })
            result.append(entry)
        return result

    @staticmethod
    def _extract_parameters(raw: Dict[str, Any]) -> Dict[str, Any]:
        params = raw.get("parameters", {})
        return {k: v.get("default") if isinstance(v, dict) else v for k, v in params.items()}


def parse_core_file(path: str) -> Dict[str, Any]:
    """Convenience: read .core file and return DesignSpec-compatible dict."""
    with open(path, "r") as f:
        return CoreParser().parse(f.read())