def runTest(self): globals.init_openram("config_{0}".format(OPTS.tech_name)) # checking hierarchical precode 2x4 for single port debug.info(1, "Testing sample for hierarchy_predecode2x4") a = factory.create(module_type="hierarchical_predecode2x4") self.local_check(a) # checking hierarchical precode 2x4 for multi-port OPTS.bitcell = "pbitcell" OPTS.num_rw_ports = 1 OPTS.num_w_ports = 0 OPTS.num_r_ports = 0 debug.info( 1, "Testing sample for hierarchy_predecode2x4 (multi-port case)") a = factory.create(module_type="hierarchical_predecode2x4") self.local_check(a) globals.end_openram()
def runTest(self): config_file = "{}/tests/configs/config".format( os.getenv("OPENRAM_HOME")) globals.init_openram(config_file) # check wordline driver for single port debug.info(2, "Checking driver") tx = factory.create(module_type="wordline_driver") self.local_check(tx) globals.end_openram()
def add_modules(self): self.inv_list = [] add_well = self.add_wells for size in self.size_list: temp_inv = factory.create(module_type="pinv", size=size, height=self.height, add_wells=add_well) add_well=False self.inv_list.append(temp_inv) self.add_mod(temp_inv)
def runTest(self): globals.init_openram("config_{0}".format(OPTS.tech_name)) # check wordline driver for single port debug.info(2, "Checking driver") tx = factory.create(module_type="wordline_driver", rows=8, cols=32) self.local_check(tx) # check wordline driver for multi-port OPTS.bitcell = "pbitcell" OPTS.num_rw_ports = 1 OPTS.num_w_ports = 0 OPTS.num_r_ports = 0 factory.reset() debug.info(2, "Checking driver (multi-port case)") tx = factory.create(module_type="wordline_driver", rows=8, cols=64) self.local_check(tx) globals.end_openram()
def __init__(self, corner): # This must match the spice model order self.dff = factory.create(module_type=OPTS.dff) self.period = tech.spice["feasible_period"] debug.info( 2, "Feasible period from technology file: {0} ".format(self.period)) self.set_corner(corner)
def runTest(self): config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME")) globals.init_openram(config_file) # check precharge array in multi-port OPTS.num_rw_ports = 1 OPTS.num_r_ports = 1 OPTS.num_w_ports = 0 globals.setup_bitcell() debug.info(2, "Checking precharge for 1rw1r port 0") tx = factory.create(module_type="precharge", size=1, bitcell_bl="bl0", bitcell_br="br0") self.local_check(tx) factory.reset() debug.info(2, "Checking precharge for 1rw1r port 1") tx = factory.create(module_type="precharge", size=1, bitcell_bl="bl1", bitcell_br="br1") self.local_check(tx) globals.end_openram()
def runTest(self): config_file = "{}/tests/configs/config".format( os.getenv("OPENRAM_HOME")) globals.init_openram(config_file) # check precharge in single port debug.info(2, "Checking precharge for handmade bitcell") tx = factory.create(module_type="precharge", size=1) self.local_check(tx) globals.end_openram()
def runTest(self): config_file = "{}/tests/configs/config".format( os.getenv("OPENRAM_HOME")) globals.init_openram(config_file) # check single level column mux in single port debug.info(2, "Checking column mux") tx = factory.create(module_type="single_level_column_mux", tx_size=8) self.local_check(tx) globals.end_openram()
def runTest(self): config_file = "{}/tests/configs/config".format( os.getenv("OPENRAM_HOME")) globals.init_openram(config_file) # Use the 2 port cell since it is usually bigger/easier OPTS.num_rw_ports = 1 OPTS.num_r_ports = 1 OPTS.num_w_ports = 0 globals.setup_bitcell() debug.info(1, "Port address 16 rows") a = factory.create("port_address", cols=16, rows=16, port=0) self.local_check(a) debug.info(1, "Port address 256 rows") a = factory.create("port_address", cols=256, rows=256, port=1) self.local_check(a) globals.end_openram()
def runTest(self): config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME")) globals.init_openram(config_file) # check write driver array for multi-port OPTS.bitcell = "pbitcell" OPTS.num_rw_ports = 1 OPTS.num_w_ports = 0 OPTS.num_r_ports = 0 factory.reset() debug.info(2, "Testing write_driver_array for columns=8, word_size=8 (multi-port case)") a = factory.create(module_type="write_driver_array", columns=8, word_size=8) self.local_check(a) debug.info(2, "Testing write_driver_array for columns=16, word_size=8 (multi-port case)") a = factory.create(module_type="write_driver_array", columns=16, word_size=8) self.local_check(a) globals.end_openram()
def setup_layout_constants(self): """ Pre-compute some handy layout parameters. """ # Compute the overlap of the source and drain pins self.ptx_offset = self.pmos_left.get_pin( "D").center() - self.pmos_left.get_pin("S").center() # This is the extra space needed to ensure DRC rules # to the active contacts nmos = factory.create(module_type="ptx", tx_type="nmos") extra_contact_space = max(-nmos.get_pin("D").by(), 0)
def runTest(self): config_file = "{}/tests/configs/config".format( os.getenv("OPENRAM_HOME")) globals.init_openram(config_file) OPTS.num_rw_ports = 1 OPTS.num_r_ports = 1 OPTS.num_w_ports = 0 globals.setup_bitcell() debug.info(2, "Testing one left replica column for dual port") a = factory.create(module_type="replica_column", rows=4, rbl=[1, 0], replica_bit=1) self.local_check(a) debug.info(2, "Testing one right replica column for dual port") a = factory.create(module_type="replica_column", rows=4, rbl=[0, 1], replica_bit=5) self.local_check(a) debug.info(2, "Testing two (left, right) replica columns for dual port") a = factory.create(module_type="replica_column", rows=4, rbl=[1, 1], replica_bit=1) self.local_check(a) debug.info(2, "Testing two (left, right) replica columns for dual port") a = factory.create(module_type="replica_column", rows=4, rbl=[1, 1], replica_bit=6) self.local_check(a) globals.end_openram()
def runTest(self): config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME")) globals.init_openram(config_file) from sram_config import sram_config c = sram_config(word_size=4, num_words=16) c.words_per_row=1 factory.reset() c.recompute_sizes() debug.info(1, "No column mux") a = factory.create("port_data", sram_config=c, port=0) self.local_check(a) c.num_words=32 c.words_per_row=2 factory.reset() c.recompute_sizes() debug.info(1, "Two way column mux") a = factory.create("port_data", sram_config=c, port=0) self.local_check(a) c.num_words=64 c.words_per_row=4 factory.reset() c.recompute_sizes() debug.info(1, "Four way column mux") a = factory.create("port_data", sram_config=c, port=0) self.local_check(a) c.word_size=2 c.num_words=128 c.words_per_row=8 factory.reset() c.recompute_sizes() debug.info(1, "Eight way column mux") a = factory.create("port_data", sram_config=c, port=0) self.local_check(a) globals.end_openram()
def runTest(self): config_file = "{}/tests/configs/config".format( os.getenv("OPENRAM_HOME")) globals.init_openram(config_file) OPTS.num_rw_ports = 1 OPTS.num_r_ports = 1 OPTS.num_w_ports = 0 globals.setup_bitcell() debug.info( 2, "Testing write_mask_and_array for columns=8, word_size=8, write_size=4" ) a = factory.create(module_type="write_mask_and_array", columns=8, word_size=8, write_size=4) self.local_check(a) debug.info( 2, "Testing write_mask_and_array for columns=16, word_size=16, write_size=4" ) a = factory.create(module_type="write_mask_and_array", columns=16, word_size=16, write_size=4) self.local_check(a) debug.info( 2, "Testing write_mask_and_array for columns=16, word_size=8, write_size=2" ) a = factory.create(module_type="write_mask_and_array", columns=16, word_size=8, write_size=2) self.local_check(a) globals.end_openram()
def runTest(self): config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME")) globals.init_openram(config_file) # check single level column mux in multi-port OPTS.bitcell = "pbitcell" OPTS.num_rw_ports = 1 OPTS.num_r_ports = 1 OPTS.num_w_ports = 1 factory.reset() debug.info(2, "Checking column mux for pbitcell (innermost connections)") tx = factory.create(module_type="single_level_column_mux", tx_size=8, bitcell_bl="bl0", bitcell_br="br0") self.local_check(tx) factory.reset() debug.info(2, "Checking column mux for pbitcell (outermost connections)") tx = factory.create(module_type="single_level_column_mux",tx_size=8, bitcell_bl="bl2", bitcell_br="br2") self.local_check(tx) globals.end_openram()
def add_ptx(self): """ Create the PMOS and NMOS transistors. """ self.nmos = factory.create(module_type="ptx", width=self.nmos_width, mults=self.tx_mults, tx_type="nmos", add_source_contact=self.route_layer, add_drain_contact=self.route_layer, connect_poly=True, connect_drain_active=True) self.add_mod(self.nmos) self.pmos = factory.create(module_type="ptx", width=self.pmos_width, mults=self.tx_mults, tx_type="pmos", add_source_contact=self.route_layer, add_drain_contact=self.route_layer, connect_poly=True, connect_drain_active=True) self.add_mod(self.pmos)
def runTest(self): globals.init_openram("config_{0}".format(OPTS.tech_name)) import tech debug.info(2, "Checking min size PMOS with 1 finger") fet = factory.create(module_type="ptx", width=tech.drc["minwidth_tx"], mults=1, tx_type="pmos") self.local_drc_check(fet) globals.end_openram()
def create_netlist(self): """ Create and connect the netlist """ # This will create a default set of bitline/wordline names self.cell = factory.create(module_type=OPTS.bitcell) if not self.cell.end_caps: self.create_all_wordline_names() self.create_all_bitline_names() self.add_modules() self.add_pins() self.create_instances()
def runTest(self): globals.init_openram("config_{0}".format(OPTS.tech_name)) debug.info(2, "Testing 4x4 array for cell_1rw_1r") OPTS.bitcell = "bitcell_1rw_1r" OPTS.num_rw_ports = 1 OPTS.num_r_ports = 1 OPTS.num_w_ports = 0 a = factory.create(module_type="bitcell_array", cols=4, rows=4) self.local_check(a) globals.end_openram()
def add_layout_pins(self): self.nand2 = factory.create(module_type="pnand2") supply_pin = self.nand2.get_pin("vdd") # Create the enable pin that connects all write mask AND array's B pins beg_en_pin = self.and2_insts[0].get_pin("B") end_en_pin = self.and2_insts[self.num_wmasks - 1].get_pin("B") if self.port % 2: # Extend metal3 to edge of AND array in multiport en_to_edge = self.and2.width - beg_en_pin.cx() self.add_layout_pin(text="en", layer="metal3", offset=beg_en_pin.bc(), width=end_en_pin.cx() - beg_en_pin.cx() + en_to_edge) self.add_via_center(layers=("metal1", "via1", "metal2"), offset=vector(end_en_pin.cx() + en_to_edge, end_en_pin.cy())) self.add_via_center(layers=("metal2", "via2", "metal3"), offset=vector(end_en_pin.cx() + en_to_edge, end_en_pin.cy())) else: self.add_layout_pin(text="en", layer="metal3", offset=beg_en_pin.bc(), width=end_en_pin.cx() - beg_en_pin.cx()) for i in range(self.num_wmasks): # Copy remaining layout pins self.copy_layout_pin(self.and2_insts[i], "A", "wmask_in_{0}".format(i)) self.copy_layout_pin(self.and2_insts[i], "Z", "wmask_out_{0}".format(i)) # Add via connections to metal3 for AND array's B pin en_pin = self.and2_insts[i].get_pin("B") self.add_via_center(layers=("metal1", "via1", "metal2"), offset=en_pin.center()) self.add_via_center(layers=("metal2", "via2", "metal3"), offset=en_pin.center()) self.add_power_pin( "gnd", vector(supply_pin.width() + i * self.wmask_en_len, 0)) self.add_power_pin( "vdd", vector(supply_pin.width() + i * self.wmask_en_len, self.height)) # Route power and ground rails together if i < self.num_wmasks - 1: for n in ["gnd", "vdd"]: pin = self.and2_insts[i].get_pin(n) next_pin = self.and2_insts[i + 1].get_pin(n) self.add_path("metal1", [pin.center(), next_pin.center()])
def add_ptx(self): """ Initializes the upper and lower pmos """ if (OPTS.tech_name == "sky130"): (self.ptx_width, self.ptx_mults) = pgate.bin_width("pmos", self.ptx_width) self.pmos = factory.create(module_type="ptx", width=self.ptx_width, mults=self.ptx_mults, tx_type="pmos") self.add_mod(self.pmos)
def create_column_decoder(self): """ Create a 2:4 or 3:8 column address decoder. """ # Height is a multiple of DFF so that it can be staggered # and rows do not align with the control logic module self.dff = factory.create(module_type="dff") if self.col_addr_size == 0: return elif self.col_addr_size == 1: self.column_decoder = factory.create(module_type="pinvbuf", height=self.dff.height) elif self.col_addr_size == 2: self.column_decoder = factory.create( module_type="hierarchical_predecode2x4", height=self.dff.height) elif self.col_addr_size == 3: self.column_decoder = factory.create( module_type="hierarchical_predecode3x8", height=self.dff.height) else: # No error checking before? debug.error("Invalid column decoder?", -1) self.add_mod(self.column_decoder) self.column_decoder_inst = [None] * len(self.all_ports) for port in self.all_ports: self.column_decoder_inst[port] = self.add_inst( name="col_address_decoder{}".format(port), mod=self.column_decoder) temp = [] for bit in range(self.col_addr_size): temp.append("addr{0}_{1}".format(port, bit)) for bit in range(self.num_col_addr_lines): temp.append("sel{0}_{1}".format(port, bit)) temp.extend(["vdd", "gnd"]) self.connect_inst(temp)
def runTest(self): globals.init_openram("config_{0}".format(OPTS.tech_name)) from sram_config import sram_config c = sram_config(word_size=4, num_words=16) c.words_per_row=1 factory.reset() c.recompute_sizes() debug.info(1, "No column mux") a = factory.create("bank", sram_config=c) self.local_check(a) c.num_words=32 c.words_per_row=2 factory.reset() c.recompute_sizes() debug.info(1, "Two way column mux") a = factory.create("bank", sram_config=c) self.local_check(a) c.num_words=64 c.words_per_row=4 factory.reset() c.recompute_sizes() debug.info(1, "Four way column mux") a = factory.create("bank", sram_config=c) self.local_check(a) c.word_size=2 c.num_words=128 c.words_per_row=8 factory.reset() c.recompute_sizes() debug.info(1, "Eight way column mux") a = factory.create("bank", sram_config=c) self.local_check(a) globals.end_openram()
def create_instances(self): """ Create the module instances used in this design """ if not cell_properties.compare_ports(cell_properties.bitcell_array.use_custom_cell_arrangement): self.supplies = ["vdd", "gnd"] # Used for names/dimensions only self.cell = factory.create(module_type="bitcell") # Main array self.bitcell_array_inst=self.add_inst(name="bitcell_array", mod=self.bitcell_array) self.connect_inst(self.all_bitline_names + self.all_wordline_names + self.supplies) # Replica columns self.replica_col_insts = [] for port in self.all_ports: if port in self.rbls: self.replica_col_insts.append(self.add_inst(name="replica_col_{}".format(port), mod=self.replica_columns[port])) self.connect_inst(self.rbl_bitline_names[port] + self.replica_array_wordline_names + self.supplies) else: self.replica_col_insts.append(None) # Dummy rows under the bitcell array (connected with with the replica cell wl) self.dummy_row_replica_insts = [] # Note, this is the number of left and right even if we aren't adding the columns to this bitcell array! for port in self.all_ports: self.dummy_row_replica_insts.append(self.add_inst(name="dummy_row_{}".format(port), mod=self.dummy_row)) self.connect_inst([x if x not in self.gnd_wordline_names else "gnd" for x in self.rbl_wordline_names[port]] + self.supplies) # Top/bottom dummy rows or col caps self.dummy_row_insts = [] self.dummy_row_insts.append(self.add_inst(name="dummy_row_bot", mod=self.col_cap)) self.connect_inst(["gnd"] * len(self.col_cap.get_wordline_names()) + self.supplies) self.dummy_row_insts.append(self.add_inst(name="dummy_row_top", mod=self.col_cap)) self.connect_inst(["gnd"] * len(self.col_cap.get_wordline_names()) + self.supplies) # Left/right Dummy columns self.dummy_col_insts = [] self.dummy_col_insts.append(self.add_inst(name="dummy_col_left", mod=self.row_cap_left)) self.connect_inst(self.replica_array_wordline_names + self.supplies) self.dummy_col_insts.append(self.add_inst(name="dummy_col_right", mod=self.row_cap_right)) self.connect_inst(self.replica_array_wordline_names + self.supplies) else: from tech import custom_replica_bitcell_array_arrangement custom_replica_bitcell_array_arrangement(self)
def create_instances(self): """ Create the module instances used in this design """ supplies = ["vdd", "gnd"] # Used for names/dimensions only self.cell = factory.create(module_type="bitcell") # Main array self.bitcell_array_inst = self.add_inst(name="bitcell_array", mod=self.bitcell_array) self.connect_inst(self.bitcell_array_bl_names + self.bitcell_array_wl_names + supplies) # Replica columns self.replica_col_inst = {} for port in range(self.left_rbl + self.right_rbl): self.replica_col_inst[port] = self.add_inst( name="replica_col_{}".format(port), mod=self.replica_columns[port]) self.connect_inst(self.replica_bl_names[port] + self.replica_col_wl_names + supplies) # Dummy rows under the bitcell array (connected with with the replica cell wl) self.dummy_row_replica_inst = {} for port in range(self.left_rbl + self.right_rbl): self.dummy_row_replica_inst[port] = self.add_inst( name="dummy_row_{}".format(port), mod=self.dummy_row) self.connect_inst(self.dummy_row_bl_names + self.replica_wl_names[port] + supplies) # Top/bottom dummy rows self.dummy_row_bot_inst = self.add_inst(name="dummy_row_bot", mod=self.dummy_row) self.connect_inst(self.dummy_row_bl_names + [x + "_bot" for x in self.dummy_cell_wl_names] + supplies) self.dummy_row_top_inst = self.add_inst(name="dummy_row_top", mod=self.dummy_row) self.connect_inst(self.dummy_row_bl_names + [x + "_top" for x in self.dummy_cell_wl_names] + supplies) # Left/right Dummy columns self.dummy_col_left_inst = self.add_inst(name="dummy_col_left", mod=self.dummy_col_left) self.connect_inst([x + "_left" for x in self.dummy_cell_bl_names] + self.dummy_col_wl_names + supplies) self.dummy_col_right_inst = self.add_inst(name="dummy_col_right", mod=self.dummy_col_right) self.connect_inst([x + "_right" for x in self.dummy_cell_bl_names] + self.dummy_col_wl_names + supplies)
def runTest(self): config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME")) globals.init_openram(config_file) import tech debug.info(2, "Checking min size NMOS with 1 finger") fet = factory.create(module_type="ptx", width=tech.drc["minwidth_tx"], mults=1, tx_type="nmos") self.local_drc_check(fet) globals.end_openram()
def add_modules(self): """ Add the modules for later usage """ self.replica_bitcell = factory.create(module_type="replica_bitcell") self.add_mod(self.replica_bitcell) # This is the replica bitline load column that is the height of our array self.rbl = factory.create(module_type="bitcell_array", cols=1, rows=self.bitcell_loads) self.add_mod(self.rbl) # FIXME: The FO and depth of this should be tuned self.delay_chain = factory.create(module_type="delay_chain", fanout_list=self.delay_fanout_list) self.add_mod(self.delay_chain) self.inv = factory.create(module_type="pinv") self.add_mod(self.inv) self.access_tx = factory.create(module_type="ptx", tx_type="pmos") self.add_mod(self.access_tx)
def runTest(self): config_file = "{}/tests/configs/config".format( os.getenv("OPENRAM_HOME")) globals.init_openram(config_file) # check wordline driver for single port debug.info(2, "Checking driver") tx = factory.create(module_type="wordline_driver", rows=8, cols=32) self.local_check(tx) # check wordline driver for multi-port OPTS.bitcell = "pbitcell" OPTS.num_rw_ports = 1 OPTS.num_w_ports = 0 OPTS.num_r_ports = 0 factory.reset() debug.info(2, "Checking driver (multi-port case)") tx = factory.create(module_type="wordline_driver", rows=8, cols=64) self.local_check(tx) globals.end_openram()
def add_modules(self): """ Add all the modules using the class loader """ # create arrays of bitline and bitline_bar names for read, write, or all ports self.bitcell = factory.create(module_type="bitcell") self.bl_names = self.bitcell.get_all_bl_names() self.br_names = self.bitcell.get_all_br_names() self.wl_names = self.bitcell.get_all_wl_names() self.bitline_names = self.bitcell.get_all_bitline_names() self.port_data = [] for port in self.all_ports: temp_pre = factory.create(module_type="port_data", sram_config=self.sram_config, port=port) self.port_data.append(temp_pre) self.add_mod(self.port_data[port]) self.port_address = factory.create(module_type="port_address", cols=self.num_cols + self.num_spare_cols, rows=self.num_rows) self.add_mod(self.port_address) self.port_rbl_map = self.all_ports self.num_rbl = len(self.all_ports) self.bitcell_array = factory.create( module_type="replica_bitcell_array", cols=self.num_cols + self.num_spare_cols, rows=self.num_rows, left_rbl=1, right_rbl=1 if len(self.all_ports) > 1 else 0, bitcell_ports=self.all_ports) self.add_mod(self.bitcell_array) if (self.num_banks > 1): self.bank_select = factory.create(module_type="bank_select") self.add_mod(self.bank_select)
def runTest(self): config_file = "{}/tests/configs/config".format( os.getenv("OPENRAM_HOME")) globals.init_openram(config_file) debug.info(1, "Testing sample for control_logic_rw") a = factory.create(module_type="control_logic", num_rows=128, words_per_row=1, word_size=32) self.local_check(a) globals.end_openram()