def ternaryOpsToIf(statements): """Convert all ternary operators to IfContainers""" stms = [] for st in statements: if isinstance(st, Assignment): try: if not isinstance(st.src, RtlSignalBase): raise DoesNotContainsTernary() d = st.src.singleDriver() if not isinstance(d, Operator) or d.operator != AllOps.TERNARY: raise DoesNotContainsTernary() else: ops = d.operands ifc = IfContainer(ops[0], [Assignment(ops[1], st.dst)], [Assignment(ops[2], st.dst)] ) stms.append(ifc) continue except (MultipleDriversErr, DoesNotContainsTernary): pass except NoDriverErr: assert (hasattr(st.src, "_interface") and st.src._interface is not None)\ or st.src.defVal.vldMask, st.src stms.append(st) return stms
def SwitchContainer(cls, sw: SwitchContainer, ctx: HwtSerializerCtx): switchOn = sw.switchOn if not sw.cases: # this should be usually reduced, but can appear while debugging if sw.default: return "\n".join([cls.asHdl(obj, ctx) for obj in sw.default]) else: return cls.comment(" fully reduced switch on %s" % cls.asHdl(switchOn, ctx)) def mkCond(c): return switchOn._eq(c) elIfs = [] for key, statements in sw.cases[1:]: elIfs.append((mkCond(key), statements)) ifFalse = sw.default topCond = mkCond(sw.cases[0][0]) topIf = IfContainer(topCond, sw.cases[0][1], ifFalse, elIfs) return cls.IfContainer(topIf, ctx)
def test_baicIf(self): a = self.n.sig('a') b = self.n.sig('b') obj = If(a, b(1)).Else(b(0)) container, io_change = obj._try_reduce() self.assertFalse(io_change) self.assertEqual(len(container), 1) container = container[0] tmpl = IfContainer(a, ifTrue=[b(1)], ifFalse=[b(0)]) self.compareStructure(tmpl, container)
def test_ifContSeqEval(self): for a_in, b_in in [(0, 0), (0, 1), (1, 0), (1, 1)]: resT = Bits(2) nl = RtlNetlist() res = nl.sig("res", resT) a = nl.sig("a", BIT) b = nl.sig("b", BIT) def w(val): return res(val) a.def_val = hBit(a_in) b.def_val = hBit(b_in) stm = IfContainer(a & b, ifTrue=[ res(0), ], elIfs=[ (a, [res(1)]), ], ifFalse=[ res(2), ]) if a_in and b_in: expected = 0 elif a_in: expected = 1 else: expected = 2 stm.seqEval() newVal = res._val self.assertEqual(newVal.val, expected) self.assertEqual(newVal.vld_mask, 3)
def SwitchContainer(cls, sw: SwitchContainer, ctx: SerializerCtx): switchOn = sw.switchOn def mkCond(c): return switchOn._eq(c) elIfs = [] for key, statements in sw.cases[1:]: elIfs.append((mkCond(key), statements)) ifFalse = sw.default topCond = mkCond(sw.cases[0][0]) topIf = IfContainer(topCond, ifTrue=sw.cases[0][1], ifFalse=ifFalse, elIfs=elIfs) topIf._sensitivity = sw._sensitivity topIf._inputs = sw._inputs topIf._outputs = sw._outputs return cls.IfContainer(topIf, ctx)
def test_ifContSeqEval(self): for a_in, b_in in [(0, 0), (0, 1), (1, 0), (1, 1)]: resT = Bits(2) nl = RtlNetlist() res = nl.sig("res", resT) a = nl.sig("a", BIT) b = nl.sig("b", BIT) def w(val): return res(val) a.defVal = hBit(a_in) b.defVal = hBit(b_in) stm = IfContainer(a & b, ifTrue=[res(0), ], elIfs=[(a, [res(1)]), ], ifFalse=[res(2), ] ) if a_in and b_in: expected = 0 elif a_in: expected = 1 else: expected = 2 stm.seqEval() newVal = res._val self.assertEqual(newVal.val, expected) self.assertEqual(newVal.vldMask, 3)
def as_hdl_SwitchContainer(self, sw: SwitchContainer) -> HdlStmIf: "switch -> if" switchOn = sw.switchOn def mkCond(c): return switchOn._eq(c) elIfs = [] for key, statements in sw.cases[1:]: elIfs.append((mkCond(key), statements)) ifFalse = sw.default topCond = mkCond(sw.cases[0][0]) topIf = IfContainer(topCond, ifTrue=sw.cases[0][1], ifFalse=ifFalse, elIfs=elIfs) topIf._sensitivity = sw._sensitivity topIf._inputs = sw._inputs topIf._outputs = sw._outputs return self.as_hdl_IfContainer(topIf)
def IfContainer(cls, ifc: IfContainer, ctx: SerializerCtx): cond = cls.condAsHdl(ifc.cond, ctx) ifTrue = ifc.ifTrue if ifc.elIfs: # replace elifs with nested if statements ifFalse = [] topIf = IfContainer(ifc.cond, ifc.ifTrue, ifFalse) topIf._inputs = ifc._inputs topIf._outputs = ifc._outputs topIf._sensitivity = ifc._sensitivity for c, stms in ifc.elIfs: _ifFalse = [] lastIf = IfContainer(c, stms, _ifFalse) lastIf._inputs = ifc._inputs lastIf._outputs = ifc._outputs lastIf._sensitivity = ifc._sensitivity ifFalse.append(lastIf) ifFalse = _ifFalse if ifc.ifFalse is None: lastIf.ifFalse = [] else: lastIf.ifFalse = ifc.ifFalse return cls.IfContainer(topIf, ctx) else: ifFalse = ifc.ifFalse if ifFalse is None: ifFalse = [] childCtx = ctx.withIndent() outputInvalidateStms = [] for o in ifc._outputs: # [TODO] look up indexes indexes = None oa = Assignment(o._dtype.fromPy(None), o, indexes, virtualOnly=True, parentStm=ifc, is_completly_event_dependent=ifc._is_completly_event_dependent) outputInvalidateStms.append(cls.stmAsHdl(oa, childCtx)) return ifTmpl.render( indent=getIndent(ctx.indent), indentNum=ctx.indent, cond=cond, outputInvalidateStms=outputInvalidateStms, ifTrue=tuple(map( lambda obj: cls.stmAsHdl(obj, childCtx), ifTrue)), ifFalse=tuple(map( lambda obj: cls.stmAsHdl(obj, childCtx), ifFalse)))