def _get_read_op_id(self, ram, port, ram_method): ram_id = ram._id() port = vtypes.to_int(port) ram_method_name = (ram_method.func.__name__ if isinstance(ram_method, functools.partial) else ram_method.__name__) op = (ram_id, port, ram_method_name) if op in self.read_op_id_map: op_id = self.read_op_id_map[op] else: op_id = self.read_op_id_count self.read_op_id_count += 1 self.read_op_id_map[op] = op_id return op_id
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) #set_cond = fsm.here set_cond = self._set_flag(fsm) self.seq.If(set_cond)( var.sink_mode(0), var.sink_offset(offset), var.sink_size(size), var.sink_stride(stride) ) port = vtypes.to_int(port) self._setup_sink_ram(ram, var, port, set_cond) self._synthesize_set_sink(var, name) fsm.goto_next()
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,) pattern = tuple(pattern) if len(pattern) > self.max_pattern_length: raise ValueError( "'pattern' length exceeds maximum pattern length.") self._make_sink_pattern_vars(var, name) #set_cond = fsm.here set_cond = self._set_flag(fsm) self.seq.If(set_cond)( var.sink_mode(1), var.sink_offset(offset) ) pad = tuple([(1, 0) for _ in range(self.max_pattern_length - len(pattern))]) for (sink_pat_size, sink_pat_stride, (size, stride)) in zip(var.sink_pat_sizes, var.sink_pat_strides, pattern + pad): self.seq.If(set_cond)( sink_pat_size(size), sink_pat_stride(stride) ) port = vtypes.to_int(port) self._setup_sink_ram(ram, var, port, set_cond) self._synthesize_set_sink_pattern(var, name) fsm.goto_next()
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_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_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 _set_read_request(self, ram, port, ram_method, start, local_addr, size, local_stride): op_id = self._get_read_op_id(ram, port, ram_method) if op_id in self.read_reqs: (read_start, read_op_sel, read_local_addr_in, read_size_in, read_local_stride_in) = self.read_reqs[op_id] self.seq.If(start)( read_start(1), read_op_sel(op_id), read_local_addr_in(local_addr), read_size_in(size), read_local_stride_in(local_stride) ) return port = str(vtypes.to_int(port)) read_start = self.m.Reg( '_'.join(['', self.name, ram.name, port, 'read_start']), initval=0) read_op_sel = self.m.Reg( '_'.join(['', self.name, ram.name, port, 'read_op_sel']), self.op_sel_width, initval=0) read_local_addr = self.m.Reg( '_'.join(['', self.name, ram.name, port, 'read_local_addr']), self.addrwidth, initval=0) read_size = self.m.Reg( '_'.join(['', self.name, ram.name, port, 'read_size']), self.addrwidth + 1, initval=0) read_local_stride = self.m.Reg( '_'.join(['', self.name, ram.name, port, 'read_local_stride']), self.addrwidth, initval=0) self.seq( read_start(0) ) self.seq.If(start)( read_start(1), read_op_sel(op_id), read_local_addr(local_addr), read_size(size), read_local_stride(local_stride) ) self.read_reqs[op_id] = (read_start, read_op_sel, read_local_addr, read_size, read_local_stride) if self.num_cmd_delay > 0: read_start = self.seq.Prev(read_start, self.num_cmd_delay) read_op_sel = self.seq.Prev(read_op_sel, self.num_cmd_delay) read_local_addr = self.seq.Prev( read_local_addr, self.num_cmd_delay) read_size = self.seq.Prev(read_size, self.num_cmd_delay) read_local_stride = self.seq.Prev( read_local_stride, self.num_cmd_delay) self.seq.If(read_start)( self.read_idle(0) ) self.seq.If(read_start)( self.read_start(1), self.read_op_sel(read_op_sel), self.read_local_addr(read_local_addr), self.read_size(read_size), self.read_local_stride(read_local_stride) )