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])
class ToHdlAstHwt(ToHdlAstHwt_value, ToHdlAstHwt_ops, ToHdlAstHwt_types, ToHdlAst): """ Serializer which converts Hwt objects back to Hwt code for debugging purposes/code ports :ivar ~._valueWidthRequired: flag which tells if the values are required to have the width specified """ _keywords_dict = {kw: LanguageKeyword() for kw in HWT_KEYWORDS} def __init__(self, name_scope: Optional[NameScope] = None): super(ToHdlAstHwt, self).__init__(name_scope=name_scope) self._valueWidthRequired = False self.currentUnit = None self.debug = False def has_to_be_process(self, proc): return True def can_pop_process_wrap(self, statements, hasToBeVhdlProcess): return False def _as_hdl_HdlModuleDef(self, new_m: HdlModuleDef) -> HdlModuleDef: return ToHdlAstSimModel._as_hdl_HdlModuleDef(self, new_m) 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 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 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)
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)
class ToHdlAstVhdl2008(ToHdlAstVhdl2008_Value, ToHdlAstVhdl2008_ops, ToHdlAstVhdl2008_types, ToHdlAstVhdl2008_statements, ToHdlAst): """ :ivar ~.name_scope: name scope used to generate a unique names for tmp variables (all object should be registered in namescope before serialization) """ _keywords_dict = {kw: LanguageKeyword() for kw in VHLD2008_KEYWORDS} DEFAULT_IMPORTS = [ HdlLibrary("IEEE"), HdlImport([IEEE, std_logic_1164, HdlAll]), HdlImport([IEEE, numeric_std, HdlAll]), ] @classmethod def getBaseNameScope(cls): s = VhdlNameScope.make_top(True) s.update(cls._keywords_dict) return s def as_hdl_HdlModuleDef(self, o: HdlModuleDef): """ Translate hwt types and expressions to HDL AST and add explicit components """ _o = super(ToHdlAstVhdl2008, self).as_hdl_HdlModuleDef(o) component_insts = [] for c in _o.objs: if isinstance(c, HdlCompInst): component_insts.append(c) # select comonent instances whith an unique module_name components = [ x[1][0] for x in groupedby(component_insts, lambda c: c.module_name) ] components.sort(key=lambda c: c.module_name) components = [self.as_hdl_HldComponent(c) for c in components] if components: _o.objs = components + _o.objs res = HdlContext() res.objs.extend(self.DEFAULT_IMPORTS) res.objs.append(_o) return res def as_hdl_HldComponent(self, o: HdlCompInst): c = self.as_hdl_HdlModuleDec(o.origin._ctx.ent) return c
def BitsT(width, is_signed=False, bits_cls_name="Bits3t"): """ Create an AST expression of Bits type constructor (reg/std_logic_vector equivalent for BasicHdlSimModel) :type width: iHdlExpr """ width = verilog_slice_to_width(width) if isinstance(width, int): width = HdlValueInt(width, None, None) c = HdlOp(HdlOpType.CALL, [ HdlValueId(bits_cls_name, obj=LanguageKeyword()), width, NONE if is_signed is None else HdlValueInt(int(is_signed), None, None) ]) return c
class ToHdlAstSimModel_types(): """ part of ToHdlAstSimModel responsible for type serialization """ SELF = HdlValueId("self", obj=LanguageKeyword()) BITS3T = HdlValueId("Bits3t", obj=Bits3t) SLICE = HdlValueId("slice", obj=slice) def as_hdl_HdlType_bits(self, typ: Bits, declaration=False): assert not declaration w = typ.bit_length() if isinstance(w, int): pass else: w = int(w) return hdl_call(self.BITS3T, [ HdlValueInt(w, None, None), HdlValueInt(int(bool(typ.signed)), None, None) ]) def as_hdl_HdlType_slice(self, typ: Slice, declaration=False): if declaration: raise NotImplementedError() else: return self.SLICE def as_hdl_HdlType_array(self, typ, declaration=False): if declaration: return super(ToHdlAstSimModel_types, self).as_hdl_HdlType_array(typ, declaration=declaration) else: t_name = self.name_scope.get_object_name(typ) return hdl_getattr(self.SELF, t_name) def as_hdl_HdlType_enum(self, typ, declaration=False): if declaration: return super(ToHdlAstSimModel_types, self).as_hdl_HdlType_enum(typ, declaration=True) else: t_name = self.name_scope.get_object_name(typ) return hdl_getattr(self.SELF, t_name)
def BitsT(width, is_signed=False, bits_cls_name="Bits3t"): """ Create an AST expression of Bits type constructor (reg/std_logic_vector equivalent for BasicHdlSimModel) :type width: iHdlExpr """ if isinstance(width, HdlOp): if width.fn == HdlOpType.DOWNTO: high, low = width.ops assert int(low) == 0 width = int(high) + 1 else: raise NotImplementedError(width) c = HdlOp(HdlOpType.CALL, [ HdlValueId(bits_cls_name, obj=LanguageKeyword()), HdlValueInt(width, None, None), NONE if is_signed is None else HdlValueInt(int(is_signed), None, None) ]) return c
def BitsT(width, is_signed=False, bits_cls_name="Bits"): """ Create an AST expression of Bits type constructor (reg/std_logic_vector equivalent for hwt) :type width: iHdlExpr """ width = verilog_slice_to_width(width) if isinstance(width, int): width = HdlValueInt(width, None, None) args = [ HdlValueId(bits_cls_name, obj=LanguageKeyword()), width, ] if is_signed is not None: args.append(HdlValueInt(int(is_signed), None, None)) return HdlOp(HdlOpType.CALL, args)
def check_file(self, name, to_hdl_cls): """ Load AST from json and convert it to target language and compare it with reference file """ json_suffix, ref_file_suffix = self.FILE_SUFFIX[to_hdl_cls] d = parse_hdlConvertor_json_file(os.path.join(ROOT, name + json_suffix)) buff = StringIO() ser = to_hdl_cls(buff) if to_hdl_cls is ToBasicHdlSimModel: # it is required to know outputs of each process stm_outputs = discover_stm_outputs_context(d) stm_outputs = rm_ToBasicHdlSimModel_io_prefix_and_tmp_vars_from_outputs( stm_outputs) ser.visit_HdlContext(d, stm_outputs) else: if to_hdl_cls is ToHwt: # it is required to know the direction of port connections link_module_dec_def(d) name_scope = NameScope.make_top(False) for kw in HWT_KEYWORDS: name_scope.register_name(kw, LanguageKeyword()) DiscoverDeclarations(name_scope).visit_HdlContext(d) ResolveNames(name_scope).visit_HdlContext(d) ser.visit_HdlContext(d) res_str = buff.getvalue() ref_file = os.path.join(ROOT, "ref", name + ref_file_suffix) # with open(ref_file, "w", encoding="utf-8") as f: # f.write(res_str) with open(ref_file, encoding="utf-8") as f: ref = f.read() self.assertEqual(ref, res_str)
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])
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)])
class ToHdlAstVerilog(ToHdlAstVerilog_types, ToHdlAstVerilog_Value, ToHdlAstVerilog_statements, ToHdlAstVerilog_ops, ToHdlAst): _keywords_dict = {kw: LanguageKeyword() for kw in IEEE1800_2017_KEYWORDS} def __init__(self, name_scope: Optional[NameScope] = None): ToHdlAst.__init__(self, name_scope=name_scope) self.signalType = SIGNAL_TYPE.PORT_WIRE def as_hdl_HdlModuleDef_variable(self, v, types, hdl_types, hdl_variables, processes, component_insts): new_v = copy(v) with SignalTypeSwap(self, verilogTypeOfSig(v.origin)): t = v.type # if type requires extra definition if self.does_type_requires_extra_def(t, types): _t = self.as_hdl_HdlType(t, declaration=True) hdl_types.append(_t) types.add(t) new_v.type = self.as_hdl_HdlType(t, declaration=False) # this is a array variable which requires value intialization in init # process if isinstance(t, HArray): if v.value.vld_mask: rom = v.origin p = HdlStmProcess() label = self.name_scope.checked_name( rom.name + "_rom_init", p) p.labels.append(label) p.body = HdlStmBlock() body = p.body.body for i, _v in enumerate(rom.def_val.val): a = HdlStmAssign(self.as_hdl_int(int(_v)), self.as_hdl(rom[i])) a.is_blocking = True body.append(a) w = HdlStmWait() w.val = [] # initial process body.append(w) processes.append(p) # because we would not be able to initialize const/localparam variable later new_v.is_const = False new_v.value = None elif new_v.value is not None: new_v.value = self.as_hdl_Value(new_v.value) return new_v def as_hdl_GenericItem(self, g: HdlIdDef): with SignalTypeSwap(self, SIGNAL_TYPE.PORT_WIRE): new_v = copy(g) v = g.value if v._dtype == STR or v._dtype == INT or v._dtype == BOOL: t = HdlTypeAuto else: t = self.as_hdl_HdlType(v._dtype) new_v.type = t assert new_v.value is not None, g new_v.value = self.as_hdl_Value(v) return new_v def as_hdl_HdlPortItem(self, pi: HdlPortItem): with SignalTypeSwap(self, verilogTypeOfSig(pi)): v = super(ToHdlAstVerilog, self).as_hdl_HdlPortItem(pi) v.is_latched = self.signalType == SIGNAL_TYPE.PORT_REG return v
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 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]
from hwt.serializer.generic.to_hdl_ast import ToHdlAst from hwt.serializer.vhdl.ops import ToHdlAstVhdl2008_ops from hwt.serializer.vhdl.statements import ToHdlAstVhdl2008_statements from hwt.serializer.vhdl.types import ToHdlAstVhdl2008_types from hwt.serializer.vhdl.value import ToHdlAstVhdl2008_Value class VhdlNameScope(NameScope): RE_MANY_UNDERSCORES = re.compile(r"(_{2,})") def checked_name(self, actualName, actualObj): actualName = self.RE_MANY_UNDERSCORES.sub(r"_", actualName) return NameScope.checked_name(self, actualName, actualObj) IEEE = HdlValueId("IEEE", obj=LanguageKeyword()) std_logic_1164 = HdlValueId("std_logic_1164", obj=LanguageKeyword()) numeric_std = HdlValueId("numeric_std", obj=LanguageKeyword()) class ToHdlAstVhdl2008(ToHdlAstVhdl2008_Value, ToHdlAstVhdl2008_ops, ToHdlAstVhdl2008_types, ToHdlAstVhdl2008_statements, ToHdlAst): """ :ivar ~.name_scope: name scope used to generate a unique names for tmp variables (all object should be registered in namescope before serialization) """ _keywords_dict = {kw: LanguageKeyword() for kw in VHLD2008_KEYWORDS} DEFAULT_IMPORTS = [ HdlLibrary("IEEE"),
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
class ToHdlAstSystemC(ToHdlAstSystemC_expr, ToHdlAstSystemC_type, ToHdlAstSystemC_statements, ToHdlAst): """ Serialized used to convert HWT design to SystemC code """ _keywords_dict = {kw: LanguageKeyword() for kw in SYSTEMC_KEYWORDS} sc_in_clk = HdlValueId("sc_in_clk", obj=LanguageKeyword()) sc_out_clk = HdlValueId("sc_out_clk", obj=LanguageKeyword()) sc_inout_clk = HdlValueId("sc_inout_clk", obj=LanguageKeyword()) sc_in = HdlValueId("sc_in", obj=LanguageKeyword()) sc_out = HdlValueId("sc_out", obj=LanguageKeyword()) sc_inout = HdlValueId("sc_inout", obj=LanguageKeyword()) def __init__(self, name_scope: Optional[NameScope] = None): ToHdlAst.__init__(self, name_scope=name_scope) self._is_target = False self._in_sensitivity_list = False self.signalType = None def as_hdl_HdlModuleDec(self, o: HdlModuleDec): return ToHdlAstSimModel.as_hdl_HdlModuleDec(self, o) def as_hdl_HdlPortItem(self, o: HdlPortItem): i = o.getInternSig()._interface d = o.direction if isinstance(i, Clk): assert i._dtype.bit_length() == 1, i if d == DIRECTION.IN: t = self.sc_in_clk elif d == DIRECTION.OUT: t = self.sc_out_clk elif d == DIRECTION.INOUT: t = self.sc_inout_clk else: raise ValueError(d) else: if d == DIRECTION.IN: pt = self.sc_in elif d == DIRECTION.OUT: pt = self.sc_out elif d == DIRECTION.INOUT: pt = self.sc_inout else: raise ValueError(d) t = self.as_hdl_HdlType(o._dtype) t = HdlOp(HdlOpType.PARAMETRIZATION, [pt, t]) var = HdlIdDef() var.direction = HWT_TO_HDLCONVEROTR_DIRECTION[o.direction] s = o.getInternSig() var.name = s.name var.origin = o var.type = t return var def as_hdl_HdlCompInst(self, o: HdlCompInst) -> HdlCompInst: new_o = copy(o) new_o.param_map = [] orig_is_target = self._is_target try: self._is_target = True port_map = [] for pi in o.port_map: pm = self.as_hdl_PortConnection(pi) port_map.append(pm) new_o.port_map = port_map finally: self._is_target = orig_is_target return new_o
class ToHdlAstVhdl2008_Value(ToHdlAst_Value): TRUE = HdlValueId("TRUE", obj=LanguageKeyword()) FALSE = HdlValueId("FALSE", obj=LanguageKeyword()) #TO_UNSIGNED = HdlValueId("TO_UNSIGNED", obj=LanguageKeyword()) #TO_SIGNED = HdlValueId("TO_SIGNED", obj=LanguageKeyword()) def as_hdl_cond(self, c, forceBool): assert isinstance(c, (RtlSignalBase, HValue)), c if not forceBool or c._dtype == BOOL: return self.as_hdl(c) elif c._dtype == BIT: return self.as_hdl(c._eq(1)) elif isinstance(c._dtype, Bits): return self.as_hdl(c != 0) else: raise NotImplementedError() def as_hdl_HEnumVal(self, val: HEnumVal): name = self.name_scope.get_object_name(val) return HdlValueId(name, obj=val) def as_hdl_HArrayVal(self, val): return [self.as_hdl_Value(v) for v in val] def sensitivityListItem(self, item, anyIsEventDependnt): if isinstance(item, Operator): item = item.operands[0] return self.as_hdl(item) def as_hdl_BitString(self, v, width: int, force_vector: bool, vld_mask: int, signed): is_bit = not force_vector and width == 1 #if vld_mask != mask(width) or width >= 32 or is_bit: v = bit_string(v, width, vld_mask) if is_bit: v.base = 256 return v if signed is None: return v elif signed: cast = self.SIGNED else: cast = self.UNSIGNED return HdlOp(HdlOpType.APOSTROPHE, [cast, v]) #else: # v = HdlValueInt(v, None, None) # # if signed is None: # return v # elif signed: # cast_fn = self.TO_SIGNED # else: # cast_fn = self.TO_UNSIGNED # return hdl_call(cast_fn, [v, HdlValueInt(width, None, None)]) def as_hdl_BoolVal(self, val: BitsVal): if val.val: return self.TRUE else: return self.FALSE def as_hdl_BitsVal(self, val: BitsVal): t = val._dtype v = super(ToHdlAstVhdl2008_Value, self).as_hdl_BitsVal(val) # handle '1' vs "1" difference (bit literal vs vector) if not t.force_vector and t.bit_length() == 1 and t != BOOL: if isinstance(v, HdlValueInt): v.base = 256 else: # assert is cast assert isinstance(v, HdlOp) and v.fn == HdlOpType.CALL, v _v = v.ops[1] if isinstance(_v, HdlValueInt): _v.base = 256 else: raise NotImplementedError() return v def as_hdl_SliceVal(self, val: SliceVal): upper = val.val.start if int(val.val.step) == -1: if isinstance(upper, HValue): upper = HdlValueInt(int(upper) - 1, None, None) else: upper = HdlOp(HdlOpType.SUB, [self.as_hdl_Value(upper), HdlValueInt(1, None, None)]) else: raise NotImplementedError(val.val.step) return HdlOp(HdlOpType.DOWNTO, [upper, self.as_hdl(val.val.stop)])