def write_sequential(self, obj, start_addr, size, value, when=None, port=0): flag = self.m.Reg(compiler._tmp_name('_'.join(['', self.name, 'flag'])), initval=0) self.done_flags.append(flag) fsm = FSM(self.m, compiler._tmp_name('_'.join(['', self.name, 'fsm'])), self.clk, self.rst) fsm.If(self.start_cond)(flag(0)) fsm.If(self.start_cond).goto_next() done = obj.write_dataflow(port, start_addr, value, size, cond=fsm, when=when) fsm.goto_next() fsm.If(done)(flag(1)) fsm.If(done).goto_init() return 0
def run(self, fsm, *args, **kwargs): """ start as a child thread """ if not self.is_child and self.end_state is not None: raise ValueError('already started.') self.fsm = FSM(self.m, self.name, self.clk, self.rst) self.is_child = True if self.start_state is None: self.start_state = self.fsm.current start_flag = (fsm.state == fsm.current) self.fsm.goto_from(self.start_state, self.start_state + 1, start_flag) self.fsm._set_index(self.start_state + 1) if self.end_state is not None: return 0 self._synthesize_fsm(self.fsm, args, kwargs) if self.end_state is None: self.end_state = self.fsm.current return 0
def write_pattern(self, obj, addr, value, pattern, when=None, port=0): flag = self.m.Reg(compiler._tmp_name('_'.join(['', self.name, 'flag'])), initval=0) self.done_flags.append(flag) fsm = FSM(self.m, compiler._tmp_name('_'.join(['', self.name, 'fsm'])), self.clk, self.rst) fsm.If(self.start_cond)(flag(0)) fsm.If(self.start_cond).goto_next() if hasattr(obj, 'write_dataflow_pattern_interleave'): done = obj.write_dataflow_pattern_interleave(port, addr, value, pattern, cond=fsm, when=when) else: done = obj.write_dataflow_pattern(port, addr, value, pattern, cond=fsm, when=when) fsm.goto_next() fsm.If(done)(flag(1)) fsm.If(done).goto_init() return 0
def read_sequential(self, obj, start_addr, size, point=0, signed=False, port=0, with_last=False): flag = self.m.Reg(compiler._tmp_name('_'.join(['', self.name, 'flag'])), initval=0) self.done_flags.append(flag) fsm = FSM(self.m, compiler._tmp_name('_'.join(['', self.name, 'fsm'])), self.clk, self.rst) fsm.If(self.start_cond)(flag(0)) fsm.If(self.start_cond).goto_next() rdata, rlast, done = obj.read_dataflow(port, start_addr, size, cond=fsm, point=point, signed=signed) fsm.goto_next() fsm.If(done)(flag(1)) fsm.If(done).goto_init() if with_last: return rdata, rlast return rdata
def run(self, fsm, *args, **kwargs): """ start as a child thread """ if not self.is_child and self.end_state is not None: raise ValueError('already started') if self.fsm is None: self.fsm = FSM(self.m, self.name, self.clk, self.rst, as_module=self.fsm_as_module) self.is_child = True if self.start_state is not None: self.fsm._set_index(self.start_state) else: self.start_state = self.fsm.current self._synthesize_run_fsm(fsm, args, kwargs) if self.end_state is None: self.end_state = self.fsm.current start_flag = (self.fsm.state == self.start_state) return start_flag
def read_reuse_pattern(self, obj, addr, pattern, reuse_size=1, num_outputs=1, point=0, signed=False, port=0, with_last=False): flag = self.m.Reg(compiler._tmp_name('_'.join(['', self.name, 'flag'])), initval=0) self.done_flags.append(flag) fsm = FSM(self.m, compiler._tmp_name('_'.join(['', self.name, 'fsm'])), self.clk, self.rst) fsm.If(self.start_cond)(flag(0)) fsm.If(self.start_cond).goto_next() if hasattr(obj, 'read_dataflow_reuse_pattern_interleave'): ret = obj.read_dataflow_reuse_pattern_interleave(port, addr, pattern, reuse_size, num_outputs, cond=fsm, point=point, signed=signed) else: ret = obj.read_dataflow_reuse_pattern(port, addr, pattern, reuse_size, num_outputs, cond=fsm, point=point, signed=signed) rdata = ret[:-2] done = ret[-1] rlast = ret[-2] fsm.goto_next() fsm.If(done)(flag(1)) fsm.If(done).goto_init() if with_last: return tuple(rdata + [rlast]) if len(rdata) == 1: rdata = rdata[0] else: rdata = tuple(rdata) return rdata
def _setup_register_lite_fsm(self): fsm = FSM(self.m, '_'.join(['', self.name, 'register_fsm']), self.clk, self.rst) # request addr, readvalid, writevalid = self.pull_request(cond=fsm) maskaddr = self.m.TmpReg(self.maskwidth) fsm.If(vtypes.Ors(readvalid, writevalid))(maskaddr((addr >> self.shift) & self.mask), ) init_state = fsm.current # read read_state = fsm.current + 1 fsm.If(readvalid).goto_from(init_state, read_state) fsm.set_index(read_state) rdata = self.m.TmpWire(self.datawidth) pat = [(maskaddr == i, r) for i, r in enumerate(self.register)] pat.append((None, vtypes.IntX())) rval = vtypes.PatternMux(pat) rdata.assign(rval) flag = self.m.TmpWire() pat = [(maskaddr == i, r) for i, r in enumerate(self.flag)] pat.append((None, vtypes.IntX())) rval = vtypes.PatternMux(pat) flag.assign(rval) resetval = self.m.TmpWire(self.datawidth) pat = [(maskaddr == i, r) for i, r in enumerate(self.resetval)] pat.append((None, vtypes.IntX())) rval = vtypes.PatternMux(pat) resetval.assign(rval) ack = self.push_read_data(rdata, cond=fsm) # flag reset state_cond = fsm.state == fsm.current for i, r in enumerate(self.register): self.seq.If(state_cond, ack, flag, maskaddr == i)(self.register[i](resetval), self.flag[i](0)) fsm.If(ack).goto_init() # write write_state = fsm.current + 1 fsm.If(writevalid).goto_from(init_state, write_state) fsm.set_index(write_state) data, mask, valid = self.pull_write_data(cond=fsm) state_cond = fsm.state == fsm.current for i, r in enumerate(self.register): self.seq.If(state_cond, valid, maskaddr == i)(self.register[i](data)) fsm.goto_init()
def __init__(self, m, name, clk, rst, datawidth=32, addrwidth=32, max_pattern_length=4, ram_sel_width=8, fsm_as_module=False): BaseStream.__init__(self, module=m, clock=clk, reset=rst, no_hook=True) self.name = name self.datawidth = datawidth self.addrwidth = addrwidth self.max_pattern_length = max_pattern_length self.ram_sel_width = ram_sel_width self.fsm_as_module = fsm_as_module self.stream_synthesized = False self.fsm_synthesized = False self.fsm = FSM(self.module, '_%s_fsm' % self.name, self.clock, self.reset, as_module=self.fsm_as_module) self.start_flag = self.module.Wire( '_'.join(['', self.name, 'start_flag'])) self.start = self.module.Reg( '_'.join(['', self.name, 'start']), initval=0) self.busy = self.module.Reg( '_'.join(['', self.name, 'busy']), initval=0) self.reduce_reset = None self.reduce_reset_var = None self.sources = OrderedDict() self.sinks = OrderedDict() self.constants = OrderedDict() self.substreams = [] self.var_name_map = OrderedDict() self.var_id_map = OrderedDict() self.var_id_name_map = OrderedDict() self.var_name_id_map = OrderedDict() self.var_id_count = 0 self.source_idle_map = OrderedDict() self.sink_when_map = OrderedDict() self.ram_id_count = 1 # '0' is reserved for idle self.ram_id_map = OrderedDict() # key: ran._id(), value: count self.fsm_id_count = 0 self.ram_delay = 4
def _synthesize_set_sink(self, var, name): if var.sink_fsm is not None: return sink_start = vtypes.Ands(self.start, var.sink_mode == 0, var.sink_size > 0) fsm_id = self.fsm_id_count self.fsm_id_count += 1 prefix = self._prefix(name) fsm_name = '_%s_sink_fsm_%d' % (prefix, fsm_id) var.sink_fsm = FSM(self.module, fsm_name, self.clock, self.reset, as_module=self.fsm_as_module) self.seq.If(var.sink_fsm.here)( var.sink_ram_wenable(0) ) var.sink_fsm.If(sink_start).goto_next() self.seq.If(var.sink_fsm.here)( var.sink_ram_waddr(var.sink_offset - var.sink_stride), var.sink_count(var.sink_size) ) num_wdelay = self._write_delay() for _ in range(num_wdelay): var.sink_fsm.goto_next() if name in self.sink_when_map: when = self.sink_when_map[name] wcond = when.read() else: wcond = None rdata = var.read() self.seq.If(var.sink_fsm.here)( var.sink_ram_wenable(0) ) self.seq.If(var.sink_fsm.here, wcond)( var.sink_ram_waddr.add(var.sink_stride), var.sink_ram_wdata(rdata), var.sink_ram_wenable(1), var.sink_count.dec() ) var.sink_fsm.If(wcond, var.sink_count == 1).goto_init()
def read_multidim(self, obj, addr, shape, order=None, point=0, signed=False, port=0, with_last=False): flag = self.m.Reg(compiler._tmp_name('_'.join(['', self.name, 'flag'])), initval=0) self.done_flags.append(flag) fsm = FSM(self.m, compiler._tmp_name('_'.join(['', self.name, 'fsm'])), self.clk, self.rst) fsm.If(self.start_cond)(flag(0)) fsm.If(self.start_cond).goto_next() if hasattr(obj, 'read_dataflow_multidim_interleave'): rdata, rlast, done = obj.read_dataflow_multidim_interleave( port, addr, shape, order=order, cond=fsm, point=point, signed=signed) else: rdata, rlast, done = obj.read_dataflow_multidim(port, addr, shape, order=order, cond=fsm, point=point, signed=signed) fsm.goto_next() fsm.If(done)(flag(1)) fsm.If(done).goto_init() if with_last: return rdata, rlast return rdata
def _synthesize_set_source(self, var, name): if var.source_fsm is not None: return wdata = var.source_ram_rdata wenable = var.source_ram_rvalid var.write(wdata, wenable) source_start = vtypes.Ands(self.start, var.source_mode == 0, var.source_size > 0) self.seq.If(source_start)( var.source_idle(0) ) fsm_id = self.fsm_id_count self.fsm_id_count += 1 prefix = self._prefix(name) fsm_name = '_%s_source_fsm_%d' % (prefix, fsm_id) var.source_fsm = FSM(self.module, fsm_name, self.clock, self.reset, as_module=self.fsm_as_module) var.source_fsm.If(source_start).goto_next() self.seq.If(var.source_fsm.here)( var.source_ram_raddr(var.source_offset), var.source_ram_renable(1), var.source_count(var.source_size) ) var.source_fsm.goto_next() self.seq.If(var.source_fsm.here)( var.source_ram_raddr.add(var.source_stride), var.source_ram_renable(1), var.source_count.dec() ) self.seq.If(var.source_fsm.here, var.source_count == 1)( var.source_ram_renable(0), var.source_idle(1) ) var.source_fsm.If(var.source_count == 1).goto_init()
def start(self, *args, **kwargs): """ build up a new FSM based on the arguments """ if self.is_child: raise ValueError('already started as a child thread') if self.end_state is not None: raise ValueError('already started') frame = inspect.currentframe() self.start_frame = frame.f_back self.fsm = FSM(self.m, self.name, self.clk, self.rst) self.start_state = self.fsm.current self._synthesize_start_fsm(args, kwargs) self.end_state = self.fsm.current return self.fsm
def run(self, fsm, tid, *args, **kwargs): """ start as a child thread """ fsm(self.start[tid](1)) fsm.goto_next() for thread in self.threads: start_cond = self.start[thread.tid] if not thread.is_child and thread.end_state is not None: raise ValueError('thread %d already started' % thread.tid) if thread.fsm is None: thread.fsm = FSM(thread.m, thread.name, thread.clk, thread.rst, as_module=thread.fsm_as_module) thread.is_child = True if thread.start_state is not None: thread.fsm._set_index(thread.start_state) else: thread.start_state = thread.fsm.current fsm_start = fsm.current for thread in self.threads: start_cond = self.start[thread.tid] fsm._set_index(fsm_start) thread._synthesize_run_fsm(fsm, args, kwargs, cond=start_cond) if thread.end_state is None: thread.end_state = thread.fsm.current fsm(self.start[tid](0)) fsm.goto_next() return 0
def __init__(self, m, name, clk, rst, datawidth=32, fsm_sel_width=16): BaseStream.__init__(self, module=m, clock=clk, reset=rst, no_hook=True) self.name = name self.datawidth = datawidth self.fsm_sel_width = fsm_sel_width self.stream_synthesized = False self.fsm_synthesized = False self.fsm = FSM(self.module, '_%s_fsm' % self.name, self.clock, self.reset) self.start = self.module.Reg( '_'.join(['', self.name, 'start']), initval=0) self.busy = self.module.Reg( '_'.join(['', self.name, 'busy']), initval=0) self.reduce_reset = None self.reduce_reset_var = None self.sources = OrderedDict() self.sinks = OrderedDict() self.constants = OrderedDict() self.substreams = [] self.var_name_map = OrderedDict() self.var_id_map = OrderedDict() self.var_id_name_map = OrderedDict() self.var_name_id_map = OrderedDict() self.var_id_count = 0 self.source_idle_map = OrderedDict() self.sink_when_map = OrderedDict() self.fsm_id_map = OrderedDict() self.fsm_id_count = 1 # '0' is reserved for idle self.var_id_fsm_sel_map = OrderedDict() # key: var_id, value: fsm_id reg self.ram_delay = 4
def start(self, *args, **kwargs): """ build up a new FSM based on the arguments """ if self.is_child: raise ValueError('already started as a child thread') if self.end_state is not None: raise ValueError('already started') frame = inspect.currentframe() _locals = frame.f_back.f_locals self.local_objects = OrderedDict() for key, value in _locals.items(): self.local_objects[key] = value self.fsm = FSM(self.m, self.name, self.clk, self.rst) self.start_state = self.fsm.current self._synthesize_start_fsm(args, kwargs) self.end_state = self.fsm.current return self.fsm
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 mkUartRx(baudrate=19200, clockfreq=100 * 1000 * 1000): m = Module("UartRx") waitnum = int(clockfreq / baudrate) clk = m.Input('CLK') rst = m.Input('RST') rxd = m.Input('rxd') dout = m.OutputReg('dout', 8, initval=0) valid = m.OutputReg('valid', initval=0) fsm = FSM(m, 'fsm', clk, rst) mem = m.TmpReg(9, initval=0) waitcount = m.TmpReg(int(math.log(waitnum, 2)) + 1, initval=0) fsm(valid(0), waitcount(int(waitnum / 2) - 1), mem(vtypes.Cat(rxd, mem[1:9]))) fsm.If(rxd == 0).goto_next() for i in range(10): if i == 0: # check the start bit again fsm.If(vtypes.Ands(waitcount == 1, rxd != 0)).goto_init() fsm.If(waitcount > 0)(waitcount.dec()).Else( mem(vtypes.Cat(rxd, mem[1:9])), waitcount(waitnum - 1)) fsm.Then().goto_next() fsm(valid(1), dout(mem[0:9])) fsm.goto_init() fsm.make_always() return m
def _synthesize_read_fsm_fifo_same(self, fifo, fifo_datawidth): op_id = self._get_read_op_id_fifo(fifo) if op_id in self.read_ops: """ already synthesized op """ return if self.read_fsm is not None: """ new op """ self.read_ops.append(op_id) fsm = self.read_fsm data = self.read_data_wire valid = self.read_valid_wire rest_size = self.read_rest_size # state 0 fsm.set_index(0) cond = vtypes.Ands(self.read_start, self.read_op_sel == op_id) fsm.If(cond).goto_next() # state 1 fsm.set_index(1) valid_cond = vtypes.Ands(valid, self.read_op_sel == op_id) ack, _ = fifo.enq_rtl(data, cond=valid_cond) fsm.If(valid_cond)( rest_size.dec() ) return """ new op and fsm """ fsm = FSM(self.m, '_'.join(['', self.name, 'read_fsm']), self.clk, self.rst, as_module=self.fsm_as_module) self.read_fsm = fsm self.read_ops.append(op_id) rest_size = self.m.Reg('_'.join(['', self.name, 'read_rest_size']), self.addrwidth + 1, initval=0) self.read_rest_size = rest_size # state 0 cond = vtypes.Ands(self.read_start, self.read_op_sel == op_id) fsm.If(self.read_start)( rest_size(self.read_size) ) fsm.If(cond).goto_next() # state 1 ready = vtypes.Not(fifo.almost_full) read_cond = vtypes.Ands(fsm.here, ready) data, last, _id, user, dest, valid = self.read_data(cond=read_cond) self.read_data_wire = data self.read_valid_wire = valid valid_cond = vtypes.Ands(valid, self.read_op_sel == op_id) ack, _ = fifo.enq_rtl(data, cond=valid_cond) fsm.If(valid_cond)( rest_size.dec() ) fsm.If(valid, rest_size <= 1).goto_next() # state 2 set_idle = self._set_flag(fsm) self.seq.If(set_idle)( self.read_idle(1) ) fsm.goto_init()
def _synthesize_read_fsm_wide(self, ram, port, ram_method, ram_datawidth): """ axi.datawidth > ram.datawidth """ if self.datawidth % ram_datawidth != 0: raise ValueError( 'axi.datawidth must be multiple number of ram_datawidth') pack_size = self.datawidth // ram_datawidth shamt = int(math.log(pack_size, 2)) res = vtypes.Mux( vtypes.And(self.read_size, 2 ** shamt - 1) > 0, 1, 0) dma_size = (self.read_size >> shamt) + res actual_read_size = dma_size << shamt op_id = self._get_read_op_id(ram, port, ram_method) port = vtypes.to_int(port) if op_id in self.read_ops: """ already synthesized op """ return if pack_size in self.read_wide_fsms: """ new op """ self.read_ops.append(op_id) fsm = self.read_wide_fsms[pack_size] pack_count = self.read_wide_pack_counts[pack_size] data = self.read_wide_data_wires[pack_size] valid = self.read_wide_valid_wires[pack_size] rest_size = self.read_wide_rest_size_wires[pack_size] # state 0 fsm.set_index(0) wdata, wvalid, w = self._get_op_write_dataflow(ram_datawidth) cond = vtypes.Ands(self.read_start, self.read_op_sel == op_id) ram_method(port, self.read_local_addr, w, actual_read_size, stride=self.read_local_stride, cond=cond) fsm.If(cond).goto_next() # state 1 fsm.set_index(1) valid_cond = vtypes.Ands(valid, self.read_op_sel == op_id) stay_cond = self.read_op_sel == op_id fsm.Delay(1)( wvalid(0) ) fsm.If(pack_count == 0, valid_cond)( wdata(data), wvalid(1), pack_count.inc() ) fsm.If(pack_count > 0, stay_cond)( wdata(wdata >> ram_datawidth), wvalid(1), pack_count.inc() ) fsm.If(valid_cond)( rest_size.dec() ) return """ new op and fsm """ fsm = FSM(self.m, '_'.join(['', self.name, 'read_wide', str(pack_size), 'fsm']), self.clk, self.rst, as_module=self.fsm_as_module) self.read_wide_fsms[pack_size] = fsm self.read_ops.append(op_id) rest_size = self.m.Reg('_'.join(['', self.name, 'read_wide', str(pack_size), 'rest_size']), self.addrwidth + 1, initval=0) self.read_wide_rest_size_wires[pack_size] = rest_size # state 0 wdata, wvalid, w = self._get_op_write_dataflow(ram_datawidth) cond = vtypes.Ands(self.read_start, self.read_op_sel == op_id) ram_method(port, self.read_local_addr, w, actual_read_size, stride=self.read_local_stride, cond=cond) fsm.If(self.read_start)( rest_size(dma_size) ) fsm.If(cond).goto_next() # state 1 pack_count = self.m.Reg('_'.join(['', self.name, 'read_wide', str(pack_size), 'pack_count']), int(math.ceil(math.log(pack_size, 2))), initval=0) self.read_wide_pack_counts[pack_size] = pack_count cond = vtypes.Ands(fsm.here, pack_count == 0) data, last, _id, user, dest, valid = self.read_data(cond=cond) self.read_wide_data_wires[pack_size] = data self.read_wide_valid_wires[pack_size] = valid valid_cond = vtypes.Ands(valid, self.read_op_sel == op_id) stay_cond = self.read_op_sel == op_id wlast = self.m.Reg('_'.join(['', self.name, 'read_wide', str(pack_size), 'wlast']), initval=0) fsm.Delay(1)( wvalid(0) ) fsm.If(pack_count == 0, valid_cond)( wdata(data), wvalid(1), wlast(last), pack_count.inc() ) fsm.If(pack_count > 0, stay_cond)( wdata(wdata >> ram_datawidth), wvalid(1), pack_count.inc() ) fsm.If(pack_count == pack_size - 1)( pack_count(0) ) fsm.If(pack_count == 0, valid_cond)( rest_size.dec() ) fsm.If(pack_count == pack_size - 1, rest_size == 0).goto_next() for _ in range(self.num_data_delay): fsm.goto_next() # state 2 set_idle = self._set_flag(fsm) self.seq.If(set_idle)( self.read_idle(1) ) fsm.goto_init()
def _synthesize_write_fsm(self): op_id = 1 if op_id in self.write_ops: """ already synthesized op """ return if self.write_fsm is not None: """ new op """ self.write_ops.append(op_id) return """ new op and fsm """ fsm = FSM(self.m, '_'.join(['', self.name, 'write_fsm']), self.clk, self.rst, as_module=self.fsm_as_module) self.write_fsm = fsm self.write_ops.append(op_id) cur_global_addr = self.m.Reg('_'.join(['', self.name, 'write_cur_global_addr']), self.addrwidth, initval=0) cur_size = self.m.Reg('_'.join(['', self.name, 'write_cur_size']), self.addrwidth + 1, initval=0) rest_size = self.m.Reg('_'.join(['', self.name, 'write_rest_size']), self.addrwidth + 1, initval=0) max_burstlen = 2 ** self.burst_size_width # state 0 if not self.use_global_base_addr: gaddr = self.write_global_addr else: gaddr = self.write_global_addr + self.global_base_addr fsm.If(self.write_start)( cur_global_addr(self.mask_addr(gaddr)), rest_size(self.write_size) ) fsm.If(self.write_start).goto_next() # state 1 check_state = fsm.current self._check_4KB_boundary(fsm, max_burstlen, cur_global_addr, cur_size, rest_size) # state 2 ack, counter = self.write_request_counter(cur_global_addr, cur_size, cond=fsm) self.write_data_counter = counter fsm.If(ack).goto_next() # state 3 cond = fsm.here data, last, _id, user, dest, done = self.in_streamout.read_dataflow(cond=cond) done_out = self.write_dataflow(data, counter, cond=cond) self.write_data_done.assign(done_out) fsm.If(self.write_data_done)( cur_global_addr.add(optimize(cur_size * (self.datawidth // 8))) ) fsm.If(self.write_data_done, rest_size > 0).goto(check_state) fsm.If(self.write_data_done, rest_size == 0).goto_next() # state 4 set_idle = self._set_flag(fsm) self.seq.If(set_idle)( self.write_idle(1) ) fsm.goto_init()
def _synthesize_read_fsm_fifo_narrow(self, fifo, fifo_datawidth): """ axi.datawidth < fifo.datawidth """ if fifo_datawidth % self.datawidth != 0: raise ValueError( 'fifo_datawidth must be multiple number of axi.datawidth') pack_size = fifo_datawidth // self.datawidth dma_size = (self.read_size << int(math.log(pack_size, 2)) if math.log(pack_size, 2) % 1.0 == 0.0 else self.read_size * pack_size) op_id = self._get_read_op_id_fifo(fifo) if op_id in self.read_ops: """ already synthesized op """ return if pack_size in self.read_narrow_fsms: """ new op """ self.read_ops.append(op_id) fsm = self.read_narrow_fsms[pack_size] pack_count = self.read_narrow_pack_counts[pack_size] data = self.read_narrow_data_wires[pack_size] valid = self.read_narrow_valid_wires[pack_size] rest_size = self.read_narrow_rest_size_wires[pack_size] # state 0 fsm.set_index(0) cond = vtypes.Ands(self.read_start, self.read_op_sel == op_id) fsm.If(cond).goto_next() # state 1 fsm.set_index(1) wdata = self.m.Reg('_'.join(['', self.name, 'read_narrow', str(pack_size), 'wdata']), fifo_datawidth, initval=0) wvalid = self.m.Reg('_'.join(['', self.name, 'read_narrow', str(pack_size), 'wvalid'])) valid_cond = vtypes.Ands(valid, self.read_op_sel == op_id) ack, _ = fifo.enq_rtl(wdata, cond=wvalid) fsm.Delay(1)( wvalid(0) ) fsm.If(rest_size == 0, pack_count > 0)( wdata(vtypes.Cat(data, wdata[self.datawidth:fifo_datawidth])), wvalid(0), pack_count.inc() ) fsm.If(valid_cond)( wdata(vtypes.Cat(data, wdata[self.datawidth:fifo_datawidth])), wvalid(0), pack_count.inc() ) fsm.If(rest_size == 0, pack_count == pack_size - 1)( wdata(vtypes.Cat(data, wdata[self.datawidth:fifo_datawidth])), wvalid(1), pack_count(0) ) fsm.If(valid_cond, pack_count == pack_size - 1)( wdata(vtypes.Cat(data, wdata[self.datawidth:fifo_datawidth])), wvalid(1), pack_count(0) ) fsm.If(valid_cond)( rest_size.dec() ) return """ new op and fsm """ fsm = FSM(self.m, '_'.join(['', self.name, 'read_narrow', str(pack_size), 'fsm']), self.clk, self.rst, as_module=self.fsm_as_module) self.read_narrow_fsms[pack_size] = fsm self.read_ops.append(op_id) rest_size = self.m.Reg('_'.join(['', self.name, 'read_narrow', str(pack_size), 'rest_size']), self.addrwidth + 1, initval=0) self.read_narrow_rest_size_wires[pack_size] = rest_size # state 0 cond = vtypes.Ands(self.read_start, self.read_op_sel == op_id) fsm.If(self.read_start)( rest_size(dma_size) ) fsm.If(cond).goto_next() # state 1 pack_count = self.m.Reg('_'.join(['', self.name, 'read_narrow', str(pack_size), 'pack_count']), int(math.ceil(math.log(pack_size, 2))), initval=0) self.read_narrow_pack_counts[pack_size] = pack_count ready = vtypes.Not(fifo.almost_full) read_cond = vtypes.Ands(fsm.here, ready) data, last, _id, user, dest, valid = self.read_data(cond=read_cond) self.read_narrow_data_wires[pack_size] = data self.read_narrow_valid_wires[pack_size] = valid wdata = self.m.Reg('_'.join(['', self.name, 'read_narrow', str(pack_size), 'wdata']), fifo_datawidth, initval=0) wvalid = self.m.Reg('_'.join(['', self.name, 'read_narrow', str(pack_size), 'wvalid'])) valid_cond = vtypes.Ands(valid, self.read_op_sel == op_id) ack, _ = fifo.enq_rtl(wdata, cond=wvalid) fsm.Delay(1)( wvalid(0) ) fsm.If(rest_size == 0, pack_count > 0)( wdata(vtypes.Cat(data, wdata[self.datawidth:fifo_datawidth])), wvalid(0), pack_count.inc() ) fsm.If(valid_cond)( wdata(vtypes.Cat(data, wdata[self.datawidth:fifo_datawidth])), wvalid(0), pack_count.inc() ) fsm.If(rest_size == 0, pack_count == pack_size - 1)( wdata(vtypes.Cat(data, wdata[self.datawidth:fifo_datawidth])), wvalid(1), pack_count(0) ) fsm.If(valid_cond, pack_count == pack_size - 1)( wdata(vtypes.Cat(data, wdata[self.datawidth:fifo_datawidth])), wvalid(1), pack_count(0) ) fsm.If(valid_cond)( rest_size.dec() ) fsm.If(wvalid, rest_size == 0).goto_next() # state 2 set_idle = self._set_flag(fsm) self.seq.If(set_idle)( self.read_idle(1) ) fsm.goto_init()
def _synthesize_read_fsm_same(self, ram, port, ram_method, ram_datawidth): op_id = self._get_read_op_id(ram, port, ram_method) port = vtypes.to_int(port) if op_id in self.read_ops: """ already synthesized op """ return if self.read_fsm is not None: """ new op """ self.read_ops.append(op_id) fsm = self.read_fsm data = self.read_data_wire valid = self.read_valid_wire rest_size = self.read_rest_size # state 0 fsm.set_index(0) wdata, wvalid, w = self._get_op_write_dataflow(ram_datawidth) cond = vtypes.Ands(self.read_start, self.read_op_sel == op_id) ram_method(port, self.read_local_addr, w, self.read_size, stride=self.read_local_stride, cond=cond) fsm.If(cond).goto_next() # state 1 fsm.set_index(1) valid_cond = vtypes.Ands(valid, self.read_op_sel == op_id) fsm.Delay(1)( wvalid(0) ) fsm.If(valid_cond)( wdata(data), wvalid(1) ) fsm.If(valid_cond)( rest_size.dec() ) return """ new op and fsm """ fsm = FSM(self.m, '_'.join(['', self.name, 'read_fsm']), self.clk, self.rst, as_module=self.fsm_as_module) self.read_fsm = fsm self.read_ops.append(op_id) rest_size = self.m.Reg('_'.join(['', self.name, 'read_rest_size']), self.addrwidth + 1, initval=0) self.read_rest_size = rest_size # state 0 wdata, wvalid, w = self._get_op_write_dataflow(ram_datawidth) cond = vtypes.Ands(self.read_start, self.read_op_sel == op_id) ram_method(port, self.read_local_addr, w, self.read_size, stride=self.read_local_stride, cond=cond) fsm.If(self.read_start)( rest_size(self.read_size) ) fsm.If(cond).goto_next() # state 1 data, last, _id, user, dest, valid = self.read_data(cond=fsm) self.read_data_wire = data self.read_valid_wire = valid valid_cond = vtypes.Ands(valid, self.read_op_sel == op_id) fsm.Delay(1)( wvalid(0) ) fsm.If(valid_cond)( wdata(data), wvalid(1), ) fsm.If(valid_cond)( rest_size.dec() ) fsm.If(valid, rest_size <= 1).goto_next() for _ in range(self.num_data_delay): fsm.goto_next() # state 2 set_idle = self._set_flag(fsm) self.seq.If(set_idle)( self.read_idle(1) ) fsm.goto_init()
def _synthesize_read_fsm(self): op_id = 1 if op_id in self.read_ops: """ already synthesized op """ return if self.read_fsm is not None: """ new op """ self.read_ops.append(op_id) return """ new op and fsm """ fsm = FSM(self.m, '_'.join(['', self.name, 'read_fsm']), self.clk, self.rst, as_module=self.fsm_as_module) self.read_fsm = fsm self.read_ops.append(op_id) cur_global_addr = self.m.Reg('_'.join(['', self.name, 'read_cur_global_addr']), self.addrwidth, initval=0) cur_size = self.m.Reg('_'.join(['', self.name, 'read_cur_size']), self.addrwidth + 1, initval=0) rest_size = self.m.Reg('_'.join(['', self.name, 'read_rest_size']), self.addrwidth + 1, initval=0) max_burstlen = 2 ** self.burst_size_width # state 0 if not self.use_global_base_addr: gaddr = self.read_global_addr else: gaddr = self.read_global_addr + self.global_base_addr fsm.If(self.read_start)( cur_global_addr(self.mask_addr(gaddr)), rest_size(self.read_size) ) fsm.If(self.read_start).goto_next() # state 1 check_state = fsm.current self._check_4KB_boundary(fsm, max_burstlen, cur_global_addr, cur_size, rest_size) # state 2 ack = self.read_request(cur_global_addr, cur_size, cond=fsm) fsm.If(ack).goto_next() accept = vtypes.Ands(self.raddr.arvalid, self.raddr.arready) fsm.If(accept)( cur_global_addr.add(optimize(cur_size * (self.datawidth // 8))) ) fsm.If(accept, rest_size > 0).goto(check_state) fsm.If(accept, rest_size == 0).goto_next() for _ in range(self.num_data_delay): fsm.goto_next() # state 3 set_idle = self._set_flag(fsm) self.seq.If(set_idle)( self.read_idle(1) ) fsm.goto_init()
def _synthesize_set_source_pattern(self, var, name): if var.source_pat_fsm is not None: return wdata = var.source_ram_rdata wenable = var.source_ram_rvalid var.write(wdata, wenable) source_start = vtypes.Ands(self.start, var.source_mode == 1) for source_pat_size in var.source_pat_sizes: source_start = vtypes.Ands(source_start, source_pat_size > 0) self.seq.If(source_start)( var.source_idle(0) ) for source_pat_offset in var.source_pat_offsets: self.seq.If(source_start)( source_pat_offset(0) ) for (source_pat_size, source_pat_count) in zip( var.source_pat_sizes, var.source_pat_counts): self.seq.If(source_start)( source_pat_count(source_pat_size - 1) ) fsm_id = self.fsm_id_count self.fsm_id_count += 1 prefix = self._prefix(name) fsm_name = '_%s_source_pat_fsm_%d' % (prefix, fsm_id) var.source_pat_fsm = FSM(self.module, fsm_name, self.clock, self.reset, as_module=self.fsm_as_module) var.source_pat_fsm.If(source_start).goto_next() source_all_offset = self.module.Wire('_%s_source_pat_all_offset' % prefix, self.addrwidth) source_all_offset_val = var.source_offset for source_pat_offset in var.source_pat_offsets: source_all_offset_val += source_pat_offset source_all_offset.assign(source_all_offset_val) self.seq.If(var.source_pat_fsm.here)( var.source_ram_raddr(source_all_offset), var.source_ram_renable(1) ) upcond = None for (source_pat_offset, source_pat_size, source_pat_stride, source_pat_count) in zip( var.source_pat_offsets, var.source_pat_sizes, var.source_pat_strides, var.source_pat_counts): self.seq.If(var.source_pat_fsm.here, upcond)( source_pat_offset.add(source_pat_stride), source_pat_count.dec() ) reset_cond = source_pat_count == 0 self.seq.If(var.source_pat_fsm.here, upcond, reset_cond)( source_pat_offset(0), source_pat_count(source_pat_size - 1) ) upcond = make_condition(upcond, reset_cond) fin_cond = upcond var.source_pat_fsm.If(fin_cond).goto_next() self.seq.If(var.source_pat_fsm.here)( var.source_ram_renable(0), var.source_idle(1) ) var.source_pat_fsm.goto_init()
def set_sink_pattern(self, fsm, name, ram, offset, pattern, port=0): """ intrinsic method to assign RAM property to a sink stream """ if not self.stream_synthesized: self._implement_stream() if isinstance(name, str): var = self.var_name_map[name] elif isinstance(name, vtypes.Str): name = name.value var = self.var_name_map[name] elif isinstance(name, int): var = self.var_id_map[name] elif isinstance(name, vtypes.Int): name = name.value var = self.var_id_map[name] else: raise TypeError('Unsupported index name') if name not in self.sinks: raise NameError("No such stream '%s'" % name) if not isinstance(pattern, (tuple, list)): raise TypeError('pattern must be list or tuple.') if not pattern: raise ValueError( 'pattern must have one (size, stride) pair at least.') if not isinstance(pattern[0], (tuple, list)): pattern = (pattern,) prefix = self._prefix(name) fsm_id = self.fsm_id_count fsm_name = '_%s_fsm_%d' % (prefix, fsm_id) sink_fsm = FSM(self.module, fsm_name, self.clock, self.reset) self.fsm_id_map[fsm_id] = sink_fsm self.fsm_id_count += 1 sink_offset = self.module.Reg('_%s_offset_%d' % (prefix, fsm_id), ram.addrwidth, initval=0) sink_pat_offsets = [self.module.Reg('_%s_pat_offset_%d_%d' % (prefix, fsm_id, i), ram.addrwidth, initval=0) for i, _ in enumerate(pattern)] sink_pat_sizes = [self.module.Reg('_%s_pat_size_%d_%d' % (prefix, fsm_id, i), ram.addrwidth + 1, initval=0) for i, _ in enumerate(pattern)] sink_pat_strides = [self.module.Reg('_%s_pat_stride_%d_%d' % (prefix, fsm_id, i), ram.addrwidth, initval=0) for i, _ in enumerate(pattern)] sink_pat_counts = [self.module.Reg('_%s_pat_count_%d_%d' % (prefix, fsm_id, i), ram.addrwidth + 1, initval=0) for i, _ in enumerate(pattern)] var_id = self.var_name_id_map[name] fsm_sel = self.var_id_fsm_sel_map[var_id] set_cond = (fsm.state == fsm.current) sink_fsm.If(set_cond)( sink_offset(offset) ) self.seq.If(set_cond)( fsm_sel(fsm_id) ) for sink_pat_offset in sink_pat_offsets: sink_fsm.If(set_cond)( sink_pat_offset(0) ) for (sink_pat_size, sink_pat_stride, (size, stride)) in zip( sink_pat_sizes, sink_pat_strides, pattern): sink_fsm.If(set_cond)( sink_pat_size(size), sink_pat_stride(stride) ) sink_start = vtypes.Ands(self.start, fsm_sel == fsm_id) for sink_pat_size in sink_pat_sizes: sink_start = vtypes.Ands(sink_start, sink_pat_size > 0) for (sink_pat_size, sink_pat_count) in zip( sink_pat_sizes, sink_pat_counts): sink_fsm.If(sink_start)( sink_pat_count(sink_pat_size - 1) ) sink_fsm.If(sink_start).goto_next() num_wdelay = self._write_delay() for i in range(num_wdelay): sink_fsm.goto_next() sink_all_offset = self.module.Wire('_%s_all_offset_%d' % (prefix, fsm_id), ram.addrwidth) sink_all_offset_val = sink_offset for sink_pat_offset in sink_pat_offsets: sink_all_offset_val += sink_pat_offset sink_all_offset.assign(sink_all_offset_val) waddr = self.module.Reg('_%s_waddr_%d' % (prefix, fsm_id), ram.addrwidth, initval=0) wenable = self.module.Reg('_%s_wenable_%d' % (prefix, fsm_id), initval=0) wdata = self.module.Reg('_%s_wdata_%d' % (prefix, fsm_id), ram.datawidth, initval=0, signed=True) rdata = var.read() ram.write_rtl(waddr, wdata, port=port, cond=wenable) if name in self.sink_when_map: when = self.sink_when_map[name] wcond = when.read() else: wcond = None sink_fsm.If(wcond)( waddr(sink_all_offset), wdata(rdata), wenable(1) ) sink_fsm.Delay(1)( wenable(0) ) upcond = None for (sink_pat_offset, sink_pat_size, sink_pat_stride, sink_pat_count) in zip( sink_pat_offsets, sink_pat_sizes, sink_pat_strides, sink_pat_counts): sink_fsm.If(upcond)( sink_pat_offset.add(sink_pat_stride), sink_pat_count.dec() ) reset_cond = sink_pat_count == 0 sink_fsm.If(upcond, reset_cond)( sink_pat_offset(0), sink_pat_count(sink_pat_size - 1) ) upcond = make_condition(upcond, reset_cond) fin_cond = upcond sink_fsm.If(fin_cond).goto_init() sink_fsm._set_index(0) fsm.goto_next()
def _synthesize_read_fsm_narrow(self, ram, port, ram_method, ram_datawidth): """ axi.datawidth < ram.datawidth """ if ram_datawidth % self.datawidth != 0: raise ValueError( 'ram_datawidth must be multiple number of axi.datawidth') pack_size = ram_datawidth // self.datawidth dma_size = (self.read_size << int(math.log(pack_size, 2)) if math.log(pack_size, 2) % 1.0 == 0.0 else self.read_size * pack_size) op_id = self._get_read_op_id(ram, port, ram_method) port = vtypes.to_int(port) if op_id in self.read_ops: """ already synthesized op """ return if pack_size in self.read_narrow_fsms: """ new op """ self.read_ops.append(op_id) fsm = self.read_narrow_fsms[pack_size] pack_count = self.read_narrow_pack_counts[pack_size] data = self.read_narrow_data_wires[pack_size] valid = self.read_narrow_valid_wires[pack_size] rest_size = self.read_narrow_rest_size_wires[pack_size] # state 0 fsm.set_index(0) wdata, wvalid, w = self._get_op_write_dataflow(ram_datawidth) cond = vtypes.Ands(self.read_start, self.read_op_sel == op_id) ram_method(port, self.read_local_addr, w, self.read_size, stride=self.read_local_stride, cond=cond) fsm.If(cond).goto_next() # state 1 fsm.set_index(1) valid_cond = vtypes.Ands(valid, self.read_op_sel == op_id) fsm.Delay(1)( wvalid(0) ) fsm.If(rest_size == 0, pack_count > 0)( wdata(vtypes.Cat(data, wdata[self.datawidth:ram_datawidth])), wvalid(0), pack_count.inc() ) fsm.If(valid_cond)( wdata(vtypes.Cat(data, wdata[self.datawidth:ram_datawidth])), wvalid(0), pack_count.inc() ) fsm.If(rest_size == 0, pack_count == pack_size - 1)( wdata(vtypes.Cat(data, wdata[self.datawidth:ram_datawidth])), wvalid(1), pack_count(0) ) fsm.If(valid_cond, pack_count == pack_size - 1)( wdata(vtypes.Cat(data, wdata[self.datawidth:ram_datawidth])), wvalid(1), pack_count(0) ) fsm.If(valid_cond)( rest_size.dec() ) return """ new op and fsm """ fsm = FSM(self.m, '_'.join(['', self.name, 'read_narrow', str(pack_size), 'fsm']), self.clk, self.rst, as_module=self.fsm_as_module) self.read_narrow_fsms[pack_size] = fsm self.read_ops.append(op_id) rest_size = self.m.Reg('_'.join(['', self.name, 'read_narrow', str(pack_size), 'rest_size']), self.addrwidth + 1, initval=0) self.read_narrow_rest_size_wires[pack_size] = rest_size # state 0 wdata, wvalid, w = self._get_op_write_dataflow(ram_datawidth) cond = vtypes.Ands(self.read_start, self.read_op_sel == op_id) ram_method(port, self.read_local_addr, w, self.read_size, stride=self.read_local_stride, cond=cond) fsm.If(self.read_start)( rest_size(dma_size) ) fsm.If(cond).goto_next() # state 1 pack_count = self.m.Reg('_'.join(['', self.name, 'read_narrow', str(pack_size), 'pack_count']), int(math.ceil(math.log(pack_size, 2))), initval=0) self.read_narrow_pack_counts[pack_size] = pack_count data, last, _id, user, dest, valid = self.read_data(cond=fsm) self.read_narrow_data_wires[pack_size] = data self.read_narrow_valid_wires[pack_size] = valid valid_cond = vtypes.Ands(valid, self.read_op_sel == op_id) fsm.Delay(1)( wvalid(0) ) fsm.If(rest_size == 0, pack_count > 0)( wdata(vtypes.Cat(data, wdata[self.datawidth:ram_datawidth])), wvalid(0), pack_count.inc() ) fsm.If(valid_cond)( wdata(vtypes.Cat(data, wdata[self.datawidth:ram_datawidth])), wvalid(0), pack_count.inc() ) fsm.If(rest_size == 0, pack_count == pack_size - 1)( wdata(vtypes.Cat(data, wdata[self.datawidth:ram_datawidth])), wvalid(1), pack_count(0) ) fsm.If(valid_cond, pack_count == pack_size - 1)( wdata(vtypes.Cat(data, wdata[self.datawidth:ram_datawidth])), wvalid(1), pack_count(0) ) fsm.If(valid_cond)( rest_size.dec() ) fsm.If(wvalid, rest_size == 0).goto_next() for _ in range(self.num_data_delay): fsm.goto_next() # state 2 set_idle = self._set_flag(fsm) self.seq.If(set_idle)( self.read_idle(1) ) fsm.goto_init()
def _synthesize_set_sink_pattern(self, var, name): if var.sink_pat_fsm is not None: return sink_start = vtypes.Ands(self.start, var.sink_mode == 1) for sink_pat_size in var.sink_pat_sizes: sink_start = vtypes.Ands(sink_start, sink_pat_size > 0) fsm_id = self.fsm_id_count self.fsm_id_count += 1 prefix = self._prefix(name) fsm_name = '_%s_sink_pat_fsm_%d' % (prefix, fsm_id) var.sink_pat_fsm = FSM(self.module, fsm_name, self.clock, self.reset, as_module=self.fsm_as_module) self.seq.If(var.sink_pat_fsm.here)( var.sink_ram_wenable(0) ) var.sink_pat_fsm.If(sink_start).goto_next() self.seq.If(var.sink_pat_fsm.here)( var.sink_ram_waddr(var.sink_offset - var.sink_stride) ) for sink_pat_offset in var.sink_pat_offsets: self.seq.If(var.sink_pat_fsm.here)( sink_pat_offset(0) ) for (sink_pat_size, sink_pat_count) in zip( var.sink_pat_sizes, var.sink_pat_counts): self.seq.If(var.sink_pat_fsm.here)( sink_pat_count(sink_pat_size - 1) ) num_wdelay = self._write_delay() for _ in range(num_wdelay): var.sink_pat_fsm.goto_next() if name in self.sink_when_map: when = self.sink_when_map[name] wcond = when.read() else: wcond = None sink_all_offset = self.module.Wire('_%s_sink_pat_all_offset' % prefix, self.addrwidth) sink_all_offset_val = var.sink_offset for sink_pat_offset in var.sink_pat_offsets: sink_all_offset_val += sink_pat_offset sink_all_offset.assign(sink_all_offset_val) if name in self.sink_when_map: when = self.sink_when_map[name] wcond = when.read() else: wcond = None rdata = var.read() self.seq.If(var.sink_pat_fsm.here)( var.sink_ram_wenable(0) ) self.seq.If(var.sink_pat_fsm.here, wcond)( var.sink_ram_waddr(sink_all_offset), var.sink_ram_wdata(rdata), var.sink_ram_wenable(1) ) upcond = None for (sink_pat_offset, sink_pat_size, sink_pat_stride, sink_pat_count) in zip( var.sink_pat_offsets, var.sink_pat_sizes, var.sink_pat_strides, var.sink_pat_counts): self.seq.If(var.sink_pat_fsm.here, upcond)( sink_pat_offset.add(sink_pat_stride), sink_pat_count.dec() ) reset_cond = sink_pat_count == 0 self.seq.If(var.sink_pat_fsm.here, upcond, reset_cond)( sink_pat_offset(0), sink_pat_count(sink_pat_size - 1) ) upcond = make_condition(upcond, reset_cond) fin_cond = upcond var.sink_pat_fsm.If(fin_cond).goto_init()
def set_source(self, fsm, name, ram, offset, size, stride=1, port=0): """ intrinsic method to assign RAM property to a source stream """ if not self.stream_synthesized: self._implement_stream() if isinstance(name, str): var = self.var_name_map[name] elif isinstance(name, vtypes.Str): name = name.value var = self.var_name_map[name] elif isinstance(name, int): var = self.var_id_map[name] elif isinstance(name, vtypes.Int): name = name.value var = self.var_id_map[name] else: raise TypeError('Unsupported index name') if name not in self.sources: raise NameError("No such stream '%s'" % name) prefix = self._prefix(name) fsm_id = self.fsm_id_count fsm_name = '_%s_fsm_%d' % (prefix, fsm_id) source_fsm = FSM(self.module, fsm_name, self.clock, self.reset) self.fsm_id_map[fsm_id] = source_fsm self.fsm_id_count += 1 source_idle = self.source_idle_map[name] source_offset = self.module.Reg('_%s_offset_%d' % (prefix, fsm_id), ram.addrwidth, initval=0) source_size = self.module.Reg('_%s_size_%d' % (prefix, fsm_id), ram.addrwidth + 1, initval=0) source_stride = self.module.Reg('_%s_stride_%d' % (prefix, fsm_id), ram.addrwidth, initval=0) source_count = self.module.Reg('_%s_count_%d' % (prefix, fsm_id), ram.addrwidth + 1, initval=0) var_id = self.var_name_id_map[name] fsm_sel = self.var_id_fsm_sel_map[var_id] set_cond = (fsm.state == fsm.current) source_fsm.If(set_cond)( source_offset(offset), source_size(size), source_stride(stride) ) self.seq.If(set_cond)( fsm_sel(fsm_id) ) self.seq.If(self.start)( source_idle(0) ) source_start = vtypes.Ands( self.start, fsm_sel == fsm_id, source_size > 0) source_fsm.If(source_start)( source_count(source_size) ) source_fsm.If(source_start).goto_next() raddr = self.module.Reg('_%s_raddr_%d' % (prefix, fsm_id), ram.addrwidth, initval=0) renable = self.module.Reg('_%s_renable_%d' % (prefix, fsm_id), initval=0) rdata, rvalid = ram.read_rtl(raddr, port=port, cond=renable) wdata = rdata wenable = rvalid var.write(wdata, wenable) source_fsm( raddr(source_offset), renable(1), source_count.dec() ) source_fsm.Delay(1)( renable(0) ) self.seq.If(source_fsm.state == source_fsm.current, source_count == 1)( source_idle(1) ) source_fsm.If(source_count == 1).goto_init() source_fsm.If(source_count > 1).goto_next() source_fsm( raddr.add(source_stride), renable(1), source_count.dec() ) source_fsm.Delay(1)( renable(0) ) source_fsm.If(source_count == 1).goto_init() self.seq.If(source_fsm.state == source_fsm.current, source_count == 1)( source_idle(1) ) source_fsm._set_index(0) fsm.goto_next()
def _synthesize_read_fsm_fifo_wide(self, fifo, fifo_datawidth): """ axi.datawidth > fifo.datawidth """ if self.datawidth % fifo_datawidth != 0: raise ValueError( 'axi.datawidth must be multiple number of fifo_datawidth') pack_size = self.datawidth // fifo_datawidth shamt = int(math.log(pack_size, 2)) res = vtypes.Mux( vtypes.And(self.read_size, 2 ** shamt - 1) > 0, 1, 0) dma_size = (self.read_size >> shamt) + res actual_read_size = dma_size << shamt op_id = self._get_read_op_id_fifo(fifo) if op_id in self.read_ops: """ already synthesized op """ return if pack_size in self.read_wide_fsms: """ new op """ self.read_ops.append(op_id) fsm = self.read_wide_fsms[pack_size] pack_count = self.read_wide_pack_counts[pack_size] data = self.read_wide_data_wires[pack_size] valid = self.read_wide_valid_wires[pack_size] rest_size = self.read_wide_rest_size_wires[pack_size] # state 0 fsm.set_index(0) cond = vtypes.Ands(self.read_start, self.read_op_sel == op_id) fsm.If(cond).goto_next() # state 1 fsm.set_index(1) valid_cond = vtypes.Ands(valid, self.read_op_sel == op_id) stay_cond = self.read_op_sel == op_id fsm.Delay(1)( wvalid(0) ) fsm.If(pack_count == 0, valid_cond)( wdata(data), wvalid(1), pack_count.inc() ) fsm.If(pack_count > 0, stay_cond)( wdata(wdata >> fifo_datawidth), wvalid(1), pack_count.inc() ) fsm.If(valid_cond)( rest_size.dec() ) return """ new op and fsm """ fsm = FSM(self.m, '_'.join(['', self.name, 'read_wide', str(pack_size), 'fsm']), self.clk, self.rst, as_module=self.fsm_as_module) self.read_wide_fsms[pack_size] = fsm self.read_ops.append(op_id) rest_size = self.m.Reg('_'.join(['', self.name, 'read_wide', str(pack_size), 'rest_size']), self.addrwidth + 1, initval=0) self.read_wide_rest_size_wires[pack_size] = rest_size # state 0 cond = vtypes.Ands(self.read_start, self.read_op_sel == op_id) fsm.If(self.read_start)( rest_size(dma_size) ) fsm.If(cond).goto_next() # state 1 pack_count = self.m.Reg('_'.join(['', self.name, 'read_wide', str(pack_size), 'pack_count']), int(math.ceil(math.log(pack_size, 2))), initval=0) self.read_wide_pack_counts[pack_size] = pack_count ready = vtypes.Not(fifo.almost_full) read_cond = vtypes.Ands(fsm.here, ready) cond = vtypes.Ands(fsm.here, pack_count == 0, read_cond) data, last, _id, user, dest, valid = self.read_data(cond=cond) self.read_wide_data_wires[pack_size] = data self.read_wide_valid_wires[pack_size] = valid wdata = self.m.Reg('_'.join(['', self.name, 'read_wide', str(pack_size), 'wdata']), self.datawidth, initval=0) wvalid = self.m.Reg('_'.join(['', self.name, 'read_wide', str(pack_size), 'wvalid'])) valid_cond = vtypes.Ands(valid, self.read_op_sel == op_id) stay_cond = self.read_op_sel == op_id ack, _ = fifo.enq_rtl(wdata, cond=wvalid) wlast = self.m.Reg('_'.join(['', self.name, 'read_wide', str(pack_size), 'wlast']), initval=0) fsm.Delay(1)( wvalid(0) ) fsm.If(pack_count == 0, valid_cond)( wdata(data), wvalid(1), wlast(last), pack_count.inc() ) fsm.If(pack_count > 0, stay_cond)( wdata(wdata >> fifo_datawidth), wvalid(1), pack_count.inc() ) fsm.If(pack_count == pack_size - 1)( pack_count(0) ) fsm.If(pack_count == 0, valid_cond)( rest_size.dec() ) fsm.If(pack_count == pack_size - 1, rest_size == 0).goto_next() # state 2 set_idle = self._set_flag(fsm) self.seq.If(set_idle)( self.read_idle(1) ) fsm.goto_init()
def set_sink(self, fsm, name, ram, offset, size, stride=1, port=0): """ intrinsic method to assign RAM property to a sink stream """ if not self.stream_synthesized: self._implement_stream() if isinstance(name, str): var = self.var_name_map[name] elif isinstance(name, vtypes.Str): name = name.value var = self.var_name_map[name] elif isinstance(name, int): var = self.var_id_map[name] elif isinstance(name, vtypes.Int): name = name.value var = self.var_id_map[name] else: raise TypeError('Unsupported index name') if name not in self.sinks: raise NameError("No such stream '%s'" % name) prefix = self._prefix(name) fsm_id = self.fsm_id_count fsm_name = '_%s_fsm_%d' % (prefix, fsm_id) sink_fsm = FSM(self.module, fsm_name, self.clock, self.reset) self.fsm_id_map[fsm_id] = sink_fsm self.fsm_id_count += 1 sink_offset = self.module.Reg('_%s_offset_%d' % (prefix, fsm_id), ram.addrwidth, initval=0) sink_size = self.module.Reg('_%s_size_%d' % (prefix, fsm_id), ram.addrwidth + 1, initval=0) sink_stride = self.module.Reg('_%s_stride_%d' % (prefix, fsm_id), ram.addrwidth, initval=0) sink_count = self.module.Reg('_%s_count_%d' % (prefix, fsm_id), ram.addrwidth + 1, initval=0) var_id = self.var_name_id_map[name] fsm_sel = self.var_id_fsm_sel_map[var_id] set_cond = (fsm.state == fsm.current) sink_fsm.If(set_cond)( sink_offset(offset), sink_size(size), sink_stride(stride) ) self.seq.If(set_cond)( fsm_sel(fsm_id) ) sink_start = vtypes.Ands( self.start, fsm_sel == fsm_id, sink_size > 0) sink_fsm.If(sink_start)( sink_count(sink_size) ) sink_fsm.If(sink_start).goto_next() num_wdelay = self._write_delay() for i in range(num_wdelay): sink_fsm.goto_next() waddr = self.module.Reg('_%s_waddr_%d' % (prefix, fsm_id), ram.addrwidth, initval=0) wenable = self.module.Reg('_%s_wenable_%d' % (prefix, fsm_id), initval=0) wdata = self.module.Reg('_%s_wdata_%d' % (prefix, fsm_id), ram.datawidth, initval=0, signed=True) rdata = var.read() ram.write_rtl(waddr, wdata, port=port, cond=wenable) if name in self.sink_when_map: when = self.sink_when_map[name] wcond = when.read() else: wcond = None sink_fsm.If(wcond)( waddr(sink_offset), wdata(rdata), wenable(1), sink_count.dec() ) sink_fsm.Delay(1)( wenable(0) ) sink_fsm.If(wcond, sink_count == 1).goto_init() sink_fsm.If(wcond, sink_count > 1).goto_next() sink_fsm.If(wcond)( waddr.add(sink_stride), wdata(rdata), wenable(1), sink_count.dec() ) sink_fsm.Delay(1)( wenable(0) ) sink_fsm.If(wcond, sink_count == 1).goto_init() sink_fsm._set_index(0) fsm.goto_next()