def fixed_to_int_low(value, point): if point < 0: raise ValueError('point must be more than 0') if point == 0: return 0 if isinstance(value, (int, bool, float)) and isinstance(point, int): mag = 2**point return int(value % mag) return vtypes.And(value, vtypes.Repeat(vtypes.Int(1, 1), point))
def _to_pattern(self, shape, order): pattern = [] for p in order: if not isinstance(p, int): raise TypeError( "Values of 'order' must be 'int', not %s" % str(type(p))) size = shape[p] basevalue = 1 if isinstance(size, int) else vtypes.Int(1) stride = functools.reduce(lambda x, y: x * y, shape[p + 1:], basevalue) pattern.append((size, stride)) return tuple(pattern)
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 _for_range(self, node): if len(node.iter.args) == 0: raise ValueError('not enough arguments') begin_node = (vtypes.Int(0) if len(node.iter.args) == 1 else self.visit(node.iter.args[0])) end_node = (self.visit(node.iter.args[0]) if len(node.iter.args) == 1 else self.visit(node.iter.args[1])) step_node = (vtypes.Int(1) if len(node.iter.args) < 3 else self.visit( node.iter.args[2])) iter_node = self.visit(node.target) cond_node = vtypes.LessThan(iter_node, end_node) update_node = vtypes.Plus(iter_node, step_node) node_body = node.body return self._for_range_fsm(begin_node, end_node, step_node, iter_node, cond_node, update_node, node_body)
def to_fixed(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)): 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 mkMultiplierCore(index, lwidth=32, rwidth=32, lsigned=True, rsigned=True, depth=6): retwidth = lwidth + rwidth m = module.Module('multiplier_core_%d' % index) clk = m.Input('CLK') update = m.Input('update') a = m.Input('a', lwidth) b = m.Input('b', rwidth) c = m.Output('c', retwidth) _a = m.Reg('_a', lwidth, signed=lsigned) _b = m.Reg('_b', rwidth, signed=rsigned) _mul = m.Wire('_mul', retwidth, signed=True) _pipe_mul = [m.Reg('_pipe_mul%d' % i, retwidth, signed=True) for i in range(depth - 1)] __a = _a __b = _b if not lsigned: __a = vtypes.SystemTask( 'signed', vtypes.Cat(vtypes.Int(0, width=1), _a)) if not rsigned: __b = vtypes.SystemTask( 'signed', vtypes.Cat(vtypes.Int(0, width=1), _b)) m.Assign(_mul(__a * __b)) m.Assign(c(_pipe_mul[depth - 2])) m.Always(vtypes.Posedge(clk))( vtypes.If(update)( _a(a), _b(b), _pipe_mul[0](_mul), [_pipe_mul[i](_pipe_mul[i - 1]) for i in range(1, depth - 1)] )) return m
def __init__(self, m, clk, rst, thread_name, thread_id, id, sub_id=None, datawidth=32, addrwidth=4): self.m = m self.clk = clk self.rst = rst self.thread_name = thread_name self.thread_id = thread_id self.id = id self.sub_id = sub_id self.name = '_'.join([thread_name, 'channel', str(id)]) self.datawidth = datawidth self.addrwidth = addrwidth self.wif = CoramChannelWriteInterface(self.m, self.name, datawidth) self.rif = CoramChannelReadInterface(self.m, self.name, datawidth) self.definition = get_coram_channel_definition() params = [] params.append(('CORAM_THREAD_NAME', self.thread_name)) params.append(('CORAM_THREAD_ID', self.thread_id)) params.append(('CORAM_ID', self.id)) if self.sub_id is not None: params.append(('CORAM_SUB_ID', self.sub_id)) params.append(('CORAM_ADDR_LEN', self.addrwidth)) params.append(('CORAM_DATA_WIDTH', self.datawidth)) ports = [] ports.append(('CLK', self.clk)) ports.append(('RST', self.rst)) ports.extend(m.connect_ports(self.definition, prefix=self.name + '_')) self.inst = self.m.Instance(self.definition, 'inst_' + self.name, params, ports) self.seq = Seq(m, self.name, clk, rst) self._max_size = (2**self.addrwidth - 1 if isinstance( self.addrwidth, int) else vtypes.Int(2)**self.addrwidth - 1) self._count = 0 self._enq_disabled = False self._deq_disabled = False
def to_fixed(value, point, signed=False): 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)): mag = vtypes.Int(2) ** point return vtypes.Int(value) * mag if isinstance(value, float): mag = vtypes.Int(2) ** point return vtypes.Float(value) * mag if hasattr(value, 'signed') and value.signed: signed = True return shift_left(value, point, signed)
def write_data(self, data, counter=None, cond=None): """ @return ack, last """ if self._write_disabled: raise TypeError('Write disabled.') if counter is not None and not isinstance(counter, vtypes.Reg): raise TypeError("counter must be Reg or None.") if counter is None: counter = self.write_counters[-1] if cond is not None: self.seq.If(cond) ack = vtypes.Ands(counter > 0, vtypes.Ors(self.wdata.wready, vtypes.Not(self.wdata.wvalid))) last = self.m.TmpReg(initval=0) self.seq.If(vtypes.Ands(ack, counter > 0))( self.wdata.wdata(data), self.wdata.wvalid(1), self.wdata.wlast(0), self.wdata.wstrb(vtypes.Repeat( vtypes.Int(1, 1), (self.wdata.datawidth // 8))), counter.dec() ) self.seq.Then().If(counter == 1)( self.wdata.wlast(1), last(1) ) # de-assert self.seq.Delay(1)( self.wdata.wvalid(0), self.wdata.wlast(0), last(0) ) # retry self.seq.If(vtypes.Ands(self.wdata.wvalid, vtypes.Not(self.wdata.wready)))( self.wdata.wvalid(self.wdata.wvalid), self.wdata.wlast(self.wdata.wlast), last(last) ) return ack, last
def mkUartTx(baudrate=19200, clockfreq=100 * 1000 * 1000): m = Module("UartTx") waitnum = int(clockfreq / baudrate) clk = m.Input('CLK') rst = m.Input('RST') din = m.Input('din', 8) enable = m.Input('enable') ready = m.OutputReg('ready', initval=1) txd = m.OutputReg('txd', initval=1) fsm = FSM(m, 'fsm', clk, rst) mem = m.TmpReg(9, initval=0) waitcount = m.TmpReg(int(math.log(waitnum, 2)) + 1, initval=0) fsm(waitcount(waitnum - 1), txd(1), mem(vtypes.Cat(din, vtypes.Int(0, 1)))) fsm.If(enable)(ready(0)) fsm.Then().goto_next() for i in range(10): fsm.If(waitcount > 0)(waitcount.dec()).Else( txd(mem[0]), mem(vtypes.Cat(vtypes.Int(1, 1), mem[1:9])), waitcount(waitnum - 1)) fsm.Then().goto_next() fsm(ready(1)) fsm.goto_init() fsm.make_always() return m
def visit_Pointer(self, node): val = self.visit(node.var) if val is None: return None left = vtypes.Pointer(val.left, node.pos) if not isinstance(val.right, (vtypes._Variable, vtypes.Scope)): if isinstance(val.right, (int, bool)): val_right = vtypes.Int(val.right) elif isinstance(val.right, float): val_right = vtypes.Float(val.right) else: raise TypeError("unsupported value type: %s" % str(val.right)) right = (val_right >> node.pos) & 0x1 else: right = vtypes.Pointer(val.right, node.pos) return vtypes.Subst(left, right)
def __init__(self, m, name, clk, rst, datawidth=32, addrwidth=32, noio=False, length=4, fsm_as_module=False): AXISLite.__init__(self, m, name, clk, rst, datawidth, addrwidth, noio) self.fsm_as_module = fsm_as_module if not isinstance(length, int): raise TypeError("length must be 'int', not '%s'" % str(type(length))) self.register = [ self.m.Reg('_'.join(['', self.name, 'register', '%d' % i]), width=self.datawidth, initval=0, signed=True) for i in range(length) ] self.flag = [ self.m.Reg('_'.join(['', self.name, 'flag', '%d' % i]), initval=0) for i in range(length) ] self.resetval = [ self.m.Reg('_'.join(['', self.name, 'resetval', '%d' % i]), width=self.datawidth, initval=0, signed=True) for i in range(length) ] self.length = length self.maskwidth = self.m.Localparam( '_'.join(['', self.name, 'maskwidth']), util.log2(length)) self.mask = self.m.Localparam( '_'.join(['', self.name, 'mask']), vtypes.Repeat(vtypes.Int(1, 1), self.maskwidth)) self.shift = self.m.Localparam('_'.join(['', self.name, 'shift']), util.log2(self.datawidth // 8)) self._set_register_lite_fsm()
def __init__(self, df, stage_id, data, valid=None, ready=None, src_data=None, ops=None, resetcond=None, initval=None, oplabel=None): self.df = df self.stage_id = stage_id self.data = data self.valid = valid self.ready = ready self.output_vars = None self.src_data = src_data self.dst_data = None self.ops = ops self.resetcond = resetcond self.initval = initval self.oplabel = oplabel self.prev_dict = {} self.preg_dict = {} if self.ready is not None: ready = vtypes.Int(1) _connect_ready(self.df.m, self.ready, ready)
def __init__(self, m, name, clk, rst, datawidth=32, addrwidth=4): self.m = m self.name = name self.clk = clk self.rst = rst self.datawidth = datawidth self.addrwidth = addrwidth self.wif = FifoWriteInterface(self.m, name, datawidth) self.rif = FifoReadInterface(self.m, name, datawidth) self.definition = mkFifoDefinition(name, datawidth, addrwidth) self.inst = self.m.Instance(self.definition, 'inst_' + name, ports=m.connect_ports(self.definition)) self.seq = Seq(m, name, clk, rst) # entry counter self._max_size = (2 ** self.addrwidth - 1 if isinstance(self.addrwidth, int) else vtypes.Int(2) ** self.addrwidth - 1) self._count = self.m.Reg( 'count_' + name, self.addrwidth + 1, initval=0) self.seq.If( vtypes.Ands(vtypes.Ands(self.wif.enq, vtypes.Not(self.wif.full)), vtypes.Ands(self.rif.deq, vtypes.Not(self.rif.empty))))( self._count(self._count) ).Elif(vtypes.Ands(self.wif.enq, vtypes.Not(self.wif.full)))( self._count.inc() ).Elif(vtypes.Ands(self.rif.deq, vtypes.Not(self.rif.empty)))( self._count.dec() ) self._enq_disabled = False self._deq_disabled = False self.mutex = None
def enq_rtl(self, wdata, cond=None): """ Enque """ if self._enq_disabled: raise TypeError('Enq disabled.') cond = make_condition(cond) ready = vtypes.Not(self.wif.almost_full) if cond is not None: enq_cond = vtypes.Ands(cond, ready) enable = cond else: enq_cond = ready enable = vtypes.Int(1, 1) util.add_mux(self.wif.wdata, enable, wdata) util.add_enable_cond(self.wif.enq, enable, enq_cond) ack = self.seq.Prev(ready, 1) return ack, ready
def visit_Cat(self, node): left_values = [] right_values = [] for v in node.vars: val = self.visit(v) width = v.bit_length() if width is None: width = 1 if val is None: right = vtypes.IntX(width) elif isinstance(val.right, int): right = vtypes.Int(val.right, width) elif isinstance(val.right, vtypes._Constant): right = copy.deepcopy(val.right) right.width = width else: right = v._get_module().TmpLocalparam(val.right, width) left_values.append(v) right_values.append(right) return vtypes.Subst(vtypes.Cat(*left_values), vtypes.Cat(*right_values))
def _saturate_single(value, width=8, max=None, min=None, signed=False): if hasattr(value, 'saturated') and value.saturated: return value if (signed or (isinstance(value, (int, float, bool)) and value < 0)): if not isinstance(value, int) and isinstance(min, int): min = vtypes.Int(min, signed=True) cond = value < min sat_val = _saturate_both(value, cond, width=width, max=max, min=min, signed=signed) else: sat_val = _saturate_overflow(value, width=width, max=max, signed=signed) try: sat_val.saturated = True except: pass return sat_val
def to_width(raw_width): if raw_width is None: return None msb = raw_width[0] lsb = raw_width[1] if isinstance(msb, vtypes.Int): msb = msb.value if isinstance(lsb, vtypes.Int): lsb = lsb.value if isinstance(lsb, int): if lsb == 0: return msb + 1 return msb - (lsb - 1) if isinstance(msb, vtypes._Numeric): return msb - lsb + 1 msb = vtypes.Int(msb) return msb - lsb + 1
def visit_IntConst(self, node): return vtypes.Int(node.value)
def raw(self): return vtypes.Int(self.value, self.width, self.base, self.signed)
def dec_part(self): mask = vtypes.Mux(self.point == 0, 0, vtypes.Repeat( vtypes.Int(1, width=1), self.point)) return self & mask
def visit_Num(self, node): if isinstance(node.n, int): return vtypes.Int(node.n) return vtypes.Constant(node.n)
def _visit_next_function(self, node): self.generic_visit(node) retvar = self.getReturnVariable() if retvar is not None: return retvar return vtypes.Int(0)
def mkRAMDefinition(name, datawidth=32, addrwidth=10, numports=2, initvals=None, sync=True, with_enable=False, nocheck_initvals=False, ram_style=None): m = Module(name) clk = m.Input('CLK') interfaces = [] for i in range(numports): interface = RAMSlaveInterface(m, name + '_%d' % i, datawidth, addrwidth, with_enable=with_enable) if sync: interface.delay_addr = m.Reg(name + '_%d_daddr' % i, addrwidth) interfaces.append(interface) if ram_style is not None: m.EmbeddedCode(ram_style) mem = m.Reg('mem', datawidth, 2**addrwidth) if initvals is not None: if not isinstance(initvals, (tuple, list)): raise TypeError("initvals must be tuple or list, not '%s" % str(type(initvals))) base = 16 if not nocheck_initvals: new_initvals = [] for initval in initvals: if isinstance(initval, int): new_initvals.append(vtypes.Int(initval, datawidth, base=16)) elif isinstance(initval, vtypes.Int) and isinstance( initval.value, int): v = copy.deepcopy(initval) v.width = datawidth v.base = base new_initvals.append(v) elif isinstance(initval, vtypes.Int) and isinstance( initval.value, str): v = copy.deepcopy(initval) v.width = datawidth if v.base != 2 and v.base != 16: raise ValueError('base must be 2 or 16') base = v.base new_initvals.append(v) else: raise TypeError("values of initvals must be int, not '%s" % str(type(initval))) initvals = new_initvals if 2**addrwidth > len(initvals): initvals.extend([ vtypes.Int(0, datawidth, base=base) for _ in range(2**addrwidth - len(initvals)) ]) m.Initial(*[mem[i](initval) for i, initval in enumerate(initvals)]) for interface in interfaces: body = [ vtypes.If(interface.wenable)(mem[interface.addr](interface.wdata)) ] if sync: body.append(interface.delay_addr(interface.addr)) if with_enable: body = vtypes.If(interface.enable)(*body) m.Always(vtypes.Posedge(clk))(body) if sync: m.Assign(interface.rdata(mem[interface.delay_addr])) else: m.Assign(interface.rdata(mem[interface.addr])) return m
def dataflow(self, *args, **kwargs): """ synthesize a dataflow module and create its instance """ clock_domain = kwargs[ 'clock_domain'] if 'clock_domain' in kwargs else self.clock_domain with_valid = kwargs['with_valid'] if 'with_valid' in kwargs else False with_ready = kwargs['with_ready'] if 'with_ready' in kwargs else False input_visitor = visitor.InputVisitor() input_vars = set() for arg in args: input_vars.update(input_visitor.visit(arg)) for arg in args: if arg.output_data is None: tmp = self.get_tmp() data = 'outport%d_data' % tmp valid = 'outport%d_valid' % tmp if with_valid else None ready = 'outport%d_ready' % tmp if with_ready else None arg.output(data, valid, ready) else: if with_valid and arg.output_valid is None: #arg.output_valid = arg.output_data + '_valid' raise ValueError( 'valid name must be specified when with_valid is enabled' ) if with_ready and arg.output_ready is None: #arg.output_ready = arg.output_data + '_ready' raise ValueError( 'ready name must be specified when with_ready is enabled' ) df = dataflow.Dataflow(*args) mod_name = "dataflow_module_%d" % self.get_tmp() mod = df.to_module(mod_name) inst_ports = [] inst_ports.append(('CLK', clock_domain.clock)) inst_ports.append(('RST', clock_domain.reset)) for input_var in sorted(input_vars, key=lambda x: x.object_id): inst_ports.append((input_var.input_data, input_var.rtl_data)) if input_var.input_valid is not None: inst_ports.append((input_var.input_valid, input_var.rtl_valid)) if input_var.input_ready is not None: inst_ports.append((input_var.input_ready, input_var.rtl_ready)) output_ports = [] for arg in args: output_port_pair = [] data = self.Wire(arg.output_data, width=arg.bit_length()) inst_ports.append((arg.output_data, data)) output_port_pair.append(data) if with_valid: valid = self.Wire(arg.output_valid) inst_ports.append((arg.output_valid, valid)) output_port_pair.append(valid) if with_ready: ready = self.Wire(arg.output_ready) inst_ports.append((arg.output_ready, ready)) output_port_pair.append(ready) elif arg.output_ready is not None: ready = vtypes.Int(1, width=1) inst_ports.append((arg.output_ready, ready)) output_ports.append(tuple(output_port_pair)) self.Instance(mod, 'inst_' + mod_name, params=(), ports=inst_ports) return tuple(output_ports)
def visit_For(self, node): if self.skip(): return if (isinstance(node.iter, ast.Call) and isinstance(node.iter.func, ast.Name) and node.iter.func.id == 'range'): # typical for-loop if len(node.iter.args) == 0: raise TypeError() begin_node = (vtypes.Int(0) if len(node.iter.args) == 1 else self.visit(node.iter.args[0])) end_node = (self.visit(node.iter.args[0]) if len(node.iter.args) == 1 else self.visit(node.iter.args[1])) step_node = (vtypes.Int(1) if len(node.iter.args) < 3 else self.visit(node.iter.args[2])) iter_node = self.visit(node.target) cond_node = vtypes.LessThan(iter_node, end_node) update_node = vtypes.Plus(iter_node, step_node) self.pushScope() # initialize self.setBind(iter_node, begin_node) self.setFsm() self.incFsmCount() # condition check check_count = self.getFsmCount() self.incFsmCount() body_begin_count = self.getFsmCount() for b in node.body: self.visit(b) self.popScope() body_end_count = self.getFsmCount() # update self.setBind(iter_node, update_node) self.incFsmCount() loop_exit_count = self.getFsmCount() self.setFsm(body_end_count, check_count) self.setFsm(check_count, body_begin_count, cond_node, loop_exit_count) unresolved_break = self.getUnresolvedBreak() for b in unresolved_break: self.setFsm(b, loop_exit_count) unresolved_continue = self.getUnresolvedContinue() for c in unresolved_continue: self.setFsm(c, body_end_count) self.clearBreak() self.clearContinue() self.setFsmLoop(check_count, body_end_count, iter_node, step_node)
def visit_bool(self, node): if node: return (None, vtypes.Int(1), None, []) return (None, vtypes.Int(0), None, [])
def space(self): if isinstance(self._max_size, int): return vtypes.Int(self._max_size) - self.count return self._max_size - self.count
def _pow2(p): if isinstance(p, int): return 2**p return vtypes.Int(2, signed=True)**p
def visit_int(self, node): return (None, vtypes.Int(node), None, [])