def as_hdl_HdlType_bits(self, typ: Bits, declaration=False): isVector = typ.force_vector or typ.bit_length() > 1 sigType = self.signalType if typ == INT: t = HdlValueId("int", obj=int) elif sigType is SIGNAL_TYPE.PORT_WIRE: t = HdlTypeAuto elif sigType is SIGNAL_TYPE.REG or sigType is SIGNAL_TYPE.PORT_REG: t = HdlValueId("reg", obj=LanguageKeyword()) elif sigType is SIGNAL_TYPE.WIRE: t = HdlValueId("wire", obj=LanguageKeyword()) else: raise ValueError(sigType) if typ.signed is None: is_signed = None else: is_signed = self.as_hdl_int(int(typ.signed)) if isVector: w = typ.bit_length() assert isinstance(w, int) or (isinstance(w, RtlSignal) and w._const), w w = hdl_downto(self.as_hdl(w - 1), self.as_hdl_int(0)) else: w = None return HdlOp(HdlOpType.PARAMETRIZATION, [t, w, is_signed])
def as_hdl_PortConnection(self, o: HdlPortItem): assert isinstance(o, HdlPortItem), o intern, outer = o.getInternSig(), o.getOuterSig() assert not intern.hidden, intern assert not outer.hidden, outer intern_hdl = HdlValueId(intern.name, obj=intern) outer_hdl = HdlValueId(outer.name, obj=outer) pm = hdl_map_asoc(intern_hdl, outer_hdl) return pm
def create_HdlModuleDef(self, target_platform: DummyPlatform, store_manager: "StoreManager"): """ Generate a module body (architecture) for this module * Resolve name collisions * Convert netlist representation to HdlProcesses * Remove unconnected * Mark visibility of signals """ removeUnconnectedSignals(self) markVisibilityOfSignalsAndCheckDrivers(self.signals, self.interfaces) for proc in target_platform.beforeHdlArchGeneration: proc(self) ns = store_manager.name_scope mdef = HdlModuleDef() mdef.dec = self.ent mdef.module_name = HdlValueId(self.ent.name, obj=self.ent) mdef.name = "rtl" processes = sorted(self.statements, key=HdlStatement_sort_key) processes = sorted(statements_to_HdlStatementBlocks(processes), key=HdlStatement_sort_key) # add signals, variables etc. in architecture for s in sorted((s for s in self.signals if not s.hidden and s not in self.interfaces.keys()), key=RtlSignal_sort_key): v = HdlIdDef() v.origin = s s.name = v.name = ns.checked_name(s.name, s) v.type = s._dtype v.value = s.def_val v.is_const = s._const mdef.objs.append(v) for p in processes: p.name = ns.checked_name(p.name, p) mdef.objs.extend(processes) # instantiate subUnits in architecture for u in self.subUnits: ci = HdlCompInst() ci.origin = u ci.module_name = HdlValueId(u._ctx.ent.name, obj=u._ctx.ent) ci.name = HdlValueId(ns.checked_name(u._name + "_inst", ci), obj=u) e = u._ctx.ent ci.param_map.extend(e.params) ci.port_map.extend(e.ports) mdef.objs.append(ci) self.arch = mdef return mdef
def sensitivityListItem(self, item, anyEventDependent): if isinstance(item, Operator): op = item.operator if op == AllOps.RISING_EDGE: sens = HdlOpType.RISING elif op == AllOps.FALLING_EDGE: sens = HdlOpType.FALLING else: raise TypeError("This is not an event sensitivity", op) return HdlOp(sens, [HdlValueId(item.operands[0].name)]) else: return HdlValueId(item.name)
def hdl_getattr(o, prop_name): """ :type o: iHdlExpr :type prop_name: str :return: HdlOp """ return HdlOp(HdlOpType.DOT, [o, HdlValueId(prop_name)])
def as_hdl_HdlStatementBlock(self, proc: HdlStatementBlock) -> HdlStmProcess: p = ToHdlAst.as_hdl_HdlStatementBlock(self, proc) self.stm_outputs[p] = sorted( [HdlValueId(i.name, obj=i) for i in proc._outputs] ) return p
class ToHdlAstHwt_ops(): CONCAT = HdlValueId("Concat", obj=LanguageKeyword()) op_transl_dict = ToHdlAstSimModel_value.op_transl_dict _cast_ops = ToHdlAstSimModel_value._cast_ops def as_hdl_Operator(self, op: Operator): ops = op.operands o = op.operator with ValueWidthRequirementScope(self, o == AllOps.CONCAT): if o in self._cast_ops: op0 = hdl_getattr(self.as_hdl(ops[0]), "_reinterpret_cast") op1 = self.as_hdl_HdlType(op.result._dtype) return hdl_call(op0, [ op1, ]) elif o == AllOps.EQ: return hdl_call(hdl_getattr(self.as_hdl(ops[0]), "_eq"), [self.as_hdl(ops[1])]) elif o == AllOps.CONCAT: return hdl_call(self.CONCAT, [self.as_hdl(o2) for o2 in ops]) elif o == AllOps.TERNARY: cond, op0, op1 = ops cond = self.as_hdl(cond) with ValueWidthRequirementScope(self, True): op0 = self.as_hdl(op0) op1 = self.as_hdl(op1) return hdl_call(hdl_getattr(cond, "_ternary"), [op0, op1]) else: o = self.op_transl_dict[o] return HdlOp(o, [self.as_hdl(o2) for o2 in ops])
class ToHdlAstHwt_types(): """ part of ToHdlAstSimModel responsible for type serialization """ BOOL = HdlValueId("BOOL", obj=BOOL) INT = HdlValueId("INT", obj=INT) BITS = HdlValueId("Bits", obj=Bits) def does_type_requires_extra_def(self, t, other_types): try: return t._as_hdl_requires_def(self, other_types) except MethodNotOverloaded: pass return isinstance(t, HEnum) and t not in other_types def as_hdl_HdlType_array(self, typ: HArray, declaration=False): assert not declaration, "declaration should not be required" t = self.as_hdl_HdlType(typ.element_t, declaration=declaration) return hdl_index(t, HdlValueInt(int(typ.size), None, None)) def as_hdl_HdlType_bits(self, typ: Bits, declaration=False): if declaration: raise NotImplementedError() elif typ == BOOL: return self.BOOL elif typ == INT: return self.INT w = typ.bit_length() assert isinstance(w, int), w def add_kw(name, val): kw = hdl_map_asoc(HdlValueId(name), HdlValueInt(val, None, None)) args.append(kw) args = [HdlValueInt(w, None, None)] if typ.signed is not BITS_DEFAUTL_SIGNED: add_kw("signed", typ.signed) if typ.force_vector is not BITS_DEFAUTL_FORCEVECTOR and w <= 1: add_kw("force_vector", typ.force_vector) if typ.negated is not BITS_DEFAUTL_NEGATED: add_kw("negated", typ.negated) return hdl_call(self.BITS, args) def as_hdl_HdlType_float(self, typ: HFloat, declaration=False): return hdl_call(HdlValueId("HFloat"), typ.exponent_w, typ.mantisa_w)
def sensitivityListItem(self, item, anyIsEventDependnt): if isinstance(item, Operator): op = item.operator assert op in (AllOps.RISING_EDGE, AllOps.FALLING_EDGE), item assert not item.operands[0].hidden, item return self.as_hdl_Operator(item) else: return HdlValueId(item.name, obj=item)
class ToHdlAstVhdl2008_types(): BOOLEAN = HdlValueId("BOOLEAN", obj=LanguageKeyword()) INTEGER = HdlValueId("INTEGER", obj=LanguageKeyword()) STRING = HdlValueId("STRING", obj=LanguageKeyword()) STD_LOGIC_VECTOR = HdlValueId("STD_LOGIC_VECTOR", obj=LanguageKeyword()) STD_LOGIC = HdlValueId("STD_LOGIC", obj=LanguageKeyword()) SIGNED = HdlValueId("SIGNED", obj=LanguageKeyword()) UNSIGNED = HdlValueId("UNSIGNED", obj=LanguageKeyword()) def as_hdl_HdlType_str(self, typ, declaration=False): assert not declaration return self.STRING def as_hdl_HdlType_bits(self, typ: Bits, declaration=False): if declaration: raise NotImplementedError() if typ == BOOL: return self.BOOLEAN if typ == INT: return self.INTEGER bitLength = typ.bit_length() w = typ.bit_length() isVector = typ.force_vector or bitLength > 1 if typ.signed is None: if isVector: name = self.STD_LOGIC_VECTOR else: return self.STD_LOGIC elif typ.signed: name = self.SIGNED else: name = self.UNSIGNED return HdlOp(HdlOpType.CALL, [ name, HdlOp(HdlOpType.DOWNTO, [self.as_hdl(w - 1), self.as_hdl_int(0)]) ]) def as_hdl_HdlType_array(self, typ: HArray, declaration=False): if declaration: v = HdlIdDef() name = getattr(typ, "name", None) if name is None: name = "arr_t_" v.name = self.name_scope.checked_name(name, typ) v.type = HdlTypeType v.origin = typ size = hdl_downto(self.as_hdl_int(int(typ.size) - 1), self.as_hdl_int(0)) if self.does_type_requires_extra_def(typ.element_t, ()): raise NotImplementedError(typ.element_t) e_t = self.as_hdl_HdlType(typ.element_t, declaration=False) v.value = hdl_index(e_t, size) return v else: return super(ToHdlAstVhdl2008_types, self).as_hdl_HdlType_array(typ, declaration)
def rm_ToBasicHdlSimModel_io_prefix_and_tmp_vars_from_outputs(stm_outputs): C = HdlValueId("c") CVLD = HdlValueId("cVld") SELF = HdlValueId("self") IO = HdlValueId("io") VAL_NEXT = HdlValueId("val_next") res = {} for stm, outputs in stm_outputs.items(): new_outputs = [] for o in outputs: if o in (C, CVLD): continue assert o[0] == SELF, o assert o[1] == IO, o assert o[-1] == VAL_NEXT new_o = o[2:-1] if len(new_o) == 1: new_o = new_o[0] new_outputs.append(new_o) res[stm] = new_outputs return res
def as_hdl_HEnumVal(self, val: HEnumVal): try: t_name = self.name_scope.get_object_name(val._dtype) except ObjectForNameNotFound: if self.debug: t_name = val._dtype.name else: raise if val.vld_mask: try: name = self.name_scope.get_object_name(val) except ObjectForNameNotFound: if self.debug: name = val.val else: raise return hdl_getattr(HdlValueId(t_name, obj=val._dtype), name) else: return hdl_call(hdl_getattr(HdlValueId(t_name, obj=val._dtype), "from_py"), [None, ])
def array1d_t_to_vhdl(to_hdl: ToHdlAstVhdl2008, declaration=False): if not isinstance(to_hdl, ToHdlAstVhdl2008): raise NotImplementedError() if declaration: raise ValueError( "_as_hdl_requires_def specifies that this should not be required" ) # "mem(0 to %d)(%d downto 0)" % (t.size, t.element_t.bit_length() - 1) _int = to_hdl.as_hdl_int size = HdlOp(HdlOpType.TO, [_int(0), _int(int(array1d_t.size))]) e_width = hdl_downto(_int(array1d_t.element_t.bit_length() - 1), _int(0)) return hdl_index(hdl_index(HdlValueId("mem"), size), e_width)
class ToHdlAstSystemC_type(): sc_int = HdlValueId("sc_int", obj=LanguageKeyword()) sc_uint = HdlValueId("sc_uint", obj=LanguageKeyword()) sc_bigint = HdlValueId("sc_bigint", obj=LanguageKeyword()) sc_biguint = HdlValueId("sc_biguint", obj=LanguageKeyword()) sc_signal = HdlValueId("sc_signal", obj=LanguageKeyword()) STRING = HdlOp(HdlOpType.DOUBLE_COLON, HdlValueId("string", obj=LanguageKeyword())) def does_type_requires_extra_def(self, t, other_types): try: return t._as_hdl_requires_def(self, other_types) except MethodNotOverloaded: pass return False def as_hdl_HdlType_str(self, typ, declaration=False): assert not declaration return self.STRING def as_hdl_HdlType_bits(self, typ: Bits, declaration=False): if declaration: raise NotImplementedError() w = typ.bit_length() if w <= 64: if typ.signed: typeBaseName = self.sc_int else: typeBaseName = self.sc_uint else: if typ.signed: typeBaseName = self.sc_bigint else: typeBaseName = self.sc_biguint t = HdlOp(HdlOpType.PARAMETRIZATION, [typeBaseName, self.as_hdl_int(w)]) if self.signalType == SIGNAL_TYPE.WIRE: t = HdlOp(HdlOpType.PARAMETRIZATION, [self.sc_signal, t]) return t def as_hdl_HdlType_array(self, typ: HArray, declaration=False): if declaration: return super(ToHdlAstSystemC_type, self).as_hdl_HdlType_array(self, typ, declaration=declaration) else: _int = self.as_hdl_int size = _int(int(typ.size)) return hdl_index(self.as_hdl_HdlType(typ.element_t), size) def as_hdl_HdlType_enum(self, typ: HEnum, declaration=False): return ToHdlAstVerilog_types.as_hdl_HdlType_enum( self, typ, declaration=declaration)
def as_hdl_SignalItem(self, si: SignalItem, declaration=False): if declaration: sigType = systemCTypeOfSig(si) with SignalTypeSwap(self, sigType): return ToHdlAst_Value.as_hdl_SignalItem(self, si, declaration=True) else: if si.hidden and si.origin is not None: return self.as_hdl(si.origin) else: sigType = systemCTypeOfSig(si) _si = HdlValueId(si.name, obj=si) if self._in_sensitivity_list or self._is_target or sigType is SIGNAL_TYPE.REG: return _si else: return hdl_call(hdl_getattr(_si, "read"), [])
def as_hdl_SignalItem(self, si: Union[SignalItem, HdlIdDef], declaration=False): if declaration: if isinstance(si, HdlIdDef): new_si = copy(si) new_si.type = self.as_hdl_HdlType(si.type) if si.value is not None: new_si.value = self.as_hdl_Value(si.value) return new_si else: raise NotImplementedError() else: # if isinstance(si, SignalItem) and si._const: # # to allow const cache to extract constants # return self.as_hdl_Value(si._val) if si.hidden and si.origin is not None: return self.as_hdl(si.origin) else: return HdlValueId(si.name, obj=si)
def visit_HdlOp(self, o): """ :type o: HdlOp """ op = o.fn if op == HdlOpType.EQ: # HdlOpType.EQ: '%s._eq(%s)', to_property_call(o, "_eq") elif op == HdlOpType.CONCAT: to_property_call(o, "_concat") elif op == HdlOpType.TERNARY: to_property_call(o, "_ternary__val") elif op == HdlOpType.DOWNTO: # HdlOpType.DOWNTO: "slice(%s, %s)", o.fn = HdlOpType.CALL o.ops = [ HdlValueId("slice"), ] + o.ops elif op == HdlOpType.TO: raise NotImplementedError(o) elif op == HdlOpType.CALL: raise NotImplementedError("inline", o)
def link_module_dec_def(context): """ :type context: HdlContext """ objs = [] last = None for o in context.objs: if isinstance(o, HdlModuleDef) and o.dec is None: assert isinstance(last, HdlModuleDec) \ and o.module_name == HdlValueId(last.name), ( "Module body has to be behind the module header", last, o) o.dec = last objs.append(o) last = None else: if last is not None: objs.append(last) last = o if last is not None: objs.append(last) context.objs = objs
class ToHdlAstHwt_ops(): CONCAT = HdlValueId("Concat", obj=LanguageKeyword()) op_transl_dict = { **HWT_TO_HDLCONVEROTR_OPS, AllOps.INDEX: HdlOpType.INDEX, } _cast_ops = { AllOps.BitsAsSigned, AllOps.BitsAsUnsigned, AllOps.BitsAsVec, } def as_hdl_Operator(self, op: Operator): ops = op.operands o = op.operator with ValueWidthRequirementScope(self, o == AllOps.CONCAT): if o in self._cast_ops: op0 = hdl_getattr(self.as_hdl(ops[0]), "_reinterpret_cast") op1 = self.as_hdl_HdlType(op.result._dtype) return hdl_call(op0, [ op1, ]) elif o == AllOps.EQ: return hdl_call(hdl_getattr(self.as_hdl(ops[0]), "_eq"), [self.as_hdl(ops[1])]) elif o == AllOps.CONCAT: return hdl_call(self.CONCAT, [self.as_hdl(o2) for o2 in ops]) elif o == AllOps.TERNARY: cond, op0, op1 = ops cond = self.visit_iHdlObj(cond) with ValueWidthRequirementScope(self, True): op0 = self.as_hdl(op0) op1 = self.as_hdl(op1) return HdlOp(o, [cond, op0, op1]) else: o = self.op_transl_dict[o] return HdlOp(o, [self.as_hdl(o2) for o2 in ops])
def visit_HdlOp(self, o): """ :type o: HdlOp """ fn = o.ops[0] if fn == HdlValueId("assert"): self.visit_assert(o.ops[1:]) return elif fn == HdlValueId("report"): self.visit_report(o.ops[1:]) return w = self.out.write op = o.fn if op == HdlOpType.RISING: w("RISING_EDGE(") self.visit_iHdlExpr(o.ops[0]) w(")") elif op == HdlOpType.FALLING: w("FALLING_EDGE(") self.visit_iHdlExpr(o.ops[0]) w(")") elif op == HdlOpType.INDEX or op == HdlOpType.CALL: self._visit_operand(o.ops[0], 0, o, False, False) w("(") for isLast, (o_i, _o) in iter_with_last(enumerate(o.ops[1:])): self._visit_operand(_o, o_i + 1, o, False, True) if not isLast: w(", ") w(")") elif op == HdlOpType.TERNARY: has_3_ops = len(o.ops) == 3 if has_3_ops: cond, o0, o1 = o.ops else: cond, o0 = o.ops self._visit_operand(o0, 1, o, True, False) w(" WHEN ") self._visit_operand(cond, 0, o, True, False) if has_3_ops: if isinstance(o1, HdlOp) and o1.fn == HdlOpType.TERNARY: w(" ELSE\n") self.visit_iHdlExpr(o1) # must not have parenthesis else: w(" ELSE ") self._visit_operand(o1, 2, o, False, False) elif op == HdlOpType.APOSTROPHE: self._visit_operand(o.ops[0], 0, o, True, False) w("'") args = o.ops[1] if isinstance(args, list): self.visit_iHdlExpr(args) elif isinstance(args, HdlValueId): # normal attribute self.visit_iHdlExpr(args) else: w("(") self._visit_operand(args, 0, o, False, True) w(")") elif op == HdlOpType.ABS: w("ABS(") self.visit_iHdlExpr(o.ops[0]) w(")") elif op == HdlOpType.DEFINE_RESOLVER: assert self.in_typedef self.visit_iHdlExpr(o.ops[0]) w(" ") self.visit_iHdlExpr(o.ops[1]) else: return ToHdlCommon.visit_HdlOp(self, o)
def apply_cast(self, t_name, op): return hdl_call(HdlValueId(t_name, obj=LanguageKeyword()), [op, ])
class ToHdlAstSimModel_value(ToHdlAst_Value): Bits3val = HdlValueId("Bits3val", obj=Bits3val) Bits3t = HdlValueId("Bits3t", obj=Bits3t) SELF = HdlValueId("self", obj=LanguageKeyword()) Array3val = HdlValueId("Array3val", obj=Array3val) SLICE = HdlValueId("slice", obj=slice) TRUE = HdlValueId("True", obj=True) FALSE = HdlValueId("False", obj=False) Bits3val = HdlValueId("Bits3val", obj=Bits3val) ABits3t = HdlValueId("Bits3t", obj=Bits3t) SELF_IO = hdl_getattr(HdlValueId("self", obj=LanguageKeyword()), "io") CONCAT = HdlValueId("Concat", obj=Concat) op_transl_dict = { **HWT_TO_HDLCONVEROTR_OPS, AllOps.INDEX: HdlOpType.INDEX, } _cast_ops = { AllOps.BitsAsSigned, AllOps.BitsAsUnsigned, AllOps.BitsAsVec, } def is_suitable_for_const_extract(self, val: HValue): return not isinstance(val._dtype, HEnum) or val.vld_mask == 0 def as_hdl_SignalItem(self, si: Union[SignalItem, HdlIdDef], declaration=False): if not declaration and not si.hidden: if si._const: return hdl_getattr(self.SELF, si.name) else: return hdl_getattr(hdl_getattr(self.SELF_IO, si.name), "val") else: return super(ToHdlAstSimModel_value, self).as_hdl_SignalItem(si, declaration=declaration) def as_hdl_BitsVal(self, val: BitsVal): dtype = val._dtype as_hdl_int = self.as_hdl_int t = hdl_call(self.Bits3t, [ as_hdl_int(dtype.bit_length()), as_hdl_int(int(bool(dtype.signed))) ]) return hdl_call(self.Bits3val, [t, as_hdl_int(val.val), as_hdl_int(val.vld_mask)]) def as_hdl_DictVal(self, val): return { self.as_hdl_int(int(k)): self.as_hdl_Value(v) for k, v in val.items() } def as_hdl_HArrayVal(self, val): return hdl_call(self.Array3val, [ self.as_hdl_HdlType(val._dtype), self.as_hdl_DictVal(val.val), self.as_hdl_int(val.vld_mask) ]) def as_hdl_SliceVal(self, val): args = (val.val.start, val.val.stop, val.val.step) return hdl_call(self.SLICE, [self.as_hdl_int(int(a)) for a in args]) def as_hdl_HEnumVal(self, val: HEnumVal): t_name = self.name_scope.get_object_name(val._dtype) if val.vld_mask: name = self.name_scope.get_object_name(val) return hdl_getattr(hdl_getattr(self.SELF, t_name), name) else: return hdl_call( hdl_getattr(hdl_getattr(self.SELF, t_name), "from_py"), [ None, ]) def as_hdl_Operator(self, op: Operator): ops = op.operands o = op.operator if o == AllOps.EQ: op0 = self.as_hdl_Value(ops[0]) op1 = self.as_hdl_Value(ops[1]) return hdl_call(hdl_getattr(op0, "_eq"), [ op1, ]) elif o == AllOps.TERNARY: if ops[1] == one and ops[2] == zero: # ignore redundant x ? 1 : 0 return self.as_hdl_cond(ops[0], True) else: op0 = self.as_hdl_cond(ops[0], True) op1 = self.as_hdl_Value(ops[1]) op2 = self.as_hdl_Value(ops[2]) return hdl_call(hdl_getattr(op0, "_ternary"), [op1, op2]) elif o == AllOps.RISING_EDGE or o == AllOps.FALLING_EDGE: if o == AllOps.RISING_EDGE: fn = "_onRisingEdge" else: fn = "_onFallingEdge" op0 = self.as_hdl_Value(ops[0]) # pop .val op0 = op0.ops[0] return hdl_call(hdl_getattr(op0, fn), []) elif o in self._cast_ops: op0, = ops do_cast = bool(op0._dtype.signed) != bool(op.result._dtype.signed) op_hdl = self.as_hdl_Value(op0) if do_cast: if bool(op.result._dtype.signed): sign = self.TRUE else: sign = self.FALSE return hdl_call(hdl_getattr(op_hdl, "cast_sign"), [ sign, ]) else: return op_hdl elif o == AllOps.CONCAT: return hdl_call(hdl_getattr(self.as_hdl_Value(ops[0]), "_concat"), [ self.as_hdl_Value(ops[1]), ]) elif o == AllOps.EQ: return hdl_call(hdl_getattr(self.as_hdl_Value(ops[0]), "_eq"), [ self.as_hdl_Value(ops[1]), ]) else: o = self.op_transl_dict[o] return HdlOp(o, [self.as_hdl_Value(o2) for o2 in ops])
class ToHdlAstHwt_value(ToHdlAst_Value): NONE = HdlValueId("None") SLICE = HdlValueId("SLICE", obj=SLICE) def is_suitable_for_const_extract(self, val: Value): # full valid values can be represented as int and do not have any # constructor overhead, entirely invalid values can be represented by None return not val._is_full_valid() and not isinstance(val._dtype, HEnum) def as_hdl_BitsVal(self, val: BitsVal): isFullVld = val._is_full_valid() if not self._valueWidthRequired: if isFullVld: return HdlValueInt(val.val, None, 16) elif val.vld_mask == 0: return self.NONE t = self.as_hdl_HdlType_bits(val._dtype, declaration=False) c = hdl_getattr(t, "from_py") args = [ HdlValueInt(val.val, None, 16), ] if not isFullVld: args.append(HdlValueInt(val.vld_mask, None, 16)) return hdl_call(c, args) def as_hdl_SignalItem(self, si: Union[SignalItem, HdlIdDef], declaration=False): if declaration: if isinstance(si, HdlIdDef): new_si = copy(si) new_si.type = self.as_hdl_HdlType(si.type) if si.value is not None: new_si.value = self.as_hdl_Value(si.value) return new_si else: raise NotImplementedError() else: # if isinstance(si, SignalItem) and si._const: # # to allow const cache to extract constants # return self.as_hdl_Value(si._val) if si.hidden and hasattr(si, "origin"): return self.as_hdl(si.origin) else: return HdlValueId(si.name, obj=si) def as_hdl_DictVal(self, val): return ToHdlAstSimModel_value.as_hdl_DictVal(self, val) def as_hdl_HArrayVal(self, val: HArrayVal): if not val.vld_mask: return self.NONE # else: # if len(val.val) == val._dtype.size: # allValuesSame = True # values = iter(val.val.values()) # reference = next(values) # for v in values: # if allValuesSame: # allValuesSame = isSameHVal(reference, v) # else: # break # if allValuesSame: # # all values of items in array are same, use generator # # exression # raise NotImplementedError() # return "[%s for _ in range(%d)]" % (self.Value(reference)) # if value can not be simplified it is required to serialize it item # by item return self.as_hdl_DictVal(val.val) def as_hdl_SliceVal(self, val: SliceVal): if val._is_full_valid(): return HdlOp(HdlOpType.DOWNTO, [ HdlValueInt(int(val.val.start), None, None), HdlValueInt(int(val.val.stop), None, None) ]) else: raise NotImplementedError() return "SliceVal(slice(%s, %s, %s), SLICE, %d)" % ( self.as_hdl_Value(val.val.start), self.as_hdl_Value(val.val.stop), self.as_hdl_Value( val.val.step), val.vld_mask) def as_hdl_HEnumVal(self, val: HEnumVal): try: t_name = self.name_scope.get_object_name(val._dtype) except ObjectForNameNotFound: if self.debug: t_name = val._dtype.name else: raise if val.vld_mask: try: name = self.name_scope.get_object_name(val) except ObjectForNameNotFound: if self.debug: name = val.val else: raise return hdl_getattr(HdlValueId(t_name, obj=val._dtype), name) else: return hdl_call( hdl_getattr(HdlValueId(t_name, obj=val._dtype), "from_py"), [ None, ])
class ToHdlAstSystemC_expr(ToHdlAst_Value): static_cast = HdlValueId("static_cast", obj=LanguageKeyword()) op_transl_dict = ToHdlAstVerilog_ops.op_transl_dict def as_hdl_Value(self, v): if isinstance(v, tuple): return tuple((self.as_hdl(o2) for o2 in v)) return super(ToHdlAstSystemC_expr, self).as_hdl_Value(v) def as_hdl_operand(self, operand: Union[RtlSignal, HValue], i: int, operator: Operator): return self.as_hdl(operand) def as_hdl_Operator(self, op: Operator): ops = op.operands o = op.operator if o == AllOps.INDEX: assert len(ops) == 2 o0, o1 = ops if o1._dtype == SLICE: # index to .range(x, y) o0_hdl = self.as_hdl_operand(o0, 0, op) o0_hdl = hdl_getattr(o0_hdl, "range") return hdl_call(o0_hdl, [self.as_hdl_Value(o1.val.start), self.as_hdl_Value(o1.val.stop)]) else: return ToHdlAstVerilog_ops.as_hdl_Operator(self, op) elif o in ToHdlAstHwt_ops._cast_ops: assert len(ops) == 1, ops t = self.as_hdl_HdlType(op.result._dtype) return hdl_call( HdlOp(HdlOpType.PARAMETRIZATION, [self.static_cast, t]), [self.as_hdl_Value(ops[0]), ]) elif o == AllOps.CONCAT: isNew, o = self.tmpVars.create_var_cached("tmpConcat_", op.result._dtype, postponed_init=True, extra_args=(AllOps.CONCAT, op.result)) if isNew: o.drivers.append(Assignment(op, o, virtual_only=True)) self.tmpVars.finish_var_init(o) return self.as_hdl(o) else: return ToHdlAstVerilog_ops.as_hdl_Operator(self, op) def as_hdl_SignalItem(self, si: SignalItem, declaration=False): if declaration: sigType = systemCTypeOfSig(si) with SignalTypeSwap(self, sigType): return ToHdlAst_Value.as_hdl_SignalItem(self, si, declaration=True) else: if si.hidden and si.origin is not None: return self.as_hdl(si.origin) else: sigType = systemCTypeOfSig(si) _si = HdlValueId(si.name, obj=si) if self._in_sensitivity_list or self._is_target or sigType is SIGNAL_TYPE.REG: return _si else: return hdl_call(hdl_getattr(_si, "read"), []) def as_hdl_BitsVal(self, val): t = val._dtype w = t.bit_length() _v = bit_string(val.val, w, val.vld_mask) t = self.as_hdl_HdlType_bits(Bits(w, signed=t.signed)) return hdl_call(t, [_v, ]) def as_hdl_HEnumVal(self, val: HEnumVal): i = val._dtype._allValues.index(val.val) assert i >= 0 return self.as_hdl_int(i) def as_hdl_HArrayVal(self, val): return [self.as_hdl_Value(v) for v in val]
class ToHdlAstSimModel(ToHdlAstSimModel_value, ToHdlAstSimModel_types, ToHdlAst): """ Serializer which converts Unit instances to simulator code """ _keywords_dict = {kw: LanguageKeyword() for kw in SIMMODEL_KEYWORDS} SIM_EVAL_COND = HdlValueId("sim_eval_cond", obj=sim_eval_cond) C = HdlValueId("c", obj=LanguageKeyword()) CVLD = HdlValueId("cVld", obj=LanguageKeyword()) def __init__(self, name_scope: Optional[NameScope] = None): super(ToHdlAstSimModel, self).__init__(name_scope) self.currentUnit = None self.stm_outputs = {} def as_hdl_HdlModuleDec(self, o: HdlModuleDec): # convert types, exprs # delete params because they should not be used in expressions and thus # are useless new_o = copy(o) new_o.params = [] new_o.ports = [self.as_hdl_HdlPortItem(p) for p in o.ports] return new_o def as_hdl_PortConnection(self, o: HdlPortItem): assert isinstance(o, HdlPortItem), o intern, outer = o.getInternSig(), o.getOuterSig() assert not intern.hidden, intern assert not outer.hidden, outer intern_hdl = HdlValueId(intern.name, obj=intern) outer_hdl = HdlValueId(outer.name, obj=outer) pm = hdl_map_asoc(intern_hdl, outer_hdl) return pm def as_hdl_Assignment(self, a: Assignment): dst, dst_indexes, src = self._as_hdl_Assignment_auto_conversions(a) ev = HdlValueInt(int(a._event_dependent_from_branch == 0), None, None) if dst_indexes is not None: src = (src, dst_indexes, ev) else: src = (src, ev) hdl_dst = hdl_getattr(hdl_getattr(self.SELF_IO, dst.name), "val_next") hdl_a = HdlStmAssign(src, hdl_dst) hdl_a.is_blocking = dst.virtual_only return hdl_a def as_hdl_IfContainer_out_invalidate_section(self, outputs: List[RtlSignalBase], parent: IfContainer): outputInvalidateStms = [] for o in outputs: # [TODO] look up indexes indexes = None v = o._dtype.from_py(None) oa = Assignment(v, o, indexes, virtual_only=True, parentStm=parent, event_dependent_from_branch=parent. _event_dependent_from_branch) outputInvalidateStms.append(self.as_hdl_Assignment(oa)) if len(outputInvalidateStms) == 1: return outputInvalidateStms[0] else: b = HdlStmBlock() b.body = outputInvalidateStms return b def as_hdl_IfContainer_cond_eval(self, cond): """ constructs condition evaluation statement c, cVld = sim_eval_cond(cond) """ c, cVld = self.C, self.CVLD cond = self.as_hdl_cond(cond, True) cond_eval = hdl_call(self.SIM_EVAL_COND, [cond]) cond_eval = HdlStmAssign(cond_eval, (c, cVld)) cond_eval.is_blocking = True return c, cVld, cond_eval def as_hdl_IfContainer(self, ifc: IfContainer) -> HdlStmIf: """ .. code-block:: python if cond: ... else: ... will become .. code-block:: python c, cVld = sim_eval_cond(cond) if not cVld: # ivalidate outputs elif c: ... # original if true branch else: ... # original if else brach """ invalidate_block = self.as_hdl_IfContainer_out_invalidate_section( ifc._outputs, ifc) c, cVld, cond_eval = self.as_hdl_IfContainer_cond_eval(ifc.cond) _if = HdlStmIf() res = HdlStmBlock() res.body = [cond_eval, _if] _if.cond = HdlOp(HdlOpType.NEG_LOG, [ cVld, ]) _if.if_true = invalidate_block if_true = self.as_hdl_statements(ifc.ifTrue) _if.elifs.append((c, if_true)) elifs = iter(ifc.elIfs) for eif_c, eif_stms in elifs: c, cVld, cond_eval = self.as_hdl_IfContainer_cond_eval(eif_c) newIf = HdlStmIf() newIf.cond = HdlOp(HdlOpType.NEG_LOG, [ cVld, ]) newIf.if_true = invalidate_block if_true = self.as_hdl_statements(eif_stms) newIf.elifs.append((c, if_true)) _if.if_false = HdlStmBlock() _if.if_false.body = [cond_eval, newIf] _if = newIf _if.if_false = self.as_hdl_statements(ifc.ifFalse) return res 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 sensitivityListItem(self, item, anyEventDependent): if isinstance(item, Operator): op = item.operator if op == AllOps.RISING_EDGE: sens = HdlOpType.RISING elif op == AllOps.FALLING_EDGE: sens = HdlOpType.FALLING else: raise TypeError("This is not an event sensitivity", op) return HdlOp(sens, [HdlValueId(item.operands[0].name)]) else: return HdlValueId(item.name) def has_to_be_process(self, proc): return True def can_pop_process_wrap(self, statements, hasToBeVhdlProcess): return False def as_hdl_HdlStatementBlock(self, proc: HdlStatementBlock) -> HdlStmProcess: p = ToHdlAst.as_hdl_HdlStatementBlock(self, proc) self.stm_outputs[p] = sorted( [HdlValueId(i.name, obj=i) for i in proc._outputs]) return p def as_hdl_extraVarsInit(self, extraVars): return [] def _as_hdl_HdlModuleDef_body(self, *args) -> HdlModuleDef: orig_const_cache = self.constCache try: self.constCache = ConstantCache(self.createTmpVarFn) return ToHdlAst._as_hdl_HdlModuleDef_body(self, *args) finally: self.constCache = orig_const_cache
def add_kw(name, val): kw = hdl_map_asoc(HdlValueId(name), HdlValueInt(val, None, None)) args.append(kw)
def as_hdl_HdlType_float(self, typ: HFloat, declaration=False): return hdl_call(HdlValueId("HFloat"), typ.exponent_w, typ.mantisa_w)
def as_hdl_SignalItem(self, si: Union[SignalItem, HdlIdDef], declaration=False): if declaration: if isinstance(si, HdlIdDef): var = copy(si) si = si.origin else: var = HdlIdDef() var.name = si.name var.origin = si var.value = si._val var.type = si._dtype var.is_const = si._const v = var.value if isinstance(si, RtlSignalBase): if si.virtual_only: var.is_latched = True elif si.drivers or var.direction != HdlDirection.UNKNOWN: # has drivers or is port/param pass elif si.endpoints: if not v.vld_mask: raise SerializerException( "Signal %s is constant and has undefined value" % si.name) var.is_const = True else: raise SerializerException( "Signal %s should be declared but it is not used" % si.name) if v is None: pass elif isinstance(v, RtlSignalBase): if v._const: var.value = self.as_hdl(v) else: # default value has to be set by reset, # because it is not resolvable in compile time var.value = None pass elif isinstance(v, Value): if v.vld_mask or var.is_const: orig_const_cache = self.constCache try: self.constCache = None var.value = self.as_hdl_Value(v) finally: self.constCache = orig_const_cache else: # remove value if it is entirely undefined var.value = None else: raise NotImplementedError(v) var.type = self.as_hdl_HdlType(var.type) return var else: if si.hidden and hasattr(si, "origin"): # hidden signal, render it's driver instead return self.as_hdl(si.origin) return HdlValueId(si.name, obj=si)
class ToHdlAstVerilog_ops(): SIGNED = HdlValueId("$signed", obj=LanguageKeyword()) UNSIGNED = HdlValueId("$unsigned", obj=LanguageKeyword()) op_transl_dict = { **HWT_TO_HDLCONVEROTR_OPS, AllOps.INDEX: HdlOpType.INDEX, } def _operandIsAnotherOperand(self, operand): if isinstance(operand, RtlSignal) and operand.hidden\ and isinstance(operand.origin, Operator): return True def as_hdl_operand(self, operand: Union[RtlSignal, Value], i: int, operator: Operator): # [TODO] if operand is concatenation and parent operator # is not concatenation operand should be extracted # as tmp variable # * maybe flatten the concatenations if operator.operator != AllOps.CONCAT\ and self._operandIsAnotherOperand(operand)\ and operand.origin.operator == AllOps.CONCAT: tmpVar = self.createTmpVarFn("tmp_concat_", operand._dtype) tmpVar.def_val = operand # Assignment(tmpVar, operand, virtual_only=True) operand = tmpVar oper = operator.operator width = None if operand._dtype == INT and\ oper not in [AllOps.BitsAsUnsigned, AllOps.BitsAsVec, AllOps.BitsAsSigned, AllOps.INDEX] and\ operator.result is not None and\ not operator.result._dtype == INT: # have to lock the width for o in operator.operands: try: bl = o._dtype.bit_length except AttributeError: bl = None if bl is not None: width = bl() break assert width is not None, (operator, operand) hdl_op = self.as_hdl_Value(operand) if width is not None: return HdlOp(HdlOpType.APOSTROPHE, [self.as_hdl_int(width), hdl_op]) else: return hdl_op def as_hdl_Operator(self, op: Operator): ops = op.operands o = op.operator if o == AllOps.TERNARY: zero, one = BIT.from_py(0), BIT.from_py(1) if ops[1] == one and ops[2] == zero: # ignore redundant x ? 1 : 0 return self.as_hdl_cond([ops[0]], True) else: op0 = self.as_hdl_cond([ops[0]], True) op1 = self.as_hdl_operand(ops[1], 1, op) op2 = self.as_hdl_operand(ops[2], 2, op) return HdlOp(HdlOpType.TERNARY, [op0, op1, op2]) elif o == AllOps.RISING_EDGE or o == AllOps.FALLING_EDGE: raise UnsupportedEventOpErr() elif o in [ AllOps.BitsAsUnsigned, AllOps.BitsAsVec, AllOps.BitsAsSigned ]: op0, = ops do_cast = bool(op0._dtype.signed) != bool(op.result._dtype.signed) op_hdl = self.as_hdl_operand(op0, 0, op) if do_cast: if bool(op0._dtype.signed): cast = self.SIGNED else: cast = self.UNSIGNED return hdl_call(cast, [ op_hdl, ]) else: return op_hdl else: _o = self.op_transl_dict[o] return HdlOp( _o, [self.as_hdl_operand(o2, i, op) for i, o2 in enumerate(ops)])
def as_hdl_HdlType_float(self, typ: HFloat, declaration=False): if typ == FLOAT64: return HdlValueId("real") else: raise NotImplementedError(typ)