diff --git a/compiler/base/utils.py b/compiler/base/utils.py index f02b2b85..b6a62788 100644 --- a/compiler/base/utils.py +++ b/compiler/base/utils.py @@ -96,10 +96,12 @@ def get_libcell_size(name, units, lpp): Open a GDS file and return the library cell size from either the bounding box or a border layer. """ + cell_gds = OPTS.openram_tech + "gds_lib/" + str(name) + ".gds" return(get_gds_size(name, cell_gds, units, lpp)) + def get_gds_pins(pin_names, name, gds_filename, units): """ Open a GDS file and find the pins in pin_names as text on a given layer. @@ -128,6 +130,7 @@ def get_libcell_pins(pin_list, name, units): Open a GDS file and find the pins in pin_list as text on a given layer. Return these as a rectangle layer pair for each pin. """ + cell_gds = OPTS.openram_tech + "gds_lib/" + str(name) + ".gds" return(get_gds_pins(pin_list, name, cell_gds, units)) diff --git a/compiler/bitcells/bitcell.py b/compiler/bitcells/bitcell.py index 5b552832..49fdf19f 100644 --- a/compiler/bitcells/bitcell.py +++ b/compiler/bitcells/bitcell.py @@ -25,11 +25,12 @@ class bitcell(bitcell_base.bitcell_base): if cell_properties.bitcell.split_wl: pin_names = ["bl", "br", "wl0", "wl1", "vdd", "gnd"] + type_list = ["OUTPUT", "OUTPUT", "INPUT", "INPUT", "POWER", "GROUND"] else: pin_names = ["bl", "br", "wl", "vdd", "gnd"] - + type_list = ["OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"] storage_nets = ['Q', 'Qbar'] - type_list = ["OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"] + (width, height) = utils.get_libcell_size("cell_6t", GDS["unit"], layer["boundary"]) @@ -81,8 +82,11 @@ class bitcell(bitcell_base.bitcell_base): def get_wl_name(self, port=0): """Get wl name""" - debug.check(port == 0, "One port for bitcell only.") - return "wl" + if cell_properties.bitcell.split_wl: + return "wl{}".format(port) + else: + debug.check(port == 0, "One port for bitcell only.") + return "wl" def build_graph(self, graph, inst_name, port_nets): """ diff --git a/compiler/bitcells/replica_bitcell.py b/compiler/bitcells/replica_bitcell.py index 2f804bf0..a869e4b7 100644 --- a/compiler/bitcells/replica_bitcell.py +++ b/compiler/bitcells/replica_bitcell.py @@ -8,7 +8,8 @@ import design import debug import utils -from tech import GDS,layer,drc,parameter +from tech import GDS,layer,drc,parameter,cell_properties +from globals import OPTS class replica_bitcell(design.design): """ @@ -17,10 +18,19 @@ class replica_bitcell(design.design): is a hand-made cell, so the layout and netlist should be available in the technology library. """ - pin_names = ["bl", "br", "wl", "vdd", "gnd"] - type_list = ["OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"] - (width,height) = utils.get_libcell_size("replica_cell_6t", GDS["unit"], layer["boundary"]) - pin_map = utils.get_libcell_pins(pin_names, "replica_cell_6t", GDS["unit"]) + if cell_properties.bitcell.split_wl: + pin_names = ["bl", "br", "wl0", "wl1", "vdd", "gnd"] + type_list = ["OUTPUT", "OUTPUT", "INPUT", "INPUT" , "POWER", "GROUND"] + else: + pin_names = ["bl", "br", "wl", "vdd", "gnd"] + type_list = ["OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"] + + if not OPTS.netlist_only: + (width,height) = utils.get_libcell_size("replica_cell_6t", GDS["unit"], layer["boundary"]) + pin_map = utils.get_libcell_pins(pin_names, "replica_cell_6t", GDS["unit"]) + else: + (width,height) = (0,0) + pin_map = [] def __init__(self, name=""): # Ignore the name argument diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index 915aa064..133a66c2 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -53,6 +53,7 @@ class bank(design.design): def create_netlist(self): + self.compute_sizes() self.add_modules() self.add_pins() # Must create the replica bitcell array first diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index dbb7c3b7..fa11e30b 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -7,7 +7,7 @@ # from math import log import design -from tech import drc, parameter +from tech import drc, parameter, module_properties import debug import contact from sram_factory import factory @@ -742,7 +742,11 @@ class control_logic(design.design): def create_dffs(self): self.ctrl_dff_inst=self.add_inst(name="ctrl_dffs", mod=self.ctrl_dff_array) - self.connect_inst(self.input_list + self.dff_output_list + ["clk_buf"] + self.supply_list) + inst_pins = self.input_list + self.dff_output_list + ["clk_buf"] + self.supply_list + if module_properties.dff_buff_array.add_body_contacts: + inst_pins.append("vpb") + inst_pins.append("vnb") + self.connect_inst(inst_pins) def place_dffs(self): self.ctrl_dff_inst.place(vector(0,0)) diff --git a/compiler/modules/custom_module_properties.py b/compiler/modules/custom_module_properties.py new file mode 100644 index 00000000..768a8c18 --- /dev/null +++ b/compiler/modules/custom_module_properties.py @@ -0,0 +1,56 @@ +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2020 Regents of the University of California and The Board +# of Regents for the Oklahoma Agricultural and Mechanical College +# (acting for and on behalf of Oklahoma State University) +# All rights reserved. +# + +class _dff: + def __init__(self, use_custom_ports, custom_port_list, custom_type_list, clk_pin): + self.use_custom_ports = use_custom_ports + self.custom_port_list = custom_port_list + self.custom_type_list = custom_type_list + self.clk_pin = clk_pin + +class _dff_buff: + def __init__(self, use_custom_ports, custom_buff_ports, add_body_contacts): + self.use_custom_ports = use_custom_ports + self.buf_ports = custom_buff_ports + self.add_body_contacts = add_body_contacts + +class _dff_buff_array: + def __init__(self, use_custom_ports, add_body_contacts): + self.use_custom_ports = use_custom_ports + self.add_body_contacts = add_body_contacts + +class module_properties(): + """ + TODO + """ + def __init__(self): + self.names = {} + + self._dff = _dff(use_custom_ports = False, + custom_port_list = ["D", "Q", "clk", "vdd", "gnd"], + custom_type_list = ["INPUT", "OUTPUT", "INPUT", "POWER", "GROUND"], + clk_pin= "clk") + + self._dff_buff = _dff_buff(use_custom_ports = False, + custom_buff_ports = ["D", "qint", "clk", "vdd", "gnd"], + add_body_contacts = False) + + self._dff_buff_array = _dff_buff_array(use_custom_ports = False, + add_body_contacts = False) + + @property + def dff(self): + return self._dff + + @property + def dff_buff(self): + return self._dff_buff + + @property + def dff_buff_array(self): + return self._dff_buff_array \ No newline at end of file diff --git a/compiler/modules/dff.py b/compiler/modules/dff.py index 8871872d..45d20a62 100644 --- a/compiler/modules/dff.py +++ b/compiler/modules/dff.py @@ -7,6 +7,7 @@ # import design from tech import GDS, layer, spice, parameter +from tech import module_properties import utils @@ -14,9 +15,15 @@ class dff(design.design): """ Memory address flip-flop """ + if not module_properties.dff.use_custom_ports: + pin_names = ["D", "Q", "clk", "vdd", "gnd"] + type_list = ["INPUT", "OUTPUT", "INPUT", "POWER", "GROUND"] + clk_pin = "clk" + else: + pin_names = module_properties.dff.custom_port_list + type_list = module_properties.dff.custom_type_list + clk_pin = module_properties.dff.clk_pin - pin_names = ["D", "Q", "clk", "vdd", "gnd"] - type_list = ["INPUT", "OUTPUT", "INPUT", "POWER", "GROUND"] (width, height) = utils.get_libcell_size("dff", GDS["unit"], layer["boundary"]) diff --git a/compiler/modules/dff_array.py b/compiler/modules/dff_array.py index 6ba020c7..62464834 100644 --- a/compiler/modules/dff_array.py +++ b/compiler/modules/dff_array.py @@ -69,11 +69,12 @@ class dff_array(design.design): name = "dff_r{0}_c{1}".format(row,col) self.dff_insts[row,col]=self.add_inst(name=name, mod=self.dff) - self.connect_inst([self.get_din_name(row,col), - self.get_dout_name(row,col), - "clk", - "vdd", - "gnd"]) + instance_ports = [self.get_din_name(row,col), + self.get_dout_name(row,col)] + for port in self.dff.pin_names: + if port != 'D' and port != 'Q': + instance_ports.append(port) + self.connect_inst(instance_ports) def place_dff_array(self): for row in range(self.rows): @@ -142,7 +143,7 @@ class dff_array(design.design): # Create vertical spines to a single horizontal rail - clk_pin = self.dff_insts[0,0].get_pin("clk") + clk_pin = self.dff_insts[0,0].get_pin(self.dff.clk_pin) clk_ypos = 2*self.m3_pitch+self.m3_width debug.check(clk_pin.layer=="m2","DFF clk pin not on metal2") self.add_layout_pin_segment_center(text="clk", @@ -150,7 +151,7 @@ class dff_array(design.design): 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(self.dff.clk_pin) # Make a vertical strip for each column self.add_rect(layer="m2", offset=clk_pin.ll().scale(1,0), diff --git a/compiler/modules/dff_buf.py b/compiler/modules/dff_buf.py index 82f567e6..7c95a2a5 100644 --- a/compiler/modules/dff_buf.py +++ b/compiler/modules/dff_buf.py @@ -7,7 +7,7 @@ # import debug import design -from tech import drc,parameter +from tech import drc,parameter,module_properties from math import log from vector import vector from globals import OPTS @@ -83,10 +83,15 @@ class dff_buf(design.design): self.add_pin("vdd", "POWER") self.add_pin("gnd", "GROUND") + if module_properties.dff_buff.add_body_contacts: + self.add_pin("vpb", "INPUT") + self.add_pin("vpn", "INPUT") + def create_instances(self): self.dff_inst=self.add_inst(name="dff_buf_dff", mod=self.dff) - self.connect_inst(["D", "qint", "clk", "vdd", "gnd"]) + self.connect_inst(module_properties.dff_buff.buf_ports) + #self.connect_inst(["D", "qint", "clk", "vdd", "gnd"]) self.inv1_inst=self.add_inst(name="dff_buf_inv1", mod=self.inv1) diff --git a/compiler/modules/dff_buf_array.py b/compiler/modules/dff_buf_array.py index 4f2140c4..42d117db 100644 --- a/compiler/modules/dff_buf_array.py +++ b/compiler/modules/dff_buf_array.py @@ -7,7 +7,7 @@ # import debug import design -from tech import drc +from tech import drc, module_properties from math import log from vector import vector from globals import OPTS @@ -64,6 +64,10 @@ class dff_buf_array(design.design): self.add_pin("vdd", "POWER") self.add_pin("gnd", "GROUND") + if module_properties.dff_buff_array.add_body_contacts: + self.add_pin("vpb", "INPUT") + self.add_pin("vnb", "INPUT") + def add_modules(self): self.dff = factory.create(module_type="dff_buf", inv1_size=self.inv1_size, @@ -78,12 +82,16 @@ class dff_buf_array(design.design): name = "dff_r{0}_c{1}".format(row,col) self.dff_insts[row,col]=self.add_inst(name=name, mod=self.dff) - self.connect_inst([self.get_din_name(row,col), + inst_ports = [self.get_din_name(row,col), self.get_dout_name(row,col), self.get_dout_bar_name(row,col), "clk", "vdd", - "gnd"]) + "gnd"] + if module_properties.dff_buff_array.add_body_contacts: + inst_ports.append("vpb") + inst_ports.append("vnb") + self.connect_inst(inst_ports) def place_dff_array(self): diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index 178c2f91..a8b3ec30 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -158,7 +158,7 @@ class replica_bitcell_array(design.design): # Left port WLs (one dummy for each port when we allow >1 port) for port in range(self.left_rbl): # Make names for all RBLs - wl_names=["rbl_{0}_{1}".format(self.cell.get_wl_name(x),port) for x in range(len(self.all_ports))] + wl_names=["rbl_{0}_{1}".format(self.cell.get_wl_name(x),port) for x in range(len(self.cell.get_all_wl_names()))] # Keep track of the pin that is the RBL self.rbl_wl_names[port]=wl_names[self.bitcell_ports[port]] self.replica_col_wl_names.extend(wl_names) @@ -167,7 +167,7 @@ class replica_bitcell_array(design.design): # Right port WLs (one dummy for each port when we allow >1 port) for port in range(self.left_rbl,self.left_rbl+self.right_rbl): # Make names for all RBLs - wl_names=["rbl_{0}_{1}".format(self.cell.get_wl_name(x),port) for x in range(len(self.all_ports))] + wl_names=["rbl_{0}_{1}".format(self.cell.get_wl_name(x),port) for x in range(len(self.cell.get_all_wl_names()))] # Keep track of the pin that is the RBL self.rbl_wl_names[port]=wl_names[self.bitcell_ports[port]] self.replica_col_wl_names.extend(wl_names) diff --git a/compiler/modules/sense_amp.py b/compiler/modules/sense_amp.py index e77d577f..ac3a859c 100644 --- a/compiler/modules/sense_amp.py +++ b/compiler/modules/sense_amp.py @@ -9,6 +9,7 @@ import design import debug import utils from tech import GDS,layer, parameter,drc +from globals import OPTS import logical_effort class sense_amp(design.design): @@ -21,8 +22,12 @@ class sense_amp(design.design): pin_names = ["bl", "br", "dout", "en", "vdd", "gnd"] type_list = ["INPUT", "INPUT", "OUTPUT", "INPUT", "POWER", "GROUND"] - (width,height) = utils.get_libcell_size("sense_amp", GDS["unit"], layer["boundary"]) - pin_map = utils.get_libcell_pins(pin_names, "sense_amp", GDS["unit"]) + if not OPTS.netlist_only: + (width,height) = utils.get_libcell_size("sense_amp", GDS["unit"], layer["boundary"]) + pin_map = utils.get_libcell_pins(pin_names, "sense_amp", GDS["unit"]) + else: + (width, height) = (0,0) + pin_map = [] def __init__(self, name): design.design.__init__(self, name) diff --git a/compiler/modules/write_driver.py b/compiler/modules/write_driver.py index 85a58fd5..11b14f00 100644 --- a/compiler/modules/write_driver.py +++ b/compiler/modules/write_driver.py @@ -8,6 +8,7 @@ import debug import design import utils +from globals import OPTS from tech import GDS,layer class write_driver(design.design): @@ -20,8 +21,12 @@ class write_driver(design.design): pin_names = ["din", "bl", "br", "en", "vdd", "gnd"] type_list = ["INPUT", "OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"] - (width,height) = utils.get_libcell_size("write_driver", GDS["unit"], layer["boundary"]) - pin_map = utils.get_libcell_pins(pin_names, "write_driver", GDS["unit"]) + if not OPTS.netlist_only: + (width,height) = utils.get_libcell_size("write_driver", GDS["unit"], layer["boundary"]) + pin_map = utils.get_libcell_pins(pin_names, "write_driver", GDS["unit"]) + else: + (width,height) = (0,0) + pin_map = [] def __init__(self, name): design.design.__init__(self, name) diff --git a/compiler/sram/sram_config.py b/compiler/sram/sram_config.py index 376bf42b..3a7e6d39 100644 --- a/compiler/sram/sram_config.py +++ b/compiler/sram/sram_config.py @@ -23,9 +23,9 @@ class sram_config: # This will get over-written when we determine the organization self.words_per_row = words_per_row - self.compute_sizes() + def set_local_config(self, module): """ Copy all of the member variables to the given module for convenience """ diff --git a/technology/freepdk45/tech/tech.py b/technology/freepdk45/tech/tech.py index c60abeb5..f91be16c 100644 --- a/technology/freepdk45/tech/tech.py +++ b/technology/freepdk45/tech/tech.py @@ -9,7 +9,7 @@ import os from design_rules import * from module_type import * from custom_cell_properties import cell_properties - +from custom_module_properties import module_properties """ File containing the process technology parameters for FreePDK 45nm. """ @@ -25,6 +25,7 @@ File containing the process technology parameters for FreePDK 45nm. # For example: tech_modules['contact'] = 'contact_freepdk45' tech_modules = module_type() +module_properties = module_properties() ################################################### # Custom cell properties ################################################### diff --git a/technology/scn4m_subm/tech/tech.py b/technology/scn4m_subm/tech/tech.py index 7c360d38..bb379478 100644 --- a/technology/scn4m_subm/tech/tech.py +++ b/technology/scn4m_subm/tech/tech.py @@ -9,6 +9,7 @@ import os from design_rules import * from module_type import * from custom_cell_properties import cell_properties +from custom_module_properties import module_properties """ File containing the process technology parameters for SCMOS 4m, 0.35um @@ -24,6 +25,7 @@ File containing the process technology parameters for SCMOS 4m, 0.35um # implementation in '$OPENRAM_TECHDIR/modules/' # For example: tech_modules['contact'] = 'contact_scn4m' tech_modules = module_type() +module_properties = module_properties() ################################################### # Custom cell properties