def test_ram(): main = m.DefineCircuit("main", "rdata", m.Out(m.Bit), "CLKIN", m.In(m.Clock)) ram = mantle.RAM(4, 1, name="ram") waddr = mantle.Counter(2, cout=False) wdata = mantle.Counter(1, cout=False) we = 1 raddr = mantle.Counter(2, cout=False) ram(raddr, waddr, wdata, we, CLK=main.CLKIN) m.wire(ram.RDATA[0], main.rdata) m.EndDefine() if m.mantle_target == "coreir": output = "coreir" suffix = "json" else: output = "verilog" suffix = "v" m.compile(f"build/test_common_ram_{m.mantle_target}", main, output) assert check_files_equal( __file__, f"build/test_common_ram_{m.mantle_target}.{suffix}", f"gold/test_common_ram_{m.mantle_target}.{suffix}")
def __init__(self, ARES_design_type, depth): #这个self.name 和self.io必须得有 #self.name = "ARES_FIFO_DESIGN" self.io = io = m.IO(ARES_design = ARES_design_type) #io += m.ClockIO() addr_width = m.bitutils.clog2(depth) print ("ARES addr width : " + str(addr_width) ) buffer = mantle.RAM(2**addr_width, io.ARES_design.WData.flat_length()) buffer.WDATA @= m.as_bits(io.ARES_design.WData) io.ARES_design.RData @= buffer.RDATA read_pointer = mantle.Register(addr_width + 1) write_pointer = mantle.Register(addr_width + 1) buffer.RADDR @= read_pointer.O[:addr_width] buffer.WADDR @= write_pointer.O[:addr_width] reset = io.ARES_design.RESET full = \ (read_pointer.O[:addr_width] == write_pointer.O[:addr_width]) \ & \ (read_pointer.O[addr_width] != write_pointer.O[addr_width]) empty = read_pointer.O == write_pointer.O write_valid = io.ARES_design.Write & ~full read_valid = io.ARES_design.Read & ~empty io.ARES_design.Full @= full buffer.WE @= write_valid write_p = mantle.mux([ write_pointer.O, m.uint(write_pointer.O) + 1 ], write_valid) write_pointer.I @= mantle.mux([ write_p, 0 ], reset) io.ARES_design.Empty @= empty read_p = mantle.mux([ read_pointer.O, m.uint(read_pointer.O) + 1 ], read_valid) read_pointer.I @= mantle.mux([ read_p, 0 ], reset)
def test_ram(): main = m.DefineCircuit("main", "rdata", m.Out(m.Bit), "CLKIN", m.In(m.Clock)) ram = mantle.RAM(4, 1) waddr = mantle.Counter(4) wdata = mantle.Counter(1) we = 1 raddr = mantle.FF()(mantle.Counter(4)) ram(raddr, waddr, wdata, we, CLK=main.CLKIN) m.wire(ram.RDATA, main.rdata) m.EndDefine() m.compile("build/test_common_ram", main)
class FIFO(m.Circuit): io = m.IO(ARES_design = ARES_design_type) #io += m.ClockIO() addr_width = m.bitutils.clog2(depth) buffer = mantle.RAM(2**addr_width, io.ARES_design.WData.flat_length()) buffer.WDATA @= m.as_bits(io.ARES_design.WData) io.ARES_design.RData @= buffer.RDATA read_pointer = mantle.Register(addr_width + 1) write_pointer = mantle.Register(addr_width + 1) buffer.RADDR @= read_pointer.O[:addr_width] buffer.WADDR @= write_pointer.O[:addr_width] reset = io.ARES_design.RESET full = \ (read_pointer.O[:addr_width] == write_pointer.O[:addr_width]) \ & \ (read_pointer.O[addr_width] != write_pointer.O[addr_width]) empty = read_pointer.O == write_pointer.O write_valid = io.ARES_design.Write & ~full read_valid = io.ARES_design.Read & ~empty io.ARES_design.Full @= full buffer.WE @= write_valid write_p = mantle.mux([ write_pointer.O, m.uint(write_pointer.O) + 1 ], write_valid) write_pointer.I @= mantle.mux([ write_p, 0 ], reset) io.ARES_design.Empty @= empty read_p = mantle.mux([ read_pointer.O, m.uint(read_pointer.O) + 1 ], read_valid) read_pointer.I @= mantle.mux([ read_p, 0 ], reset)
def definition(io): # save the weights to memory (ROM) weights_rom = ROMB(len(weights_list), 16, weights_list) wire(io.CYCLE, weights_rom.RADDR[:n]) wire(io.IDX, weights_rom.RADDR[n:n + b]) if n + b < 8: wire(bits(0, 8 - n - b), weights_rom.RADDR[n + b:]) wire(1, weights_rom.RE) wire(weights_rom.RDATA, io.WEIGHT) wire(io.CLK, weights_rom.RCLK) # save the image to RAM, 16 bits at a time image_ram = mantle.RAM(4, 16) wire(io.WE, image_ram.WE) wire(io.CLK, image_ram.CLK) wire(io.CYCLE, image_ram.RADDR) wire(io.WADDR, image_ram.WADDR) wire(io.DATA, image_ram.WDATA) wire(image_ram.RDATA, io.IMAGE)
def test_ram(): main = m.DefineCircuit("main", "rdata", m.Out(m.Bit), "CLKIN", m.In(m.Clock)) ram = mantle.RAM(4, 1) waddr = mantle.Counter(4, cout=False) wdata = mantle.Counter(1, cout=False) we = 1 raddr = mantle.Counter(4, cout=False) ram(raddr, waddr, wdata, we, CLK=main.CLKIN) m.wire(ram.RDATA[0], main.rdata) m.EndDefine() if m.mantle_target == "coreir": output = "coreir" else: output = "verilog" m.compile("build/test_common_ram", main, output)
def definition(io): addr_width = m.bitutils.clog2(depth) buffer = mantle.RAM(addr_width, flat_length(io.data_in.data)) # pack data into bits buffer.WDATA <= flatten_fields_to_bits(io.data_in.data) # unpack bits into tuple io.data_out.data <= unflatten_bits_to_fields( io.data_out.data, buffer.RDATA) read_pointer = mantle.Register(addr_width + 1) write_pointer = mantle.Register(addr_width + 1) buffer.RADDR <= read_pointer.O[:addr_width] buffer.WADDR <= write_pointer.O[:addr_width] full = \ (read_pointer.O[:addr_width] == write_pointer.O[:addr_width]) \ & \ (read_pointer.O[addr_width] != write_pointer.O[addr_width]) empty = read_pointer == write_pointer write_valid = io.data_in.valid & ~full read_valid = io.data_out.ready & ~empty io.data_in.ready <= ~full buffer.WE <= write_valid write_pointer.I <= mantle.mux( [write_pointer.O, m.uint(write_pointer.O) + 1], write_valid) io.data_out.valid <= read_valid read_pointer.I <= mantle.mux( [read_pointer.O, m.uint(read_pointer.O) + 1], read_valid)
class AXI(m.Circuit): interface = make_HandshakeData(data_type) io = m.IO(ARES_design=interface) addr_width = m.bitutils.clog2(depth) reset = io.ARES_design.RESET #data_buffer #=============================================================== buffer = mantle.RAM(2**addr_width, io.ARES_design.W_data.flat_length()) #WReq 操作 #=============================================================== WReq_size_reg = mantle.Register(32) WReq_addr_reg = mantle.Register(32) #不要改! 这个have_WReq_signal 代表我现在有一个WReq要处理 have_WReq_signal = ~(WReq_size_reg.O == 0) #不要改! 有WReq就不能再接新的了!所以WReq_ready要为0 io.ARES_design.WReq_ready @= mantle.mux([~have_WReq_signal, 1], reset) WReq_valid_signal = io.ARES_design.WReq_valid & ~have_WReq_signal receive_WReq_size_signal = mantle.mux( [m.uint(0, 32), io.ARES_design.WReq_size], WReq_valid_signal) receive_WReq_addr_signal = mantle.mux( [m.uint(0, 32), io.ARES_design.WReq_addr], WReq_valid_signal) #这个是真Write_valid 这个东西的意思就是,我用have_WReq_signal代表W_ready。假如W_valid为1,那就是握手完成 #本来应该放在Write 操作里的,我放在这里是要reduce WReq_size W_valid_signal = io.ARES_design.W_valid & have_WReq_signal reduce_WReq_size_signal = mantle.mux( [WReq_size_reg.O, m.uint(WReq_size_reg.O) - 1], W_valid_signal) #有WReq则处理size,没有则准备好从外面拿 WReq_size_signal = mantle.mux( [receive_WReq_size_signal, reduce_WReq_size_signal], have_WReq_signal) WReq_size_reg.I @= mantle.mux([WReq_size_signal, m.uint(0, 32)], reset) #有WReq则保留addr,没有则准备好从外面拿 WReq_addr_signal = mantle.mux( [receive_WReq_addr_signal, WReq_addr_reg.O], have_WReq_signal) WReq_addr_reg.I @= mantle.mux([WReq_addr_signal, m.uint(0, 32)], reset) #Write 操作 #=============================================================== #W_ready io.ARES_design.W_ready @= mantle.mux([have_WReq_signal, 0], reset) #W_size_reg W_size_reg = mantle.Register(32) W_size_reg_increase_signal = mantle.mux( [W_size_reg.O, m.uint(W_size_reg.O) + 1], W_valid_signal) W_size_signal = mantle.mux([m.uint(0, 32), W_size_reg_increase_signal], have_WReq_signal) W_size_reg.I @= mantle.mux([W_size_signal, 0], reset) #buffer buffer.WDATA @= io.ARES_design.W_data buffer.WADDR @= mantle.add(WReq_addr_reg.O[:addr_width], W_size_reg.O[:addr_width]) #have_WReq_signal 就是W_ready,这意味着W_valid和W_ready 同时为1 buffer.WE @= W_valid_signal #RReq 操作 #=============================================================== RReq_size_reg = mantle.Register(32) RReq_addr_reg = mantle.Register(32) #不要改! 这个have_RReq_signal 代表我现在有一个WReq要处理 have_RReq_signal = ~(RReq_size_reg.O == 0) #TODO 关于RReq,我现在的办法是从reset起我就能接受RReq,外面随便发读请求,但是读出什么来不好说,大不了就是X io.ARES_design.RReq_ready @= mantle.mux([~have_RReq_signal, 1], reset) RReq_valid_signal = io.ARES_design.RReq_valid & ~have_RReq_signal receive_RReq_size_signal = mantle.mux( [m.uint(0, 32), io.ARES_design.RReq_size], RReq_valid_signal) receive_RReq_addr_signal = mantle.mux( [m.uint(0, 32), io.ARES_design.RReq_addr], RReq_valid_signal) #这个是真.R_valid。这个东西的意思就是,我用have_RReq_signal代表R_valid。假如R_ready为1,那就是握手完成 #其实这个信号应该放在Read操作里,但是由于我要用R_valid_signal来让RReq_size减少,所以放在这弄 R_valid_signal = io.ARES_design.R_ready & have_RReq_signal #减少RReq_size reduce_RReq_size_signal = mantle.mux( [RReq_size_reg.O, m.uint(RReq_size_reg.O) - 1], R_valid_signal) #有RReq则处理size,没有则准备好从外面拿 RReq_size_signal = mantle.mux( [receive_RReq_size_signal, reduce_RReq_size_signal], have_RReq_signal) RReq_size_reg.I @= mantle.mux([RReq_size_signal, m.uint(0, 32)], reset) #有RReq则保留addr,没有则准备好从外面拿 RReq_addr_signal = mantle.mux( [receive_RReq_addr_signal, RReq_addr_reg.O], have_RReq_signal) RReq_addr_reg.I @= mantle.mux([RReq_addr_signal, m.uint(0, 32)], reset) #Read操作 #=============================================================== io.ARES_design.R_valid @= mantle.mux([have_RReq_signal, 0], reset) #R_size_reg R_size_reg = mantle.Register(32) R_size_reg_increase_signal = mantle.mux( [R_size_reg.O, m.uint(R_size_reg.O) + 1], R_valid_signal) R_size_signal = mantle.mux([m.uint(0, 32), R_size_reg_increase_signal], have_RReq_signal) R_size_reg.I @= mantle.mux([R_size_signal, 0], reset) buffer.RADDR @= mantle.add(RReq_addr_reg.O[:addr_width], R_size_reg.O[:addr_width]) io.ARES_design.R_data @= buffer.RDATA