mirror of https://github.com/VLSIDA/OpenRAM.git
Add no well option. Add stack gates vertical option.
This commit is contained in:
parent
b7c66d7e07
commit
c96a6d0b9d
|
|
@ -15,14 +15,14 @@ class pand2(pgate.pgate):
|
|||
"""
|
||||
This is a simple buffer used for driving loads.
|
||||
"""
|
||||
def __init__(self, name, size=1, height=None):
|
||||
debug.info(1, "Creating pnand2 {}".format(name))
|
||||
def __init__(self, name, size=1, height=None, vertical=False):
|
||||
debug.info(1, "Creating pand2 {}".format(name))
|
||||
self.add_comment("size: {}".format(size))
|
||||
|
||||
|
||||
self.vertical = vertical
|
||||
self.size = size
|
||||
|
||||
# Creates the netlist and layout
|
||||
pgate.pgate.__init__(self, name, height)
|
||||
|
||||
pgate.pgate.__init__(self, name)
|
||||
|
||||
def create_netlist(self):
|
||||
self.add_pins()
|
||||
|
|
@ -30,17 +30,22 @@ class pand2(pgate.pgate):
|
|||
self.create_insts()
|
||||
|
||||
def create_modules(self):
|
||||
self.nand = factory.create(module_type="pnand2", height=self.height)
|
||||
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=self.size,
|
||||
size_list=[self.size],
|
||||
height=self.height)
|
||||
self.add_mod(self.inv)
|
||||
|
||||
def create_layout(self):
|
||||
self.width = self.nand.width + self.inv.width
|
||||
if self.vertical:
|
||||
self.height = 2 * self.nand.height
|
||||
self.width = max(self.nand.width, self.inv.width)
|
||||
else:
|
||||
self.width = self.nand.width + self.inv.width
|
||||
|
||||
self.place_insts()
|
||||
self.add_wires()
|
||||
self.add_layout_pins()
|
||||
|
|
@ -68,17 +73,60 @@ class pand2(pgate.pgate):
|
|||
# Add NAND to the right
|
||||
self.nand_inst.place(offset=vector(0, 0))
|
||||
|
||||
# Add INV to the right
|
||||
self.inv_inst.place(offset=vector(self.nand_inst.rx(), 0))
|
||||
if self.vertical:
|
||||
# Add INV above
|
||||
self.inv_inst.place(offset=vector(self.inv.width,
|
||||
2 * self.nand.height),
|
||||
mirror="XY")
|
||||
else:
|
||||
# Add INV to the right
|
||||
self.inv_inst.place(offset=vector(self.nand_inst.rx(), 0))
|
||||
|
||||
def route_supply_rails(self):
|
||||
""" Add vdd/gnd rails to the top, (middle), and bottom. """
|
||||
self.add_layout_pin_rect_center(text="gnd",
|
||||
layer=self.route_layer,
|
||||
offset=vector(0.5 * self.width, 0),
|
||||
width=self.width)
|
||||
|
||||
# Second gnd of the inverter gate
|
||||
if self.vertical:
|
||||
self.add_layout_pin_rect_center(text="gnd",
|
||||
layer=self.route_layer,
|
||||
offset=vector(0.5 * self.width, self.height),
|
||||
width=self.width)
|
||||
|
||||
if self.vertical:
|
||||
# Shared between two gates
|
||||
y_offset = 0.5 * self.height
|
||||
else:
|
||||
y_offset = self.height
|
||||
self.add_layout_pin_rect_center(text="vdd",
|
||||
layer=self.route_layer,
|
||||
offset=vector(0.5 * self.width, y_offset),
|
||||
width=self.width)
|
||||
|
||||
def add_wires(self):
|
||||
# nand Z to inv A
|
||||
z1_pin = self.nand_inst.get_pin("Z")
|
||||
a2_pin = self.inv_inst.get_pin("A")
|
||||
mid1_point = vector(0.5 * (z1_pin.cx() + a2_pin.cx()), z1_pin.cy())
|
||||
mid2_point = vector(mid1_point, a2_pin.cy())
|
||||
self.add_path(self.route_layer,
|
||||
[z1_pin.center(), mid1_point, mid2_point, a2_pin.center()])
|
||||
if self.vertical:
|
||||
route_layer = "m2"
|
||||
self.add_via_stack_center(offset=z1_pin.center(),
|
||||
from_layer=z1_pin.layer,
|
||||
to_layer=route_layer)
|
||||
self.add_zjog(route_layer,
|
||||
z1_pin.uc(),
|
||||
a2_pin.bc(),
|
||||
"V")
|
||||
self.add_via_stack_center(offset=a2_pin.center(),
|
||||
from_layer=a2_pin.layer,
|
||||
to_layer=route_layer)
|
||||
else:
|
||||
route_layer = self.route_layer
|
||||
mid1_point = vector(z1_pin.cx(), a2_pin.cy())
|
||||
self.add_path(route_layer,
|
||||
[z1_pin.center(), mid1_point, a2_pin.center()])
|
||||
|
||||
def add_layout_pins(self):
|
||||
pin = self.inv_inst.get_pin("Z")
|
||||
|
|
|
|||
|
|
@ -15,10 +15,11 @@ class pand3(pgate.pgate):
|
|||
"""
|
||||
This is a simple buffer used for driving loads.
|
||||
"""
|
||||
def __init__(self, name, size=1, height=None):
|
||||
def __init__(self, name, size=1, height=None, vertical=False):
|
||||
debug.info(1, "Creating pand3 {}".format(name))
|
||||
self.add_comment("size: {}".format(size))
|
||||
|
||||
|
||||
self.vertical = vertical
|
||||
self.size = size
|
||||
|
||||
# Creates the netlist and layout
|
||||
|
|
@ -31,16 +32,22 @@ class pand3(pgate.pgate):
|
|||
|
||||
def create_modules(self):
|
||||
# Shield the cap, but have at least a stage effort of 4
|
||||
self.nand = factory.create(module_type="pnand3", height=self.height)
|
||||
self.nand = factory.create(module_type="pnand3",
|
||||
height=self.height)
|
||||
self.add_mod(self.nand)
|
||||
|
||||
self.inv = factory.create(module_type="pinv",
|
||||
size=self.size,
|
||||
self.inv = factory.create(module_type="pdriver",
|
||||
size_list=[self.size],
|
||||
height=self.height)
|
||||
self.add_mod(self.inv)
|
||||
|
||||
def create_layout(self):
|
||||
self.width = self.nand.width + self.inv.width
|
||||
if self.vertical:
|
||||
self.height = 2 * self.nand.height
|
||||
self.width = max(self.nand.width, self.inv.width)
|
||||
else:
|
||||
self.width = self.nand.width + self.inv.width
|
||||
|
||||
self.place_insts()
|
||||
self.add_wires()
|
||||
self.add_layout_pins()
|
||||
|
|
@ -69,18 +76,61 @@ class pand3(pgate.pgate):
|
|||
# Add NAND to the right
|
||||
self.nand_inst.place(offset=vector(0, 0))
|
||||
|
||||
# Add INV to the right
|
||||
self.inv_inst.place(offset=vector(self.nand_inst.rx(), 0))
|
||||
if self.vertical:
|
||||
# Add INV above
|
||||
self.inv_inst.place(offset=vector(self.inv.width,
|
||||
2 * self.nand.height),
|
||||
mirror="XY")
|
||||
else:
|
||||
# Add INV to the right
|
||||
self.inv_inst.place(offset=vector(self.nand_inst.rx(), 0))
|
||||
|
||||
def route_supply_rails(self):
|
||||
""" Add vdd/gnd rails to the top, (middle), and bottom. """
|
||||
self.add_layout_pin_rect_center(text="gnd",
|
||||
layer=self.route_layer,
|
||||
offset=vector(0.5 * self.width, 0),
|
||||
width=self.width)
|
||||
|
||||
# Second gnd of the inverter gate
|
||||
if self.vertical:
|
||||
self.add_layout_pin_rect_center(text="gnd",
|
||||
layer=self.route_layer,
|
||||
offset=vector(0.5 * self.width, self.height),
|
||||
width=self.width)
|
||||
|
||||
if self.vertical:
|
||||
# Shared between two gates
|
||||
y_offset = 0.5 * self.height
|
||||
else:
|
||||
y_offset = self.height
|
||||
self.add_layout_pin_rect_center(text="vdd",
|
||||
layer=self.route_layer,
|
||||
offset=vector(0.5 * self.width, y_offset),
|
||||
width=self.width)
|
||||
|
||||
def add_wires(self):
|
||||
# nand Z to inv A
|
||||
z1_pin = self.nand_inst.get_pin("Z")
|
||||
a2_pin = self.inv_inst.get_pin("A")
|
||||
mid1_point = vector(0.5 * (z1_pin.cx()+a2_pin.cx()), z1_pin.cy())
|
||||
mid2_point = vector(mid1_point, a2_pin.cy())
|
||||
self.add_path(z1_pin.layer,
|
||||
[z1_pin.center(), mid1_point, mid2_point, a2_pin.center()])
|
||||
|
||||
if self.vertical:
|
||||
route_layer = "m2"
|
||||
self.add_via_stack_center(offset=z1_pin.center(),
|
||||
from_layer=z1_pin.layer,
|
||||
to_layer=route_layer)
|
||||
self.add_zjog(route_layer,
|
||||
z1_pin.uc(),
|
||||
a2_pin.bc(),
|
||||
"V")
|
||||
self.add_via_stack_center(offset=a2_pin.center(),
|
||||
from_layer=a2_pin.layer,
|
||||
to_layer=route_layer)
|
||||
else:
|
||||
route_layer = self.route_layer
|
||||
mid1_point = vector(z1_pin.cx(), a2_pin.cy())
|
||||
self.add_path(route_layer,
|
||||
[z1_pin.center(), mid1_point, a2_pin.center()])
|
||||
|
||||
def add_layout_pins(self):
|
||||
pin = self.inv_inst.get_pin("Z")
|
||||
self.add_layout_pin_rect_center(text="Z",
|
||||
|
|
|
|||
|
|
@ -56,7 +56,8 @@ class pbuf(pgate.pgate):
|
|||
|
||||
self.inv2 = factory.create(module_type="pinv",
|
||||
size=self.size,
|
||||
height=self.height)
|
||||
height=self.height,
|
||||
add_wells=False)
|
||||
self.add_mod(self.inv2)
|
||||
|
||||
def create_insts(self):
|
||||
|
|
|
|||
|
|
@ -87,10 +87,13 @@ class pdriver(pgate.pgate):
|
|||
|
||||
def add_modules(self):
|
||||
self.inv_list = []
|
||||
add_well = True
|
||||
for size in self.size_list:
|
||||
temp_inv = factory.create(module_type="pinv",
|
||||
size=size,
|
||||
height=self.height)
|
||||
height=self.height,
|
||||
add_wells=add_well)
|
||||
add_well=False
|
||||
self.inv_list.append(temp_inv)
|
||||
self.add_mod(temp_inv)
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ class pgate(design.design):
|
|||
functions for parameterized gates.
|
||||
"""
|
||||
|
||||
def __init__(self, name, height=None):
|
||||
def __init__(self, name, height=None, add_wells=True):
|
||||
""" Creates a generic cell """
|
||||
design.design.__init__(self, name)
|
||||
|
||||
|
|
@ -33,7 +33,8 @@ class pgate(design.design):
|
|||
elif not height:
|
||||
# By default, something simple
|
||||
self.height = 14 * self.m1_pitch
|
||||
|
||||
self.add_wells = add_wells
|
||||
|
||||
if "li" in layer:
|
||||
self.route_layer = "li"
|
||||
else:
|
||||
|
|
@ -150,7 +151,7 @@ class pgate(design.design):
|
|||
|
||||
# This should match the cells in the cell library
|
||||
self.nwell_y_offset = 0.48 * self.height
|
||||
full_height = self.height + 0.5* self.m1_width
|
||||
full_height = self.height + 0.5 * self.m1_width
|
||||
|
||||
# FIXME: float rounding problem
|
||||
if "nwell" in layer:
|
||||
|
|
@ -302,10 +303,17 @@ class pgate(design.design):
|
|||
|
||||
def determine_width(self):
|
||||
""" Determine the width based on the well contacts (assumed to be on the right side) """
|
||||
|
||||
# Width is determined by well contact and spacing and allowing a supply via between each cell
|
||||
self.width = max(self.nwell_contact.rx(), self.pwell_contact.rx()) + self.m1_space + 0.5 * contact.m1_via.width
|
||||
if self.add_wells:
|
||||
self.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.
|
||||
else:
|
||||
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
|
||||
self.width = max(max_active_xoffset, max_route_xoffset)
|
||||
|
||||
self.well_width = self.width + 2 * self.nwell_enclose_active
|
||||
# Height is an input parameter, so it is not recomputed.
|
||||
|
||||
@staticmethod
|
||||
def bin_width(tx_type, target_width):
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ class pinv(pgate.pgate):
|
|||
from center of rail to rail.
|
||||
"""
|
||||
|
||||
def __init__(self, name, size=1, beta=parameter["beta"], height=None):
|
||||
def __init__(self, name, size=1, beta=parameter["beta"], height=None, add_wells=True):
|
||||
|
||||
debug.info(2,
|
||||
"creating pinv structure {0} with size of {1}".format(name,
|
||||
|
|
@ -44,7 +44,7 @@ class pinv(pgate.pgate):
|
|||
self.pmos_size = beta * size
|
||||
self.beta = beta
|
||||
|
||||
pgate.pgate.__init__(self, name, height)
|
||||
pgate.pgate.__init__(self, name, height, add_wells)
|
||||
|
||||
def create_netlist(self):
|
||||
""" Calls all functions related to the generation of the netlist """
|
||||
|
|
@ -56,7 +56,8 @@ class pinv(pgate.pgate):
|
|||
def create_layout(self):
|
||||
""" Calls all functions related to the generation of the layout """
|
||||
self.place_ptx()
|
||||
self.add_well_contacts()
|
||||
if self.add_wells:
|
||||
self.add_well_contacts()
|
||||
self.determine_width()
|
||||
self.extend_wells()
|
||||
self.route_supply_rails()
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ class pnand2(pgate.pgate):
|
|||
This module generates gds of a parametrically sized 2-input nand.
|
||||
This model use ptx to generate a 2-input nand within a cetrain height.
|
||||
"""
|
||||
def __init__(self, name, size=1, height=None):
|
||||
def __init__(self, name, size=1, height=None, add_wells=True):
|
||||
""" Creates a cell for a simple 2 input nand """
|
||||
|
||||
debug.info(2,
|
||||
|
|
@ -43,7 +43,7 @@ class pnand2(pgate.pgate):
|
|||
(self.pmos_width, self.tx_mults) = self.bin_width("pmos", self.pmos_width)
|
||||
|
||||
# Creates the netlist and layout
|
||||
pgate.pgate.__init__(self, name, height)
|
||||
pgate.pgate.__init__(self, name, height, add_wells)
|
||||
|
||||
def create_netlist(self):
|
||||
self.add_pins()
|
||||
|
|
@ -55,13 +55,14 @@ class pnand2(pgate.pgate):
|
|||
|
||||
self.setup_layout_constants()
|
||||
self.place_ptx()
|
||||
self.add_well_contacts()
|
||||
if self.add_wells:
|
||||
self.add_well_contacts()
|
||||
self.route_output()
|
||||
self.determine_width()
|
||||
self.route_supply_rails()
|
||||
self.connect_rails()
|
||||
self.extend_wells()
|
||||
self.route_inputs()
|
||||
self.route_output()
|
||||
self.add_boundary()
|
||||
|
||||
def add_pins(self):
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ class pnand3(pgate.pgate):
|
|||
This module generates gds of a parametrically sized 2-input nand.
|
||||
This model use ptx to generate a 2-input nand within a cetrain height.
|
||||
"""
|
||||
def __init__(self, name, size=1, height=None):
|
||||
def __init__(self, name, size=1, height=None, add_wells=True):
|
||||
""" Creates a cell for a simple 3 input nand """
|
||||
|
||||
debug.info(2,
|
||||
|
|
@ -45,7 +45,7 @@ class pnand3(pgate.pgate):
|
|||
(self.pmos_width, self.tx_mults) = self.bin_width("pmos", self.pmos_width)
|
||||
|
||||
# Creates the netlist and layout
|
||||
pgate.pgate.__init__(self, name, height)
|
||||
pgate.pgate.__init__(self, name, height, add_wells)
|
||||
|
||||
def add_pins(self):
|
||||
""" Adds pins for spice netlist """
|
||||
|
|
@ -63,7 +63,8 @@ class pnand3(pgate.pgate):
|
|||
|
||||
self.setup_layout_constants()
|
||||
self.place_ptx()
|
||||
self.add_well_contacts()
|
||||
if self.add_wells:
|
||||
self.add_well_contacts()
|
||||
self.determine_width()
|
||||
self.route_supply_rails()
|
||||
self.connect_rails()
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ class pnor2(pgate.pgate):
|
|||
This module generates gds of a parametrically sized 2-input nor.
|
||||
This model use ptx to generate a 2-input nor within a cetrain height.
|
||||
"""
|
||||
def __init__(self, name, size=1, height=None):
|
||||
def __init__(self, name, size=1, height=None, add_wells=True):
|
||||
""" Creates a cell for a simple 2 input nor """
|
||||
|
||||
debug.info(2,
|
||||
|
|
@ -42,7 +42,7 @@ class pnor2(pgate.pgate):
|
|||
(self.pmos_width, self.tx_mults) = self.bin_width("pmos", self.pmos_width)
|
||||
|
||||
# Creates the netlist and layout
|
||||
pgate.pgate.__init__(self, name, height)
|
||||
pgate.pgate.__init__(self, name, height, add_wells)
|
||||
|
||||
def create_netlist(self):
|
||||
self.add_pins()
|
||||
|
|
@ -54,13 +54,14 @@ class pnor2(pgate.pgate):
|
|||
|
||||
self.setup_layout_constants()
|
||||
self.place_ptx()
|
||||
self.add_well_contacts()
|
||||
if self.add_wells:
|
||||
self.add_well_contacts()
|
||||
self.route_inputs()
|
||||
self.route_output()
|
||||
self.determine_width()
|
||||
self.route_supply_rails()
|
||||
self.connect_rails()
|
||||
self.extend_wells()
|
||||
self.route_inputs()
|
||||
self.route_output()
|
||||
self.add_boundary()
|
||||
|
||||
def add_pins(self):
|
||||
|
|
|
|||
|
|
@ -29,6 +29,10 @@ class pand2_test(openram_test):
|
|||
a = pand2.pand2(name="pand2x4", size=4)
|
||||
self.local_check(a)
|
||||
|
||||
debug.info(2, "Testing vertical pand2 gate 4x")
|
||||
a = pand2.pand2(name="pand2x4", size=4, vertical=True)
|
||||
self.local_check(a)
|
||||
|
||||
globals.end_openram()
|
||||
|
||||
# instantiate a copdsay of the class to actually run the test
|
||||
|
|
|
|||
|
|
@ -29,6 +29,10 @@ class pand3_test(openram_test):
|
|||
a = pand3.pand3(name="pand3x4", size=4)
|
||||
self.local_check(a)
|
||||
|
||||
debug.info(2, "Testing vertical pand3 gate 4x")
|
||||
a = pand3.pand3(name="pand3x4", size=4, vertical=True)
|
||||
self.local_check(a)
|
||||
|
||||
globals.end_openram()
|
||||
|
||||
# instantiate a copdsay of the class to actually run the test
|
||||
|
|
|
|||
|
|
@ -25,6 +25,11 @@ class pnand2_test(openram_test):
|
|||
tx = factory.create(module_type="pnand2", size=1)
|
||||
self.local_check(tx)
|
||||
|
||||
debug.info(2, "Checking 2-input nand gate")
|
||||
tx = factory.create(module_type="pnand2", size=1, add_wells=False)
|
||||
# Only DRC because well contacts will fail LVS
|
||||
self.local_drc_check(tx)
|
||||
|
||||
globals.end_openram()
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,11 @@ class pnand3_test(openram_test):
|
|||
tx = factory.create(module_type="pnand3", size=1)
|
||||
self.local_check(tx)
|
||||
|
||||
debug.info(2, "Checking 3-input nand gate")
|
||||
tx = factory.create(module_type="pnand3", size=1, add_wells=False)
|
||||
# Only DRC because well contacts will fail LVS
|
||||
self.local_drc_check(tx)
|
||||
|
||||
globals.end_openram()
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,10 @@ class pnor2_test(openram_test):
|
|||
tx = factory.create(module_type="pnor2", size=1)
|
||||
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()
|
||||
|
||||
# run the test from the command line
|
||||
|
|
|
|||
Loading…
Reference in New Issue