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

Nic30 / hwt / 156bdd0a-ad87-4660-9f89-b625d8a529f1

06 Mar 2024 05:00PM UTC coverage: 87.632% (-0.01%) from 87.646%
156bdd0a-ad87-4660-9f89-b625d8a529f1

push

circleci

Nic30
style(RtlSyncSignal): extra asserts

3854 of 4723 branches covered (81.6%)

Branch coverage included in aggregate %.

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

22 existing lines in 2 files now uncovered.

11039 of 12272 relevant lines covered (89.95%)

0.9 hits per line

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

79.78
/hwt/code.py
1
from operator import and_, or_, xor, add
1✔
2
from typing import Union, Sequence, Optional, Tuple
1✔
3

4
from hwt.code_utils import _mkOp, _intfToSig
1✔
5
from hwt.hdl.operatorDefs import concatFn
1✔
6
from hwt.hdl.statements.codeBlockContainer import HdlStmCodeBlockContainer
1✔
7
from hwt.hdl.statements.ifContainter import IfContainer
1✔
8
from hwt.hdl.statements.statement import HwtSyntaxError, HdlStatement
1✔
9
from hwt.hdl.statements.switchContainer import SwitchContainer
1✔
10
from hwt.hdl.statements.utils.listOfHdlStatements import ListOfHdlStatement
1✔
11
from hwt.hdl.types.bits import Bits
1✔
12
from hwt.hdl.types.enum import HEnum
1✔
13
from hwt.hdl.types.typeCast import toHVal
1✔
14
from hwt.hdl.value import HValue
1✔
15
from hwt.math import log2ceil
1✔
16
from hwt.pyUtils.arrayQuery import arr_any
1✔
17
from hwt.synthesizer.interfaceLevel.mainBases import InterfaceBase, UnitBase
1✔
18
from hwt.synthesizer.rtlLevel.mainBases import RtlSignalBase
1✔
19
from hwt.synthesizer.rtlLevel.signalUtils.walkers import \
1✔
20
    discoverEventDependency
21

22

23
class CodeBlock(HdlStmCodeBlockContainer):
1✔
24
    """
25
    Container for list of statements
26
    """
27

28
    def __init__(self, *statements: Sequence[HdlStatement]):
1✔
29
        super(CodeBlock, self).__init__()
1✔
30
        self._register_stements(statements, self.statements)
1✔
31
        self.rank = sum(map(lambda s: s.rank, statements))
1✔
32

33
        if self._outputs:
1!
34
            ctx = self._get_rtl_context()
1✔
35
            ctx.statements.add(self)
1✔
36

37

38
class If(IfContainer):
1✔
39
    """
40
    If statement generator
41
    """
42

43
    def __init__(self, cond: Union[RtlSignalBase, InterfaceBase], *statements: Sequence[HdlStatement]):
1✔
44
        """
45
        :param cond: condition in if statement
46
        :param statements: list of statements which should be active
47
            if condition is met
48
        """
49
        cond_sig = _intfToSig(cond)
1✔
50
        if not isinstance(cond_sig, RtlSignalBase):
1!
51
            raise HwtSyntaxError("Condition is not signal, it is not certain"
×
52
                                 " if this is an error or desire ", cond_sig)
53

54
        assert cond_sig._dtype.bit_length() == 1, cond_sig
1✔
55
        super(If, self).__init__(cond_sig)
1✔
56
        self.rank = 1
1✔
57
        self._inputs.append(cond_sig)
1✔
58
        cond_sig.endpoints.append(self)
1✔
59

60
        ev_dep = arr_any(discoverEventDependency(cond_sig), lambda x: True)
1✔
61
        self._event_dependent_from_branch = 0 if ev_dep else None
1✔
62

63
        self._register_stements(statements, self.ifTrue)
1✔
64
        self._get_rtl_context().statements.add(self)
1✔
65

66
    def Elif(self, cond: Union[RtlSignalBase, InterfaceBase], *statements: Sequence[HdlStatement]):
1✔
67
        assert self.parentStm is None
1✔
68
        self.rank += 1
1✔
69
        cond_sig = _intfToSig(cond)
1✔
70

71
        assert cond_sig._dtype.bit_length() == 1, cond_sig
1✔
72
        ev_dep = arr_any(discoverEventDependency(cond_sig), lambda x: True)
1✔
73
        self._event_dependent_from_branch = len(self.elIfs) + 1 if ev_dep else None
1✔
74

75
        self._inputs.append(cond_sig)
1✔
76
        cond_sig.endpoints.append(self)
1✔
77

78
        stms = ListOfHdlStatement()
1✔
79
        self.elIfs.append((cond_sig, stms))
1✔
80
        self._register_stements(statements, stms)
1✔
81

82
        return self
1✔
83

84
    def Else(self, *statements: Sequence[HdlStatement]):
1✔
85
        assert self.parentStm is None
1✔
86
        if self.ifFalse is not None:
1!
87
            raise HwtSyntaxError(
×
88
                "Else on this if-then-else statement was already used")
89

90
        self.rank += 1
1✔
91

92
        self.ifFalse = ListOfHdlStatement()
1✔
93
        self._register_stements(statements, self.ifFalse)
1✔
94
        return self
1✔
95

96

97
class Switch(SwitchContainer):
1✔
98
    """
99
    Switch statement generator
100
    """
101

102
    def __init__(self, switchOn: Union[RtlSignalBase, InterfaceBase]):
1✔
103
        switchOn = _intfToSig(switchOn)
1✔
104
        if not isinstance(switchOn, RtlSignalBase):
1!
105
            raise HwtSyntaxError("Select is not signal, it is not certain"
×
106
                                 " if this is an error or desire")
107
        if arr_any(discoverEventDependency(switchOn), lambda x: True):
1!
108
            raise HwtSyntaxError("Can not switch on result of event operator")
×
109

110
        super(Switch, self).__init__(switchOn, [])
1✔
111
        switchOn.ctx.statements.add(self)
1✔
112
        self._inputs.append(switchOn)
1✔
113
        switchOn.endpoints.append(self)
1✔
114

115
    def add_cases(self, tupesValStms: Sequence[Tuple[Union[HValue, int], Sequence[HdlStatement]]]):
1✔
116
        """
117
        Add multiple case statements from iterable of tuples
118
        (caseVal, statements)
119
        """
120
        s = self
1✔
121
        for val, statements in tupesValStms:
1✔
122
            s = s.Case(val, statements)
1✔
123
        return s
1✔
124

125
    def Case(self, caseVal: Union[HValue, int], *statements: Sequence[HdlStatement]):
1✔
126
        "c-like case of switch statement"
127
        assert self.parentStm is None
1✔
128
        caseVal = toHVal(caseVal, self.switchOn._dtype)
1✔
129

130
        assert isinstance(caseVal, HValue), caseVal
1✔
131
        assert caseVal._is_full_valid(), "Cmp with invalid value"
1✔
132
        assert caseVal not in self._case_value_index, (
1✔
133
            "Switch statement already has case for value ", caseVal)
134

135
        self.rank += 1
1✔
136
        stms = ListOfHdlStatement()
1✔
137
        self._case_value_index[caseVal] = len(self.cases)
1✔
138
        self.cases.append((caseVal, stms))
1✔
139
        self._register_stements(statements, stms)
1✔
140

141
        return self
1✔
142

143
    def Default(self, *statements: Sequence[HdlStatement]):
1✔
144
        """c-like default of switch statement
145
        """
146
        assert self.parentStm is None
1✔
147
        self.rank += 1
1✔
148
        self.default = ListOfHdlStatement()
1✔
149
        self._register_stements(statements, self.default)
1✔
150
        return self
1✔
151

152

153
def SwitchLogic(cases: Sequence[Tuple[Union[RtlSignalBase, InterfaceBase, HValue, bool], Sequence[HdlStatement]]],
1✔
154
                default: Optional[Sequence[HdlStatement]]=None):
155
    """
156
    Generate if tree for cases like (syntax sugar for large generated elifs)
157

158
    ..code-block:: python
159
        if cond0:
160
            statements0
161
        elif cond1:
162
            statements1
163
        else:
164
            default
165

166
    :param case: iterable of tuples (condition, statements)
167
    :param default: default statements
168
    """
169
    assigTop = None
1✔
170
    hasElse = False
1✔
171
    for cond, statements in cases:
1✔
172
        if isinstance(cond, (RtlSignalBase, InterfaceBase)):
1✔
173
            if assigTop is None:
1✔
174
                assigTop = If(cond,
1✔
175
                             statements
176
                           )
177
            else:
178
                assigTop = assigTop.Elif(cond, statements)
1✔
179
        else:
180
            if cond:
1!
181
                if assigTop is None:
1!
182
                    assigTop = statements
1✔
183
                else:
184
                    assigTop.Else(statements)
×
UNCOV
185
                    hasElse = True
×
186
            else:
UNCOV
187
                raise HwtSyntaxError("Condition is not a signal, it is not certain"
×
188
                                     " if this is an error or desire ", cond)
189

190
    if assigTop is None:
1✔
191
        if default is None:
1!
UNCOV
192
            return []
×
193
        else:
194
            return default
1✔
195
    else:
196
        if hasElse:
1!
UNCOV
197
            return assigTop
×
198
        elif default is not None:
1✔
199
            assigTop = assigTop.Else(default)
1✔
200

201
        return assigTop
1✔
202

203

204
def In(sigOrVal: Union[RtlSignalBase, InterfaceBase, HValue], iterable: Sequence[Union[RtlSignalBase, InterfaceBase, HValue]]):
1✔
205
    """
206
    HDL convertible "in" operator, check if any of items
207
    in "iterable" equals "sigOrVal"
208
    """
209
    res = None
1✔
210
    for i in iterable:
1✔
211
        i = toHVal(i)
1✔
212
        if res is None:
1✔
213
            res = sigOrVal._eq(i)
1✔
214
        else:
215
            res = res | sigOrVal._eq(i)
1✔
216

217
    assert res is not None, "argument iterable is empty"
1✔
218
    return res
1✔
219

220

221
def StaticForEach(parentUnit: UnitBase, items, bodyFn, name=""):
1✔
222
    """
223
    Generate for loop for static items
224

225
    :param parentUnit: unit where this code should be instantiated
226
    :param items: items which this "for" iterating on
227
    :param bodyFn: function which fn(item, index) or fn(item)
228
        returns (statementList, ack).
229
        It's content is performed in every iteration.
230
        When ack is high loop will fall to next iteration
231
    """
232

233
    items = list(items)
1✔
234
    itemsCnt = len(items)
1✔
235
    if itemsCnt == 0:
1!
236
        # if there are no items there is nothing to generate
UNCOV
237
        return []
×
238
    elif itemsCnt == 1:
1✔
239
        # if there is only one item do not generate counter logic generate
240
        return bodyFn(items[0], 0)
1✔
241
    else:
242
        # if there is multiple items we have to generate counter logic
243
        index = parentUnit._reg(name + "for_index",
1✔
244
                                Bits(log2ceil(itemsCnt + 1), signed=False),
245
                                def_val=0)
246
        ackSig = parentUnit._sig(name + "for_ack")
1✔
247

248
        statementLists = []
1✔
249
        for i, (statementList, ack) in [(i, bodyFn(item, i))
1✔
250
                                        for i, item in enumerate(items)]:
251
            statementLists.append(statementList + [(ackSig(ack)), ])
1✔
252

253
        If(ackSig,
1✔
254
           If(index._eq(itemsCnt - 1),
255
              index(0)
256
              ).Else(
257
               index(index + 1)
258
           )
259
           )
260

261
        return Switch(index)\
1✔
262
            .add_cases(
263
            enumerate(statementLists)
264
        ).Default(
265
            bodyFn(items[0], 0)[0],
266
            ackSig(True)
267
        )
268

269

270
class FsmBuilder(Switch):
1✔
271
    """
272
    A syntax sugar which automatically construct the state transition switch and state register
273

274
    :ivar ~.stateReg: register with state
275
    """
276

277
    def __init__(self, parent, stateT, stateRegName="st"):
1✔
278
        """
279
        :param parent: parent unit where fsm should be builded
280
        :param stateT: enum type of state
281
        :param stateRegName: name of register where sate is stored
282
        """
283
        if isinstance(stateT, HEnum):
1!
284
            beginVal = stateT.from_py(stateT._allValues[0])
1✔
285
        else:
UNCOV
286
            beginVal = 0
×
287

288
        self.stateReg = parent._reg(stateRegName, stateT, beginVal)
1✔
289
        Switch.__init__(self, self.stateReg)
1✔
290

291
    def Trans(self, stateFrom, *condAndNextState):
1✔
292
        """
293
        :param stateFrom: apply when FSM is in this state
294
        :param condAndNextState: tuples (condition, newState),
295
            last does not to have condition
296

297
        :attention: transitions has priority, first has the biggest
298
        :attention: if stateFrom is None it is evaluated as default
299
        """
300
        top = []
1✔
301
        last = True
1✔
302

303
        for cAndS in reversed(condAndNextState):
1✔
304
            if last is True:
1✔
305
                last = False
1✔
306
                # if this is last trans. it does not have to condition
307
                try:
1✔
308
                    condition, newvalue = cAndS
1✔
309
                except TypeError:
1✔
310
                    top = self.stateReg(cAndS)
1✔
311
                    continue
1✔
312
                top = []
1✔
313

314
            else:
315
                condition, newvalue = cAndS
1✔
316

317
            # building decision tree
318
            top = \
1✔
319
                If(condition,
320
                   self.stateReg(newvalue)
321
                ).Else(
322
                    top
323
                )
324
        if stateFrom is None:
1!
UNCOV
325
            return Switch.Default(self, top)
×
326
        else:
327
            return Switch.Case(self, stateFrom, top)
1✔
328

329
    def Default(self, *condAndNextState):
1✔
330
        d = self.Trans(None, *condAndNextState)
×
331
        d.stateReg = self.stateReg
×
UNCOV
332
        return d
×
333

334

335
# variadic operator functions
336
And = _mkOp(and_)
1✔
337
Add = _mkOp(add)
1✔
338
Or = _mkOp(or_)
1✔
339
Xor = _mkOp(xor)
1✔
340
Concat = _mkOp(concatFn)
1✔
341

342

343
def ror(sig:Union[RtlSignalBase, HValue], howMany: int) -> RtlSignalBase:
1✔
344
    "Rotate right"
345
    if sig._dtype.bit_length() == 1:
1✔
346
        return sig
1✔
347

348
    if isinstance(howMany, int):
1!
349
        return sig[howMany:]._concat(sig[:howMany])
1✔
350
    elif isinstance(howMany, HValue):
×
UNCOV
351
        return ror(sig, int(howMany))
×
352
    else:
353
        t = howMany._dtype
×
UNCOV
354
        if not isinstance(t, Bits) or t.signed:
×
355
            raise NotImplementedError(t)
356
        res = sig
×
357
        for i in range(1, t.domain_size() - 1):
×
358
            res = howMany._eq(i)._ternary(ror(sig, i), res)
×
UNCOV
359
        return  res
×
360

361

362
def rol(sig:Union[RtlSignalBase, HValue], howMany:Union[RtlSignalBase, int]) -> RtlSignalBase:
1✔
363
    "Rotate left"
364
    if isinstance(howMany, int):
1!
365
        width = sig._dtype.bit_length()
1✔
366
        if width == 1:
1!
UNCOV
367
            return sig
×
368
        return sig[(width - howMany):]._concat(sig[:(width - howMany)])
1✔
369
    elif isinstance(howMany, HValue):
×
UNCOV
370
        return rol(sig, int(howMany))
×
371
    else:
372
        t = howMany._dtype
×
UNCOV
373
        if not isinstance(t, Bits) or t.signed:
×
374
            raise NotImplementedError(t)
375
        res = sig
×
376
        for i in range(1, t.domain_size() - 1):
×
377
            res = howMany._eq(i)._ternary(rol(sig, i), res)
×
UNCOV
378
        return  res
×
379

380

381
def replicate(n, v):
1✔
382
    return Concat(*(v for _ in range(n)))
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