def instantiate_single_port(self, banks_tall, banks_wide, macro_width, macro_depth): ''' Hook up the set of single port memories ''' self._sub_addr = self.var("addr_macro", self.addr_width_macro) self.wire(self._sub_addr, self._addr[self.addr_width_macro - 1, 0]) # Hook up the grid of SRAM banks for i in range(banks_tall): for j in range(banks_wide): self.add_child(f"sram_d{i}_w{j}", SRAMStub(macro_width, macro_depth)) self.wire(self[f"sram_d{i}_w{j}"].ports.i_clk, self._clk) self.wire(self[f"sram_d{i}_w{j}"].ports.i_rst_n, self._rst_n) self.wire(self[f"sram_d{i}_w{j}"].ports.i_addr, self._sub_addr) if (banks_tall > 1): self.wire( self[f"sram_d{i}_w{j}"].ports.i_wen, self._wen & (self._addr[self.full_addr - 1, self.addr_width_macro] == i)) self.wire(self[f"sram_d{i}_w{j}"].ports.i_cen, (self._ren | self._wen) & (self._addr[self.full_addr - 1, self.addr_width_macro] == i)) else: self.wire(self[f"sram_d{i}_w{j}"].ports.i_wen, self._wen) self.wire(self[f"sram_d{i}_w{j}"].ports.i_cen, (self._ren | self._wen)) # Send the data across horizontally based on j and the macro width self.wire( self[f"sram_d{i}_w{j}"].ports.i_data, self._wr_data[((j + 1) * macro_width) - 1, j * macro_width]) for i in range(banks_tall): if (banks_wide > 1): self.wire( self._memory_space[i], concat(*[ self[f"sram_d{i}_w{j}"].ports.o_data for j in range(banks_wide) ])) else: self.wire(self._memory_space, self[f"sram_d{i}_w{j}"].ports.o_data) if (banks_tall > 1): self.wire(self._rd_data, self._memory_space[self._bank_sel_reg]) else: self.wire(self._rd_data, self._memory_space) return 0
def build_two_port(self, banks_tall, banks_wide, macro_width, macro_depth): ''' Takes a single port memory and constructs a virtualized two port memory from a single port memory ''' # We need one extra bank to create 1R1W logical_banks = banks_tall + 1 # Create all logical banks as a bank array for i in range(logical_banks): for j in range(banks_wide): self.add_child(f"sram_d{i}_w{j}", SRAMStub(macro_width, macro_depth)) return 5
def __init__(self, macro_width, logical_banks, macro_depth): super().__init__("virtual_remap_table") self._virt_addr = self.input("i_virt_addr", width) self._ren = self.input("i_ren", 1) self._out = self.output("o_data_out", width) self._in = self.input("i_data_in", width) self._clk = self.clock("i_clk") self._rst_n = self.reset("i_rst_n") # First wrap sram_stub sram_stub = SRAMStub(width, 1024) self.add_child_generator(f"u_sram_stub_0", sram_stub) self.wire(sram_stub.i_data, self._in) self.wire(self._out, sram_stub.o_data) self.wire(sram_stub.i_addr, 0) self.wire(sram_stub.i_cen, 0) self.wire(sram_stub.i_wen, 0) self.wire(sram_stub.i_clk, self._clk) self.wire(sram_stub.i_rst_n, self._rst_n)
def __init__(self, use_sram_stub, sram_name, data_width, fw_int, mem_depth, mem_input_ports, mem_output_ports, address_width, bank_num, num_tiles): super().__init__(f"{sram_name}_generator") self.use_sram_stub = use_sram_stub self.sram_name = sram_name self.data_width = data_width self.fw_int = fw_int self.mem_depth = mem_depth self.mem_input_ports = mem_input_ports self.mem_output_ports = mem_output_ports self.address_width = address_width self.bank_num = bank_num self.num_tiles = num_tiles self.chain_idx_bits = max(1, clog2(num_tiles)) self._gclk = self.clock("clk") self._clk_en = self.input("clk_en", 1) if self.fw_int > 1: self._mem_data_in_bank = self.input("mem_data_in_bank", self.data_width, size=self.fw_int, packed=True, explicit_array=True) self._mem_data_out_bank = self.output("mem_data_out_bank", self.data_width, size=(self.mem_output_ports, self.fw_int), packed=True, explicit_array=True) if not self.use_sram_stub: # flattened version of input data self._sram_mem_data_in_bank = self.var( "sram_mem_data_in_bank", self.data_width * self.fw_int * self.mem_input_ports) # flattened version of output data self._sram_mem_data_out_bank = self.var( "sram_mem_data_out_bank", self.data_width * self.fw_int * self.mem_output_ports) else: self._mem_data_in_bank = self.input("mem_data_in_bank", self.data_width, packed=True) self._mem_data_out_bank = self.output("mem_data_out_bank", self.data_width, packed=True) self._mem_addr_in_bank = self.input("mem_addr_in_bank", self.address_width) if num_tiles == 1: self._mem_addr_to_sram = self.var("mem_addr_to_sram", self.address_width) else: self._mem_addr_to_sram = self.var( "mem_addr_to_sram", self.address_width - self.chain_idx_bits) self._mem_cen_in_bank = self.input("mem_cen_in_bank", self.mem_output_ports) self._mem_wen_in_bank = self.input("mem_wen_in_bank", self.mem_input_ports) self._wtsel = self.input("wtsel", 2) self._rtsel = self.input("rtsel", 2) if self.use_sram_stub: mbank = SRAMStub(data_width=self.data_width, width_mult=self.fw_int, depth=self.mem_depth) self.add_child(f"mem_{self.bank_num}", mbank, clk=self._gclk, data_in=self._mem_data_in_bank, addr=self._mem_addr_to_sram, cen=self._mem_cen_in_bank, wen=self._mem_wen_in_bank, data_out=self._mem_data_out_bank) # instantiante external provided sram macro and flatten input/output data # if fetch width is greater than 1 else: mbank = SRAMStubGenerator(sram_name=self.sram_name, data_width=self.data_width, width_mult=self.fw_int, depth=self.mem_depth) compose_wide = True if self.fw_int > 1: flatten_data_in = FlattenND(self.data_width, self.fw_int, self.mem_input_ports) self.add_child(f"flatten_data_in_{self.bank_num}", flatten_data_in, input_array=self._mem_data_in_bank, output_array=self._sram_mem_data_in_bank) if compose_wide: for j in range(2): mbank = SRAMStubGenerator(sram_name=self.sram_name, data_width=self.data_width, width_mult=self.fw_int // 2, depth=self.mem_depth) self.add_child( f"mem_inst_{self.bank_num}_pt_{j}", mbank, sram_addr=self._mem_addr_to_sram, sram_cen=~self._mem_cen_in_bank, sram_clk=self._gclk, sram_data_in=self._sram_mem_data_in_bank[j * 32 + 32 - 1, j * 32], sram_data_out=self._sram_mem_data_out_bank[j * 32 + 32 - 1, j * 32], sram_wen=~self._mem_wen_in_bank, sram_wtsel=self._wtsel, sram_rtsel=self._rtsel) else: self.add_child(f"mem_inst_{self.bank_num}", mbank, sram_addr=self._mem_addr_to_sram, sram_cen=~self._mem_cen_in_bank, sram_clk=self._gclk, sram_data_in=self._sram_mem_data_in_bank, sram_data_out=self._sram_mem_data_out_bank, sram_wen=~self._mem_wen_in_bank, sram_wtsel=self._wtsel, sram_rtsel=self._rtsel) flatten_data_out = ReverseFlatten(self.data_width, self.fw_int, self.mem_output_ports) self.add_child(f"flatten_data_out_{self.bank_num}", flatten_data_out, input_array=self._sram_mem_data_out_bank, output_array=self._mem_data_out_bank) else: self.add_child(f"mem_inst_{self.bank_num}", mbank, sram_addr=self._mem_addr_to_sram, sram_cen=~self._mem_cen_in_bank, sram_clk=self._gclk, sram_data_in=self._mem_data_in_bank, sram_data_out=self._mem_data_out_bank, sram_wen=~self._mem_wen_in_bank, sram_wtsel=self._wtsel, sram_rtsel=self._rtsel) self.add_code(self.set_mem_addr)
def __init__(self, data_width=16, fetch_width=1, mem_depth=512, config_width=16, input_addr_iterator_support=6, output_addr_iterator_support=6, input_sched_iterator_support=6, output_sched_iterator_support=6 ): super().__init__("lake_top_test") # generation parameters # inputs self._clk = self.clock("clk") self._rst_n = self.reset("rst_n") self._clk_en = self.input("clk_en", 1) self._flush = self.input("flush", 1) self._data_in = self.input("data_in", data_width, packed=True) # outputs self._data_out = self.output("data_out", data_width, packed=True) # local variables self._write = self.var("write", 1) self._read = self.var("read", 1) self._write_addr = self.var("write_addr", config_width) self._read_addr = self.var("read_addr", config_width) self._addr = self.var("addr", clog2(mem_depth)) # memory module self.add_child(f"sram", SRAMStub(data_width, fetch_width, mem_depth), clk=self._clk, wen=self._write, cen=self._write | self._read, addr=self._addr, data_in=self._data_in, data_out=self._data_out) # addressor modules self.add_child(f"input_addr_gen", AddrGen(input_addr_iterator_support, config_width), clk=self._clk, rst_n=self._rst_n, step=self._write, addr_out=self._write_addr, clk_en=self._clk_en, flush=self._flush) self.add_child(f"output_addr_gen", AddrGen(output_addr_iterator_support, config_width), clk=self._clk, rst_n=self._rst_n, step=self._read, addr_out=self._read_addr, clk_en=self._clk_en, flush=self._flush) # scheduler modules self.add_child(f"input_sched_gen", SchedGen(input_sched_iterator_support, config_width), clk=self._clk, rst_n=self._rst_n, clk_en=self._clk_en, flush=self._flush, valid_output=self._write) self.add_child(f"output_sched_gen", SchedGen(output_sched_iterator_support, config_width), clk=self._clk, rst_n=self._rst_n, clk_en=self._clk_en, flush=self._flush, valid_output=self._read) lift_config_reg(self.internal_generator) self.add_code(self.set_sram_addr)
def test_sram_basic(data_width, depth, width_mult, num_tiles=1): # Set up model... model_sram = SRAMModel(data_width=data_width, width_mult=width_mult, depth=depth, num_tiles=num_tiles) new_config = {} model_sram.set_config(new_config=new_config) ### # Set up dut... dut = SRAMStub(data_width=data_width, width_mult=width_mult, depth=depth) magma_dut = kts.util.to_magma(dut, flatten_array=True, check_flip_flop_always_ff=False) tester = fault.Tester(magma_dut, magma_dut.clk) ### for key, value in new_config.items(): setattr(tester.circuit, key, value) rand.seed(0) data = [0 for i in range(width_mult)] for z in range(1000): # Generate new input wen = rand.randint(0, 1) cen = rand.randint(0, 1) addr = rand.randint(0, depth - 1) for i in range(width_mult): data[i] = rand.randint(0, 2**data_width - 1) tester.circuit.wen = wen tester.circuit.cen = cen tester.circuit.addr = addr if width_mult == 1: tester.circuit.data_in = data[0] else: for i in range(width_mult): setattr(tester.circuit, f"data_in_{i}", data[i]) model_dat_out = model_sram.interact(wen, cen, addr, data) tester.eval() if width_mult == 1: tester.circuit.data_out.expect(model_dat_out[0]) else: for i in range(width_mult): getattr(tester.circuit, f"data_out_{i}").expect(model_dat_out[i]) tester.step(2) with tempfile.TemporaryDirectory() as tempdir: tester.compile_and_run(target="verilator", directory=tempdir, magma_output="verilog", flags=["-Wno-fatal"])
def __init__(self, data_width=16, fetch_width=4, mem_depth=512, config_width=9, input_addr_iterator_support=6, output_addr_iterator_support=6, input_sched_iterator_support=6, output_sched_iterator_support=6): super().__init__("lake_top_test") # generation parameters # inputs self._clk = self.clock("clk") self._rst_n = self.reset("rst_n") self._clk_en = self.input("clk_en", 1) self._flush = self.input("flush", 1) self._data_in = self.input("data_in", data_width, packed=True) # outputs self._data_out = self.output("data_out", data_width, packed=True) # local variables self._write = self.var("write", 1) self._read = self.var("read", 1) self._write_addr = self.var("write_addr", config_width) self._read_addr = self.var("read_addr", config_width) self._addr = self.var("addr", clog2(mem_depth)) self._agg_write = self.var("agg_write", 1) self._agg_write_addr = self.var("agg_write_addr", 2) self._agg_read_addr = self.var("agg_read_addr", 2) self._tb_read = self.var("tb_read", 1) self._tb_write_addr = self.var("tb_write_addr", 2) self._tb_read_addr = self.var("tb_read_addr", 2) self._sram_write_data = self.var("sram_write_data", data_width, size=fetch_width, packed=True) self._sram_read_data = self.var("sram_read_data", data_width, size=fetch_width, packed=True) # self._aggw_start_addr = self.input("aggw_start_addr", 2) # self._aggw_start_addr.add_attribute(ConfigRegAttr("agg write start addr")) # self._agg_start_addr = self.input("agg_start_addr", 2) # self._agg_start_addr.add_attribute(ConfigRegAttr("agg read start addr")) self._agg_write_index = self.var("agg_write_index", 2, size=4) self._agg = self.var("agg", width=data_width, size=fetch_width, packed=True) self.add_child(f"agg_write_addr_gen", AddrGen(2, 2), clk=self._clk, rst_n=self._rst_n, step=self._agg_write, addr_out=self._agg_write_addr, clk_en=self._clk_en, flush=self._flush) self.add_child(f"agg_read_addr_gen", AddrGen(2, 2), clk=self._clk, rst_n=self._rst_n, step=self._write, addr_out=self._agg_read_addr, clk_en=self._clk_en, flush=self._flush) self.add_child(f"agg_write_sched_gen", SchedGen(2, 2), clk=self._clk, rst_n=self._rst_n, clk_en=self._clk_en, flush=self._flush, valid_output=self._agg_write) self._tb = self.var("tb", width=data_width, size=fetch_width) self.add_child(f"tb_write_addr_gen", AddrGen(2, 2), clk=self._clk, rst_n=self._rst_n, step=self._read, addr_out=self._tb_write_addr, clk_en=self._clk_en, flush=self._flush) self.add_child(f"tb_read_addr_gen", AddrGen(2, 2), clk=self._clk, rst_n=self._rst_n, step=self._tb_read, addr_out=self._tb_read_addr, clk_en=self._clk_en, flush=self._flush) self.add_child(f"tb_read_sched_gen", SchedGen(2, 2), clk=self._clk, rst_n=self._rst_n, clk_en=self._clk_en, flush=self._flush, valid_output=self._tb_read) # memory module self.add_child(f"sram", SRAMStub(data_width, fetch_width, mem_depth), clk=self._clk, wen=self._write, cen=self._write | self._read, addr=self._addr, data_in=self._sram_write_data, data_out=self._sram_read_data) # addressor modules self.add_child(f"input_addr_gen", AddrGen(input_addr_iterator_support, config_width), clk=self._clk, rst_n=self._rst_n, step=self._write, addr_out=self._write_addr, clk_en=self._clk_en, flush=self._flush) self.add_child(f"output_addr_gen", AddrGen(output_addr_iterator_support, config_width), clk=self._clk, rst_n=self._rst_n, step=self._read, addr_out=self._read_addr, clk_en=self._clk_en, flush=self._flush) # scheduler modules self.add_child(f"input_sched_gen", SchedGen(input_sched_iterator_support, config_width), clk=self._clk, rst_n=self._rst_n, clk_en=self._clk_en, flush=self._flush, valid_output=self._write) self.add_child(f"output_sched_gen", SchedGen(output_sched_iterator_support, config_width), clk=self._clk, rst_n=self._rst_n, clk_en=self._clk_en, flush=self._flush, valid_output=self._read) lift_config_reg(self.internal_generator) self.add_code(self.set_sram_addr) self.add_code(self.agg_ctrl) self.add_code(self.tb_ctrl) self.add_code(self.agg_to_sram) self.add_code(self.tb_to_out)