def slice_to_SLICE(sliceVals, width): """convert python slice to value of SLICE hdl type""" if sliceVals.step is not None: raise NotImplementedError() start = sliceVals.start stop = sliceVals.stop if sliceVals.start is None: start = INT.fromPy(width) else: start = toHVal(sliceVals.start) if sliceVals.stop is None: stop = INT.fromPy(0) else: stop = toHVal(sliceVals.stop) startIsVal = isinstance(start, Value) stopIsVal = isinstance(stop, Value) indexesAreValues = startIsVal and stopIsVal if indexesAreValues: updateTime = max(start.updateTime, stop.updateTime) else: updateTime = -1 return Slice.getValueCls()((start, stop), SLICE, 1, updateTime)
def test_int_neg(self): self.assertEqual(int(INT.fromPy(-10)), -10) self.assertEqual(int(-INT.fromPy(10)), -10) self.assertEqual(int(-INT.fromPy(10)), -10) v = -INT.fromPy(None) self.assertEqual(v.val, 0) self.assertEqual(v.vldMask, 0)
def test_int_to_bool(self): self.assertFalse(bool(INT.fromPy(0)._auto_cast(BOOL))) self.assertTrue(bool(INT.fromPy(1)._auto_cast(BOOL))) self.assertTrue(bool(INT.fromPy(-11)._auto_cast(BOOL))) self.assertTrue(bool(INT.fromPy(500)._auto_cast(BOOL))) with self.assertRaises(ValueError): bool(INT.fromPy(None)._auto_cast(BOOL))
def test_Bits_int_autocast(self): uint2_t = Bits(2) v0 = INT.from_py(3) v1 = v0._auto_cast(uint2_t) self.assertEqual(v1._dtype, uint2_t) v2 = INT.from_py(10) with self.assertRaises(ValueError): v2._auto_cast(uint2_t)
def serialzeValueToTCL(self, val, do_eval=False) -> Tuple[str, str, bool]: """ :see: doc of method on parent class """ if isinstance(val, int): val = INT.from_py(val) if do_eval: val = val.staticEval() buff = StringIO() to_hdl = ToHdlAstVivadoTclExpr() ser = Vhdl2008Serializer.TO_HDL(buff) hdl = to_hdl.as_hdl(val) ser.visit_iHdlObj(hdl) tclVal = buff.getvalue() if isinstance(val, RtlSignalBase): buff = StringIO() hdl = to_hdl.as_hdl(val.staticEval()) ser = Vhdl2008Serializer.TO_HDL(buff) ser.visit_iHdlObj(hdl) tclValVal = buff.getvalue() return tclVal, tclValVal, False else: return tclVal, tclVal, True
def convertBits__val(self: Bits, val: "BitVal", toType: HdlType): if toType == BOOL: return val != self.getValueCls().from_py(self, 0) elif isinstance(toType, Bits): if self.signed != toType.signed: if self.strict_sign and bool(self.signed) != bool(toType.signed): raise TypeConversionErr(self, toType) val = val._convSign__val(toType.signed) w_from, w_to = self.bit_length(), toType.bit_length() if w_from != w_to: if self.strict_width: raise TypeConversionErr(self, toType) if w_from > w_to: # cut off some bits from value new_m = val.vld_mask & toType.all_mask() else: # w_from < w_to, extend the value to some bit length extra_mask_bits = mask(w_to - w_from) new_m = set_bit_range(val.vld_mask, w_from, w_to - w_from, extra_mask_bits) val = toType.from_py(val.val, new_m) if val._dtype != toType: # sign and width checked, only name, strict_* flags can be different val = toType.from_py(val.val, val.vld_mask) return val elif toType == INT: return INT.getValueCls()(INT, val.val, int(val._is_full_valid())) return default_auto_cast_fn(self, val, toType)
def __setitem__(self, index, value): """ this []= operator can not be called in desing description, it can be only used to update HValues """ if not isinstance(self, HValue): raise TypeError( "To assign a member of hdl arrray/vector/list/... use a[index](val) instead of a[index] = val" ) # convert index to hSlice or hInt if isinstance(index, HValue): index = index elif isinstance(index, slice): length = self._dtype.bit_length() index = slice_to_SLICE(index, length) if not index._is_full_valid(): raise ValueError("invalid index", index) else: index = INT.from_py(index) # convert value to bits of length specified by index if index._dtype == SLICE: Bits = self._dtype.__class__ itemT = Bits(index._size()) else: itemT = BIT if isinstance(value, HValue): value = value._auto_cast(itemT) else: value = itemT.from_py(value) return Bits3val.__setitem__(self, index, value)
def __lt__(self, other): if self.val.step != other.val.step: raise ValueError() if isinstance(other, INT.getValueCls()): return self.val.start < other else: return (self.val.start, self.val.stop) < (other.val.start, other.val.stop)
def getVectorFromType(self, dtype) -> Union[bool, None, Tuple[int, int]]: """ :see: doc of method on parent class """ if dtype == BIT: return False elif isinstance(dtype, Bits): return [dtype.bit_length() - 1, INT.from_py(0)]
def slice_member_to_hval(v): if isinstance(v, RtlSignalBase): # is signal assert isinstance(v._dtype, Bits) return v elif isinstance(v, HValue): if isinstance(v, Bits): return v else: return v._auto_cast(INT) else: return INT.from_py(v)
def convertBits__val(self, val, toType): if isinstance(toType, HBool): return val._eq(self.getValueCls().fromPy(1, self)) elif isinstance(toType, Bits): return val._convSign__val(toType.signed) elif toType == INT: return INT.getValueCls()(val.val, INT, int(val._isFullVld()), val.updateTime) return default_auto_cast_fn(self, val, toType)
def _config(self): self.PARAM_0 = Param(0) self.PARAM_10 = Param(10) try: self.PARAM_1_sll_512 = Param(INT.from_py(1 << 512)) raise AssertionError( "Parameter with int value which is" "too big to fit in integer type of target hdl language") except ValueError: # portable type for large int, generally int in verilog/vhdl is 32b wide self.PARAM_1_sll_512 = Param(Bits(512 + 1).from_py(1 << 512)) self.PARAM_1_sll_512_py_int = Param(1 << 512)
def convertSimBits__val(self, sigOrVal, toType): if toType == INT or toType == SIM_INT: if self.signed: raise NotImplementedError() else: fullMask = self._allMask return INT.getValueCls()(sigOrVal.val, INT, sigOrVal.vldMask == fullMask, sigOrVal.updateTime) # other conversions should be akreadt done return default_auto_cast_fn(self, sigOrVal, toType)
def __setitem__(self, index, value): """ Only syntax sugar for user, not used inside HWT * Not used in HW design (__getitem__ and overloaded call operator is used instead for item assigning) * In simulator _setitem__val is used directly """ if isinstance(index, int): index = INT.from_py(index) else: assert isinstance(self, HValue) assert isinstance(index._dtype, Bits), index._dtype if not isinstance(value, HValue): value = self._dtype.element_t.from_py(value) else: assert value._dtype == self._dtype.element_t, ( value._dtype, self._dtype.element_t) return self._setitem__val(index, value)
def convertBits__val(self: Bits, val: "BitVal", toType: HdlType): if toType == BOOL: return val != self.getValueCls().from_py(self, 0) elif isinstance(toType, Bits): if self.signed != toType.signed: if self.strict_sign and bool(self.signed) != bool(toType.signed): raise TypeConversionErr(self, toType) val = val._convSign__val(toType.signed) if self.bit_length() != toType.bit_length(): if self.strict_width: raise TypeConversionErr(self, toType) val = toType.from_py(val.val, val.vld_mask & toType.all_mask()) if val._dtype != toType: # sign and width checked, only name, strict_* flags can be different val = toType.from_py(val.val, val.vld_mask) return val elif toType == INT: return INT.getValueCls()(INT, val.val, int(val._is_full_valid())) return default_auto_cast_fn(self, val, toType)
def __setitem__(self, index, value): """ Only syntax sugar for user, not used inside HWT * In HW design is not used (__getitem__ returns "reference" and it is used) * In simulator is used _setitem__val directly """ if isinstance(index, int): index = INT.from_py(index) else: assert isinstance(self, HValue) assert isinstance(index._dtype, Bits), index._dtype if not isinstance(value, HValue): value = self._dtype.element_t.from_py(value) else: assert value._dtype == self._dtype.element_t, ( value._dtype, self._dtype.element_t) return self._setitem__val(index, value)
def hInt(pyVal): """ create hdl integer value (for example integer value in vhdl)""" return INT.fromPy(pyVal)
def test_bits_mul(self): n = RtlNetlist() s = n.sig("s", Bits(16)) s * 10 s * s self.assertEqual(int(INT.from_py(10) * INT.from_py(11)), 10 * 11)
def hInt(v): return INT.from_py(v)
def _injectParametersIntoPortTypes( self, port_type_variants: List[Tuple[HdlPortItem, Dict[Tuple[Param, HValue], List[HdlType]]]], param_signals: List[RtlSignal]): updated_type_ids = set() param_sig_by_name = {p.name: p for p in param_signals} param_value_domain = {} for parent_port, param_val_to_t in port_type_variants: for (param, param_value), port_types in param_val_to_t.items(): param_value_domain.setdefault(param, set()).add(param_value) for parent_port, param_val_to_t in port_type_variants: if id(parent_port._dtype) in updated_type_ids: continue # check which unique parameter values affects the type of the port # if the type changes with any parameter value integrate it in to type of the port # print(parent_port, param_val_to_t) type_to_param_values = {} for (param, param_value), port_types in param_val_to_t.items(): for pt in port_types: cond = type_to_param_values.setdefault(pt, UniqList()) cond.append((param, param_value)) assert type_to_param_values, parent_port if len(type_to_param_values) == 1: continue # type does not change # Param: values params_used = {} for t, param_values in type_to_param_values.items(): for (param, param_val) in param_values: params_used.setdefault(param, set()).add(param_val) # filter out parameters which are not part of type specification process for p, p_vals in list(params_used.items()): if len(param_value_domain[p]) == len(p_vals): params_used.pop(p) # reset sets used to check parameter values for p, p_vals in params_used.items(): p_vals.clear() if not params_used: raise AssertionError( parent_port, "Type changes between the variants but it does not depend on parameter", param_val_to_t) if len(params_used) == 1 and list( params_used.keys())[0].get_hdl_type() == INT: # try to extract param * x + y p_val_to_port_w = {} for t, param_values in type_to_param_values.items(): for (param, param_val) in param_values: if param not in params_used: continue assert param_val not in p_val_to_port_w or p_val_to_port_w[ param_val] == t.bit_length(), parent_port p_val_to_port_w[param_val] = t.bit_length() # t_width = n*p + c _p_val_to_port_w = sorted(p_val_to_port_w.items()) t_width0, p0 = _p_val_to_port_w[0] t_width1, p1 = _p_val_to_port_w[1] # 0 == t_width0 - n*p0 + c # 0 == t_width1 - n*p1 + c # 0 == t_width0 - n*p0 - c + t_width1 - n*p1 - c # 0 == t_width0 + t_width1 - n*(p0 + p1) - 2c # c == (t_width0 + t_width1 - n*(p0 + p1) ) //2 # n has to be int, 0 < n <= t_width0/p0 # n is something like base size of port which is multipled by parameter # we searching n for which we can resolve c found_nc = None for n in range(1, t_width0 // p0 + 1): c = (t_width0 + t_width1 - n * (p0 + p1)) // 2 if t_width0 - n * p0 + c == 0 and t_width1 - n * p1 + c == 0: found_nc = (n, c) break if found_nc is None: raise NotImplementedError() else: p = list(params_used.keys())[0] p = param_sig_by_name[p._name] (n, c) = found_nc t = parent_port._dtype t._bit_length = INT.from_py(n) * p + c t._bit_length._const = True updated_type_ids.add(id(t)) else: condition_and_type_width = [] default_width = None for t, p_vals in sorted(type_to_param_values.items(), key=lambda x: x[0].bit_length()): cond = And(*(param_sig_by_name[p.hdl_name]._eq(p_val) for p, p_val in p_vals if p in params_used)) w = t.bit_length() if default_width is None: default_width = w condition_and_type_width.append((cond, w)) t = parent_port._dtype t._bit_length = reduce_ternary(condition_and_type_width, default_width) t._bit_length._const = True updated_type_ids.add(id(t))