mirror of https://github.com/VLSIDA/OpenRAM.git
Add option to remove wells. Save area in pgates with redundant wells.
This commit is contained in:
parent
848241a3ad
commit
617bf302d1
|
|
@ -15,14 +15,14 @@ class pand2(pgate.pgate):
|
||||||
"""
|
"""
|
||||||
This is a simple buffer used for driving loads.
|
This is a simple buffer used for driving loads.
|
||||||
"""
|
"""
|
||||||
def __init__(self, name, size=1, height=None, vertical=False):
|
def __init__(self, name, size=1, height=None, vertical=False, add_wells=True):
|
||||||
debug.info(1, "Creating pand2 {}".format(name))
|
debug.info(1, "Creating pand2 {}".format(name))
|
||||||
self.add_comment("size: {}".format(size))
|
self.add_comment("size: {}".format(size))
|
||||||
|
|
||||||
self.vertical = vertical
|
self.vertical = vertical
|
||||||
self.size = size
|
self.size = size
|
||||||
|
|
||||||
pgate.pgate.__init__(self, name)
|
pgate.pgate.__init__(self, name, height, add_wells)
|
||||||
|
|
||||||
def create_netlist(self):
|
def create_netlist(self):
|
||||||
self.add_pins()
|
self.add_pins()
|
||||||
|
|
@ -31,12 +31,15 @@ class pand2(pgate.pgate):
|
||||||
|
|
||||||
def create_modules(self):
|
def create_modules(self):
|
||||||
self.nand = factory.create(module_type="pnand2",
|
self.nand = factory.create(module_type="pnand2",
|
||||||
height=self.height)
|
height=self.height,
|
||||||
self.add_mod(self.nand)
|
add_wells=False)
|
||||||
|
|
||||||
self.inv = factory.create(module_type="pdriver",
|
self.inv = factory.create(module_type="pdriver",
|
||||||
size_list=[self.size],
|
size_list=[self.size],
|
||||||
height=self.height)
|
height=self.height,
|
||||||
|
add_wells=self.add_wells)
|
||||||
|
|
||||||
|
self.add_mod(self.nand)
|
||||||
self.add_mod(self.inv)
|
self.add_mod(self.inv)
|
||||||
|
|
||||||
def create_layout(self):
|
def create_layout(self):
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ class pand3(pgate.pgate):
|
||||||
"""
|
"""
|
||||||
This is a simple buffer used for driving loads.
|
This is a simple buffer used for driving loads.
|
||||||
"""
|
"""
|
||||||
def __init__(self, name, size=1, height=None, vertical=False):
|
def __init__(self, name, size=1, height=None, vertical=False, add_wells=True):
|
||||||
debug.info(1, "Creating pand3 {}".format(name))
|
debug.info(1, "Creating pand3 {}".format(name))
|
||||||
self.add_comment("size: {}".format(size))
|
self.add_comment("size: {}".format(size))
|
||||||
|
|
||||||
|
|
@ -23,7 +23,7 @@ class pand3(pgate.pgate):
|
||||||
self.size = size
|
self.size = size
|
||||||
|
|
||||||
# Creates the netlist and layout
|
# Creates the netlist and layout
|
||||||
pgate.pgate.__init__(self, name, height)
|
pgate.pgate.__init__(self, name, height, add_wells)
|
||||||
|
|
||||||
def create_netlist(self):
|
def create_netlist(self):
|
||||||
self.add_pins()
|
self.add_pins()
|
||||||
|
|
@ -33,12 +33,17 @@ class pand3(pgate.pgate):
|
||||||
def create_modules(self):
|
def create_modules(self):
|
||||||
# Shield the cap, but have at least a stage effort of 4
|
# Shield the cap, but have at least a stage effort of 4
|
||||||
self.nand = factory.create(module_type="pnand3",
|
self.nand = factory.create(module_type="pnand3",
|
||||||
height=self.height)
|
height=self.height,
|
||||||
self.add_mod(self.nand)
|
add_wells=False)
|
||||||
|
|
||||||
|
# Add the well tap to the inverter because when stacked
|
||||||
|
# vertically it is sometimes narrower
|
||||||
self.inv = factory.create(module_type="pdriver",
|
self.inv = factory.create(module_type="pdriver",
|
||||||
size_list=[self.size],
|
size_list=[self.size],
|
||||||
height=self.height)
|
height=self.height,
|
||||||
|
add_wells=self.add_wells)
|
||||||
|
|
||||||
|
self.add_mod(self.nand)
|
||||||
self.add_mod(self.inv)
|
self.add_mod(self.inv)
|
||||||
|
|
||||||
def create_layout(self):
|
def create_layout(self):
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ class pdriver(pgate.pgate):
|
||||||
sized for driving a load.
|
sized for driving a load.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, name, neg_polarity=False, fanout=0, size_list=None, height=None):
|
def __init__(self, name, neg_polarity=False, fanout=0, size_list=None, height=None, add_wells=True):
|
||||||
|
|
||||||
debug.info(1, "creating pdriver {}".format(name))
|
debug.info(1, "creating pdriver {}".format(name))
|
||||||
|
|
||||||
|
|
@ -35,7 +35,7 @@ class pdriver(pgate.pgate):
|
||||||
debug.error("Cannot specify both size_list and neg_polarity.", -1)
|
debug.error("Cannot specify both size_list and neg_polarity.", -1)
|
||||||
|
|
||||||
# Creates the netlist and layout
|
# Creates the netlist and layout
|
||||||
pgate.pgate.__init__(self, name, height)
|
pgate.pgate.__init__(self, name, height, add_wells)
|
||||||
|
|
||||||
def compute_sizes(self):
|
def compute_sizes(self):
|
||||||
# size_list specified
|
# size_list specified
|
||||||
|
|
@ -73,9 +73,9 @@ class pdriver(pgate.pgate):
|
||||||
self.place_modules()
|
self.place_modules()
|
||||||
self.route_wires()
|
self.route_wires()
|
||||||
self.add_layout_pins()
|
self.add_layout_pins()
|
||||||
|
|
||||||
self.width = self.inv_inst_list[-1].rx()
|
self.width = self.inv_inst_list[-1].rx()
|
||||||
self.height = self.inv_inst_list[0].height
|
self.height = self.inv_inst_list[0].height
|
||||||
|
self.extend_wells()
|
||||||
self.route_supply_rails()
|
self.route_supply_rails()
|
||||||
self.add_boundary()
|
self.add_boundary()
|
||||||
|
|
||||||
|
|
@ -87,7 +87,7 @@ class pdriver(pgate.pgate):
|
||||||
|
|
||||||
def add_modules(self):
|
def add_modules(self):
|
||||||
self.inv_list = []
|
self.inv_list = []
|
||||||
add_well = True
|
add_well = self.add_wells
|
||||||
for size in self.size_list:
|
for size in self.size_list:
|
||||||
temp_inv = factory.create(module_type="pinv",
|
temp_inv = factory.create(module_type="pinv",
|
||||||
size=size,
|
size=size,
|
||||||
|
|
|
||||||
|
|
@ -162,12 +162,12 @@ class pgate(design.design):
|
||||||
nwell_height = nwell_max_offset - self.nwell_y_offset
|
nwell_height = nwell_max_offset - self.nwell_y_offset
|
||||||
self.add_rect(layer="nwell",
|
self.add_rect(layer="nwell",
|
||||||
offset=nwell_position,
|
offset=nwell_position,
|
||||||
width=self.well_width,
|
width=self.width + 2 * self.well_extend_active,
|
||||||
height=nwell_height)
|
height=nwell_height)
|
||||||
if "vtg" in layer:
|
if "vtg" in layer:
|
||||||
self.add_rect(layer="vtg",
|
self.add_rect(layer="vtg",
|
||||||
offset=nwell_position,
|
offset=nwell_position,
|
||||||
width=self.well_width,
|
width=self.width + 2 * self.well_extend_active,
|
||||||
height=nwell_height)
|
height=nwell_height)
|
||||||
|
|
||||||
# Start this half a rail width below the cell
|
# Start this half a rail width below the cell
|
||||||
|
|
@ -178,12 +178,12 @@ class pgate(design.design):
|
||||||
pwell_height = self.nwell_y_offset - pwell_position.y
|
pwell_height = self.nwell_y_offset - pwell_position.y
|
||||||
self.add_rect(layer="pwell",
|
self.add_rect(layer="pwell",
|
||||||
offset=pwell_position,
|
offset=pwell_position,
|
||||||
width=self.well_width,
|
width=self.width + 2 * self.well_extend_active,
|
||||||
height=pwell_height)
|
height=pwell_height)
|
||||||
if "vtg" in layer:
|
if "vtg" in layer:
|
||||||
self.add_rect(layer="vtg",
|
self.add_rect(layer="vtg",
|
||||||
offset=pwell_position,
|
offset=pwell_position,
|
||||||
width=self.well_width,
|
width=self.width + 2 * self.well_extend_active,
|
||||||
height=pwell_height)
|
height=pwell_height)
|
||||||
|
|
||||||
def add_nwell_contact(self, pmos, pmos_pos):
|
def add_nwell_contact(self, pmos, pmos_pos):
|
||||||
|
|
@ -304,16 +304,17 @@ class pgate(design.design):
|
||||||
def determine_width(self):
|
def determine_width(self):
|
||||||
""" Determine the width based on the well contacts (assumed to be on the right side) """
|
""" Determine the width based on the well contacts (assumed to be on the right side) """
|
||||||
|
|
||||||
|
# It was already set or is left as default (minimum)
|
||||||
# Width is determined by well contact and spacing and allowing a supply via between each cell
|
# Width is determined by well contact and spacing and allowing a supply via between each cell
|
||||||
if self.add_wells:
|
if self.add_wells:
|
||||||
self.width = max(self.nwell_contact.rx(), self.pwell_contact.rx()) + self.m1_space + 0.5 * contact.m1_via.width
|
width = max(self.nwell_contact.rx(), self.pwell_contact.rx()) + self.m1_space + 0.5 * contact.m1_via.width
|
||||||
# Height is an input parameter, so it is not recomputed.
|
# Height is an input parameter, so it is not recomputed.
|
||||||
else:
|
else:
|
||||||
max_active_xoffset = self.find_highest_layer_coords("active").x
|
max_active_xoffset = self.find_highest_layer_coords("active").x
|
||||||
max_route_xoffset = self.find_highest_layer_coords(self.route_layer).x + 0.5 * self.m1_space
|
max_route_xoffset = self.find_highest_layer_coords(self.route_layer).x + 0.5 * self.m1_space
|
||||||
self.width = max(max_active_xoffset, max_route_xoffset)
|
width = max(max_active_xoffset, max_route_xoffset)
|
||||||
|
|
||||||
self.well_width = self.width + 2 * self.nwell_enclose_active
|
self.width = width
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def bin_width(tx_type, target_width):
|
def bin_width(tx_type, target_width):
|
||||||
|
|
|
||||||
|
|
@ -60,14 +60,14 @@ class pinv(pgate.pgate):
|
||||||
self.add_well_contacts()
|
self.add_well_contacts()
|
||||||
self.determine_width()
|
self.determine_width()
|
||||||
self.extend_wells()
|
self.extend_wells()
|
||||||
self.route_supply_rails()
|
|
||||||
self.connect_rails()
|
|
||||||
self.route_input_gate(self.pmos_inst,
|
self.route_input_gate(self.pmos_inst,
|
||||||
self.nmos_inst,
|
self.nmos_inst,
|
||||||
self.output_pos.y,
|
self.output_pos.y,
|
||||||
"A",
|
"A",
|
||||||
position="farleft")
|
position="farleft")
|
||||||
self.route_outputs()
|
self.route_outputs()
|
||||||
|
self.route_supply_rails()
|
||||||
|
self.connect_rails()
|
||||||
self.add_boundary()
|
self.add_boundary()
|
||||||
|
|
||||||
def add_pins(self):
|
def add_pins(self):
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@
|
||||||
# (acting for and on behalf of Oklahoma State University)
|
# (acting for and on behalf of Oklahoma State University)
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
import contact
|
|
||||||
import pgate
|
import pgate
|
||||||
import debug
|
import debug
|
||||||
from tech import drc, parameter, spice
|
from tech import drc, parameter, spice
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ class single_level_column_mux(pgate.pgate):
|
||||||
self.connect_poly()
|
self.connect_poly()
|
||||||
self.add_bitline_pins()
|
self.add_bitline_pins()
|
||||||
self.connect_bitlines()
|
self.connect_bitlines()
|
||||||
self.add_wells()
|
self.add_pn_wells()
|
||||||
|
|
||||||
def add_modules(self):
|
def add_modules(self):
|
||||||
self.bitcell = factory.create(module_type="bitcell")
|
self.bitcell = factory.create(module_type="bitcell")
|
||||||
|
|
@ -218,7 +218,7 @@ class single_level_column_mux(pgate.pgate):
|
||||||
self.add_path(self.col_mux_stack[2],
|
self.add_path(self.col_mux_stack[2],
|
||||||
[br_pin.bc(), mid1, mid2, nmos_lower_d_pin.center()])
|
[br_pin.bc(), mid1, mid2, nmos_lower_d_pin.center()])
|
||||||
|
|
||||||
def add_wells(self):
|
def add_pn_wells(self):
|
||||||
"""
|
"""
|
||||||
Add a well and implant over the whole cell. Also, add the
|
Add a well and implant over the whole cell. Also, add the
|
||||||
pwell contact (if it exists)
|
pwell contact (if it exists)
|
||||||
|
|
|
||||||
|
|
@ -25,10 +25,6 @@ class pnor2_test(openram_test):
|
||||||
tx = factory.create(module_type="pnor2", size=1)
|
tx = factory.create(module_type="pnor2", size=1)
|
||||||
self.local_check(tx)
|
self.local_check(tx)
|
||||||
|
|
||||||
debug.info(2, "Checking 2-input nor gate")
|
|
||||||
tx = factory.create(module_type="pnor2", size=1, add_wells=False)
|
|
||||||
self.local_drc_check(tx)
|
|
||||||
|
|
||||||
globals.end_openram()
|
globals.end_openram()
|
||||||
|
|
||||||
# run the test from the command line
|
# run the test from the command line
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue