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

Nic30 / hwt / 8b945dd2-6cbf-43b3-be54-881b32d4f5e4

10 Jun 2025 09:35PM UTC coverage: 84.734% (-2.6%) from 87.284%
8b945dd2-6cbf-43b3-be54-881b32d4f5e4

push

circleci

Nic30
test: fix call of unittestMain

3415 of 4468 branches covered (76.43%)

Branch coverage included in aggregate %.

11877 of 13579 relevant lines covered (87.47%)

0.87 hits per line

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

88.15
/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.hdl.portItem import HdlPortItem
1✔
9
from hwt.mainBases import HwIOBase
1✔
10
from hwt.synthesizer.dummyPlatform import DummyPlatform
1✔
11
from hwt.synthesizer.exceptions import IntfLvlConfErr
1✔
12
from hwt.synthesizer.interfaceLevel.hwModuleImplHelpers import HwModuleImplHelpers, \
1✔
13
    _default_param_updater
14
from hwt.synthesizer.interfaceLevel.propDeclrCollector import PropDeclrCollector
1✔
15
from hwt.synthesizer.rtlLevel.netlist import RtlNetlist
1✔
16
from ipCorePackager.constants import DIRECTION
1✔
17

18

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

25

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

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

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

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

88
    @internal
1✔
89
    def _loadHwIODeclarations(self, hwIO: HwIOBase, isExtern: bool):
1✔
90
        hwIO._loadHwDeclarations()
1✔
91
        hwIO._setAsExtern(isExtern)
1✔
92

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

111
        # if I am a unit load subunits
112
        for u in self._subHwModules:
1✔
113
            u._loadHwDeclarations()
1✔
114

115
    @internal
1✔
116
    def _registerHwIOInHwImpl(self, hwIOName, hwIO):
1✔
117
        """
118
        Register interface in implementation phase
119
        """
120
        self._registerHwIO(hwIOName, hwIO, isPrivate=True)
1✔
121
        self._loadHwIODeclarations(hwIO, False)
1✔
122
        hwIO._signalsForHwIO(
1✔
123
            self._rtlCtx, None, self._store_manager.name_scope)
124

125
    def _getDefaultName(self) -> str:
1✔
126
        return self.__class__.__name__
1✔
127

128
    def _get_hdl_doc(self) -> Optional[str]:
1✔
129
        if self.__doc__ is not HwModule.__doc__:
1!
130
            return self.__doc__
1✔
131

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

168
        for proc in target_platform.beforeToRtl:
1!
169
            proc(self)
×
170

171
        mdec = self._rtlCtx.create_HdlModuleDec(
1✔
172
            self._hdl_module_name, store_manager, self._hwParams)
173
        mdec.origin = self
1✔
174
        mdec.doc = self._get_hdl_doc()
1✔
175

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

189
        if do_serialize_this:
1✔
190
            # prepare subunits
191
            for sm in self._subHwModules:
1✔
192
                yield from sm._to_rtl(target_platform, store_manager)
1✔
193

194
            # now every sub unit has a HdlModuleDec prepared
195
            for sm in self._subHwModules:
1✔
196
                subHwModuleName = sm._name
1✔
197
                sm._signalsForSubHwModuleEntity(self._rtlCtx, "sig_" + subHwModuleName)
1✔
198

199
            for proc in target_platform.beforeToRtlImpl:
1!
200
                proc(self)
×
201

202
        try:
1✔
203
            store_manager.hierarchy_push(mdec)
1✔
204
            if do_serialize_this:
1✔
205
                self._loadImpl()
1✔
206
                yield from self._lazy_loaded
1✔
207

208
                if not self._rtlCtx.hwIOs:
1!
209
                    raise IntfLvlConfErr(
×
210
                        "Can not find any external interface for unit %s"
211
                        "- unit without interfaces are not synthesisable"
212
                        % self._name)
213

214
            for proc in target_platform.afterToRtlImpl:
1!
215
                proc(self)
×
216

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

225
            for hwIO in self._hwIOs:
1✔
226
                if hwIO._isExtern:
1!
227
                    # reverse because other components
228
                    # looks at this interface from the outside
229
                    hwIO._reverseDirection()
1✔
230

231
            if do_serialize_this:
1✔
232
                if add_param_asserts and self._hwParams:
1✔
233
                    mdef.objs.extend(store_manager.as_hdl_ast._as_hdl_HdlModuleDef_param_asserts(mdec))
1✔
234
                store_manager.write(mdef)
1✔
235

236
            yield True, self
1✔
237

238
            # after synthesis clean up interface so this :class:`hwt.hwModule.HwModule` object can be
239
            # used elsewhere
240
            self._cleanThisSubunitRtlSignals()
1✔
241
            if do_serialize_this:
1✔
242
                self._checkCompInstances()
1✔
243

244
            for proc in target_platform.afterToRtl:
1!
245
                proc(self)
×
246
        finally:
247
            store_manager.hierarchy_pop(mdec)
1✔
248

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

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

282

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

308

309
def copy_HdlModuleDec(orig_m: HwModule, new_m: HwModule):
1✔
310
    assert not new_m._rtlCtx.statements
1✔
311
    assert not new_m._rtlCtx.hwIOs
1✔
312
    assert not new_m._rtlCtx.signals
1✔
313
    assert new_m._rtlCtx.hwModDec is None
1✔
314

315
    new_m._hdl_module_name = orig_m._hdl_module_name
1✔
316
    hwModDec = new_m._rtlCtx.hwModDec = copy(orig_m._rtlCtx.hwModDec)
1✔
317
    hwModDec: HdlModuleDec
318

319
    params = []
1✔
320
    param_by_name = {p._name: p for p in new_m._hwParams}
1✔
321
    for p in hwModDec.params:
1✔
322
        p: HdlIdDef
323
        new_p_def = copy(p)
1✔
324
        old_p = new_p_def.origin = param_by_name[p.origin._name]
1✔
325
        old_p._name = p.origin._name
1✔
326
        new_p_def.value = old_p.get_hdl_value()
1✔
327
        params.append(new_p_def)
1✔
328

329
    hwModDec.params = params
1✔
330

331
    hwModDec.ports = []
1✔
332
    for hwO, hwI in zip(orig_m._hwIOs, new_m._hwIOs):
1✔
333
        if hwO._isExtern:
1!
334
            copy_HdlModuleDec_HwIO(hwO, hwI, hwModDec.ports, new_m)
1✔
335

336
    # params should be already sorted
337
    # hwModDec.params[:] = natsorted(hwModDec.params, key=lambda x: x.name)
338
    hwModDec.ports[:] = natsorted(hwModDec.ports, key=lambda x: x.name)
1✔
339

340

341
def _sharedCompBuildHwIOMapList(replacement: list[HwIOBase],
1✔
342
                                          substituted: list[HwIOBase],
343
                                          res: dict[HwIOBase, HwIOBase]):
344
    assert len(replacement) == len(substituted)
1✔
345
    for r, s in zip(replacement, substituted):
1✔
346
        assert r._name == s._name, (r._name, s._name)
1✔
347
        res[r] = s
1✔
348
        if r._hwIOs:
1✔
349
            _sharedCompBuildHwIOMapList(
1✔
350
                r._hwIOs, s._hwIOs, res)
351

352

353
def sharedCompBuildHwIOMap(replacement_m: HwModule, substituted_m: HwModule):
1✔
354
    """
355
    Build a dictionary which maps
356
    interface of replacement_m to interface of substituted_m
357
    """
358
    res = {}
1✔
359
    _sharedCompBuildHwIOMapList(
1✔
360
        replacement_m._hwIOs, substituted_m._hwIOs, res)
361
    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