diff --git a/.gitignore b/.gitignore index 948e7d19..3d6e4f92 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,5 @@ *.toc *.synctex.gz **/model_data +outputs +technology/freepdk45/ncsu_basekit diff --git a/compiler/base/geometry.py b/compiler/base/geometry.py index 5d7f8d76..cfcfa73a 100644 --- a/compiler/base/geometry.py +++ b/compiler/base/geometry.py @@ -296,11 +296,11 @@ class path(geometry): def __str__(self): """ override print function output """ - return "path: layer=" + self.layerNumber + " w=" + self.width + return "path: layer=" + self.layerNumber + " purpose=" + str(self.layerPurpose) + " w=" + self.width def __repr__(self): """ override print function output """ - return "( path: layer=" + self.layerNumber + " w=" + self.width + " coords=" + str(self.coordinates) + " )" + return "( path: layer=" + self.layerNumber + " purpose=" + str(self.layerPurpose) + " w=" + self.width + " coords=" + str(self.coordinates) + " )" class label(geometry): @@ -340,11 +340,11 @@ class label(geometry): def __str__(self): """ override print function output """ - return "label: " + self.text + " layer=" + str(self.layerNumber) + return "label: " + self.text + " layer=" + str(self.layerNumber) + " purpose=" + str(self.layerPurpose) def __repr__(self): """ override print function output """ - return "( label: " + self.text + " @" + str(self.offset) + " layer=" + str(self.layerNumber) + " )" + return "( label: " + self.text + " @" + str(self.offset) + " layer=" + str(self.layerNumber) + " purpose=" + str(self.layerPurpose) + " )" class rectangle(geometry): @@ -391,4 +391,4 @@ class rectangle(geometry): def __repr__(self): """ override print function output """ - return "( rect: @" + str(self.offset) + " WxH=" + str(self.width) + "x" + str(self.height) + " layer=" + str(self.layerNumber) + " )" + return "( rect: @" + str(self.offset) + " WxH=" + str(self.width) + "x" + str(self.height) + " layer=" + str(self.layerNumber) + " purpose=" + str(self.layerPurpose) + " )" diff --git a/compiler/base/hierarchy_layout.py b/compiler/base/hierarchy_layout.py index 14136c9c..e6f9ac9f 100644 --- a/compiler/base/hierarchy_layout.py +++ b/compiler/base/hierarchy_layout.py @@ -975,6 +975,7 @@ class layout(): def create_channel_route(self, netlist, offset, layer_stack, + layer_dirs=None, vertical=False): """ The net list is a list of the nets. Each net is a list of pins @@ -1013,25 +1014,38 @@ class layout(): def vcg_pin_overlap(pin1, pin2, vertical, pitch): """ Check for vertical or horizontal overlap of the two pins """ + # FIXME: If the pins are not in a row, this may break. # However, a top pin shouldn't overlap another top pin, # for example, so the # extra comparison *shouldn't* matter. # Pin 1 must be in the "BOTTOM" set - x_overlap = pin1.by() < pin2.by() and abs(pin1.center().x-pin2.center().x)L transition on the next read self.add_read("R data 1 address {} to set dout caps".format(inverse_address), inverse_address, @@ -1208,6 +1222,10 @@ class delay(simulation): read_port) self.measure_cycles[read_port][sram_op.READ_ZERO] = len(self.cycle_times)-1 + self.add_noop_clock_one_port(read_port) + self.measure_cycles[read_port]["disabled_read0"] = len(self.cycle_times) - 1 + + self.add_noop_all_ports("Idle cycle (if read takes >1 cycle)") self.add_write("W data 1 address {} to write value".format(self.probe_address), @@ -1217,12 +1235,19 @@ class delay(simulation): write_port) self.measure_cycles[write_port][sram_op.WRITE_ONE] = len(self.cycle_times)-1 + self.add_noop_clock_one_port(write_port) + self.measure_cycles[write_port]["disabled_write1"] = len(self.cycle_times)-1 + self.add_write("W data 0 address {} to clear din caps".format(inverse_address), inverse_address, data_zeros, wmask_ones, write_port) + self.add_noop_clock_one_port(read_port) + self.measure_cycles[read_port]["disabled_read1"] = len(self.cycle_times) - 1 + + # This also ensures we will have a L->H transition on the next read self.add_read("R data 0 address {} to clear dout caps".format(inverse_address), inverse_address, diff --git a/compiler/characterizer/lib.py b/compiler/characterizer/lib.py index 1e68fc2e..e6befc2b 100644 --- a/compiler/characterizer/lib.py +++ b/compiler/characterizer/lib.py @@ -181,17 +181,20 @@ class lib: self.lib.write(" dont_touch : true;\n") self.lib.write(" area : {};\n\n".format(self.sram.width * self.sram.height)) - #Build string of all control signals. + self.write_pg_pin() + + #Build string of all control signals. control_str = 'csb0' #assume at least 1 port for i in range(1, self.total_port_num): control_str += ' & csb{0}'.format(i) # Leakage is included in dynamic when macro is enabled self.lib.write(" leakage_power () {\n") - self.lib.write(" when : \"{0}\";\n".format(control_str)) + # 'when' condition unnecessary when cs pin does not turn power to devices + # self.lib.write(" when : \"{0}\";\n".format(control_str)) self.lib.write(" value : {};\n".format(self.char_sram_results["leakage_power"])) self.lib.write(" }\n") - self.lib.write(" cell_leakage_power : {};\n".format(0)) + self.lib.write(" cell_leakage_power : {};\n".format(self.char_sram_results["leakage_power"])) def write_units(self): @@ -240,6 +243,9 @@ class lib: self.lib.write(" default_max_fanout : 4.0 ;\n") self.lib.write(" default_connection_class : universal ;\n\n") + self.lib.write(" voltage_map ( VDD, {} );\n".format(tech.spice["nom_supply_voltage"])) + self.lib.write(" voltage_map ( GND, 0 );\n\n") + def create_list(self,values): """ Helper function to create quoted, line wrapped list """ list_values = ", ".join(str(v) for v in values) @@ -516,42 +522,69 @@ class lib: if port in self.write_ports: if port in self.read_ports: web_name = " & !web{0}".format(port) - avg_write_power = np.mean(self.char_port_results[port]["write1_power"] + self.char_port_results[port]["write0_power"]) + write1_power = np.mean(self.char_port_results[port]["write1_power"]) + write0_power = np.mean(self.char_port_results[port]["write0_power"]) self.lib.write(" internal_power(){\n") - self.lib.write(" when : \"!csb{0} & clk{0}{1}\"; \n".format(port, web_name)) + self.lib.write(" when : \"!csb{0}{1}\"; \n".format(port, web_name)) self.lib.write(" rise_power(scalar){\n") - self.lib.write(" values(\"{0}\");\n".format(avg_write_power/2.0)) + self.lib.write(" values(\"{0:.6e}\");\n".format(write1_power)) self.lib.write(" }\n") self.lib.write(" fall_power(scalar){\n") - self.lib.write(" values(\"{0}\");\n".format(avg_write_power/2.0)) + self.lib.write(" values(\"{0:.6e}\");\n".format(write0_power)) + self.lib.write(" }\n") + self.lib.write(" }\n") + + # Disabled power. + disabled_write1_power = np.mean(self.char_port_results[port]["disabled_write1_power"]) + disabled_write0_power = np.mean(self.char_port_results[port]["disabled_write0_power"]) + self.lib.write(" internal_power(){\n") + self.lib.write(" when : \"csb{0}{1}\"; \n".format(port, web_name)) + self.lib.write(" rise_power(scalar){\n") + self.lib.write(" values(\"{0:.6e}\");\n".format(disabled_write1_power)) + self.lib.write(" }\n") + self.lib.write(" fall_power(scalar){\n") + self.lib.write(" values(\"{0:.6e}\");\n".format(disabled_write0_power)) self.lib.write(" }\n") self.lib.write(" }\n") if port in self.read_ports: if port in self.write_ports: web_name = " & web{0}".format(port) - avg_read_power = np.mean(self.char_port_results[port]["read1_power"] + self.char_port_results[port]["read0_power"]) + read1_power = np.mean(self.char_port_results[port]["read1_power"]) + read0_power = np.mean(self.char_port_results[port]["read0_power"]) self.lib.write(" internal_power(){\n") - self.lib.write(" when : \"!csb{0} & !clk{0}{1}\"; \n".format(port, web_name)) + self.lib.write(" when : \"!csb{0}{1}\"; \n".format(port, web_name)) self.lib.write(" rise_power(scalar){\n") - self.lib.write(" values(\"{0}\");\n".format(avg_read_power/2.0)) + self.lib.write(" values(\"{0:.6e}\");\n".format(read1_power)) self.lib.write(" }\n") self.lib.write(" fall_power(scalar){\n") - self.lib.write(" values(\"{0}\");\n".format(avg_read_power/2.0)) + self.lib.write(" values(\"{0:.6e}\");\n".format(read0_power)) self.lib.write(" }\n") self.lib.write(" }\n") - # Have 0 internal power when disabled, this will be represented as leakage power. - self.lib.write(" internal_power(){\n") - self.lib.write(" when : \"csb{0}\"; \n".format(port)) - self.lib.write(" rise_power(scalar){\n") - self.lib.write(" values(\"0\");\n") - self.lib.write(" }\n") - self.lib.write(" fall_power(scalar){\n") - self.lib.write(" values(\"0\");\n") - self.lib.write(" }\n") - self.lib.write(" }\n") - + # Disabled power. + disabled_read1_power = np.mean(self.char_port_results[port]["disabled_read1_power"]) + disabled_read0_power = np.mean(self.char_port_results[port]["disabled_read0_power"]) + self.lib.write(" internal_power(){\n") + self.lib.write(" when : \"csb{0}{1}\"; \n".format(port, web_name)) + self.lib.write(" rise_power(scalar){\n") + self.lib.write(" values(\"{0:.6e}\");\n".format(disabled_read1_power)) + self.lib.write(" }\n") + self.lib.write(" fall_power(scalar){\n") + self.lib.write(" values(\"{0:.6e}\");\n".format(disabled_read0_power)) + self.lib.write(" }\n") + self.lib.write(" }\n") + + def write_pg_pin(self): + self.lib.write(" pg_pin(vdd) {\n") + self.lib.write(" voltage_name : VDD;\n") + self.lib.write(" pg_type : primary_power;\n") + self.lib.write(" }\n\n") + self.lib.write(" pg_pin(gnd) {\n") + self.lib.write(" voltage_name : GND;\n") + self.lib.write(" pg_type : primary_ground;\n") + self.lib.write(" }\n\n") + def compute_delay(self): """Compute SRAM delays for current corner""" self.d = delay(self.sram, self.sp_file, self.corner) diff --git a/compiler/characterizer/simulation.py b/compiler/characterizer/simulation.py index adbe5f5f..0d5cfb25 100644 --- a/compiler/characterizer/simulation.py +++ b/compiler/characterizer/simulation.py @@ -279,6 +279,23 @@ class simulation(): except: self.add_wmask("0"*self.num_wmasks, port) + def add_noop_clock_one_port(self, port): + """ Add the control values for a noop to a single port. Increments the period. """ + debug.info(2, 'Clock only on port {}'.format(port)) + self.fn_cycle_comments.append('Clock only on port {}'.format(port)) + self.append_cycle_comment(port, 'Clock only on port {}'.format(port)) + + self.cycle_times.append(self.t_current) + self.t_current += self.period + + self.add_noop_one_port(port) + + #Add noops to all other ports. + for unselected_port in self.all_ports: + if unselected_port != port: + self.add_noop_one_port(unselected_port) + + def append_cycle_comment(self, port, comment): """Add comment to list to be printed in stimulus file""" #Clean up time before appending. Make spacing dynamic as well. diff --git a/compiler/globals.py b/compiler/globals.py index 4e6253ad..92780c1a 100644 --- a/compiler/globals.py +++ b/compiler/globals.py @@ -19,7 +19,7 @@ import re import copy import importlib -VERSION = "1.1.4" +VERSION = "1.1.5" NAME = "OpenRAM v{}".format(VERSION) USAGE = "openram.py [options] \nUse -h for help.\n" diff --git a/compiler/modules/bitcell_array.py b/compiler/modules/bitcell_array.py index 60461724..97b681e9 100644 --- a/compiler/modules/bitcell_array.py +++ b/compiler/modules/bitcell_array.py @@ -28,7 +28,6 @@ class bitcell_array(bitcell_base_array): # the replica bitcell in the control logic # self.offset_all_coordinates() - def create_netlist(self): """ Create and connect the netlist """ self.add_modules() @@ -56,22 +55,21 @@ class bitcell_array(bitcell_base_array): for col in range(self.column_size): for row in range(self.row_size): name = "bit_r{0}_c{1}".format(row, col) - self.cell_inst[row,col]=self.add_inst(name=name, - mod=self.cell) + self.cell_inst[row, col]=self.add_inst(name=name, + mod=self.cell) self.connect_inst(self.get_bitcell_pins(col, row)) def analytical_power(self, corner, load): """Power of Bitcell array and bitline in nW.""" - from tech import drc, parameter # Dynamic Power from Bitline bl_wire = self.gen_bl_wire() - cell_load = 2 * bl_wire.return_input_cap() + cell_load = 2 * bl_wire.return_input_cap() bl_swing = OPTS.rbl_delay_percentage freq = spice["default_event_frequency"] bitline_dynamic = self.calc_dynamic_power(corner, cell_load, freq, swing=bl_swing) - # Calculate the bitcell power which currently only includes leakage + # Calculate the bitcell power which currently only includes leakage cell_power = self.cell.analytical_power(corner, load) # Leakage power grows with entire array and bitlines. @@ -85,7 +83,7 @@ class bitcell_array(bitcell_base_array): else: width = self.width wl_wire = self.generate_rc_net(int(self.column_size), width, drc("minwidth_m1")) - wl_wire.wire_c = 2*spice["min_tx_gate_c"] + wl_wire.wire_c # 2 access tx gate per cell + wl_wire.wire_c = 2 * spice["min_tx_gate_c"] + wl_wire.wire_c # 2 access tx gate per cell return wl_wire def gen_bl_wire(self): @@ -94,26 +92,26 @@ class bitcell_array(bitcell_base_array): else: height = self.height bl_pos = 0 - bl_wire = self.generate_rc_net(int(self.row_size-bl_pos), height, drc("minwidth_m1")) + bl_wire = self.generate_rc_net(int(self.row_size - bl_pos), height, drc("minwidth_m1")) bl_wire.wire_c =spice["min_tx_drain_c"] + bl_wire.wire_c # 1 access tx d/s per cell return bl_wire def get_wordline_cin(self): """Get the relative input capacitance from the wordline connections in all the bitcell""" - #A single wordline is connected to all the bitcells in a single row meaning the capacitance depends on the # of columns + # A single wordline is connected to all the bitcells in a single row meaning the capacitance depends on the # of columns bitcell_wl_cin = self.cell.get_wl_cin() total_cin = bitcell_wl_cin * self.column_size return total_cin def graph_exclude_bits(self, targ_row, targ_col): """Excludes bits in column from being added to graph except target""" - #Function is not robust with column mux configurations + # Function is not robust with column mux configurations for row in range(self.row_size): for col in range(self.column_size): if row == targ_row and col == targ_col: continue - self.graph_inst_exclude.add(self.cell_inst[row,col]) + self.graph_inst_exclude.add(self.cell_inst[row, col]) def get_cell_name(self, inst_name, row, col): - """Gets the spice name of the target bitcell.""" - return inst_name+'.x'+self.cell_inst[row,col].name, self.cell_inst[row,col] + """Gets the spice name of the target bitcell.""" + return inst_name + '.x' + self.cell_inst[row, col].name, self.cell_inst[row, col] diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index b4c7402e..5dd8182e 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -90,7 +90,7 @@ class control_logic(design.design): self.add_mod(self.ctrl_dff_array) self.and2 = factory.create(module_type="pand2", - size=4, + size=12, height=dff_height) self.add_mod(self.and2) diff --git a/compiler/modules/delay_chain.py b/compiler/modules/delay_chain.py index a07576d4..b34974e5 100644 --- a/compiler/modules/delay_chain.py +++ b/compiler/modules/delay_chain.py @@ -7,12 +7,11 @@ # import debug import design -from tech import drc -from contact import contact from vector import vector from globals import OPTS from sram_factory import factory + class delay_chain(design.design): """ Generate a delay chain with the given number of stages and fanout. @@ -28,7 +27,7 @@ class delay_chain(design.design): # Two fanouts are needed so that we can route the vdd/gnd connections for f in fanout_list: - debug.check(f>=2,"Must have >=2 fanouts for each stage.") + debug.check(f>=2, "Must have >=2 fanouts for each stage.") # number of inverters including any fanout loads. self.fanout_list = fanout_list @@ -36,7 +35,6 @@ class delay_chain(design.design): self.create_netlist() if not OPTS.netlist_only: self.create_layout() - def create_netlist(self): self.add_modules() @@ -45,12 +43,13 @@ class delay_chain(design.design): def create_layout(self): # Each stage is a a row - self.height = len(self.fanout_list)*self.inv.height + self.height = len(self.fanout_list) * self.inv.height # The width is determined by the largest fanout plus the driver - self.width = (max(self.fanout_list)+1) * self.inv.width + self.width = (max(self.fanout_list) + 1) * self.inv.width self.place_inverters() self.route_inverters() + self.route_supplies() self.add_layout_pins() self.add_boundary() self.DRC_LVS() @@ -69,9 +68,8 @@ class delay_chain(design.design): def create_inverters(self): """ Create the inverters and connect them based on the stage list """ self.driver_inst_list = [] - self.rightest_load_inst = {} self.load_inst_map = {} - for stage_num,fanout_size in zip(range(len(self.fanout_list)),self.fanout_list): + for stage_num, fanout_size in zip(range(len(self.fanout_list)), self.fanout_list): # Add the inverter cur_driver=self.add_inst(name="dinv{}".format(stage_num), mod=self.inv) @@ -79,40 +77,37 @@ class delay_chain(design.design): self.driver_inst_list.append(cur_driver) # Hook up the driver - if stage_num+1==len(self.fanout_list): + if stage_num + 1 == len(self.fanout_list): stageout_name = "out" else: - stageout_name = "dout_{}".format(stage_num+1) + stageout_name = "dout_{}".format(stage_num + 1) if stage_num == 0: stagein_name = "in" else: - stagein_name = "dout_{}".format(stage_num) + stagein_name = "dout_{}".format(stage_num) self.connect_inst([stagein_name, stageout_name, "vdd", "gnd"]) # Now add the dummy loads to the right self.load_inst_map[cur_driver]=[] for i in range(fanout_size): - cur_load=self.add_inst(name="dload_{0}_{1}".format(stage_num,i), + cur_load=self.add_inst(name="dload_{0}_{1}".format(stage_num, i), mod=self.inv) # Fanout stage is always driven by driver and output is disconnected - disconnect_name = "n_{0}_{1}".format(stage_num,i) + disconnect_name = "n_{0}_{1}".format(stage_num, i) self.connect_inst([stageout_name, disconnect_name, "vdd", "gnd"]) # Keep track of all the loads to connect their inputs as a load self.load_inst_map[cur_driver].append(cur_load) - else: - # Keep track of the last one so we can add the the wire later - self.rightest_load_inst[cur_driver]=cur_load def place_inverters(self): """ Place the inverters and connect them based on the stage list """ - for stage_num,fanout_size in zip(range(len(self.fanout_list)),self.fanout_list): + for stage_num, fanout_size in zip(range(len(self.fanout_list)), self.fanout_list): if stage_num % 2: inv_mirror = "MX" - inv_offset = vector(0, (stage_num+1)* self.inv.height) + inv_offset = vector(0, (stage_num + 1) * self.inv.height) else: inv_mirror = "R0" - inv_offset = vector(0, stage_num * self.inv.height) + inv_offset = vector(0, stage_num * self.inv.height) # Add the inverter cur_driver=self.driver_inst_list[stage_num] @@ -122,10 +117,9 @@ class delay_chain(design.design): # Now add the dummy loads to the right load_list = self.load_inst_map[cur_driver] for i in range(fanout_size): - inv_offset += vector(self.inv.width,0) + inv_offset += vector(self.inv.width, 0) load_list[i].place(offset=inv_offset, mirror=inv_mirror) - def add_route(self, pin1, pin2): """ This guarantees that we route from the top to bottom row correctly. """ @@ -134,9 +128,9 @@ class delay_chain(design.design): if pin1_pos.y == pin2_pos.y: self.add_path("m2", [pin1_pos, pin2_pos]) else: - mid_point = vector(pin2_pos.x, 0.5*(pin1_pos.y+pin2_pos.y)) + mid_point = vector(pin2_pos.x, 0.5 * (pin1_pos.y + pin2_pos.y)) # Written this way to guarantee it goes right first if we are switching rows - self.add_path("m2", [pin1_pos, vector(pin1_pos.x,mid_point.y), mid_point, vector(mid_point.x,pin2_pos.y), pin2_pos]) + self.add_path("m2", [pin1_pos, vector(pin1_pos.x, mid_point.y), mid_point, vector(mid_point.x, pin2_pos.y), pin2_pos]) def route_inverters(self): """ Add metal routing for each of the fanout stages """ @@ -145,7 +139,7 @@ class delay_chain(design.design): inv = self.driver_inst_list[i] for load in self.load_inst_map[inv]: # Drop a via on each A pin - a_pin = load.get_pin("A") + a_pin = load.get_pin("A") self.add_via_center(layers=self.m1_stack, offset=a_pin.center()) self.add_via_center(layers=self.m2_stack, @@ -154,54 +148,42 @@ class delay_chain(design.design): # Route an M3 horizontal wire to the furthest z_pin = inv.get_pin("Z") a_pin = inv.get_pin("A") - a_max = self.rightest_load_inst[inv].get_pin("A") + a_max = self.load_inst_map[inv][-1].get_pin("A") self.add_via_center(layers=self.m1_stack, offset=a_pin.center()) self.add_via_center(layers=self.m1_stack, offset=z_pin.center()) self.add_via_center(layers=self.m2_stack, offset=z_pin.center()) - self.add_path("m3",[z_pin.center(), a_max.center()]) + self.add_path("m3", [z_pin.center(), a_max.center()]) - # Route Z to the A of the next stage - if i+1 < len(self.driver_inst_list): + if i + 1 < len(self.driver_inst_list): z_pin = inv.get_pin("Z") - next_inv = self.driver_inst_list[i+1] + next_inv = self.driver_inst_list[i + 1] next_a_pin = next_inv.get_pin("A") - y_mid = (z_pin.cy() + next_a_pin.cy())/2 + y_mid = (z_pin.cy() + next_a_pin.cy()) / 2 mid1_point = vector(z_pin.cx(), y_mid) mid2_point = vector(next_a_pin.cx(), y_mid) - self.add_path("m2",[z_pin.center(), mid1_point, mid2_point, next_a_pin.center()]) - - - def add_layout_pins(self): - """ Add vdd and gnd rails and the input/output. Connect the gnd rails internally on - the top end with no input/output to obstruct. """ + self.add_path("m2", [z_pin.center(), mid1_point, mid2_point, next_a_pin.center()]) + def route_supplies(self): # Add power and ground to all the cells except: # the fanout driver, the right-most load # The routing to connect the loads is over the first and last cells # We have an even number of drivers and must only do every other # supply rail - for i in range(0,len(self.driver_inst_list),2): - inv = self.driver_inst_list[i] - for load in self.load_inst_map[inv]: - if load==self.rightest_load_inst[inv]: - continue - for pin_name in ["vdd", "gnd"]: - pin = load.get_pin(pin_name) - self.add_power_pin(pin_name, pin.rc()) - else: - # We have an even number of rows, so need to get the last gnd rail - inv = self.driver_inst_list[-1] - for load in self.load_inst_map[inv]: - if load==self.rightest_load_inst[inv]: - continue - pin_name = "gnd" - pin = load.get_pin(pin_name) - self.add_power_pin(pin_name, pin.rc()) + for inst in self.driver_inst_list: + load_list = self.load_inst_map[inst] + for pin_name in ["vdd", "gnd"]: + pin = load_list[0].get_pin(pin_name) + self.add_power_pin(pin_name, pin.rc() - vector(self.m1_pitch, 0)) + + pin = load_list[-1].get_pin(pin_name) + self.add_power_pin(pin_name, pin.rc() - vector(0.5 * self.m1_pitch, 0)) + + def add_layout_pins(self): # input is A pin of first inverter a_pin = self.driver_inst_list[0].get_pin("A") @@ -209,36 +191,36 @@ class delay_chain(design.design): offset=a_pin.center()) self.add_layout_pin(text="in", layer="m2", - offset=a_pin.ll().scale(1,0), + offset=a_pin.ll().scale(1, 0), height=a_pin.cy()) - # output is A pin of last load inverter last_driver_inst = self.driver_inst_list[-1] - a_pin = self.rightest_load_inst[last_driver_inst].get_pin("A") + a_pin = self.load_inst_map[last_driver_inst][-1].get_pin("A") self.add_via_center(layers=self.m1_stack, offset=a_pin.center()) - mid_point = vector(a_pin.cx()+3*self.m2_width,a_pin.cy()) - self.add_path("m2",[a_pin.center(), mid_point, mid_point.scale(1,0)]) + mid_point = vector(a_pin.cx() + 3 * self.m2_width, a_pin.cy()) + self.add_path("m2", [a_pin.center(), mid_point, mid_point.scale(1, 0)]) self.add_layout_pin_segment_center(text="out", layer="m2", start=mid_point, - end=mid_point.scale(1,0)) + end=mid_point.scale(1, 0)) def get_cin(self): """Get the enable input ralative capacitance""" - #Only 1 input to the delay chain which is connected to an inverter. + # Only 1 input to the delay chain which is connected to an inverter. dc_cin = self.inv.get_cin() - return dc_cin + return dc_cin def determine_delayed_en_stage_efforts(self, ext_delayed_en_cout, inp_is_rise=True): """Get the stage efforts from the en to s_en. Does not compute the delay for the bitline load.""" stage_effort_list = [] - #Add a stage to the list for every stage in delay chain. Stages only differ in fanout except the last which has an external cout. + # Add a stage to the list for every stage in delay chain. + # Stages only differ in fanout except the last which has an external cout. last_stage_is_rise = inp_is_rise for stage_fanout in self.fanout_list: - stage_cout = self.inv.get_cin()*(stage_fanout+1) - if len(stage_effort_list) == len(self.fanout_list)-1: #last stage + stage_cout = self.inv.get_cin() * (stage_fanout + 1) + if len(stage_effort_list) == len(self.fanout_list) - 1: stage_cout+=ext_delayed_en_cout stage = self.inv.get_stage_effort(stage_cout, last_stage_is_rise) stage_effort_list.append(stage) diff --git a/compiler/modules/dff_buf.py b/compiler/modules/dff_buf.py index c30f15b6..500767d8 100644 --- a/compiler/modules/dff_buf.py +++ b/compiler/modules/dff_buf.py @@ -35,7 +35,7 @@ class dff_buf(design.design): # This causes a DRC in the pinv which assumes min width rails. This ensures the output # contact does not violate spacing to the rail in the NMOS. debug.check(inv1_size>=2, "Inverter must be greater than two for rail spacing DRC rules.") - debug.check(inv2_size>=2, "Inverter must be greater than two for rail spacing DRC rules.") + debug.check(inv2_size>=2, "Inverter must be greater than two for rail spacing DRC rules.") self.inv1_size=inv1_size self.inv2_size=inv2_size @@ -52,14 +52,13 @@ class dff_buf(design.design): def create_layout(self): self.place_instances() self.width = self.inv2_inst.rx() + self.height = self.dff.height - - self.route_wires() self.add_layout_pins() self.add_boundary() self.DRC_LVS() - + def add_modules(self): self.dff = factory.create(module_type="dff") self.add_mod(self.dff) @@ -73,8 +72,6 @@ class dff_buf(design.design): size=self.inv2_size, height=self.dff.height) self.add_mod(self.inv2) - - def add_pins(self): self.add_pin("D", "INPUT") @@ -96,17 +93,19 @@ class dff_buf(design.design): self.inv1_inst=self.add_inst(name="dff_buf_inv1", mod=self.inv1) - self.connect_inst(["qint", "Qb", "vdd", "gnd"]) + self.connect_inst(["qint", "Qb", "vdd", "gnd"]) self.inv2_inst=self.add_inst(name="dff_buf_inv2", mod=self.inv2) - self.connect_inst(["Qb", "Q", "vdd", "gnd"]) + self.connect_inst(["Qb", "Q", "vdd", "gnd"]) def place_instances(self): # Add the DFF - self.dff_inst.place(vector(0,0)) + self.dff_inst.place(vector(0, 0)) # Add INV1 to the right + # The INV needs well spacing because the DFF is likely from a library + # with different well construction rules well_spacing = 0 try: well_spacing = max(well_spacing, self.nwell_space) @@ -129,7 +128,7 @@ class dff_buf(design.design): # Route dff q to inv1 a q_pin = self.dff_inst.get_pin("Q") a1_pin = self.inv1_inst.get_pin("A") - mid_x_offset = 0.5*(a1_pin.cx() + q_pin.cx()) + mid_x_offset = 0.5 * (a1_pin.cx() + q_pin.cx()) mid1 = vector(mid_x_offset, q_pin.cy()) mid2 = vector(mid_x_offset, a1_pin.cy()) self.add_path("m3", [q_pin.center(), mid1, mid2, a1_pin.center()]) @@ -143,7 +142,7 @@ class dff_buf(design.design): # Route inv1 z to inv2 a z1_pin = self.inv1_inst.get_pin("Z") a2_pin = self.inv2_inst.get_pin("A") - mid_x_offset = 0.5*(z1_pin.cx() + a2_pin.cx()) + mid_x_offset = 0.5 * (z1_pin.cx() + a2_pin.cx()) self.mid_qb_pos = vector(mid_x_offset, z1_pin.cy()) mid2 = vector(mid_x_offset, a2_pin.cy()) self.add_path("m1", [z1_pin.center(), self.mid_qb_pos, mid2, a2_pin.center()]) @@ -181,8 +180,8 @@ class dff_buf(design.design): height=din_pin.height()) dout_pin = self.inv2_inst.get_pin("Z") - mid_pos = dout_pin.center() + vector(self.m1_pitch,0) - q_pos = mid_pos - vector(0,self.m2_pitch) + mid_pos = dout_pin.center() + vector(self.m1_pitch, 0) + q_pos = mid_pos - vector(0, self.m2_pitch) self.add_layout_pin_rect_center(text="Q", layer="m2", offset=q_pos) @@ -190,7 +189,7 @@ class dff_buf(design.design): self.add_via_center(layers=self.m1_stack, offset=q_pos) - qb_pos = self.mid_qb_pos + vector(0,self.m2_pitch) + qb_pos = self.mid_qb_pos + vector(0, self.m2_pitch) self.add_layout_pin_rect_center(text="Qb", layer="m2", offset=qb_pos) @@ -200,7 +199,7 @@ class dff_buf(design.design): def get_clk_cin(self): """Return the total capacitance (in relative units) that the clock is loaded by in the dff""" - #This is a handmade cell so the value must be entered in the tech.py file or estimated. - #Calculated in the tech file by summing the widths of all the gates and dividing by the minimum width. - #FIXME: Dff changed in a past commit. The parameter need to be updated. + # This is a handmade cell so the value must be entered in the tech.py file or estimated. + # Calculated in the tech file by summing the widths of all the gates and dividing by the minimum width. + # FIXME: Dff changed in a past commit. The parameter need to be updated. return parameter["dff_clk_cin"] diff --git a/compiler/modules/dff_buf_array.py b/compiler/modules/dff_buf_array.py index 1735a7a1..b608cdeb 100644 --- a/compiler/modules/dff_buf_array.py +++ b/compiler/modules/dff_buf_array.py @@ -7,13 +7,12 @@ # import debug import design -from tech import drc from tech import cell_properties as props -from math import log from vector import vector from globals import OPTS from sram_factory import factory + class dff_buf_array(design.design): """ This is a simple row (or multiple rows) of flops. @@ -49,18 +48,19 @@ class dff_buf_array(design.design): self.width = self.columns * self.dff.width self.height = self.rows * self.dff.height self.place_dff_array() + self.route_supplies() self.add_layout_pins() self.add_boundary() self.DRC_LVS() def add_pins(self): - for row in range(self.rows): + for row in range(self.rows): for col in range(self.columns): - self.add_pin(self.get_din_name(row,col), "INPUT") - for row in range(self.rows): + self.add_pin(self.get_din_name(row, col), "INPUT") + for row in range(self.rows): for col in range(self.columns): - self.add_pin(self.get_dout_name(row,col), "OUTPUT") - self.add_pin(self.get_dout_bar_name(row,col), "OUTPUT") + self.add_pin(self.get_dout_name(row, col), "OUTPUT") + self.add_pin(self.get_dout_bar_name(row, col), "OUTPUT") self.add_pin("clk", "INPUT") self.add_pin("vdd", "POWER") self.add_pin("gnd", "GROUND") @@ -75,17 +75,16 @@ class dff_buf_array(design.design): inv2_size=self.inv2_size) self.add_mod(self.dff) - def create_dff_array(self): self.dff_insts={} - for row in range(self.rows): + for row in range(self.rows): for col in range(self.columns): - name = "dff_r{0}_c{1}".format(row,col) - self.dff_insts[row,col]=self.add_inst(name=name, - mod=self.dff) - inst_ports = [self.get_din_name(row,col), - self.get_dout_name(row,col), - self.get_dout_bar_name(row,col), + name = "dff_r{0}_c{1}".format(row, col) + self.dff_insts[row, col]=self.add_inst(name=name, + mod=self.dff) + inst_ports = [self.get_din_name(row, col), + self.get_dout_name(row, col), + self.get_dout_bar_name(row, col), "clk", "vdd", "gnd"] @@ -96,23 +95,33 @@ class dff_buf_array(design.design): def place_dff_array(self): - well_spacing = max(self.nwell_space, - self.pwell_space, - self.pwell_to_nwell) + well_spacing = 0 + try: + well_spacing = max(self.nwell_space, well_spacing) + except AttributeError: + pass + try: + well_spacing = max(self.pwell_space, well_spacing) + except AttributeError: + pass + try: + well_spacing = max(self.pwell_to_nwell, well_spacing) + except AttributeError: + pass dff_pitch = self.dff.width + well_spacing + self.well_extend_active - for row in range(self.rows): + for row in range(self.rows): for col in range(self.columns): - name = "Xdff_r{0}_c{1}".format(row,col) + # name = "Xdff_r{0}_c{1}".format(row, col) if (row % 2 == 0): - base = vector(col*dff_pitch,row*self.dff.height) + base = vector(col * dff_pitch, row * self.dff.height) mirror = "R0" else: - base = vector(col*dff_pitch,(row+1)*self.dff.height) + base = vector(col * dff_pitch, (row + 1) * self.dff.height) mirror = "MX" - self.dff_insts[row,col].place(offset=base, - mirror=mirror) + self.dff_insts[row, col].place(offset=base, + mirror=mirror) def get_din_name(self, row, col): if self.columns == 1: @@ -120,7 +129,7 @@ class dff_buf_array(design.design): elif self.rows == 1: din_name = "din_{0}".format(col) else: - din_name = "din_{0}_{1}".format(row,col) + din_name = "din_{0}_{1}".format(row, col) return din_name @@ -130,7 +139,7 @@ class dff_buf_array(design.design): elif self.rows == 1: dout_name = "dout_{0}".format(col) else: - dout_name = "dout_{0}_{1}".format(row,col) + dout_name = "dout_{0}_{1}".format(row, col) return dout_name @@ -140,75 +149,84 @@ class dff_buf_array(design.design): elif self.rows == 1: dout_bar_name = "dout_bar_{0}".format(col) else: - dout_bar_name = "dout_bar_{0}_{1}".format(row,col) + dout_bar_name = "dout_bar_{0}_{1}".format(row, col) return dout_bar_name - - def add_layout_pins(self): + + def route_supplies(self): for row in range(self.rows): - for col in range(self.columns): + vdd0_pin=self.dff_insts[row, 0].get_pin("vdd") + vddn_pin=self.dff_insts[row, self.columns - 1].get_pin("vdd") + self.add_path(vdd0_pin.layer, [vdd0_pin.lc(), vddn_pin.rc()], width=vdd0_pin.height()) + + gnd0_pin=self.dff_insts[row, 0].get_pin("gnd") + gndn_pin=self.dff_insts[row, self.columns - 1].get_pin("gnd") + self.add_path(gnd0_pin.layer, [gnd0_pin.lc(), gndn_pin.rc()], width=gnd0_pin.height()) + + for row in range(self.rows): + for col in range(self.columns): # Continous vdd rail along with label. - vdd_pin=self.dff_insts[row,col].get_pin("vdd") + vdd_pin=self.dff_insts[row, col].get_pin("vdd") self.add_power_pin("vdd", vdd_pin.lc()) # Continous gnd rail along with label. - gnd_pin=self.dff_insts[row,col].get_pin("gnd") + gnd_pin=self.dff_insts[row, col].get_pin("gnd") self.add_power_pin("gnd", gnd_pin.lc()) + + def add_layout_pins(self): - - for row in range(self.rows): - for col in range(self.columns): - din_pin = self.dff_insts[row,col].get_pin("D") - debug.check(din_pin.layer=="m2","DFF D pin not on metal2") - self.add_layout_pin(text=self.get_din_name(row,col), + for row in range(self.rows): + for col in range(self.columns): + din_pin = self.dff_insts[row, col].get_pin("D") + debug.check(din_pin.layer=="m2", "DFF D pin not on metal2") + self.add_layout_pin(text=self.get_din_name(row, col), layer=din_pin.layer, offset=din_pin.ll(), width=din_pin.width(), height=din_pin.height()) - dout_pin = self.dff_insts[row,col].get_pin("Q") - debug.check(dout_pin.layer=="m2","DFF Q pin not on metal2") - self.add_layout_pin(text=self.get_dout_name(row,col), + dout_pin = self.dff_insts[row, col].get_pin("Q") + debug.check(dout_pin.layer=="m2", "DFF Q pin not on metal2") + self.add_layout_pin(text=self.get_dout_name(row, col), layer=dout_pin.layer, offset=dout_pin.ll(), width=dout_pin.width(), height=dout_pin.height()) - dout_bar_pin = self.dff_insts[row,col].get_pin("Qb") - debug.check(dout_bar_pin.layer=="m2","DFF Qb pin not on metal2") - self.add_layout_pin(text=self.get_dout_bar_name(row,col), + dout_bar_pin = self.dff_insts[row, col].get_pin("Qb") + debug.check(dout_bar_pin.layer=="m2", "DFF Qb pin not on metal2") + self.add_layout_pin(text=self.get_dout_bar_name(row, col), layer=dout_bar_pin.layer, offset=dout_bar_pin.ll(), width=dout_bar_pin.width(), height=dout_bar_pin.height()) - # Create vertical spines to a single horizontal rail - clk_pin = self.dff_insts[0,0].get_pin("clk") - clk_ypos = 2*self.m3_pitch+self.m3_width - debug.check(clk_pin.layer=="m2","DFF clk pin not on metal2") + clk_pin = self.dff_insts[0, 0].get_pin("clk") + clk_ypos = 2 * self.m3_pitch + self.m3_width + debug.check(clk_pin.layer=="m2", "DFF clk pin not on metal2") if self.columns==1: self.add_layout_pin(text="clk", layer="m2", - offset=clk_pin.ll().scale(1,0), + offset=clk_pin.ll().scale(1, 0), width=self.m2_width, height=self.height) else: self.add_layout_pin_segment_center(text="clk", - layer="m3", - start=vector(0,clk_ypos), - end=vector(self.width,clk_ypos)) + layer="m3", + start=vector(0, clk_ypos), + end=vector(self.width, clk_ypos)) for col in range(self.columns): - clk_pin = self.dff_insts[0,col].get_pin("clk") + clk_pin = self.dff_insts[0, col].get_pin("clk") # Make a vertical strip for each column self.add_rect(layer="m2", - offset=clk_pin.ll().scale(1,0), + offset=clk_pin.ll().scale(1, 0), width=self.m2_width, height=self.height) # Drop a via to the M3 pin self.add_via_center(layers=self.m2_stack, - offset=vector(clk_pin.cx(),clk_ypos)) + offset=vector(clk_pin.cx(), clk_ypos)) def get_clk_cin(self): """Return the total capacitance (in relative units) that the clock is loaded by in the dff array""" diff --git a/compiler/modules/hierarchical_decoder.py b/compiler/modules/hierarchical_decoder.py index f46849c6..69822149 100644 --- a/compiler/modules/hierarchical_decoder.py +++ b/compiler/modules/hierarchical_decoder.py @@ -32,7 +32,6 @@ class hierarchical_decoder(design.design): self.cell_multiple = cell_properties.bitcell.decoder_bitcell_multiple except AttributeError: self.cell_multiple = 1 - # For debugging self.cell_height = self.cell_multiple * b.height self.num_outputs = num_outputs diff --git a/compiler/modules/port_data.py b/compiler/modules/port_data.py index fbf5223a..bdf10f39 100644 --- a/compiler/modules/port_data.py +++ b/compiler/modules/port_data.py @@ -699,8 +699,13 @@ class port_data(design.design): bottom_names = self._get_bitline_pins(bot_inst_group, bit) top_names = self._get_bitline_pins(top_inst_group, bit) + if bottom_names[0].layer == "m2": + bitline_dirs = ("H", "V") + elif bottom_names[0].layer == "m1": + bitline_dirs = ("V", "H") + route_map = list(zip(bottom_names, top_names)) - self.create_horizontal_channel_route(route_map, offset, self.m1_stack) + self.create_horizontal_channel_route(route_map, offset, self.m1_stack, bitline_dirs) def connect_bitlines(self, inst1, inst2, num_bits, inst1_bls_template="{inst}_{bit}", diff --git a/compiler/modules/single_level_column_mux_array.py b/compiler/modules/single_level_column_mux_array.py index 581e20b0..5dc9cbf8 100644 --- a/compiler/modules/single_level_column_mux_array.py +++ b/compiler/modules/single_level_column_mux_array.py @@ -151,7 +151,7 @@ class single_level_column_mux_array(design.design): def add_horizontal_input_rail(self): """ Create address input rails on M1 below the mux transistors """ for j in range(self.words_per_row): - offset = vector(0, self.route_height + (j - self.words_per_row) * self.col_mux_stack_pitch) #edit + offset = vector(0, self.route_height + (j - self.words_per_row) * self.col_mux_stack_pitch) self.add_layout_pin(text="sel_{}".format(j), layer=self.col_mux_stack[0], offset=offset, diff --git a/compiler/modules/wordline_driver.py b/compiler/modules/wordline_driver.py index d84457ba..76a31074 100644 --- a/compiler/modules/wordline_driver.py +++ b/compiler/modules/wordline_driver.py @@ -7,10 +7,12 @@ # import debug import design +import math import contact from vector import vector from sram_factory import factory from globals import OPTS +from tech import cell_properties class wordline_driver(design.design): @@ -26,6 +28,13 @@ class wordline_driver(design.design): self.rows = rows self.cols = cols + + b = factory.create(module_type="bitcell") + try: + self.cell_multiple = cell_properties.bitcell.decoder_bitcell_multiple + except AttributeError: + self.cell_multiple = 1 + self.cell_height = self.cell_multiple * b.height self.create_netlist() if not OPTS.netlist_only: @@ -37,6 +46,7 @@ class wordline_driver(design.design): self.create_drivers() def create_layout(self): + self.setup_layout_constants() self.place_drivers() self.route_layout() self.route_vdd_gnd() @@ -56,17 +66,10 @@ class wordline_driver(design.design): self.add_pin("gnd", "GROUND") def add_modules(self): - b = factory.create(module_type="bitcell") - - self.inv = factory.create(module_type="pdriver", - fanout=self.cols, - neg_polarity=True, - height=b.height) - self.add_mod(self.inv) - - self.nand2 = factory.create(module_type="pnand2", - height=b.height) - self.add_mod(self.nand2) + self.and2 = factory.create(module_type="pand2", + height=self.cell_height, + size=self.cols) + self.add_mod(self.and2) def route_vdd_gnd(self): """ @@ -75,68 +78,64 @@ class wordline_driver(design.design): """ # Find the x offsets for where the vias/pins should be placed - a_xoffset = self.nand_inst[0].lx() + xoffset_list = [self.and_inst[0].lx()] for num in range(self.rows): # this will result in duplicate polygons for rails, but who cares - # use the inverter offset even though it will be the nand's too + # use the inverter offset even though it will be the and's too (gate_offset, y_dir) = self.get_gate_offset(0, - self.inv.height, + self.and2.height, num) - # Route both supplies for name in ["vdd", "gnd"]: - supply_pin = self.inv2_inst[num].get_pin(name) + supply_pin = self.and_inst[num].get_pin(name) # Add pins in two locations - for xoffset in [a_xoffset]: + for xoffset in xoffset_list: pin_pos = vector(xoffset, supply_pin.cy()) self.add_power_pin(name, pin_pos) def create_drivers(self): - self.nand_inst = [] - self.inv2_inst = [] + self.and_inst = [] for row in range(self.rows): - name_nand = "wl_driver_nand{}".format(row) - name_inv2 = "wl_driver_inv{}".format(row) + name_and = "wl_driver_and{}".format(row) - # add nand 2 - self.nand_inst.append(self.add_inst(name=name_nand, - mod=self.nand2)) + # add and2 + self.and_inst.append(self.add_inst(name=name_and, + mod=self.and2)) self.connect_inst(["en", "in_{0}".format(row), - "wl_bar_{0}".format(row), - "vdd", "gnd"]) - # add inv2 - self.inv2_inst.append(self.add_inst(name=name_inv2, - mod=self.inv)) - self.connect_inst(["wl_bar_{0}".format(row), "wl_{0}".format(row), "vdd", "gnd"]) + + def setup_layout_constants(self): + # We may have more than one bitcell per decoder row + self.num_rows = math.ceil(self.rows / self.cell_multiple) + # We will place this many final decoders per row + self.decoders_per_row = math.ceil(self.rows / self.num_rows) def place_drivers(self): - nand2_xoffset = 2 * self.m1_width + 5 * self.m1_space - inv2_xoffset = nand2_xoffset + self.nand2.width + and2_xoffset = 2 * self.m1_width + 5 * self.m1_space - self.width = inv2_xoffset + self.inv.width - self.height = self.inv.height * self.rows + self.width = and2_xoffset + self.and2.width + self.height = self.and2.height * self.num_rows for row in range(self.rows): + #row = math.floor(inst_index / self.decoders_per_row) + #dec = inst_index % self.decoders_per_row + if (row % 2): - y_offset = self.inv.height * (row + 1) + y_offset = self.and2.height * (row + 1) inst_mirror = "MX" else: - y_offset = self.inv.height * row + y_offset = self.and2.height * row inst_mirror = "R0" - nand2_offset = [nand2_xoffset, y_offset] - inv2_offset = [inv2_xoffset, y_offset] + # x_off = self.internal_routing_width + dec * and_mod.width + and2_offset = [and2_xoffset, y_offset] - # add nand 2 - self.nand_inst[row].place(offset=nand2_offset, - mirror=inst_mirror) - # add inv2 - self.inv2_inst[row].place(offset=inv2_offset, + # add and2 + self.and_inst[row].place(offset=and2_offset, mirror=inst_mirror) def route_layout(self): @@ -151,11 +150,10 @@ class wordline_driver(design.design): height=self.height) for row in range(self.rows): - nand_inst = self.nand_inst[row] - inv2_inst = self.inv2_inst[row] + and_inst = self.and_inst[row] # en connection - a_pin = nand_inst.get_pin("A") + a_pin = and_inst.get_pin("A") a_pos = a_pin.lc() clk_offset = vector(en_pin.bc().x, a_pos.y) self.add_segment_center(layer="m1", @@ -164,18 +162,10 @@ class wordline_driver(design.design): self.add_via_center(layers=self.m1_stack, offset=clk_offset) - # Nand2 out to 2nd inv - zr_pos = nand_inst.get_pin("Z").rc() - al_pos = inv2_inst.get_pin("A").lc() - # ensure the bend is in the middle - mid1_pos = vector(0.5 * (zr_pos.x + al_pos.x), zr_pos.y) - mid2_pos = vector(0.5 * (zr_pos.x + al_pos.x), al_pos.y) - self.add_path("m1", [zr_pos, mid1_pos, mid2_pos, al_pos]) - - # connect the decoder input pin to nand2 B - b_pin = nand_inst.get_pin("B") + # connect the decoder input pin to and2 B + b_pin = and_inst.get_pin("B") b_pos = b_pin.lc() - # needs to move down since B nand input is + # needs to move down since B and input is # nearly aligned with A inv input up_or_down = self.m2_space if row % 2 else -self.m2_space input_offset = vector(0, b_pos.y + up_or_down) @@ -192,7 +182,7 @@ class wordline_driver(design.design): offset=mid_via_offset, directions=("V", "V")) - # now connect to the nand2 B + # now connect to the and2 B self.add_path("m2", [mid_via_offset, b_pos]) contact_offset = b_pos - vector(0.5 * contact.m1_via.height, 0) self.add_via_center(layers=self.m1_stack, @@ -200,7 +190,7 @@ class wordline_driver(design.design): directions=("H", "H")) # output each WL on the right - wl_offset = inv2_inst.get_pin("Z").rc() + wl_offset = and_inst.get_pin("Z").rc() self.add_layout_pin_segment_center(text="wl_{0}".format(row), layer="m1", start=wl_offset, @@ -213,13 +203,8 @@ class wordline_driver(design.design): """ stage_effort_list = [] - stage1_cout = self.inv.get_cin() - stage1 = self.nand2.get_stage_effort(stage1_cout, inp_is_rise) + stage1 = self.and2.get_stage_effort(external_cout, inp_is_rise) stage_effort_list.append(stage1) - last_stage_is_rise = stage1.is_rise - - stage2 = self.inv.get_stage_efforts(external_cout, last_stage_is_rise) - stage_effort_list.extend(stage2) return stage_effort_list @@ -228,6 +213,6 @@ class wordline_driver(design.design): Get the relative capacitance of all the enable connections in the bank """ - # The enable is connected to a nand2 for every row. - total_cin = self.nand2.get_cin() * self.rows + # The enable is connected to a and2 for every row. + total_cin = self.and2.get_cin() * self.rows return total_cin diff --git a/compiler/pgates/pand2.py b/compiler/pgates/pand2.py index 23fd5e5b..4c044f1c 100644 --- a/compiler/pgates/pand2.py +++ b/compiler/pgates/pand2.py @@ -30,13 +30,12 @@ class pand2(pgate.pgate): self.create_insts() def create_modules(self): - # Shield the cap, but have at least a stage effort of 4 self.nand = factory.create(module_type="pnand2", height=self.height) self.add_mod(self.nand) self.inv = factory.create(module_type="pdriver", neg_polarity=True, - fanout=3*self.size, + fanout=self.size, height=self.height) self.add_mod(self.inv) @@ -45,6 +44,7 @@ class pand2(pgate.pgate): self.place_insts() self.add_wires() self.add_layout_pins() + self.add_boundary() self.DRC_LVS() def add_pins(self): diff --git a/compiler/pgates/pand3.py b/compiler/pgates/pand3.py index dd1d87f7..f8cc2ac3 100644 --- a/compiler/pgates/pand3.py +++ b/compiler/pgates/pand3.py @@ -44,6 +44,7 @@ class pand3(pgate.pgate): self.place_insts() self.add_wires() self.add_layout_pins() + self.add_boundary() self.DRC_LVS() def add_pins(self): diff --git a/compiler/pgates/pbuf.py b/compiler/pgates/pbuf.py index 3171324b..6f9719eb 100644 --- a/compiler/pgates/pbuf.py +++ b/compiler/pgates/pbuf.py @@ -37,6 +37,7 @@ class pbuf(pgate.pgate): self.place_insts() self.add_wires() self.add_layout_pins() + self.add_boundary() def add_pins(self): self.add_pin("A", "INPUT") diff --git a/compiler/pgates/pdriver.py b/compiler/pgates/pdriver.py index 5aa5393e..4bf654a4 100644 --- a/compiler/pgates/pdriver.py +++ b/compiler/pgates/pdriver.py @@ -76,6 +76,7 @@ class pdriver(pgate.pgate): self.width = self.inv_inst_list[-1].rx() self.height = self.inv_inst_list[0].height + self.add_boundary() def add_pins(self): self.add_pin("A", "INPUT") diff --git a/compiler/pgates/pinv.py b/compiler/pgates/pinv.py index d3062cba..0a26a2fd 100644 --- a/compiler/pgates/pinv.py +++ b/compiler/pgates/pinv.py @@ -68,6 +68,7 @@ class pinv(pgate.pgate): "A", position="farleft") self.route_outputs() + self.add_boundary() def add_pins(self): """ Adds pins for spice netlist """ diff --git a/compiler/pgates/pinvbuf.py b/compiler/pgates/pinvbuf.py index b8ecb3bf..fe376bc4 100644 --- a/compiler/pgates/pinvbuf.py +++ b/compiler/pgates/pinvbuf.py @@ -47,6 +47,7 @@ class pinvbuf(pgate.pgate): self.place_modules() self.route_wires() self.add_layout_pins() + self.add_boundary() self.offset_all_coordinates() diff --git a/compiler/pgates/pnand2.py b/compiler/pgates/pnand2.py index a2dc7d0b..08024cea 100644 --- a/compiler/pgates/pnand2.py +++ b/compiler/pgates/pnand2.py @@ -62,7 +62,8 @@ class pnand2(pgate.pgate): self.extend_wells() self.route_inputs() self.route_output() - + self.add_boundary() + def add_pins(self): """ Adds pins for spice netlist """ pin_list = ["A", "B", "Z", "vdd", "gnd"] diff --git a/compiler/pgates/pnand3.py b/compiler/pgates/pnand3.py index 866d628a..5f047fc4 100644 --- a/compiler/pgates/pnand3.py +++ b/compiler/pgates/pnand3.py @@ -70,6 +70,7 @@ class pnand3(pgate.pgate): self.extend_wells() self.route_inputs() self.route_output() + self.add_boundary() def add_ptx(self): """ Create the PMOS and NMOS transistors. """ diff --git a/compiler/pgates/pnor2.py b/compiler/pgates/pnor2.py index b1899b4c..225a795c 100644 --- a/compiler/pgates/pnor2.py +++ b/compiler/pgates/pnor2.py @@ -61,6 +61,7 @@ class pnor2(pgate.pgate): self.extend_wells() self.route_inputs() self.route_output() + self.add_boundary() def add_pins(self): """ Adds pins for spice netlist """ diff --git a/compiler/pgates/precharge.py b/compiler/pgates/precharge.py index 45128421..6985efeb 100644 --- a/compiler/pgates/precharge.py +++ b/compiler/pgates/precharge.py @@ -70,7 +70,8 @@ class precharge(design.design): self.route_vdd_rail() self.route_bitlines() self.connect_to_bitlines() - + self.add_boundary() + def add_pins(self): self.add_pin_list(["bl", "br", "en_bar", "vdd"], ["OUTPUT", "OUTPUT", "INPUT", "POWER"]) diff --git a/compiler/pgates/ptristate_inv.py b/compiler/pgates/ptristate_inv.py index 9586e72b..22f6b164 100644 --- a/compiler/pgates/ptristate_inv.py +++ b/compiler/pgates/ptristate_inv.py @@ -56,6 +56,7 @@ class ptristate_inv(pgate.pgate): self.connect_rails() self.route_inputs() self.route_outputs() + self.add_boundary() def add_pins(self): """ Adds pins for spice netlist """ diff --git a/compiler/pgates/pwrite_driver.py b/compiler/pgates/pwrite_driver.py index 16830e62..da5eacdc 100644 --- a/compiler/pgates/pwrite_driver.py +++ b/compiler/pgates/pwrite_driver.py @@ -52,6 +52,7 @@ class pwrite_driver(design.design): self.place_modules() self.route_wires() self.route_supplies() + self.add_boundary() def add_pins(self): self.add_pin("din", "INPUT") diff --git a/compiler/tests/18_port_data_1rw_1r_test.py b/compiler/tests/18_port_data_1rw_1r_test.py new file mode 100755 index 00000000..6201de6a --- /dev/null +++ b/compiler/tests/18_port_data_1rw_1r_test.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python3 +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2019 Regents of the University of California +# All rights reserved. +# +import unittest +from testutils import * +import sys,os +sys.path.append(os.getenv("OPENRAM_HOME")) +import globals +from globals import OPTS +from sram_factory import factory +import debug + +class port_data_1rw_1r_test(openram_test): + + def runTest(self): + config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME")) + globals.init_openram(config_file) + from sram_config import sram_config + + OPTS.bitcell = "bitcell_1w_1r" + OPTS.num_rw_ports = 0 + OPTS.num_r_ports = 1 + OPTS.num_w_ports = 1 + + 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) + a = factory.create("port_data", sram_config=c, port=1) + 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) + a = factory.create("port_data", sram_config=c, port=1) + 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) + a = factory.create("port_data", sram_config=c, port=1) + 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) + a = factory.create("port_data", sram_config=c, port=1) + self.local_check(a) + + globals.end_openram() + +# run the test from the command line +if __name__ == "__main__": + (OPTS, args) = globals.parse_args() + del sys.argv[1:] + header(__file__, OPTS.tech_name) + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/18_port_data_test.py b/compiler/tests/18_port_data_test.py index 71681056..57e19846 100755 --- a/compiler/tests/18_port_data_test.py +++ b/compiler/tests/18_port_data_test.py @@ -55,52 +55,6 @@ class port_data_test(openram_test): a = factory.create("port_data", sram_config=c, port=0) self.local_check(a) - OPTS.bitcell = "bitcell_1w_1r" - OPTS.num_rw_ports = 0 - OPTS.num_r_ports = 1 - OPTS.num_w_ports = 1 - - c.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) - a = factory.create("port_data", sram_config=c, port=1) - 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) - a = factory.create("port_data", sram_config=c, port=1) - 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) - a = factory.create("port_data", sram_config=c, port=1) - 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) - a = factory.create("port_data", sram_config=c, port=1) - self.local_check(a) - globals.end_openram() # run the test from the command line diff --git a/compiler/tests/21_hspice_delay_test.py b/compiler/tests/21_hspice_delay_test.py index 832a6308..a602f9d2 100755 --- a/compiler/tests/21_hspice_delay_test.py +++ b/compiler/tests/21_hspice_delay_test.py @@ -60,29 +60,36 @@ class timing_sram_test(openram_test): data, port_data = d.analyze(probe_address, probe_data, slews, loads) #Combine info about port into all data data.update(port_data[0]) - + if OPTS.tech_name == "freepdk45": - golden_data = {'delay_hl': [0.2383338], - 'delay_lh': [0.2383338], - 'leakage_power': 0.0014532999999999998, - 'min_period': 0.898, - 'read0_power': [0.30059800000000003], - 'read1_power': [0.30061810000000005], - 'slew_hl': [0.25358420000000004], - 'slew_lh': [0.25358420000000004], - 'write0_power': [0.34616749999999996], - 'write1_power': [0.2792924]} + golden_data = {'min_period': 0.898, + 'write1_power': [0.2659137999999999], + 'disabled_write0_power': [0.1782495], + 'disabled_read0_power': [0.14490679999999997], + 'write0_power': [0.3330119], + 'disabled_write1_power': [0.1865223], + 'leakage_power': 0.0014532, + 'disabled_read1_power': [0.1627516], + 'slew_lh': [0.25367799999999996], + 'slew_hl': [0.25367799999999996], + 'delay_lh': [0.23820930000000004], + 'delay_hl': [0.23820930000000004], + 'read1_power': [0.3005756], + 'read0_power': [0.3005888]} elif OPTS.tech_name == "scn4m_subm": - golden_data = {'delay_hl': [1.7448], - 'delay_lh': [1.7448], - 'leakage_power': 0.0006356744000000001, + golden_data = {'leakage_power': 0.0006356576000000001, + 'write1_power': [11.292700000000002], + 'read0_power': [12.98], + 'disabled_write1_power': [8.3707], + 'write0_power': [14.4447], 'delay_hl': [1.7445000000000002], + 'disabled_read0_power': [6.4325], + 'slew_hl': [1.7437], + 'disabled_write0_power': [8.1307], + 'slew_lh': [1.7437], + 'read1_power': [12.9869], + 'disabled_read1_power': [7.706], 'min_period': 6.25, - 'read0_power': [12.9846], - 'read1_power': [12.9722], - 'slew_hl': [1.7433], - 'slew_lh': [1.7433], - 'write0_power': [14.8772], - 'write1_power': [11.7217]} + 'delay_lh': [1.7445000000000002]} else: self.assertTrue(False) # other techs fail # Check if no too many or too few results diff --git a/compiler/tests/21_ngspice_delay_test.py b/compiler/tests/21_ngspice_delay_test.py index fb72a57d..c944b3ce 100755 --- a/compiler/tests/21_ngspice_delay_test.py +++ b/compiler/tests/21_ngspice_delay_test.py @@ -55,27 +55,35 @@ class timing_sram_test(openram_test): data.update(port_data[0]) if OPTS.tech_name == "freepdk45": - golden_data = {'delay_hl': [0.2264205], - 'delay_lh': [0.2264205], - 'leakage_power': 0.0021017429999999997, - 'min_period': 0.859, - 'read0_power': [0.3339161], - 'read1_power': [0.31329440000000003], - 'slew_hl': [0.2590786], - 'slew_lh': [0.2590786], - 'write0_power': [0.36360849999999995], - 'write1_power': [0.3486931]} + golden_data = {'slew_lh': [0.2592187], + 'slew_hl': [0.2592187], + 'delay_lh': [0.2465583], + 'disabled_write0_power': [0.1924678], + 'disabled_read0_power': [0.152483], + 'write0_power': [0.3409064], + 'disabled_read1_power': [0.1737818], + 'read0_power': [0.3096708], + 'read1_power': [0.3107916], + 'delay_hl': [0.2465583], + 'write1_power': [0.26915849999999997], + 'leakage_power': 0.002044307, + 'min_period': 0.898, + 'disabled_write1_power': [0.201411]} elif OPTS.tech_name == "scn4m_subm": - golden_data = {'delay_hl': [1.85985], - 'delay_lh': [1.85985], + golden_data = {'read1_power': [12.11658], + 'write1_power': [10.52653], + 'read0_power': [11.956710000000001], + 'disabled_write0_power': [7.673665], + 'disabled_write1_power': [7.981922000000001], + 'slew_lh': [1.868836], + 'slew_hl': [1.868836], + 'delay_hl': [1.8598510000000001], + 'delay_lh': [1.8598510000000001], 'leakage_power': 0.008613619, + 'disabled_read0_power': [5.904712], 'min_period': 6.875, - 'read0_power': [12.656310000000001], - 'read1_power': [12.11682], - 'slew_hl': [1.868942], - 'slew_lh': [1.868942], - 'write0_power': [13.978110000000001], - 'write1_power': [11.437930000000001]} + 'disabled_read1_power': [7.132159], + 'write0_power': [13.406400000000001]} else: self.assertTrue(False) # other techs fail diff --git a/compiler/tests/golden/sram_2_16_1_freepdk45_FF_1p0V_25C_analytical.lib b/compiler/tests/golden/sram_2_16_1_freepdk45_FF_1p0V_25C_analytical.lib index a1c5a04b..b3ef0e0a 100644 --- a/compiler/tests/golden/sram_2_16_1_freepdk45_FF_1p0V_25C_analytical.lib +++ b/compiler/tests/golden/sram_2_16_1_freepdk45_FF_1p0V_25C_analytical.lib @@ -35,11 +35,14 @@ library (sram_2_16_1_freepdk45_FF_1p0V_25C_lib){ default_max_fanout : 4.0 ; default_connection_class : universal ; + voltage_map ( VDD, 1.0 ); + voltage_map ( GND, 0 ); + lu_table_template(CELL_TABLE){ variable_1 : input_net_transition; variable_2 : total_output_net_capacitance; index_1("0.00125, 0.005, 0.04"); - index_2("0.052275, 0.2091, 1.6728"); + index_2("5.2275e-05, 0.0002091, 0.0008364"); } lu_table_template(CONSTRAINT_TABLE){ @@ -78,17 +81,26 @@ cell (sram_2_16_1_freepdk45){ dont_use : true; map_only : true; dont_touch : true; - area : 1124.88; + area : 0; + + pg_pin(vdd) { + voltage_name : VDD; + pg_type : primary_power; + } + + pg_pin(gnd) { + voltage_name : GND; + pg_type : primary_ground; + } leakage_power () { - when : "csb0"; - value : 0.000167; + value : 0.000198; } - cell_leakage_power : 0; + cell_leakage_power : 0.000198; bus(din0){ bus_type : data; direction : input; - capacitance : 0.2091; + capacitance : 0.00020910000000000001; memory_write(){ address : addr0; clocked_on : clk0; @@ -127,8 +139,8 @@ cell (sram_2_16_1_freepdk45){ bus(dout0){ bus_type : data; direction : output; - max_capacitance : 1.6728; - min_capacitance : 0.052275; + max_capacitance : 0.0008364000000000001; + min_capacitance : 5.2275000000000003e-05; memory_read(){ address : addr0; } @@ -138,14 +150,14 @@ cell (sram_2_16_1_freepdk45){ related_pin : "clk0"; timing_type : falling_edge; cell_rise(CELL_TABLE) { - values("0.088, 0.088, 0.088",\ - "0.088, 0.088, 0.088",\ - "0.088, 0.088, 0.088"); + values("0.193, 0.193, 0.194",\ + "0.193, 0.193, 0.194",\ + "0.193, 0.193, 0.194"); } cell_fall(CELL_TABLE) { - values("0.088, 0.088, 0.088",\ - "0.088, 0.088, 0.088",\ - "0.088, 0.088, 0.088"); + values("0.193, 0.193, 0.194",\ + "0.193, 0.193, 0.194",\ + "0.193, 0.193, 0.194"); } rise_transition(CELL_TABLE) { values("0.001, 0.001, 0.001",\ @@ -164,7 +176,7 @@ cell (sram_2_16_1_freepdk45){ bus(addr0){ bus_type : addr; direction : input; - capacitance : 0.2091; + capacitance : 0.00020910000000000001; max_transition : 0.04; pin(addr0[3:0]){ timing(){ @@ -200,7 +212,7 @@ cell (sram_2_16_1_freepdk45){ pin(csb0){ direction : input; - capacitance : 0.2091; + capacitance : 0.00020910000000000001; timing(){ timing_type : setup_rising; related_pin : "clk0"; @@ -233,7 +245,7 @@ cell (sram_2_16_1_freepdk45){ pin(web0){ direction : input; - capacitance : 0.2091; + capacitance : 0.00020910000000000001; timing(){ timing_type : setup_rising; related_pin : "clk0"; @@ -267,52 +279,61 @@ cell (sram_2_16_1_freepdk45){ pin(clk0){ clock : true; direction : input; - capacitance : 0.2091; + capacitance : 0.00020910000000000001; internal_power(){ - when : "!csb0 & clk0 & !web0"; + when : "!csb0 & !web0"; rise_power(scalar){ - values("0.033101244168888884"); + values("9.240667e-02"); } fall_power(scalar){ - values("0.033101244168888884"); + values("9.240667e-02"); } } internal_power(){ - when : "!csb0 & !clk0 & web0"; + when : "csb0 & !web0"; rise_power(scalar){ - values("0.033101244168888884"); + values("9.240667e-02"); } fall_power(scalar){ - values("0.033101244168888884"); + values("9.240667e-02"); } } internal_power(){ - when : "csb0"; + when : "!csb0 & web0"; rise_power(scalar){ - values("0"); + values("9.240667e-02"); } fall_power(scalar){ - values("0"); + values("9.240667e-02"); + } + } + internal_power(){ + when : "csb0 & web0"; + rise_power(scalar){ + values("9.240667e-02"); + } + fall_power(scalar){ + values("9.240667e-02"); } } timing(){ timing_type :"min_pulse_width"; related_pin : clk0; rise_constraint(scalar) { - values("0.009"); + values("0.0195"); } fall_constraint(scalar) { - values("0.009"); + values("0.0195"); } } timing(){ timing_type :"minimum_period"; related_pin : clk0; rise_constraint(scalar) { - values("0.018"); + values("0.039"); } fall_constraint(scalar) { - values("0.018"); + values("0.039"); } } } diff --git a/compiler/tests/golden/sram_2_16_1_freepdk45_SS_1p0V_25C_analytical.lib b/compiler/tests/golden/sram_2_16_1_freepdk45_SS_1p0V_25C_analytical.lib index 865daada..34be4fe4 100644 --- a/compiler/tests/golden/sram_2_16_1_freepdk45_SS_1p0V_25C_analytical.lib +++ b/compiler/tests/golden/sram_2_16_1_freepdk45_SS_1p0V_25C_analytical.lib @@ -35,11 +35,14 @@ library (sram_2_16_1_freepdk45_SS_1p0V_25C_lib){ default_max_fanout : 4.0 ; default_connection_class : universal ; + voltage_map ( VDD, 1.0 ); + voltage_map ( GND, 0 ); + lu_table_template(CELL_TABLE){ variable_1 : input_net_transition; variable_2 : total_output_net_capacitance; index_1("0.00125, 0.005, 0.04"); - index_2("0.052275, 0.2091, 1.6728"); + index_2("5.2275e-05, 0.0002091, 0.0008364"); } lu_table_template(CONSTRAINT_TABLE){ @@ -78,17 +81,26 @@ cell (sram_2_16_1_freepdk45){ dont_use : true; map_only : true; dont_touch : true; - area : 1124.88; + area : 0; + + pg_pin(vdd) { + voltage_name : VDD; + pg_type : primary_power; + } + + pg_pin(gnd) { + voltage_name : GND; + pg_type : primary_ground; + } leakage_power () { - when : "csb0"; - value : 0.000167; + value : 0.000198; } - cell_leakage_power : 0; + cell_leakage_power : 0.000198; bus(din0){ bus_type : data; direction : input; - capacitance : 0.2091; + capacitance : 0.00020910000000000001; memory_write(){ address : addr0; clocked_on : clk0; @@ -127,8 +139,8 @@ cell (sram_2_16_1_freepdk45){ bus(dout0){ bus_type : data; direction : output; - max_capacitance : 1.6728; - min_capacitance : 0.052275; + max_capacitance : 0.0008364000000000001; + min_capacitance : 5.2275000000000003e-05; memory_read(){ address : addr0; } @@ -138,14 +150,14 @@ cell (sram_2_16_1_freepdk45){ related_pin : "clk0"; timing_type : falling_edge; cell_rise(CELL_TABLE) { - values("0.107, 0.107, 0.107",\ - "0.107, 0.107, 0.107",\ - "0.107, 0.107, 0.107"); + values("0.236, 0.236, 0.237",\ + "0.236, 0.236, 0.237",\ + "0.236, 0.236, 0.237"); } cell_fall(CELL_TABLE) { - values("0.107, 0.107, 0.107",\ - "0.107, 0.107, 0.107",\ - "0.107, 0.107, 0.107"); + values("0.236, 0.236, 0.237",\ + "0.236, 0.236, 0.237",\ + "0.236, 0.236, 0.237"); } rise_transition(CELL_TABLE) { values("0.001, 0.001, 0.001",\ @@ -164,7 +176,7 @@ cell (sram_2_16_1_freepdk45){ bus(addr0){ bus_type : addr; direction : input; - capacitance : 0.2091; + capacitance : 0.00020910000000000001; max_transition : 0.04; pin(addr0[3:0]){ timing(){ @@ -200,7 +212,7 @@ cell (sram_2_16_1_freepdk45){ pin(csb0){ direction : input; - capacitance : 0.2091; + capacitance : 0.00020910000000000001; timing(){ timing_type : setup_rising; related_pin : "clk0"; @@ -233,7 +245,7 @@ cell (sram_2_16_1_freepdk45){ pin(web0){ direction : input; - capacitance : 0.2091; + capacitance : 0.00020910000000000001; timing(){ timing_type : setup_rising; related_pin : "clk0"; @@ -267,52 +279,61 @@ cell (sram_2_16_1_freepdk45){ pin(clk0){ clock : true; direction : input; - capacitance : 0.2091; + capacitance : 0.00020910000000000001; internal_power(){ - when : "!csb0 & clk0 & !web0"; + when : "!csb0 & !web0"; rise_power(scalar){ - values("0.033101244168888884"); + values("7.560546e-02"); } fall_power(scalar){ - values("0.033101244168888884"); + values("7.560546e-02"); } } internal_power(){ - when : "!csb0 & !clk0 & web0"; + when : "csb0 & !web0"; rise_power(scalar){ - values("0.033101244168888884"); + values("7.560546e-02"); } fall_power(scalar){ - values("0.033101244168888884"); + values("7.560546e-02"); } } internal_power(){ - when : "csb0"; + when : "!csb0 & web0"; rise_power(scalar){ - values("0"); + values("7.560546e-02"); } fall_power(scalar){ - values("0"); + values("7.560546e-02"); + } + } + internal_power(){ + when : "csb0 & web0"; + rise_power(scalar){ + values("7.560546e-02"); + } + fall_power(scalar){ + values("7.560546e-02"); } } timing(){ timing_type :"min_pulse_width"; related_pin : clk0; rise_constraint(scalar) { - values("0.0105"); + values("0.0235"); } fall_constraint(scalar) { - values("0.0105"); + values("0.0235"); } } timing(){ timing_type :"minimum_period"; related_pin : clk0; rise_constraint(scalar) { - values("0.021"); + values("0.047"); } fall_constraint(scalar) { - values("0.021"); + values("0.047"); } } } diff --git a/compiler/tests/golden/sram_2_16_1_freepdk45_TT_1p0V_25C.lib b/compiler/tests/golden/sram_2_16_1_freepdk45_TT_1p0V_25C.lib index 72d01a0f..cca9c1ed 100644 --- a/compiler/tests/golden/sram_2_16_1_freepdk45_TT_1p0V_25C.lib +++ b/compiler/tests/golden/sram_2_16_1_freepdk45_TT_1p0V_25C.lib @@ -35,11 +35,14 @@ library (sram_2_16_1_freepdk45_TT_1p0V_25C_lib){ default_max_fanout : 4.0 ; default_connection_class : universal ; + voltage_map ( VDD, 1.0 ); + voltage_map ( GND, 0 ); + lu_table_template(CELL_TABLE){ variable_1 : input_net_transition; variable_2 : total_output_net_capacitance; index_1("0.00125, 0.005, 0.04"); - index_2("0.052275, 0.2091, 1.6728"); + index_2("5.2275e-05, 0.0002091, 0.0008364"); } lu_table_template(CONSTRAINT_TABLE){ @@ -78,17 +81,26 @@ cell (sram_2_16_1_freepdk45){ dont_use : true; map_only : true; dont_touch : true; - area : 977.4951374999999; + area : 0; + + pg_pin(vdd) { + voltage_name : VDD; + pg_type : primary_power; + } + + pg_pin(gnd) { + voltage_name : GND; + pg_type : primary_ground; + } leakage_power () { - when : "csb0"; - value : 0.0011164579999999999; + value : 0.00163; } - cell_leakage_power : 0; + cell_leakage_power : 0.00163; bus(din0){ bus_type : data; direction : input; - capacitance : 0.2091; + capacitance : 0.00020910000000000001; memory_write(){ address : addr0; clocked_on : clk0; @@ -98,9 +110,9 @@ cell (sram_2_16_1_freepdk45){ timing_type : setup_rising; related_pin : "clk0"; rise_constraint(CONSTRAINT_TABLE) { - values("0.033, 0.033, 0.039",\ - "0.033, 0.033, 0.039",\ - "0.033, 0.033, 0.039"); + values("0.033, 0.033, 0.033",\ + "0.033, 0.033, 0.033",\ + "0.033, 0.033, 0.033"); } fall_constraint(CONSTRAINT_TABLE) { values("0.027, 0.027, 0.033",\ @@ -112,14 +124,14 @@ cell (sram_2_16_1_freepdk45){ timing_type : hold_rising; related_pin : "clk0"; rise_constraint(CONSTRAINT_TABLE) { - values("-0.01, -0.016, -0.022",\ - "-0.01, -0.016, -0.022",\ - "-0.01, -0.016, -0.022"); + values("-0.01, -0.01, 0.021",\ + "-0.01, -0.01, 0.021",\ + "-0.01, -0.01, 0.021"); } fall_constraint(CONSTRAINT_TABLE) { - values("-0.016, -0.016, -0.016",\ - "-0.016, -0.016, -0.016",\ - "-0.016, -0.016, -0.016"); + values("-0.016, -0.01, -0.016",\ + "-0.016, -0.01, -0.016",\ + "-0.016, -0.01, -0.016"); } } } @@ -127,8 +139,8 @@ cell (sram_2_16_1_freepdk45){ bus(dout0){ bus_type : data; direction : output; - max_capacitance : 1.6728; - min_capacitance : 0.052275; + max_capacitance : 0.0008364000000000001; + min_capacitance : 5.2275000000000003e-05; memory_read(){ address : addr0; } @@ -138,24 +150,24 @@ cell (sram_2_16_1_freepdk45){ related_pin : "clk0"; timing_type : falling_edge; cell_rise(CELL_TABLE) { - values("0.235, 0.235, 0.239",\ - "0.235, 0.236, 0.24",\ - "0.241, 0.242, 0.246"); + values("0.226, 0.227, 0.232",\ + "0.227, 0.228, 0.233",\ + "0.232, 0.234, 0.238"); } cell_fall(CELL_TABLE) { - values("2.583, 2.585, 2.612",\ - "2.584, 2.585, 2.613",\ - "2.59, 2.592, 2.62"); + values("0.226, 0.227, 0.232",\ + "0.227, 0.228, 0.233",\ + "0.232, 0.234, 0.238"); } rise_transition(CELL_TABLE) { - values("0.022, 0.022, 0.03",\ - "0.022, 0.023, 0.03",\ - "0.022, 0.022, 0.03"); + values("0.256, 0.256, 0.257",\ + "0.256, 0.256, 0.257",\ + "0.256, 0.256, 0.257"); } fall_transition(CELL_TABLE) { - values("0.078, 0.079, 0.083",\ - "0.078, 0.079, 0.083",\ - "0.079, 0.079, 0.083"); + values("0.256, 0.256, 0.257",\ + "0.256, 0.256, 0.257",\ + "0.256, 0.256, 0.257"); } } } @@ -164,16 +176,16 @@ cell (sram_2_16_1_freepdk45){ bus(addr0){ bus_type : addr; direction : input; - capacitance : 0.2091; + capacitance : 0.00020910000000000001; max_transition : 0.04; pin(addr0[3:0]){ timing(){ timing_type : setup_rising; related_pin : "clk0"; rise_constraint(CONSTRAINT_TABLE) { - values("0.033, 0.033, 0.039",\ - "0.033, 0.033, 0.039",\ - "0.033, 0.033, 0.039"); + values("0.033, 0.033, 0.033",\ + "0.033, 0.033, 0.033",\ + "0.033, 0.033, 0.033"); } fall_constraint(CONSTRAINT_TABLE) { values("0.027, 0.027, 0.033",\ @@ -185,14 +197,14 @@ cell (sram_2_16_1_freepdk45){ timing_type : hold_rising; related_pin : "clk0"; rise_constraint(CONSTRAINT_TABLE) { - values("-0.01, -0.016, -0.022",\ - "-0.01, -0.016, -0.022",\ - "-0.01, -0.016, -0.022"); + values("-0.01, -0.01, 0.021",\ + "-0.01, -0.01, 0.021",\ + "-0.01, -0.01, 0.021"); } fall_constraint(CONSTRAINT_TABLE) { - values("-0.016, -0.016, -0.016",\ - "-0.016, -0.016, -0.016",\ - "-0.016, -0.016, -0.016"); + values("-0.016, -0.01, -0.016",\ + "-0.016, -0.01, -0.016",\ + "-0.016, -0.01, -0.016"); } } } @@ -200,14 +212,14 @@ cell (sram_2_16_1_freepdk45){ pin(csb0){ direction : input; - capacitance : 0.2091; + capacitance : 0.00020910000000000001; timing(){ timing_type : setup_rising; related_pin : "clk0"; rise_constraint(CONSTRAINT_TABLE) { - values("0.033, 0.033, 0.039",\ - "0.033, 0.033, 0.039",\ - "0.033, 0.033, 0.039"); + values("0.033, 0.033, 0.033",\ + "0.033, 0.033, 0.033",\ + "0.033, 0.033, 0.033"); } fall_constraint(CONSTRAINT_TABLE) { values("0.027, 0.027, 0.033",\ @@ -219,28 +231,28 @@ cell (sram_2_16_1_freepdk45){ timing_type : hold_rising; related_pin : "clk0"; rise_constraint(CONSTRAINT_TABLE) { - values("-0.01, -0.016, -0.022",\ - "-0.01, -0.016, -0.022",\ - "-0.01, -0.016, -0.022"); + values("-0.01, -0.01, 0.021",\ + "-0.01, -0.01, 0.021",\ + "-0.01, -0.01, 0.021"); } fall_constraint(CONSTRAINT_TABLE) { - values("-0.016, -0.016, -0.016",\ - "-0.016, -0.016, -0.016",\ - "-0.016, -0.016, -0.016"); + values("-0.016, -0.01, -0.016",\ + "-0.016, -0.01, -0.016",\ + "-0.016, -0.01, -0.016"); } } } pin(web0){ direction : input; - capacitance : 0.2091; + capacitance : 0.00020910000000000001; timing(){ timing_type : setup_rising; related_pin : "clk0"; rise_constraint(CONSTRAINT_TABLE) { - values("0.033, 0.033, 0.039",\ - "0.033, 0.033, 0.039",\ - "0.033, 0.033, 0.039"); + values("0.033, 0.033, 0.033",\ + "0.033, 0.033, 0.033",\ + "0.033, 0.033, 0.033"); } fall_constraint(CONSTRAINT_TABLE) { values("0.027, 0.027, 0.033",\ @@ -252,14 +264,14 @@ cell (sram_2_16_1_freepdk45){ timing_type : hold_rising; related_pin : "clk0"; rise_constraint(CONSTRAINT_TABLE) { - values("-0.01, -0.016, -0.022",\ - "-0.01, -0.016, -0.022",\ - "-0.01, -0.016, -0.022"); + values("-0.01, -0.01, 0.021",\ + "-0.01, -0.01, 0.021",\ + "-0.01, -0.01, 0.021"); } fall_constraint(CONSTRAINT_TABLE) { - values("-0.016, -0.016, -0.016",\ - "-0.016, -0.016, -0.016",\ - "-0.016, -0.016, -0.016"); + values("-0.016, -0.01, -0.016",\ + "-0.016, -0.01, -0.016",\ + "-0.016, -0.01, -0.016"); } } } @@ -267,52 +279,61 @@ cell (sram_2_16_1_freepdk45){ pin(clk0){ clock : true; direction : input; - capacitance : 0.2091; + capacitance : 0.00020910000000000001; internal_power(){ - when : "!csb0 & clk0 & !web0"; + when : "!csb0 & !web0"; rise_power(scalar){ - values("0.03599689694444445"); + values("3.069977e-01"); } fall_power(scalar){ - values("0.03599689694444445"); + values("3.686680e-01"); } } internal_power(){ - when : "!csb0 & !clk0 & web0"; + when : "csb0 & !web0"; rise_power(scalar){ - values("0.029906643888888886"); + values("2.055845e-01"); } fall_power(scalar){ - values("0.029906643888888886"); + values("1.933561e-01"); } } internal_power(){ - when : "csb0"; + when : "!csb0 & web0"; rise_power(scalar){ - values("0"); + values("3.315565e-01"); } fall_power(scalar){ - values("0"); + values("3.314553e-01"); + } + } + internal_power(){ + when : "csb0 & web0"; + rise_power(scalar){ + values("1.777355e-01"); + } + fall_power(scalar){ + values("1.615044e-01"); } } timing(){ timing_type :"min_pulse_width"; related_pin : clk0; rise_constraint(scalar) { - values("2.422"); + values("0.449"); } fall_constraint(scalar) { - values("2.422"); + values("0.449"); } } timing(){ timing_type :"minimum_period"; related_pin : clk0; rise_constraint(scalar) { - values("4.844"); + values("0.898"); } fall_constraint(scalar) { - values("4.844"); + values("0.898"); } } } diff --git a/compiler/tests/golden/sram_2_16_1_freepdk45_TT_1p0V_25C_analytical.lib b/compiler/tests/golden/sram_2_16_1_freepdk45_TT_1p0V_25C_analytical.lib index 33587063..26028892 100644 --- a/compiler/tests/golden/sram_2_16_1_freepdk45_TT_1p0V_25C_analytical.lib +++ b/compiler/tests/golden/sram_2_16_1_freepdk45_TT_1p0V_25C_analytical.lib @@ -35,11 +35,14 @@ library (sram_2_16_1_freepdk45_TT_1p0V_25C_lib){ default_max_fanout : 4.0 ; default_connection_class : universal ; + voltage_map ( VDD, 1.0 ); + voltage_map ( GND, 0 ); + lu_table_template(CELL_TABLE){ variable_1 : input_net_transition; variable_2 : total_output_net_capacitance; index_1("0.00125, 0.005, 0.04"); - index_2("0.052275, 0.2091, 1.6728"); + index_2("5.2275e-05, 0.0002091, 0.0008364"); } lu_table_template(CONSTRAINT_TABLE){ @@ -78,17 +81,26 @@ cell (sram_2_16_1_freepdk45){ dont_use : true; map_only : true; dont_touch : true; - area : 977.4951374999999; + area : 0; + + pg_pin(vdd) { + voltage_name : VDD; + pg_type : primary_power; + } + + pg_pin(gnd) { + voltage_name : GND; + pg_type : primary_ground; + } leakage_power () { - when : "csb0"; - value : 0.000179; + value : 0.000198; } - cell_leakage_power : 0; + cell_leakage_power : 0.000198; bus(din0){ bus_type : data; direction : input; - capacitance : 0.2091; + capacitance : 0.00020910000000000001; memory_write(){ address : addr0; clocked_on : clk0; @@ -127,8 +139,8 @@ cell (sram_2_16_1_freepdk45){ bus(dout0){ bus_type : data; direction : output; - max_capacitance : 1.6728; - min_capacitance : 0.052275; + max_capacitance : 0.0008364000000000001; + min_capacitance : 5.2275000000000003e-05; memory_read(){ address : addr0; } @@ -138,14 +150,14 @@ cell (sram_2_16_1_freepdk45){ related_pin : "clk0"; timing_type : falling_edge; cell_rise(CELL_TABLE) { - values("0.098, 0.098, 0.098",\ - "0.098, 0.098, 0.098",\ - "0.098, 0.098, 0.098"); + values("0.215, 0.215, 0.216",\ + "0.215, 0.215, 0.216",\ + "0.215, 0.215, 0.216"); } cell_fall(CELL_TABLE) { - values("0.098, 0.098, 0.098",\ - "0.098, 0.098, 0.098",\ - "0.098, 0.098, 0.098"); + values("0.215, 0.215, 0.216",\ + "0.215, 0.215, 0.216",\ + "0.215, 0.215, 0.216"); } rise_transition(CELL_TABLE) { values("0.001, 0.001, 0.001",\ @@ -164,7 +176,7 @@ cell (sram_2_16_1_freepdk45){ bus(addr0){ bus_type : addr; direction : input; - capacitance : 0.2091; + capacitance : 0.00020910000000000001; max_transition : 0.04; pin(addr0[3:0]){ timing(){ @@ -200,7 +212,7 @@ cell (sram_2_16_1_freepdk45){ pin(csb0){ direction : input; - capacitance : 0.2091; + capacitance : 0.00020910000000000001; timing(){ timing_type : setup_rising; related_pin : "clk0"; @@ -233,7 +245,7 @@ cell (sram_2_16_1_freepdk45){ pin(web0){ direction : input; - capacitance : 0.2091; + capacitance : 0.00020910000000000001; timing(){ timing_type : setup_rising; related_pin : "clk0"; @@ -267,52 +279,61 @@ cell (sram_2_16_1_freepdk45){ pin(clk0){ clock : true; direction : input; - capacitance : 0.2091; + capacitance : 0.00020910000000000001; internal_power(){ - when : "!csb0 & clk0 & !web0"; + when : "!csb0 & !web0"; rise_power(scalar){ - values("0.0747594982142222"); + values("8.316600e-02"); } fall_power(scalar){ - values("0.0747594982142222"); + values("8.316600e-02"); } } internal_power(){ - when : "!csb0 & !clk0 & web0"; + when : "csb0 & !web0"; rise_power(scalar){ - values("0.0747594982142222"); + values("8.316600e-02"); } fall_power(scalar){ - values("0.0747594982142222"); + values("8.316600e-02"); } } internal_power(){ - when : "csb0"; + when : "!csb0 & web0"; rise_power(scalar){ - values("0"); + values("8.316600e-02"); } fall_power(scalar){ - values("0"); + values("8.316600e-02"); + } + } + internal_power(){ + when : "csb0 & web0"; + rise_power(scalar){ + values("8.316600e-02"); + } + fall_power(scalar){ + values("8.316600e-02"); } } timing(){ timing_type :"min_pulse_width"; related_pin : clk0; rise_constraint(scalar) { - values("0.0"); + values("0.0215"); } fall_constraint(scalar) { - values("0.0"); + values("0.0215"); } } timing(){ timing_type :"minimum_period"; related_pin : clk0; rise_constraint(scalar) { - values("0"); + values("0.043"); } fall_constraint(scalar) { - values("0"); + values("0.043"); } } } diff --git a/compiler/tests/golden/sram_2_16_1_scn4m_subm_FF_5p0V_25C_analytical.lib b/compiler/tests/golden/sram_2_16_1_scn4m_subm_FF_5p0V_25C_analytical.lib index c370f993..6912aec7 100644 --- a/compiler/tests/golden/sram_2_16_1_scn4m_subm_FF_5p0V_25C_analytical.lib +++ b/compiler/tests/golden/sram_2_16_1_scn4m_subm_FF_5p0V_25C_analytical.lib @@ -35,11 +35,14 @@ library (sram_2_16_1_scn4m_subm_FF_5p0V_25C_lib){ default_max_fanout : 4.0 ; default_connection_class : universal ; + voltage_map ( VDD, 5.0 ); + voltage_map ( GND, 0 ); + lu_table_template(CELL_TABLE){ variable_1 : input_net_transition; variable_2 : total_output_net_capacitance; index_1("0.0125, 0.05, 0.4"); - index_2("2.45605, 9.8242, 78.5936"); + index_2("0.00245605, 0.0098242, 0.0392968"); } lu_table_template(CONSTRAINT_TABLE){ @@ -78,17 +81,26 @@ cell (sram_2_16_1_scn4m_subm){ dont_use : true; map_only : true; dont_touch : true; - area : 73068.14000000001; + area : 0; + + pg_pin(vdd) { + voltage_name : VDD; + pg_type : primary_power; + } + + pg_pin(gnd) { + voltage_name : GND; + pg_type : primary_ground; + } leakage_power () { - when : "csb0"; - value : 0.000167; + value : 0.000198; } - cell_leakage_power : 0; + cell_leakage_power : 0.000198; bus(din0){ bus_type : data; direction : input; - capacitance : 9.8242; + capacitance : 0.0098242; memory_write(){ address : addr0; clocked_on : clk0; @@ -127,8 +139,8 @@ cell (sram_2_16_1_scn4m_subm){ bus(dout0){ bus_type : data; direction : output; - max_capacitance : 78.5936; - min_capacitance : 2.45605; + max_capacitance : 0.0392968; + min_capacitance : 0.00245605; memory_read(){ address : addr0; } @@ -138,24 +150,24 @@ cell (sram_2_16_1_scn4m_subm){ related_pin : "clk0"; timing_type : falling_edge; cell_rise(CELL_TABLE) { - values("0.241, 0.241, 0.241",\ - "0.241, 0.241, 0.241",\ - "0.241, 0.241, 0.241"); + values("1.183, 1.199, 1.264",\ + "1.183, 1.199, 1.264",\ + "1.183, 1.199, 1.264"); } cell_fall(CELL_TABLE) { - values("0.241, 0.241, 0.241",\ - "0.241, 0.241, 0.241",\ - "0.241, 0.241, 0.241"); + values("1.183, 1.199, 1.264",\ + "1.183, 1.199, 1.264",\ + "1.183, 1.199, 1.264"); } rise_transition(CELL_TABLE) { - values("0.004, 0.004, 0.004",\ - "0.004, 0.004, 0.004",\ - "0.004, 0.004, 0.004"); + values("0.006, 0.007, 0.014",\ + "0.006, 0.007, 0.014",\ + "0.006, 0.007, 0.014"); } fall_transition(CELL_TABLE) { - values("0.004, 0.004, 0.004",\ - "0.004, 0.004, 0.004",\ - "0.004, 0.004, 0.004"); + values("0.006, 0.007, 0.014",\ + "0.006, 0.007, 0.014",\ + "0.006, 0.007, 0.014"); } } } @@ -164,7 +176,7 @@ cell (sram_2_16_1_scn4m_subm){ bus(addr0){ bus_type : addr; direction : input; - capacitance : 9.8242; + capacitance : 0.0098242; max_transition : 0.4; pin(addr0[3:0]){ timing(){ @@ -200,7 +212,7 @@ cell (sram_2_16_1_scn4m_subm){ pin(csb0){ direction : input; - capacitance : 9.8242; + capacitance : 0.0098242; timing(){ timing_type : setup_rising; related_pin : "clk0"; @@ -233,7 +245,7 @@ cell (sram_2_16_1_scn4m_subm){ pin(web0){ direction : input; - capacitance : 9.8242; + capacitance : 0.0098242; timing(){ timing_type : setup_rising; related_pin : "clk0"; @@ -267,52 +279,61 @@ cell (sram_2_16_1_scn4m_subm){ pin(clk0){ clock : true; direction : input; - capacitance : 9.8242; + capacitance : 0.0098242; internal_power(){ - when : "!csb0 & clk0 & !web0"; + when : "!csb0 & !web0"; rise_power(scalar){ - values("4.99880645"); + values("7.797263e+00"); } fall_power(scalar){ - values("4.99880645"); + values("7.797263e+00"); } } internal_power(){ - when : "!csb0 & !clk0 & web0"; + when : "csb0 & !web0"; rise_power(scalar){ - values("4.99880645"); + values("7.797263e+00"); } fall_power(scalar){ - values("4.99880645"); + values("7.797263e+00"); } } internal_power(){ - when : "csb0"; + when : "!csb0 & web0"; rise_power(scalar){ - values("0"); + values("7.797263e+00"); } fall_power(scalar){ - values("0"); + values("7.797263e+00"); + } + } + internal_power(){ + when : "csb0 & web0"; + rise_power(scalar){ + values("7.797263e+00"); + } + fall_power(scalar){ + values("7.797263e+00"); } } timing(){ timing_type :"min_pulse_width"; related_pin : clk0; rise_constraint(scalar) { - values("0.024"); + values("0.1265"); } fall_constraint(scalar) { - values("0.024"); + values("0.1265"); } } timing(){ timing_type :"minimum_period"; related_pin : clk0; rise_constraint(scalar) { - values("0.048"); + values("0.253"); } fall_constraint(scalar) { - values("0.048"); + values("0.253"); } } } diff --git a/compiler/tests/golden/sram_2_16_1_scn4m_subm_SS_5p0V_25C_analytical.lib b/compiler/tests/golden/sram_2_16_1_scn4m_subm_SS_5p0V_25C_analytical.lib index f52de676..a7605cb3 100644 --- a/compiler/tests/golden/sram_2_16_1_scn4m_subm_SS_5p0V_25C_analytical.lib +++ b/compiler/tests/golden/sram_2_16_1_scn4m_subm_SS_5p0V_25C_analytical.lib @@ -35,11 +35,14 @@ library (sram_2_16_1_scn4m_subm_SS_5p0V_25C_lib){ default_max_fanout : 4.0 ; default_connection_class : universal ; + voltage_map ( VDD, 5.0 ); + voltage_map ( GND, 0 ); + lu_table_template(CELL_TABLE){ variable_1 : input_net_transition; variable_2 : total_output_net_capacitance; index_1("0.0125, 0.05, 0.4"); - index_2("2.45605, 9.8242, 78.5936"); + index_2("0.00245605, 0.0098242, 0.0392968"); } lu_table_template(CONSTRAINT_TABLE){ @@ -78,17 +81,26 @@ cell (sram_2_16_1_scn4m_subm){ dont_use : true; map_only : true; dont_touch : true; - area : 73068.14000000001; + area : 0; + + pg_pin(vdd) { + voltage_name : VDD; + pg_type : primary_power; + } + + pg_pin(gnd) { + voltage_name : GND; + pg_type : primary_ground; + } leakage_power () { - when : "csb0"; - value : 0.000167; + value : 0.000198; } - cell_leakage_power : 0; + cell_leakage_power : 0.000198; bus(din0){ bus_type : data; direction : input; - capacitance : 9.8242; + capacitance : 0.0098242; memory_write(){ address : addr0; clocked_on : clk0; @@ -127,8 +139,8 @@ cell (sram_2_16_1_scn4m_subm){ bus(dout0){ bus_type : data; direction : output; - max_capacitance : 78.5936; - min_capacitance : 2.45605; + max_capacitance : 0.0392968; + min_capacitance : 0.00245605; memory_read(){ address : addr0; } @@ -138,24 +150,24 @@ cell (sram_2_16_1_scn4m_subm){ related_pin : "clk0"; timing_type : falling_edge; cell_rise(CELL_TABLE) { - values("0.294, 0.294, 0.294",\ - "0.294, 0.294, 0.294",\ - "0.294, 0.294, 0.294"); + values("1.446, 1.466, 1.545",\ + "1.446, 1.466, 1.545",\ + "1.446, 1.466, 1.545"); } cell_fall(CELL_TABLE) { - values("0.294, 0.294, 0.294",\ - "0.294, 0.294, 0.294",\ - "0.294, 0.294, 0.294"); + values("1.446, 1.466, 1.545",\ + "1.446, 1.466, 1.545",\ + "1.446, 1.466, 1.545"); } rise_transition(CELL_TABLE) { - values("0.004, 0.004, 0.004",\ - "0.004, 0.004, 0.004",\ - "0.004, 0.004, 0.004"); + values("0.007, 0.009, 0.017",\ + "0.007, 0.009, 0.017",\ + "0.007, 0.009, 0.017"); } fall_transition(CELL_TABLE) { - values("0.004, 0.004, 0.004",\ - "0.004, 0.004, 0.004",\ - "0.004, 0.004, 0.004"); + values("0.007, 0.009, 0.017",\ + "0.007, 0.009, 0.017",\ + "0.007, 0.009, 0.017"); } } } @@ -164,7 +176,7 @@ cell (sram_2_16_1_scn4m_subm){ bus(addr0){ bus_type : addr; direction : input; - capacitance : 9.8242; + capacitance : 0.0098242; max_transition : 0.4; pin(addr0[3:0]){ timing(){ @@ -200,7 +212,7 @@ cell (sram_2_16_1_scn4m_subm){ pin(csb0){ direction : input; - capacitance : 9.8242; + capacitance : 0.0098242; timing(){ timing_type : setup_rising; related_pin : "clk0"; @@ -233,7 +245,7 @@ cell (sram_2_16_1_scn4m_subm){ pin(web0){ direction : input; - capacitance : 9.8242; + capacitance : 0.0098242; timing(){ timing_type : setup_rising; related_pin : "clk0"; @@ -267,52 +279,61 @@ cell (sram_2_16_1_scn4m_subm){ pin(clk0){ clock : true; direction : input; - capacitance : 9.8242; + capacitance : 0.0098242; internal_power(){ - when : "!csb0 & clk0 & !web0"; + when : "!csb0 & !web0"; rise_power(scalar){ - values("4.99880645"); + values("6.379579e+00"); } fall_power(scalar){ - values("4.99880645"); + values("6.379579e+00"); } } internal_power(){ - when : "!csb0 & !clk0 & web0"; + when : "csb0 & !web0"; rise_power(scalar){ - values("4.99880645"); + values("6.379579e+00"); } fall_power(scalar){ - values("4.99880645"); + values("6.379579e+00"); } } internal_power(){ - when : "csb0"; + when : "!csb0 & web0"; rise_power(scalar){ - values("0"); + values("6.379579e+00"); } fall_power(scalar){ - values("0"); + values("6.379579e+00"); + } + } + internal_power(){ + when : "csb0 & web0"; + rise_power(scalar){ + values("6.379579e+00"); + } + fall_power(scalar){ + values("6.379579e+00"); } } timing(){ timing_type :"min_pulse_width"; related_pin : clk0; rise_constraint(scalar) { - values("0.0295"); + values("0.1545"); } fall_constraint(scalar) { - values("0.0295"); + values("0.1545"); } } timing(){ timing_type :"minimum_period"; related_pin : clk0; rise_constraint(scalar) { - values("0.059"); + values("0.309"); } fall_constraint(scalar) { - values("0.059"); + values("0.309"); } } } diff --git a/compiler/tests/golden/sram_2_16_1_scn4m_subm_TT_5p0V_25C.lib b/compiler/tests/golden/sram_2_16_1_scn4m_subm_TT_5p0V_25C.lib index 7447a1e2..8bec74c3 100644 --- a/compiler/tests/golden/sram_2_16_1_scn4m_subm_TT_5p0V_25C.lib +++ b/compiler/tests/golden/sram_2_16_1_scn4m_subm_TT_5p0V_25C.lib @@ -35,11 +35,14 @@ library (sram_2_16_1_scn4m_subm_TT_5p0V_25C_lib){ default_max_fanout : 4.0 ; default_connection_class : universal ; + voltage_map ( VDD, 5.0 ); + voltage_map ( GND, 0 ); + lu_table_template(CELL_TABLE){ variable_1 : input_net_transition; variable_2 : total_output_net_capacitance; index_1("0.0125, 0.05, 0.4"); - index_2("2.45605, 9.8242, 78.5936"); + index_2("0.00245605, 0.0098242, 0.0392968"); } lu_table_template(CONSTRAINT_TABLE){ @@ -78,17 +81,26 @@ cell (sram_2_16_1_scn4m_subm){ dont_use : true; map_only : true; dont_touch : true; - area : 60774.3; + area : 0; + + pg_pin(vdd) { + voltage_name : VDD; + pg_type : primary_power; + } + + pg_pin(gnd) { + voltage_name : GND; + pg_type : primary_ground; + } leakage_power () { - when : "csb0"; - value : 0.0009813788999999999; + value : 0.000198; } - cell_leakage_power : 0; + cell_leakage_power : 0.000198; bus(din0){ bus_type : data; direction : input; - capacitance : 9.8242; + capacitance : 0.0098242; memory_write(){ address : addr0; clocked_on : clk0; @@ -98,28 +110,28 @@ cell (sram_2_16_1_scn4m_subm){ timing_type : setup_rising; related_pin : "clk0"; rise_constraint(CONSTRAINT_TABLE) { - values("0.167, 0.167, 0.228",\ - "0.167, 0.167, 0.228",\ - "0.167, 0.167, 0.228"); + values("0.009, 0.009, 0.009",\ + "0.009, 0.009, 0.009",\ + "0.009, 0.009, 0.009"); } fall_constraint(CONSTRAINT_TABLE) { - values("0.131, 0.125, 0.137",\ - "0.131, 0.125, 0.137",\ - "0.131, 0.125, 0.137"); + values("0.009, 0.009, 0.009",\ + "0.009, 0.009, 0.009",\ + "0.009, 0.009, 0.009"); } } timing(){ timing_type : hold_rising; related_pin : "clk0"; rise_constraint(CONSTRAINT_TABLE) { - values("-0.065, -0.071, -0.114",\ - "-0.065, -0.071, -0.114",\ - "-0.065, -0.071, -0.114"); + values("0.001, 0.001, 0.001",\ + "0.001, 0.001, 0.001",\ + "0.001, 0.001, 0.001"); } fall_constraint(CONSTRAINT_TABLE) { - values("-0.089, -0.089, -0.089",\ - "-0.089, -0.089, -0.089",\ - "-0.089, -0.089, -0.089"); + values("0.001, 0.001, 0.001",\ + "0.001, 0.001, 0.001",\ + "0.001, 0.001, 0.001"); } } } @@ -127,8 +139,8 @@ cell (sram_2_16_1_scn4m_subm){ bus(dout0){ bus_type : data; direction : output; - max_capacitance : 78.5936; - min_capacitance : 2.45605; + max_capacitance : 0.0392968; + min_capacitance : 0.00245605; memory_read(){ address : addr0; } @@ -138,24 +150,24 @@ cell (sram_2_16_1_scn4m_subm){ related_pin : "clk0"; timing_type : falling_edge; cell_rise(CELL_TABLE) { - values("1.556, 1.576, 1.751",\ - "1.559, 1.579, 1.754",\ - "1.624, 1.643, 1.819"); + values("1.314, 1.332, 1.404",\ + "1.314, 1.332, 1.404",\ + "1.314, 1.332, 1.404"); } cell_fall(CELL_TABLE) { - values("3.445, 3.504, 3.926",\ - "3.448, 3.507, 3.93",\ - "3.49, 3.549, 3.972"); + values("1.314, 1.332, 1.404",\ + "1.314, 1.332, 1.404",\ + "1.314, 1.332, 1.404"); } rise_transition(CELL_TABLE) { - values("0.13, 0.169, 0.574",\ - "0.13, 0.169, 0.574",\ - "0.13, 0.169, 0.574"); + values("0.006, 0.008, 0.015",\ + "0.006, 0.008, 0.015",\ + "0.006, 0.008, 0.015"); } fall_transition(CELL_TABLE) { - values("0.467, 0.49, 0.959",\ - "0.467, 0.49, 0.959",\ - "0.47, 0.493, 0.96"); + values("0.006, 0.008, 0.015",\ + "0.006, 0.008, 0.015",\ + "0.006, 0.008, 0.015"); } } } @@ -164,35 +176,35 @@ cell (sram_2_16_1_scn4m_subm){ bus(addr0){ bus_type : addr; direction : input; - capacitance : 9.8242; + capacitance : 0.0098242; max_transition : 0.4; pin(addr0[3:0]){ timing(){ timing_type : setup_rising; related_pin : "clk0"; rise_constraint(CONSTRAINT_TABLE) { - values("0.167, 0.167, 0.228",\ - "0.167, 0.167, 0.228",\ - "0.167, 0.167, 0.228"); + values("0.009, 0.009, 0.009",\ + "0.009, 0.009, 0.009",\ + "0.009, 0.009, 0.009"); } fall_constraint(CONSTRAINT_TABLE) { - values("0.131, 0.125, 0.137",\ - "0.131, 0.125, 0.137",\ - "0.131, 0.125, 0.137"); + values("0.009, 0.009, 0.009",\ + "0.009, 0.009, 0.009",\ + "0.009, 0.009, 0.009"); } } timing(){ timing_type : hold_rising; related_pin : "clk0"; rise_constraint(CONSTRAINT_TABLE) { - values("-0.065, -0.071, -0.114",\ - "-0.065, -0.071, -0.114",\ - "-0.065, -0.071, -0.114"); + values("0.001, 0.001, 0.001",\ + "0.001, 0.001, 0.001",\ + "0.001, 0.001, 0.001"); } fall_constraint(CONSTRAINT_TABLE) { - values("-0.089, -0.089, -0.089",\ - "-0.089, -0.089, -0.089",\ - "-0.089, -0.089, -0.089"); + values("0.001, 0.001, 0.001",\ + "0.001, 0.001, 0.001",\ + "0.001, 0.001, 0.001"); } } } @@ -200,66 +212,66 @@ cell (sram_2_16_1_scn4m_subm){ pin(csb0){ direction : input; - capacitance : 9.8242; + capacitance : 0.0098242; timing(){ timing_type : setup_rising; related_pin : "clk0"; rise_constraint(CONSTRAINT_TABLE) { - values("0.167, 0.167, 0.228",\ - "0.167, 0.167, 0.228",\ - "0.167, 0.167, 0.228"); + values("0.009, 0.009, 0.009",\ + "0.009, 0.009, 0.009",\ + "0.009, 0.009, 0.009"); } fall_constraint(CONSTRAINT_TABLE) { - values("0.131, 0.125, 0.137",\ - "0.131, 0.125, 0.137",\ - "0.131, 0.125, 0.137"); + values("0.009, 0.009, 0.009",\ + "0.009, 0.009, 0.009",\ + "0.009, 0.009, 0.009"); } } timing(){ timing_type : hold_rising; related_pin : "clk0"; rise_constraint(CONSTRAINT_TABLE) { - values("-0.065, -0.071, -0.114",\ - "-0.065, -0.071, -0.114",\ - "-0.065, -0.071, -0.114"); + values("0.001, 0.001, 0.001",\ + "0.001, 0.001, 0.001",\ + "0.001, 0.001, 0.001"); } fall_constraint(CONSTRAINT_TABLE) { - values("-0.089, -0.089, -0.089",\ - "-0.089, -0.089, -0.089",\ - "-0.089, -0.089, -0.089"); + values("0.001, 0.001, 0.001",\ + "0.001, 0.001, 0.001",\ + "0.001, 0.001, 0.001"); } } } pin(web0){ direction : input; - capacitance : 9.8242; + capacitance : 0.0098242; timing(){ timing_type : setup_rising; related_pin : "clk0"; rise_constraint(CONSTRAINT_TABLE) { - values("0.167, 0.167, 0.228",\ - "0.167, 0.167, 0.228",\ - "0.167, 0.167, 0.228"); + values("0.009, 0.009, 0.009",\ + "0.009, 0.009, 0.009",\ + "0.009, 0.009, 0.009"); } fall_constraint(CONSTRAINT_TABLE) { - values("0.131, 0.125, 0.137",\ - "0.131, 0.125, 0.137",\ - "0.131, 0.125, 0.137"); + values("0.009, 0.009, 0.009",\ + "0.009, 0.009, 0.009",\ + "0.009, 0.009, 0.009"); } } timing(){ timing_type : hold_rising; related_pin : "clk0"; rise_constraint(CONSTRAINT_TABLE) { - values("-0.065, -0.071, -0.114",\ - "-0.065, -0.071, -0.114",\ - "-0.065, -0.071, -0.114"); + values("0.001, 0.001, 0.001",\ + "0.001, 0.001, 0.001",\ + "0.001, 0.001, 0.001"); } fall_constraint(CONSTRAINT_TABLE) { - values("-0.089, -0.089, -0.089",\ - "-0.089, -0.089, -0.089",\ - "-0.089, -0.089, -0.089"); + values("0.001, 0.001, 0.001",\ + "0.001, 0.001, 0.001",\ + "0.001, 0.001, 0.001"); } } } @@ -267,52 +279,61 @@ cell (sram_2_16_1_scn4m_subm){ pin(clk0){ clock : true; direction : input; - capacitance : 9.8242; + capacitance : 0.0098242; internal_power(){ - when : "!csb0 & clk0 & !web0"; + when : "!csb0 & !web0"; rise_power(scalar){ - values("9.972790277777777"); + values("7.017537e+00"); } fall_power(scalar){ - values("9.972790277777777"); + values("7.017537e+00"); } } internal_power(){ - when : "!csb0 & !clk0 & web0"; + when : "csb0 & !web0"; rise_power(scalar){ - values("8.899322499999998"); + values("7.017537e+00"); } fall_power(scalar){ - values("8.899322499999998"); + values("7.017537e+00"); } } internal_power(){ - when : "csb0"; + when : "!csb0 & web0"; rise_power(scalar){ - values("0"); + values("7.017537e+00"); } fall_power(scalar){ - values("0"); + values("7.017537e+00"); + } + } + internal_power(){ + when : "csb0 & web0"; + rise_power(scalar){ + values("7.017537e+00"); + } + fall_power(scalar){ + values("7.017537e+00"); } } timing(){ timing_type :"min_pulse_width"; related_pin : clk0; rise_constraint(scalar) { - values("2.344"); + values("0.1405"); } fall_constraint(scalar) { - values("2.344"); + values("0.1405"); } } timing(){ timing_type :"minimum_period"; related_pin : clk0; rise_constraint(scalar) { - values("4.688"); + values("0.281"); } fall_constraint(scalar) { - values("4.688"); + values("0.281"); } } } diff --git a/compiler/tests/golden/sram_2_16_1_scn4m_subm_TT_5p0V_25C_analytical.lib b/compiler/tests/golden/sram_2_16_1_scn4m_subm_TT_5p0V_25C_analytical.lib index 4248b986..8bec74c3 100644 --- a/compiler/tests/golden/sram_2_16_1_scn4m_subm_TT_5p0V_25C_analytical.lib +++ b/compiler/tests/golden/sram_2_16_1_scn4m_subm_TT_5p0V_25C_analytical.lib @@ -35,11 +35,14 @@ library (sram_2_16_1_scn4m_subm_TT_5p0V_25C_lib){ default_max_fanout : 4.0 ; default_connection_class : universal ; + voltage_map ( VDD, 5.0 ); + voltage_map ( GND, 0 ); + lu_table_template(CELL_TABLE){ variable_1 : input_net_transition; variable_2 : total_output_net_capacitance; index_1("0.0125, 0.05, 0.4"); - index_2("2.45605, 9.8242, 78.5936"); + index_2("0.00245605, 0.0098242, 0.0392968"); } lu_table_template(CONSTRAINT_TABLE){ @@ -78,17 +81,26 @@ cell (sram_2_16_1_scn4m_subm){ dont_use : true; map_only : true; dont_touch : true; - area : 60774.3; + area : 0; + + pg_pin(vdd) { + voltage_name : VDD; + pg_type : primary_power; + } + + pg_pin(gnd) { + voltage_name : GND; + pg_type : primary_ground; + } leakage_power () { - when : "csb0"; - value : 0.000179; + value : 0.000198; } - cell_leakage_power : 0; + cell_leakage_power : 0.000198; bus(din0){ bus_type : data; direction : input; - capacitance : 9.8242; + capacitance : 0.0098242; memory_write(){ address : addr0; clocked_on : clk0; @@ -127,8 +139,8 @@ cell (sram_2_16_1_scn4m_subm){ bus(dout0){ bus_type : data; direction : output; - max_capacitance : 78.5936; - min_capacitance : 2.45605; + max_capacitance : 0.0392968; + min_capacitance : 0.00245605; memory_read(){ address : addr0; } @@ -138,24 +150,24 @@ cell (sram_2_16_1_scn4m_subm){ related_pin : "clk0"; timing_type : falling_edge; cell_rise(CELL_TABLE) { - values("0.268, 0.268, 0.268",\ - "0.268, 0.268, 0.268",\ - "0.268, 0.268, 0.268"); + values("1.314, 1.332, 1.404",\ + "1.314, 1.332, 1.404",\ + "1.314, 1.332, 1.404"); } cell_fall(CELL_TABLE) { - values("0.268, 0.268, 0.268",\ - "0.268, 0.268, 0.268",\ - "0.268, 0.268, 0.268"); + values("1.314, 1.332, 1.404",\ + "1.314, 1.332, 1.404",\ + "1.314, 1.332, 1.404"); } rise_transition(CELL_TABLE) { - values("0.004, 0.004, 0.004",\ - "0.004, 0.004, 0.004",\ - "0.004, 0.004, 0.004"); + values("0.006, 0.008, 0.015",\ + "0.006, 0.008, 0.015",\ + "0.006, 0.008, 0.015"); } fall_transition(CELL_TABLE) { - values("0.004, 0.004, 0.004",\ - "0.004, 0.004, 0.004",\ - "0.004, 0.004, 0.004"); + values("0.006, 0.008, 0.015",\ + "0.006, 0.008, 0.015",\ + "0.006, 0.008, 0.015"); } } } @@ -164,7 +176,7 @@ cell (sram_2_16_1_scn4m_subm){ bus(addr0){ bus_type : addr; direction : input; - capacitance : 9.8242; + capacitance : 0.0098242; max_transition : 0.4; pin(addr0[3:0]){ timing(){ @@ -200,7 +212,7 @@ cell (sram_2_16_1_scn4m_subm){ pin(csb0){ direction : input; - capacitance : 9.8242; + capacitance : 0.0098242; timing(){ timing_type : setup_rising; related_pin : "clk0"; @@ -233,7 +245,7 @@ cell (sram_2_16_1_scn4m_subm){ pin(web0){ direction : input; - capacitance : 9.8242; + capacitance : 0.0098242; timing(){ timing_type : setup_rising; related_pin : "clk0"; @@ -267,52 +279,61 @@ cell (sram_2_16_1_scn4m_subm){ pin(clk0){ clock : true; direction : input; - capacitance : 9.8242; + capacitance : 0.0098242; internal_power(){ - when : "!csb0 & clk0 & !web0"; + when : "!csb0 & !web0"; rise_power(scalar){ - values("11.3049604371"); + values("7.017537e+00"); } fall_power(scalar){ - values("11.3049604371"); + values("7.017537e+00"); } } internal_power(){ - when : "!csb0 & !clk0 & web0"; + when : "csb0 & !web0"; rise_power(scalar){ - values("11.3049604371"); + values("7.017537e+00"); } fall_power(scalar){ - values("11.3049604371"); + values("7.017537e+00"); } } internal_power(){ - when : "csb0"; + when : "!csb0 & web0"; rise_power(scalar){ - values("0"); + values("7.017537e+00"); } fall_power(scalar){ - values("0"); + values("7.017537e+00"); + } + } + internal_power(){ + when : "csb0 & web0"; + rise_power(scalar){ + values("7.017537e+00"); + } + fall_power(scalar){ + values("7.017537e+00"); } } timing(){ timing_type :"min_pulse_width"; related_pin : clk0; rise_constraint(scalar) { - values("0.0"); + values("0.1405"); } fall_constraint(scalar) { - values("0.0"); + values("0.1405"); } } timing(){ timing_type :"minimum_period"; related_pin : clk0; rise_constraint(scalar) { - values("0"); + values("0.281"); } fall_constraint(scalar) { - values("0"); + values("0.281"); } } } diff --git a/technology/scn4m_subm/tech/tech.py b/technology/scn4m_subm/tech/tech.py index 7c360d38..d8384d7f 100644 --- a/technology/scn4m_subm/tech/tech.py +++ b/technology/scn4m_subm/tech/tech.py @@ -89,7 +89,7 @@ power_grid = m3_stack ################################################### # create the GDS layer map -layer={} +layer={} layer["pwell"] = (41, 0) layer["nwell"] = (42, 0) layer["active"] = (43, 0) @@ -98,9 +98,9 @@ layer["nimplant"] = (45, 0) layer["poly"] = (46, 0) layer["poly_contact"] = (47, 0) layer["active_contact"] = (48, 0) -layer["m1"] = (49, 0) +layer["m1"] = (49, 0) layer["via1"] = (50, 0) -layer["m2"] = (51, 0) +layer["m2"] = (51, 0) layer["via2"] = (61, 0) layer["m3"] = (62, 0) layer["via3"] = (30, 0)