def try_lock(self, fsm): name = fsm.name new_lock_id = self._get_id(name) if new_lock_id > 2**self.width - 1: raise ValueError('too many lock IDs') # try try_state = fsm.current state_cond = fsm.state == fsm.current try_cond = vtypes.Not(self.lock_reg) self.seq.If(state_cond, try_cond)(self.lock_reg(1), self.lock_id(new_lock_id)) fsm.goto_next() # verify cond = vtypes.And(self.lock_reg, self.lock_id == new_lock_id) result = self.m.TmpReg(initval=0) fsm(result(cond)) fsm.goto_next() return result
def dma_read_async(self, fsm, ram, local_addr, global_addr, size, local_stride=1, port=0, ram_method=None): if ram_method is None: ram_method = getattr(ram, 'write_dataflow') ram_method_name = (ram_method.func.__name__ if isinstance(ram_method, functools.partial) else ram_method.__name__) ram_datawidth = (ram.datawidth if ram_method is None else ram.orig_datawidth if 'bcast' in ram_method_name else ram.orig_datawidth if 'block' in ram_method_name else ram.datawidth) if ram_datawidth == self.datawidth: dma_size = size elif ram_datawidth > self.datawidth: pack_size = ram_datawidth // self.datawidth dma_size = (size << int(math.log(pack_size, 2)) if math.log(pack_size, 2) % 1.0 == 0.0 else size * pack_size) else: pack_size = self.datawidth // ram_datawidth shamt = int(math.log(pack_size, 2)) res = vtypes.Mux( vtypes.And(size, 2 ** shamt - 1) > 0, 1, 0) dma_size = (size >> shamt) + res AXIM_for_AXIStreamIn.dma_read_async(self, fsm, global_addr, dma_size) self.streamin.write_ram_async(fsm, ram, local_addr, size, local_stride, port, ram_method)
def visit_Slice(self, node): val = self.visit(node.var) if val is None: return None if isinstance(val.right, vtypes._Variable): right = vtypes.Slice(val.right, node.msb, node.lsb) else: right = vtypes.And(vtypes.Srl(val.right, node.lsb), vtypes.Repeat(vtypes.Int(1, width=1), node.msb - node.lsb + 1)) return vtypes.Subst(vtypes.Slice(val.left, node.msb, node.lsb), right)
def fixed_to_int_low(value, point): if point < 0: return 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 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 = vtypes.And(vtypes.Srl( val_right, node.pos), vtypes.Int(1, width=1)) else: right = vtypes.Pointer(val.right, node.pos) return vtypes.Subst(left, right)
def visit_And(self, node): left = self.visit(node.left) right = self.visit(node.right) return vtypes.And(left, right)
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_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()