• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Nic30 / hwt / 3c0e0aeb-b3c7-4a03-a8af-db38639fa8a0

19 Oct 2025 05:56PM UTC coverage: 83.905% (+0.06%) from 83.85%
3c0e0aeb-b3c7-4a03-a8af-db38639fa8a0

push

circleci

Nic30
feat(SimTestCase): assign dut before compileSim in compileSimAndStart

* to allow query of dut on testcase during compilation

3470 of 4600 branches covered (75.43%)

Branch coverage included in aggregate %.

1 of 1 new or added line in 1 file covered. (100.0%)

167 existing lines in 12 files now uncovered.

12050 of 13897 relevant lines covered (86.71%)

0.87 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.57
/hwt/hwModule.py
1
from copy import copy
1✔
2
from natsort.natsort import natsorted
1✔
3
from typing import Optional, Union
1✔
4

5
from hdlConvertorAst.hdlAst._defs import HdlIdDef
1✔
6
from hdlConvertorAst.hdlAst._structural import HdlCompInst, HdlModuleDec
1✔
7
from hwt.doc_markers import internal
1✔
8
from hwt.hObjList import HObjList
1✔
9
from hwt.hdl.portItem import HdlPortItem
1✔
10
from hwt.mainBases import HwIOBase
1✔
11
from hwt.synthesizer.dummyPlatform import DummyPlatform
1✔
12
from hwt.synthesizer.exceptions import IntfLvlConfErr
1✔
13
from hwt.synthesizer.interfaceLevel.hwModuleImplHelpers import HwModuleImplHelpers, \
1✔
14
    _default_param_updater
15
from hwt.synthesizer.interfaceLevel.propDeclrCollector import PropDeclrCollector
1✔
16
from hwt.synthesizer.rtlLevel.netlist import RtlNetlist
1✔
17
from hwt.synthesizer.typePath import TypePath
1✔
18
from ipCorePackager.constants import DIRECTION
1✔
19

20

21
class HdlConstraintList(list):
1✔
22
    """
23
    Containers of hw design constraints
24
    """
25
    pass
1✔
26

27

28
class HwModule(PropDeclrCollector, HwModuleImplHelpers):
1✔
29
    """
30
    Objects of this class are representation of design in hwt HCL.
31
    This object is a container of the netlist with interfaces
32
    and internal hierarchical structure.
33

34
    :cvar ~._serializeDecision: function to decide if HDL object derived from
35
        this unit should be serialized or not, if None all is always serialized
36
    :cvar ~._PROTECTED_NAMES: set of names which can not be overridden
37
    :ivar ~._hwIOs: all public interfaces
38
    :type ~._hwIOs: List[HwIO]
39
    :ivar ~._private_hwIOs: all internal interfaces
40
        which are not accessible from outside of unit
41
    :type _private_hwIOs: List[HwIO]
42
    :ivar ~._subHwModules: all units defined on this object
43
    :type ~._subHwModules: List[HwModule]
44
    :ivar ~._hwParams: all params defined on this object
45
    :type ~._hwParams: List[HwParam]
46
    :ivar ~._constraints: additional HW specifications
47
    :ivar ~._parent: parent object
48
    :type ~._parent: Optional[HwModule]
49
    :ivar ~._lazy_loaded: container of RTL object which were lazy loaded
50
        in implementation phase (this object has to be returned
51
        from :func:`~._to_rtl` of parent before it it's own objects)
52
    :ivar ~._shared_component_with: Optional tuple of the other :class:`hwt.hwModule.HwModule` instance
53
        which produces an exactly same component in HDL and interface
54
        signal map current to shared and shared to current
55
    :type ~._shared_component_with: Optional[Tuple[HwModule,
56
        Dict[Interface, Interface],
57
        Dict[Interface, Interface]]]
58
    :attention: if :func:`~._shared_component_with` is not None the body
59
        of this instance is not generated at all
60
        and the component from :func:`~._shared_component_with` is used instead
61
    :ivar ~._target_platform: meta-informations about target platform
62
    :ivar ~._name: a name of this component
63
    :ivar ~._onParentPropertyPath: :see: :class:`HwIO`
64
    :ivar ~._hdl_module_name: a name of HDL module for this component
65
        (vhdl entity name, Verilog module name)
66
    """
67

68
    _serializeDecision = None
1✔
69
    # properties which are used internally by this library
70
    _PROTECTED_NAMES = {
1✔
71
        "_PROTECTED_NAMES",
72
        "_name", "_hdl_module_name",
73
        "_hwIOs", "_private_hwIOs",
74
        "_units", "_hwParams", "_parent", "_constraints",
75
        "_lazy_loaded", "_rtlCtx", "_shared_component_with",
76
        "_target_platform", "_store_manager",
77
    }
78

79
    def __init__(self, hdlName:Optional[str]=None):
1✔
80
        self._parent: Optional[HwModule] = None
1✔
81
        self._name: Optional[str] = None
1✔
82
        self._onParentPropertyPath: Optional[TypePath] = None
1✔
83
        self._shared_component_with = None
1✔
84
        self._hdl_module_name: Optional[str] = None
1✔
85
        assert hdlName is None or isinstance(hdlName, str), hdlName
1✔
86
        self._hdlNameOverride = hdlName
1✔
87
        self._lazy_loaded: list[Union[HwModule, HwIOBase]] = []
1✔
88
        self._rtlCtx = RtlNetlist(self)
1✔
89
        self._constraints = HdlConstraintList()
1✔
90
        self._loadConfig()
1✔
91

92
    @internal
1✔
93
    def _loadHwIODeclarations(self, hwIO: HwIOBase, isExtern: bool):
1✔
94
        hwIO._loadHwDeclarations()
1✔
95
        hwIO._setAsExtern(isExtern)
1✔
96

97
    @internal
1✔
98
    def _loadHwDeclarations(self):
1✔
99
        """
100
        Load all declarations from _decl() method, recursively
101
        for all interfaces/units.
102
        """
103
        if not hasattr(self, "_hwIOs"):
1!
104
            self._hwIOs = []
1✔
105
        if not hasattr(self, "_private_hwIOs"):
1!
106
            self._private_hwIOs = []
1✔
107
        if not hasattr(self, "_subHwModules"):
1!
108
            self._subHwModules = []
1✔
109
        self._setAttrListener = self._declrCollector
1✔
110
        self.hwDeclr()
1✔
111
        self._setAttrListener = None
1✔
112
        for hio in self._hwIOs:
1✔
113
            self._loadHwIODeclarations(hio, True)
1✔
114

115
        # if I am a unit load subunits
116
        for u in self._subHwModules:
1✔
117
            u._loadHwDeclarations()
1✔
118

119
    @internal
1✔
120
    def _registerHwIOInHwImpl(self, hwIOName: str, hwIO: HwIOBase, onParentPath: TypePath):
1✔
121
        """
122
        Register interface in implementation phase
123
        """
124
        self._registerHwIO(hwIOName, hwIO, onParentPath, True)
1✔
125
        self._loadHwIODeclarations(hwIO, False)
1✔
126
        hwIO._signalsForHwIO(
1✔
127
            self._rtlCtx, None, self._store_manager.name_scope)
128

129
    def _getDefaultName(self) -> str:
1✔
130
        return self.__class__.__name__
1✔
131

132
    def _get_hdl_doc(self) -> Optional[str]:
1✔
133
        if self.__doc__ is not HwModule.__doc__:
1!
134
            return self.__doc__
1✔
135

136
    @internal
1✔
137
    def _to_rtl(self, target_platform: DummyPlatform,
1✔
138
                store_manager: "StoreManager", add_param_asserts=True):
139
        """
140
        synthesize all subunits, make connections between them,
141
        build verilog like module/vhdl like entity and architecture for this unit
142
        """
143
        if self._hdl_module_name is None:
1✔
144
            if self._hdlNameOverride:
1!
UNCOV
145
                self._hdl_module_name = self._hdlNameOverride
×
146
            else:
147
                self._hdl_module_name = self._getDefaultName()
1✔
148
        if self._name is None:
1✔
149
            self._name = self._getDefaultName()
1✔
150
        self._target_platform = target_platform
1✔
151
        self._store_manager = store_manager
1✔
152
        do_serialize_this, replacement = store_manager.filter.do_serialize(
1✔
153
            self)
154
        if replacement is not None:
1✔
155
            assert not do_serialize_this
1✔
156
            assert len(self._hwIOs) == len(replacement._hwIOs), \
1✔
157
                "No lazy loaded interfaces declared in hwImpl()"
158
            copy_HdlModuleDec(replacement, self)
1✔
159
            yield False, self
1✔
160
            self._cleanThisSubunitRtlSignals()
1✔
161
            self._subHwModules = None
1✔
162
            self._private_hwIOs = None
1✔
163
            hwIO_map_repl_to_self = sharedCompBuildHwIOMap(
1✔
164
                replacement, self)
165
            hwIO_map_self_to_repl = {
1✔
166
                v: k
167
                for k, v in hwIO_map_repl_to_self.items()}
168
            self._shared_component_with = replacement, \
1✔
169
                hwIO_map_self_to_repl, hwIO_map_repl_to_self
170
            return
1✔
171

172
        for proc in target_platform.beforeToRtl:
1!
UNCOV
173
            proc(self)
×
174

175
        mdec = self._rtlCtx.create_HdlModuleDec(
1✔
176
            self._hdl_module_name, store_manager, self._hwParams)
177
        mdec.origin = self
1✔
178
        mdec.doc = self._get_hdl_doc()
1✔
179

180
        # prepare signals for interfaces
181
        for hwIO in self._hwIOs:
1✔
182
            if hwIO._isExtern:
1!
183
                ei = self._rtlCtx.hwIOs
1✔
184
            else:
UNCOV
185
                ei = None
×
186
            # we are reversing direction because we are looking
187
            # at the interface from inside of component
188
            hwIO._signalsForHwIO(
1✔
189
                self._rtlCtx, ei,
190
                store_manager.name_scope, reverse_dir=True)
191
        store_manager.hierarchy_pop(mdec)
1✔
192

193
        if do_serialize_this:
1✔
194
            # prepare subunits
195
            for sm in self._subHwModules:
1✔
196
                yield from sm._to_rtl(target_platform, store_manager)
1✔
197

198
            # now every sub unit has a HdlModuleDec prepared
199
            for sm in self._subHwModules:
1✔
200
                subHwModuleName = sm._name
1✔
201
                sm._signalsForSubHwModuleEntity(self._rtlCtx, "sig_" + subHwModuleName)
1✔
202

203
            for proc in target_platform.beforeToRtlImpl:
1!
UNCOV
204
                proc(self)
×
205

206
        try:
1✔
207
            store_manager.hierarchy_push(mdec)
1✔
208
            if do_serialize_this:
1✔
209
                self._loadImpl()
1✔
210
                yield from self._lazy_loaded
1✔
211

212
                if not self._rtlCtx.hwIOs:
1!
UNCOV
213
                    raise IntfLvlConfErr(
×
214
                        "Can not find any external interface for unit %s"
215
                        "- unit without interfaces are not synthesisable"
216
                        % self._name)
217

218
            for proc in target_platform.afterToRtlImpl:
1!
UNCOV
219
                proc(self)
×
220

221
            mdec.params[:] = natsorted(mdec.params, key=lambda x: x.name)
1✔
222
            mdec.ports[:] = natsorted(mdec.ports, key=lambda x: x.name)
1✔
223
            if do_serialize_this:
1✔
224
                # synthesize signal level context
225
                mdef = self._rtlCtx.create_HdlModuleDef(
1✔
226
                    target_platform, store_manager)
227
                mdef.origin = self
1✔
228

229
            for hwIO in self._hwIOs:
1✔
230
                if hwIO._isExtern:
1!
231
                    # reverse because other components
232
                    # looks at this interface from the outside
233
                    hwIO._reverseDirection()
1✔
234

235
            if do_serialize_this:
1✔
236
                if add_param_asserts and self._hwParams:
1✔
237
                    mdef.objs.extend(store_manager.as_hdl_ast._as_hdl_HdlModuleDef_param_asserts(mdec))
1✔
238
                store_manager.write(mdef)
1✔
239

240
            yield True, self
1✔
241

242
            # after synthesis clean up interface so this :class:`hwt.hwModule.HwModule` object can be
243
            # used elsewhere
244
            self._cleanThisSubunitRtlSignals()
1✔
245
            if do_serialize_this:
1✔
246
                self._checkCompInstances()
1✔
247

248
            for proc in target_platform.afterToRtl:
1!
UNCOV
249
                proc(self)
×
250
        finally:
251
            store_manager.hierarchy_pop(mdec)
1✔
252

253
    def _updateHwParamsFrom(self, otherObj: PropDeclrCollector,
1✔
254
                          updater=_default_param_updater,
255
                          exclude: Optional[tuple[set[str], set[str]]]=None,
256
                          prefix=""):
257
        """
258
        :note: doc in
259
            :func:`hwt.synthesizer.interfaceLevel.propDeclCollector._updateHwParamsFrom`
260
        """
261
        return PropDeclrCollector._updateHwParamsFrom(self, otherObj,
1✔
262
                                                    updater, exclude, prefix)
263

264
    @internal
1✔
265
    def _checkCompInstances(self):
1✔
266
        cInstances = [o for o in self._rtlCtx.hwModDef.objs
1✔
267
                      if isinstance(o, HdlCompInst)]
268
        cInst_cnt = len(cInstances)
1✔
269
        unit_cnt = len(self._subHwModules)
1✔
270
        if cInst_cnt != unit_cnt:
1!
271
            # resolve the error message
272
            inRtl = set(x.name for x in cInstances)
×
273
            inHwIO = set(x._name for x in self._subHwModules)
×
274
            cls_name = self.__class__.__name__
×
275
            if cInst_cnt > unit_cnt:
×
276
                diff = inRtl - inHwIO
×
UNCOV
277
                raise IntfLvlConfErr(
×
278
                    f"{cls_name:s}, {self._name:s}: unit(s) were found in HDL but were"
279
                    f" not registered {diff}")
280
            else:
281
                assert cInst_cnt < unit_cnt
×
282
                diff = inHwIO - inRtl
×
UNCOV
283
                raise IntfLvlConfErr(
×
284
                    f"{cls_name:s}, {self._name:s}: _to_rtl: unit(s) are missing in produced HDL {diff}")
285

286

287
def copy_HdlModuleDec_HwIO(orig_io: HwIOBase, new_io: HwIOBase,
1✔
288
                           ports: list[HdlPortItem], new_m: HwModule):
289
    new_io._direction = orig_io._direction
1✔
290
    if orig_io._hdlPort is not None:
1✔
291
        s = orig_io._sigInside
1✔
292
        assert s is not None, (
1✔
293
            "the component which shares a body with this component"
294
            " is actually some parent of this component")
295
        pi = copy(orig_io._hdlPort)
1✔
296
        pi.module = new_m
1✔
297
        ports.append(pi)
1✔
298
        d = pi.direction
1✔
299
        if d == DIRECTION.OUT:
1✔
300
            pi.dst = None
1✔
301
        elif d == DIRECTION.IN:
1✔
302
            pi.src = None
1✔
303
        else:
304
            raise NotImplementedError(d)
305
        new_io._hdlPort = pi
1✔
306
        new_io._sigInside = s
1✔
307
    elif isinstance(orig_io, HObjList):
1✔
308
        for hwIO, n_i in zip(orig_io, new_io):
1✔
309
            copy_HdlModuleDec_HwIO(hwIO, n_i, ports, new_m)
1✔
310
    else:
311
        for hwIO in orig_io._hwIOs:
1✔
312
            n_i = getattr(new_io, hwIO._name)
1✔
313
            copy_HdlModuleDec_HwIO(hwIO, n_i, ports, new_m)
1✔
314

315

316
def copy_HdlModuleDec(orig_m: HwModule, new_m: HwModule):
1✔
317
    """
318
    Copy the HdlModuleDec for HwModule from existing HwModule.
319
    This is used when the HwModule implementation was resolved as
320
    shared with some other already existing HwModule.
321
    (Happens when the body is the same and we want to avoid transpilling the same code again.) 
322
    """
323
    assert not new_m._rtlCtx.statements
1✔
324
    assert not new_m._rtlCtx.hwIOs
1✔
325
    assert not new_m._rtlCtx.signals
1✔
326
    assert new_m._rtlCtx.hwModDec is None
1✔
327

328
    new_m._hdl_module_name = orig_m._hdl_module_name
1✔
329
    hwModDec = new_m._rtlCtx.hwModDec = copy(orig_m._rtlCtx.hwModDec)
1✔
330
    hwModDec: HdlModuleDec
331

332
    params = []
1✔
333
    param_by_name = {p._name: p for p in new_m._hwParams}
1✔
334
    for p in hwModDec.params:
1✔
335
        p: HdlIdDef
336
        new_p_def = copy(p)
1✔
337
        old_p = new_p_def.origin = param_by_name[p.origin._name]
1✔
338
        old_p._name = p.origin._name
1✔
339
        new_p_def.value = old_p.get_hdl_value()
1✔
340
        params.append(new_p_def)
1✔
341

342
    hwModDec.params = params
1✔
343

344
    hwModDec.ports = []
1✔
345
    for hwO, hwI in zip(orig_m._hwIOs, new_m._hwIOs):
1✔
346
        if hwO._isExtern:
1!
347
            copy_HdlModuleDec_HwIO(hwO, hwI, hwModDec.ports, new_m)
1✔
348

349
    # params should be already sorted
350
    # hwModDec.params[:] = natsorted(hwModDec.params, key=lambda x: x.name)
351
    hwModDec.ports[:] = natsorted(hwModDec.ports, key=lambda x: x.name)
1✔
352

353

354
def _sharedCompBuildHwIOMapList(replacement: list[HwIOBase],
1✔
355
                                          substituted: list[HwIOBase],
356
                                          res: dict[HwIOBase, HwIOBase]):
357
    assert len(replacement) == len(substituted)
1✔
358
    for r, s in zip(replacement, substituted):
1✔
359
        assert r._name == s._name, (r._name, s._name)
1✔
360
        res[r] = s
1✔
361
        if r._hwIOs:
1✔
362
            _sharedCompBuildHwIOMapList(
1✔
363
                r._hwIOs, s._hwIOs, res)
364

365

366
def sharedCompBuildHwIOMap(replacement_m: HwModule, substituted_m: HwModule):
1✔
367
    """
368
    Build a dictionary which maps
369
    interface of replacement_m to interface of substituted_m
370
    """
371
    res = {}
1✔
372
    _sharedCompBuildHwIOMapList(
1✔
373
        replacement_m._hwIOs, substituted_m._hwIOs, res)
374
    return res
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc