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_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_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 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 sensitivityListItem(self, item, anyIsEventDependent): if isinstance(item, Operator): return HdlOp(HWT_TO_HDLCONVEROTR_OPS[item.operator], [ self.as_hdl(item.operands[0]), ]) elif anyIsEventDependent: if item._dtype.negated: op = HdlOpType.FALLING else: op = HdlOpType.RISING return HdlOp(op, [ self.as_hdl(item), ]) return self.as_hdl(item)
def as_hdl_Operator(self, op: Operator): ops = op.operands o = op.operator if o == AllOps.INDEX: op0, op1 = ops if isinstance(op0, RtlSignalBase) and isResultOfTypeConversion(op0): op0 = self.createTmpVarFn("tmpTypeConv_", op0._dtype) op0.def_val = ops[0] # if the op0 is not signal or other index index operator it is extracted # as tmp variable op0 = self.as_hdl_operand(op0) _op1 = self.as_hdl_operand(ops[1]) if isinstance(op1._dtype, Bits) and op1._dtype != INT: sig = op1._dtype.signed if sig is None: _op1 = self.apply_cast("UNSIGNED", _op1) _op1 = self.apply_cast("TO_INTEGER", _op1) return HdlOp(HdlOpType.INDEX, [op0, _op1]) elif o == AllOps.TERNARY: op0 = self.as_hdl_cond(ops[0], True) op1 = self.as_hdl_operand(ops[1]) op2 = self.as_hdl_operand(ops[2]) return HdlOp(HdlOpType.TERNARY, [op0, op1, op2]) else: _o = self._cast_ops.get(o, None) if _o is not None: op0 = ops[0] op0 = self._as_Bits_vec(op0) if isinstance(op0, RtlSignalBase) and op0.hidden: op0 = self.createTmpVarFn("tmpTypeConv_", op0._dtype) op0.def_val = ops[0] return self.apply_cast(_o, self.as_hdl_operand(op0)) o = self.op_transl_dict[o] if len(ops) == 2: res_t = op.result._dtype op0, op1 = ops if isinstance(res_t, Bits) and res_t != BOOL: op0 = self._as_Bits(op0) op1 = self._as_Bits(op1) op0 = self.as_hdl_operand(op0) op1 = self.as_hdl_operand(op1) return HdlOp(o, [op0, op1]) return HdlOp(o, [self.as_hdl_operand(o2) for o2 in ops])
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_HdlType_array(self, typ: HArray, declaration=False): if declaration: raise NotImplementedError() else: _int = self.as_hdl_int size = HdlOp(HdlOpType.DOWNTO, [_int(0), _int(int(typ.size) - 1)]) return hdl_index(self.as_hdl_HdlType(typ.element_t), size)
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_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_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 hdl_index(o, i): """ :type o: iHdlExpr :type args: List[iHdlExpr] :return: HdlOp """ return HdlOp(HdlOpType.INDEX, [o, i])
def hdl_map_asoc(o1, o2): """ :type o1: iHdlExpr :type o2: iHdlExpr :return: HdlOp """ return HdlOp(HdlOpType.MAP_ASSOCIATION, [o1, o2])
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: 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_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 [ AllOps.BitsAsUnsigned, AllOps.BitsAsVec, AllOps.BitsAsSigned ]: 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(op0._dtype.signed): sign = self.TRUE else: sign = self.FALSE # cast_sign() 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])
def hdl_name_prefix(prefix_name, o): """ :type o: HdlValueId :type prefix_name: iHdlExpr :return: HdlOp """ assert isinstance(o, HdlValueId), o return HdlOp(HdlOpType.DOT, [prefix_name, o])
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 hdl_call(o, args): """ :type o: iHdlExpr :type args: List[iHdlExpr] :return: HdlOp """ return HdlOp(HdlOpType.CALL, [ o, ] + args)
def hdl_or(*args): first = True res = None for o in args: if first: res = o first = False else: res = HdlOp(HdlOpType.OR, [res, o]) assert res is not None return res
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 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 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 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)
def as_hdl_operand(self, operand: Union[RtlSignal, HValue], 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.tmpVars.create_var_cached("tmp_concat_", operand._dtype, def_val=operand) # Assignment(tmpVar, operand, virtual_only=True) operand = tmpVar oper = operator.operator width = None if not isinstance(operand, RtlSignal) and 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: if isinstance(hdl_op, HdlValueInt): assert isinstance(width, int), width hdl_op.bits = width else: return HdlOp(HdlOpType.APOSTROPHE, [self.as_hdl_int(width), hdl_op]) return hdl_op
def hdl_add_int(a, b): """ :type a: iHdlExpr :type b: int :return: iHdlExpr """ if b == 0: return a elif isinstance(a, HdlValueInt): return HdlValueInt(int(a.val) + b, a.val, a.base) elif isinstance(a, HdlOp) and a.fn == HdlOpType.ADD: o0, o1 = a.ops if isinstance(o1, HdlValueInt): return hdl_add_int(o0, int(o1) + b) elif isinstance(a, HdlOp) and a.fn == HdlOpType.SUB: o0, o1 = a.ops if isinstance(o1, HdlValueInt): return hdl_sub_int(o0, int(o1) - b) return HdlOp(HdlOpType.ADD, [a, HdlValueInt(b, None, None)])
def hdl_downto(msb, lsb): return HdlOp(HdlOpType.DOWNTO, [msb, lsb])