def init(self, left, right): lpoint = left.point if isinstance(left, _FixedBase) else 0 rpoint = right.point if isinstance(right, _FixedBase) else 0 lsigned = vtypes.get_signed(left) rsigned = vtypes.get_signed(right) point = _max_mux(lpoint, rpoint) signed = lsigned and rsigned if not self.overwrite_signed else False ldata, rdata = adjust(left, right, lpoint, rpoint, signed) self.point = point return ldata, rdata
def _add_delayed_subst(self, subst, index, delay): if not isinstance(subst, vtypes.Subst): return subst left = subst.left right = subst.right if isinstance(right, (bool, int, float, str, vtypes._Constant, vtypes._ParameterVariable)): return subst width = left.bit_length() signed = vtypes.get_signed(left) prev = right name_prefix = ('_'.join([ '', left.name, str(index), str(self.tmp_count) ]) if isinstance(left, vtypes._Variable) else '_'.join([ '', self.name, 'sbst', str(index), str(self.tmp_count) ])) self.tmp_count += 1 for i in range(delay): tmp_name = '_'.join([name_prefix, str(i + 1)]) tmp = self.m.Reg(tmp_name, width, initval=0, signed=signed) self._add_statement([tmp(prev)], delay=i, no_delay_cond=True) prev = tmp return left(prev)
def __init__(self, left, right): lpoint = left.point if isinstance(left, _FixedBase) else 0 rpoint = right.point if isinstance(right, _FixedBase) else 0 lsigned = vtypes.get_signed(left) rsigned = vtypes.get_signed(right) point = _min_mux(_max_mux(lpoint, rpoint), lpoint + rpoint) signed = lsigned and rsigned if not self.overwrite_signed else False ldata = to_signed(left) if signed else left rdata = to_signed(right) if signed else right shift_size = lpoint + rpoint - point data = vtypes.Times(ldata, rdata) if signed: data = vtypes.Sra(data, shift_size) else: data = vtypes.Srl(data, shift_size) _FixedSkipUnaryOperator.__init__(self, data, point, signed)
def fixed_to_real(value, point): if point < 0: return vtypes.SystemTask('itor', fixed_to_int(value, point)) if point == 0: return vtypes.SystemTask('itor', value) if isinstance(value, float): raise TypeError("value is already float.") if isinstance(value, (int, bool)) and isinstance(point, int): mag = 2 ** point return float(value) / mag signed = vtypes.get_signed(value) width = value.bit_length() msb = (value[width - 1] if isinstance(value, vtypes._Variable) else (value >> (width - 1)) & 0x1) v0 = (vtypes.SystemTask('itor', fixed_to_int(value, point)) + vtypes.SystemTask('itor', fixed_to_int_low(value, point)) / vtypes.SystemTask('itor', vtypes.Int(2) ** point)) nv = vtypes.Unot(value) + 1 v1 = ((vtypes.SystemTask('itor', fixed_to_int(nv, point)) + vtypes.SystemTask('itor', fixed_to_int_low(nv, point)) / vtypes.SystemTask('itor', vtypes.Int(2) ** point))) * vtypes.SystemTask('itor', -1) return vtypes.Mux(signed and msb == 0, v0, v1)
def Prev(self, var, delay, initval=0, cond=None, prefix=None): """ returns a value with the specified delay """ if not isinstance(delay, int): raise TypeError('delay must be int, not %s' % str(type(delay))) if delay <= 0: return var if isinstance(var, (int, float, bool)): return var if isinstance(var, vtypes._Constant): return var if prefix is None: prefix = '_' width = vtypes.get_width(var) signed = vtypes.get_signed(var) if not isinstance(var, vtypes._Variable): width = self.m.TmpLocalparam(width) w = self.m.TmpWire(width, signed=signed) w.assign(var) var = w if hasattr(var, 'name'): name_prefix = prefix + var.name else: name_prefix = _tmp_name(prefix) key = '_'.join([name_prefix, str(delay)]) if key in self.prev_dict: return self.prev_dict[key] p = var for i in range(delay): cond = make_condition(cond) if cond is not None: tmp = self.m.TmpReg(width=width, initval=initval, signed=signed) self._add_statement([tmp(p)], cond=cond) p = tmp else: tmp_name = '_'.join([name_prefix, str(i + 1)]) if tmp_name in self.prev_dict: p = self.prev_dict[tmp_name] continue tmp = self.m.Reg(tmp_name, width, initval=initval, signed=signed) self.prev_dict[tmp_name] = tmp self._add_statement([tmp(p)]) p = tmp return p
def _saturate_overflow(raw_val, width=8, max=None, signed=False): if max is None: max = _max(width, signed) if (isinstance(max, int) and not isinstance(raw_val, int) and vtypes.get_signed(raw_val)): max = vtypes.Int(max, signed=True) return vtypes.Mux(raw_val > max, max, raw_val)
def __init__(self, left, right): lpoint = left.point if isinstance(left, _FixedBase) else 0 rpoint = right.point if isinstance(right, _FixedBase) else 0 lsigned = vtypes.get_signed(left) rsigned = vtypes.get_signed(right) point = _max_mux(lpoint, rpoint) signed = lsigned and rsigned if not self.overwrite_signed else False lwidth = vtypes.get_width(left) rwidth = vtypes.get_width(right) if lpoint <= rpoint: ldata, rdata = adjust(left, right, lpoint, rpoint, signed) shift_size = point else: ldata = left rdata = right shift_size = point - (lpoint - rpoint) try: lmsb = ldata[lwidth - 1] except: lmsb = (ldata >> (lwidth - 1) & vtypes.Int(1, 1, base=2)) try: rmsb = rdata[rwidth - 1] except: rmsb = (rdata >> (rwidth - 1) & vtypes.Int(1, 1, base=2)) abs_ldata = (ldata if not lsigned else vtypes.Mux( vtypes.Ulnot(lmsb), ldata, vtypes.Unot(ldata) + 1)) abs_rdata = (rdata if not rsigned else vtypes.Mux( vtypes.Ulnot(rmsb), rdata, vtypes.Unot(rdata) + 1)) abs_data = vtypes.Divide(abs_ldata, abs_rdata) data = (abs_data if not signed else vtypes.Mux( vtypes.Eq(lmsb, rmsb), abs_data, vtypes.Unot(abs_data) + 1)) if shift_size > 0: data = vtypes.Sll(data, shift_size) _FixedSkipUnaryOperator.__init__(self, data, point, signed)
def to_signed(value): if isinstance(value, int): return vtypes.Int(value, signed=True) if isinstance(value, vtypes.Int): return vtypes.Int(value.value, signed=True) if vtypes.get_signed(value): return value data = vtypes.SystemTask('signed', value) point = value.point if hasattr(value, 'point') else 0 return _FixedSkipUnaryOperator(data, point, True)
def _add(raw_val, left, right, width=8, max=None, min=None): signed = vtypes.get_signed(raw_val) if min is None: min = _min(width, signed) if signed: cond = left < - right + min return _saturate_both(raw_val, cond, width=width, max=max, min=min, signed=signed) return _saturate_overflow(raw_val, width=width, max=max, signed=signed)
def _saturate_both(raw_val, cond, width=8, max=None, min=None, signed=False): if max is None: max = _max(width, signed) if min is None: min = _min(width, signed) if (isinstance(max, int) and not isinstance(raw_val, int) and vtypes.get_signed(raw_val)): max = vtypes.Int(max, signed=True) return vtypes.Mux(cond, min, vtypes.Mux(raw_val > max, max, raw_val))
def _fixed_to_int_reg_point(value, point): point = -point if isinstance(value, (int, bool, float)) and isinstance(point, int): mag = 2 ** point return value * mag if isinstance(value, (int, bool, float)): mag = vtypes.Int(2) ** point return vtypes.Int(value) * mag signed = vtypes.get_signed(value) return shift_left(value, point, signed)
def write_adjust(value, point): lpoint = point rvalue = value rsigned = vtypes.get_signed(value) if not isinstance(value, _FixedBase): rpoint = 0 else: rpoint = value.point ldiff = vtypes.Mux(lpoint <= rpoint, 0, lpoint - rpoint) rdiff = vtypes.Mux(lpoint >= rpoint, 0, rpoint - lpoint) v = vtypes.Mux(lpoint > rpoint, shift_left(rvalue, ldiff, rsigned), vtypes.Mux(lpoint < rpoint, shift_right(rvalue, rdiff, rsigned), rvalue)) return v
def write(dst, value, blk=False, ldelay=None, rdelay=None, method='write'): width = dst.bit_length() signed = vtypes.get_signed(dst) if signed: max = _pow2(width - 1) - 1 min = _pow2(width - 1) * (-1) else: max = _pow2(width) - 1 min = 0 sat_val = to_saturate(value, width=width, max=max, min=min, signed=signed) return getattr(dst, method)(sat_val, blk=blk, ldelay=ldelay, rdelay=rdelay)
def write(dst, value, blk=False, ldelay=None, rdelay=None, method='write'): width = vtypes.get_width(dst) signed = vtypes.get_signed(dst) if signed: max = _pow2(width - 1) - 1 min = _pow2(width - 1) * (-1) else: max = _pow2(width) - 1 min = 0 sat_val = to_saturate(value, width=width, max=max, min=min, signed=signed) return getattr(dst, method)(sat_val, blk=blk, ldelay=ldelay, rdelay=rdelay)
def _to_fixed_neg_point(value, point): point = -point if isinstance(value, (int, bool, float)) and isinstance(point, int): mag = 2 ** point return int(value / mag) if isinstance(value, (int, bool)): return vtypes.Int(value) >> point if isinstance(value, float): mag = vtypes.Int(2) ** point return vtypes.Float(value) / mag signed = vtypes.get_signed(value) return shift_right(value, point, signed)
def fixed_to_int(value, point): if point < 0: raise ValueError('point must be more than 0') if point == 0: return value if isinstance(value, (int, bool, float)) and isinstance(point, int): mag = 2 ** point return int(value / mag) if isinstance(value, (int, bool, float)): mag = vtypes.Int(2) ** point return vtypes.Int(value) / mag signed = vtypes.get_signed(value) return shift_right(value, point, signed)
def Prev(self, var, delay, initval=0, cond=None, prefix=None): """ returns a value with the specified delay """ if not isinstance(delay, int): raise TypeError('delay must be int, not %s' % str(type(delay))) if delay <= 0: return var if prefix is None: prefix = '_' width = var.bit_length() signed = vtypes.get_signed(var) if not isinstance(var, vtypes._Variable): width = self.m.TmpLocalparam(width) w = self.m.TmpWire(width, signed=signed) w.assign(var) var = w name_prefix = prefix + var.name key = '_'.join([name_prefix, str(delay)]) if key in self.prev_dict: return self.prev_dict[key] p = var for i in range(delay): cond = make_condition(cond) if cond is not None: tmp = self.m.TmpReg( var, width=width, initval=initval, signed=signed) self._add_statement([tmp(p)], cond=cond) p = tmp else: tmp_name = '_'.join([name_prefix, str(i + 1)]) if tmp_name in self.prev_dict: p = self.prev_dict[tmp_name] continue tmp = self.m.Reg( tmp_name, width, initval=initval, signed=signed) self.prev_dict[tmp_name] = tmp self._add_statement([tmp(p)]) p = tmp return p
def _adjust(self, value): lpoint = self.point if not isinstance(value, Fixed): rvalue = value rsigned = vtypes.get_signed(value) rpoint = 0 else: rvalue = value.value rsigned = value.signed rpoint = value.point ldiff = vtypes.Mux(lpoint <= rpoint, 0, lpoint - rpoint) rdiff = vtypes.Mux(lpoint >= rpoint, 0, rpoint - lpoint) v = vtypes.Mux(lpoint > rpoint, shift_left(rvalue, ldiff, rsigned), vtypes.Mux(lpoint < rpoint, shift_right(rvalue, rdiff, rsigned), rvalue)) return v
def fixed_to_int(value, point): if point < 0: return _fixed_to_int_neg_point(value, point) if point == 0: return value if isinstance(value, (int, bool, float)) and isinstance(point, int): mag = 2 ** point return value // mag if isinstance(value, (int, bool, float)): mag = vtypes.Int(2) ** point return vtypes.Int(value) // mag signed = vtypes.get_signed(value) return shift_right(value, point, signed)
def _binary_op_div(self, op, r): lvalue = self.value lpoint = self.point lsigned = self.signed if not isinstance(r, Fixed): rvalue = r rsigned = vtypes.get_signed(r) rpoint = 0 else: rvalue = r.value rsigned = r.signed rpoint = r.point point = _max_mux(lpoint, rpoint) signed = lsigned and rsigned lwidth = lvalue.bit_length() rwidth = rvalue.bit_length() ldata, rdata = adjust(lvalue, rvalue, lpoint, rpoint, signed) try: lmsb = ldata[lwidth - 1] except: lmsb = (ldata >> (lwidth - 1) & 0x1) try: rmsb = rdata[lwidth - 1] except: rmsb = (rdata >> (rwidth - 1) & 0x1) abs_ldata = (ldata if not lsigned else vtypes.Mux(lmsb == 0, ldata, vtypes.Unot(ldata) + 1)) abs_rdata = (rdata if not rsigned else vtypes.Mux(rmsb == 0, rdata, vtypes.Unot(rdata) + 1)) abs_data = op(abs_ldata, abs_rdata) data = (abs_data if not signed else vtypes.Mux(vtypes.Ors(vtypes.Ands(lmsb, rmsb), vtypes.Ands(vtypes.Not(lmsb), vtypes.Not(rmsb))), abs_data, vtypes.Unot(abs_data) + 1)) return Fixed(data, point, signed)
def _binary_op(self, op, r): lvalue = self.value lpoint = self.point lsigned = self.signed if not isinstance(r, Fixed): rvalue = r rsigned = vtypes.get_signed(r) rpoint = 0 else: rvalue = r.value rsigned = r.signed rpoint = r.point point = _max_mux(lpoint, rpoint) signed = lsigned and rsigned ldata, rdata = adjust(lvalue, rvalue, lpoint, rpoint, signed) data = op(ldata, rdata) return Fixed(data, point, signed)
def to_fixed(value, point): if point < 0: return _to_fixed_neg_point(value, point) if point == 0: return value if isinstance(value, (int, bool, float)) and isinstance(point, int): mag = 2 ** point return int(value * mag) if isinstance(value, (int, bool)): mag = vtypes.Int(2) ** point return vtypes.Int(value) * mag if isinstance(value, float): mag = vtypes.Int(2) ** point return vtypes.Float(value) * mag signed = vtypes.get_signed(value) return shift_left(value, point, signed)
def _add_delayed_subst(self, subst, delay): if not isinstance(subst, vtypes.Subst): return subst left = subst.left right = subst.right if isinstance(right, (bool, int, float, str, vtypes._Constant, vtypes._ParameterVariable)): return subst width = left.bit_length() signed = vtypes.get_signed(left) prev = right name_prefix = ('_'.join(['', left.name, str(self.tmp_count)]) if isinstance(left, vtypes._Variable) else '_'.join(['', self.name, 'sbst', str(self.tmp_count)])) self.tmp_count += 1 for i in range(delay): tmp_name = '_'.join([name_prefix, str(i + 1)]) tmp = self.m.Reg(tmp_name, width, initval=0, signed=signed) self._add_statement([tmp(prev)], delay=i, no_delay_cond=True) prev = tmp return left(prev)
def _binary_op_mul(self, op, r): lvalue = self.value lpoint = self.point lsigned = self.signed if not isinstance(r, Fixed): rvalue = r rsigned = vtypes.get_signed(r) rpoint = 0 else: rvalue = r.value rsigned = r.signed rpoint = r.point point = _max_mux(lpoint, rpoint) signed = lsigned and rsigned ldata = vtypes.SystemTask('signed', lvalue) rdata = vtypes.SystemTask('signed', rvalue) shift_size = _min_mux(lpoint, rpoint) data = op(ldata, rdata) data = shift_right(data, shift_size, signed=signed) return Fixed(data, point, signed)
def __init__(self, value, point, signed=None, raw=True): vtypes.VeriloggenNode.__init__(self) self.value = value if raw else to_fixed(value, point) self.point = point self.signed = vtypes.get_signed(value) if signed is None else signed