mirror of https://github.com/VLSIDA/OpenRAM.git
Nwell fixes in pgates.
Fix minor PEP8 format fixes. Fix nwell to be 55% of cell height. Move contact in hierarchical decoder for DRC error.
This commit is contained in:
parent
596302d9a9
commit
f0ecf385e8
|
|
@ -5,18 +5,14 @@
|
||||||
# (acting for and on behalf of Oklahoma State University)
|
# (acting for and on behalf of Oklahoma State University)
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
from tech import drc
|
|
||||||
import debug
|
import debug
|
||||||
import design
|
import design
|
||||||
from math import log
|
|
||||||
from math import sqrt
|
|
||||||
from math import ceil
|
|
||||||
import math
|
import math
|
||||||
import contact
|
|
||||||
from sram_factory import factory
|
from sram_factory import factory
|
||||||
from vector import vector
|
from vector import vector
|
||||||
from globals import OPTS
|
from globals import OPTS
|
||||||
|
|
||||||
|
|
||||||
class hierarchical_decoder(design.design):
|
class hierarchical_decoder(design.design):
|
||||||
"""
|
"""
|
||||||
Dynamically generated hierarchical decoder.
|
Dynamically generated hierarchical decoder.
|
||||||
|
|
@ -34,13 +30,12 @@ class hierarchical_decoder(design.design):
|
||||||
self.cell_height = b.height
|
self.cell_height = b.height
|
||||||
self.rows = rows
|
self.rows = rows
|
||||||
self.num_inputs = math.ceil(math.log(self.rows, 2))
|
self.num_inputs = math.ceil(math.log(self.rows, 2))
|
||||||
(self.no_of_pre2x4,self.no_of_pre3x8)=self.determine_predecodes(self.num_inputs)
|
(self.no_of_pre2x4, self.no_of_pre3x8)=self.determine_predecodes(self.num_inputs)
|
||||||
|
|
||||||
self.create_netlist()
|
self.create_netlist()
|
||||||
if not OPTS.netlist_only:
|
if not OPTS.netlist_only:
|
||||||
self.create_layout()
|
self.create_layout()
|
||||||
|
|
||||||
|
|
||||||
def create_netlist(self):
|
def create_netlist(self):
|
||||||
self.add_modules()
|
self.add_modules()
|
||||||
self.setup_netlist_constants()
|
self.setup_netlist_constants()
|
||||||
|
|
@ -309,7 +304,6 @@ class hierarchical_decoder(design.design):
|
||||||
|
|
||||||
self.pre2x4_inst[num].place(base)
|
self.pre2x4_inst[num].place(base)
|
||||||
|
|
||||||
|
|
||||||
def place_pre3x8(self,num):
|
def place_pre3x8(self,num):
|
||||||
""" Place 3x8 predecoder to the left of the origin and above any 2x4 decoders """
|
""" Place 3x8 predecoder to the left of the origin and above any 2x4 decoders """
|
||||||
if (self.num_inputs == 3):
|
if (self.num_inputs == 3):
|
||||||
|
|
@ -321,7 +315,6 @@ class hierarchical_decoder(design.design):
|
||||||
|
|
||||||
self.pre3x8_inst[num].place(offset)
|
self.pre3x8_inst[num].place(offset)
|
||||||
|
|
||||||
|
|
||||||
def create_row_decoder(self):
|
def create_row_decoder(self):
|
||||||
""" Create the row-decoder by placing NAND2/NAND3 and Inverters
|
""" Create the row-decoder by placing NAND2/NAND3 and Inverters
|
||||||
and add the primary decoder output pins. """
|
and add the primary decoder output pins. """
|
||||||
|
|
@ -329,7 +322,6 @@ class hierarchical_decoder(design.design):
|
||||||
self.create_decoder_nand_array()
|
self.create_decoder_nand_array()
|
||||||
self.create_decoder_inv_array()
|
self.create_decoder_inv_array()
|
||||||
|
|
||||||
|
|
||||||
def create_decoder_nand_array(self):
|
def create_decoder_nand_array(self):
|
||||||
""" Add a column of NAND gates for final decode """
|
""" Add a column of NAND gates for final decode """
|
||||||
|
|
||||||
|
|
@ -556,7 +548,7 @@ class hierarchical_decoder(design.design):
|
||||||
""" Add a pin for each row of vdd/gnd which are must-connects next level up. """
|
""" Add a pin for each row of vdd/gnd which are must-connects next level up. """
|
||||||
|
|
||||||
# The vias will be placed in the center and right of the cells, respectively.
|
# The vias will be placed in the center and right of the cells, respectively.
|
||||||
xoffset = self.nand_inst[0].cx()
|
xoffset = self.nand_inst[0].rx()
|
||||||
for num in range(0,self.rows):
|
for num in range(0,self.rows):
|
||||||
for pin_name in ["vdd", "gnd"]:
|
for pin_name in ["vdd", "gnd"]:
|
||||||
# The nand and inv are the same height rows...
|
# The nand and inv are the same height rows...
|
||||||
|
|
|
||||||
|
|
@ -8,12 +8,11 @@
|
||||||
import debug
|
import debug
|
||||||
import design
|
import design
|
||||||
import math
|
import math
|
||||||
from tech import drc
|
|
||||||
import contact
|
import contact
|
||||||
from vector import vector
|
from vector import vector
|
||||||
from globals import OPTS
|
|
||||||
from sram_factory import factory
|
from sram_factory import factory
|
||||||
|
|
||||||
|
|
||||||
class hierarchical_predecode(design.design):
|
class hierarchical_predecode(design.design):
|
||||||
"""
|
"""
|
||||||
Pre 2x4 and 3x8 decoder shared code.
|
Pre 2x4 and 3x8 decoder shared code.
|
||||||
|
|
@ -42,7 +41,7 @@ class hierarchical_predecode(design.design):
|
||||||
self.add_nand(self.number_of_inputs)
|
self.add_nand(self.number_of_inputs)
|
||||||
self.add_mod(self.nand)
|
self.add_mod(self.nand)
|
||||||
|
|
||||||
def add_nand(self,inputs):
|
def add_nand(self, inputs):
|
||||||
""" Create the NAND for the predecode input stage """
|
""" Create the NAND for the predecode input stage """
|
||||||
if inputs==2:
|
if inputs==2:
|
||||||
self.nand = factory.create(module_type="pnand2",
|
self.nand = factory.create(module_type="pnand2",
|
||||||
|
|
@ -51,7 +50,7 @@ class hierarchical_predecode(design.design):
|
||||||
self.nand = factory.create(module_type="pnand3",
|
self.nand = factory.create(module_type="pnand3",
|
||||||
height=self.cell_height)
|
height=self.cell_height)
|
||||||
else:
|
else:
|
||||||
debug.error("Invalid number of predecode inputs: {}".format(inputs),-1)
|
debug.error("Invalid number of predecode inputs: {}".format(inputs), -1)
|
||||||
|
|
||||||
def setup_layout_constraints(self):
|
def setup_layout_constraints(self):
|
||||||
|
|
||||||
|
|
@ -89,7 +88,6 @@ class hierarchical_predecode(design.design):
|
||||||
names=decode_names,
|
names=decode_names,
|
||||||
length=self.height - 2*self.m1_width)
|
length=self.height - 2*self.m1_width)
|
||||||
|
|
||||||
|
|
||||||
def create_input_inverters(self):
|
def create_input_inverters(self):
|
||||||
""" Create the input inverters to invert input signals for the decode stage. """
|
""" Create the input inverters to invert input signals for the decode stage. """
|
||||||
self.in_inst = []
|
self.in_inst = []
|
||||||
|
|
@ -266,7 +264,7 @@ class hierarchical_predecode(design.design):
|
||||||
""" Add a pin for each row of vdd/gnd which are must-connects next level up. """
|
""" Add a pin for each row of vdd/gnd which are must-connects next level up. """
|
||||||
|
|
||||||
# Find the x offsets for where the vias/pins should be placed
|
# Find the x offsets for where the vias/pins should be placed
|
||||||
in_xoffset = self.in_inst[0].rx()
|
in_xoffset = self.in_inst[0].rx() + self.m1_space
|
||||||
out_xoffset = self.inv_inst[0].lx() - self.m1_space
|
out_xoffset = self.inv_inst[0].lx() - self.m1_space
|
||||||
for num in range(0,self.number_of_outputs):
|
for num in range(0,self.number_of_outputs):
|
||||||
# this will result in duplicate polygons for rails, but who cares
|
# this will result in duplicate polygons for rails, but who cares
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ import debug
|
||||||
from tech import layer
|
from tech import layer
|
||||||
from vector import vector
|
from vector import vector
|
||||||
from globals import OPTS
|
from globals import OPTS
|
||||||
from sram_factory import factory
|
|
||||||
|
|
||||||
|
|
||||||
class pgate(design.design):
|
class pgate(design.design):
|
||||||
|
|
@ -125,17 +124,20 @@ class pgate(design.design):
|
||||||
height=contact.poly_contact.first_layer_width,
|
height=contact.poly_contact.first_layer_width,
|
||||||
width=left_gate_offset.x - contact_offset.x)
|
width=left_gate_offset.x - contact_offset.x)
|
||||||
|
|
||||||
def extend_wells(self, middle_position):
|
def extend_wells(self):
|
||||||
""" Extend the n/p wells to cover whole cell """
|
""" Extend the n/p wells to cover whole cell """
|
||||||
|
|
||||||
|
# This should match the cells in the cell library
|
||||||
|
nwell_y_offset = 0.48 * self.height
|
||||||
|
full_height = self.height + 0.5*self.m1_width
|
||||||
|
|
||||||
# FIXME: float rounding problem
|
# FIXME: float rounding problem
|
||||||
middle_position = middle_position.snap_to_grid()
|
|
||||||
if "nwell" in layer:
|
if "nwell" in layer:
|
||||||
# Add a rail width to extend the well to the top of the rail
|
# Add a rail width to extend the well to the top of the rail
|
||||||
nwell_max_offset = max(self.find_highest_layer_coords("nwell").y,
|
nwell_max_offset = max(self.find_highest_layer_coords("nwell").y,
|
||||||
self.height + 0.5 * self.m1_width)
|
full_height)
|
||||||
nwell_position = middle_position - vector(self.well_extend_active, 0)
|
nwell_position = vector(0, nwell_y_offset) - vector(self.well_extend_active, 0)
|
||||||
nwell_height = nwell_max_offset - middle_position.y
|
nwell_height = nwell_max_offset - 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.well_width,
|
||||||
|
|
@ -151,7 +153,7 @@ class pgate(design.design):
|
||||||
pwell_min_offset = min(self.find_lowest_layer_coords("pwell").y,
|
pwell_min_offset = min(self.find_lowest_layer_coords("pwell").y,
|
||||||
-0.5 * self.m1_width)
|
-0.5 * self.m1_width)
|
||||||
pwell_position = vector(-self.well_extend_active, pwell_min_offset)
|
pwell_position = vector(-self.well_extend_active, pwell_min_offset)
|
||||||
pwell_height = middle_position.y - pwell_position.y
|
pwell_height = 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.well_width,
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ class pinv(pgate.pgate):
|
||||||
self.setup_layout_constants()
|
self.setup_layout_constants()
|
||||||
self.place_ptx()
|
self.place_ptx()
|
||||||
self.add_well_contacts()
|
self.add_well_contacts()
|
||||||
self.extend_wells(self.well_pos)
|
self.extend_wells()
|
||||||
self.route_supply_rails()
|
self.route_supply_rails()
|
||||||
self.connect_rails()
|
self.connect_rails()
|
||||||
self.route_input_gate(self.pmos_inst,
|
self.route_input_gate(self.pmos_inst,
|
||||||
|
|
@ -154,8 +154,11 @@ class pinv(pgate.pgate):
|
||||||
|
|
||||||
# the width is determined the multi-finger PMOS device width plus
|
# the width is determined the multi-finger PMOS device width plus
|
||||||
# the well contact width, spacing between them
|
# the well contact width, spacing between them
|
||||||
|
# space is for power supply contact to nwell m1 spacing
|
||||||
self.width = self.pmos.active_offset.x + self.pmos.active_width \
|
self.width = self.pmos.active_offset.x + self.pmos.active_width \
|
||||||
+ contact.nwell_contact.width + self.active_space + 0.5 * self.nwell_enclose_active
|
+ self.active_space + contact.nwell_contact.width \
|
||||||
|
+ 0.5 * self.nwell_enclose_active \
|
||||||
|
+ self.m1_space
|
||||||
# This includes full enclosures on each end
|
# This includes full enclosures on each end
|
||||||
self.well_width = self.width + 2*self.nwell_enclose_active
|
self.well_width = self.width + 2*self.nwell_enclose_active
|
||||||
# Height is an input parameter, so it is not recomputed.
|
# Height is an input parameter, so it is not recomputed.
|
||||||
|
|
@ -225,9 +228,6 @@ class pinv(pgate.pgate):
|
||||||
nmos_drain_pos = self.nmos_inst.get_pin("D").ul()
|
nmos_drain_pos = self.nmos_inst.get_pin("D").ul()
|
||||||
self.output_pos = vector(0, 0.5 * (pmos_drain_pos.y + nmos_drain_pos.y))
|
self.output_pos = vector(0, 0.5 * (pmos_drain_pos.y + nmos_drain_pos.y))
|
||||||
|
|
||||||
# This will help with the wells
|
|
||||||
self.well_pos = self.output_pos
|
|
||||||
|
|
||||||
def route_outputs(self):
|
def route_outputs(self):
|
||||||
"""
|
"""
|
||||||
Route the output (drains) together.
|
Route the output (drains) together.
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ class pnand2(pgate.pgate):
|
||||||
self.place_ptx()
|
self.place_ptx()
|
||||||
self.connect_rails()
|
self.connect_rails()
|
||||||
self.add_well_contacts()
|
self.add_well_contacts()
|
||||||
self.extend_wells(self.well_pos)
|
self.extend_wells()
|
||||||
self.route_inputs()
|
self.route_inputs()
|
||||||
self.route_output()
|
self.route_output()
|
||||||
|
|
||||||
|
|
@ -110,7 +110,7 @@ class pnand2(pgate.pgate):
|
||||||
extra_contact_space = max(-self.nmos.get_pin("D").by(), 0)
|
extra_contact_space = max(-self.nmos.get_pin("D").by(), 0)
|
||||||
# This is a poly-to-poly of a flipped cell
|
# This is a poly-to-poly of a flipped cell
|
||||||
self.top_bottom_space = max(0.5 * self.m1_width + self.m1_space + extra_contact_space,
|
self.top_bottom_space = max(0.5 * self.m1_width + self.m1_space + extra_contact_space,
|
||||||
self.poly_extend_active, self.poly_space)
|
self.poly_extend_active + self.poly_space)
|
||||||
|
|
||||||
def route_supply_rails(self):
|
def route_supply_rails(self):
|
||||||
""" Add vdd/gnd rails to the top and bottom. """
|
""" Add vdd/gnd rails to the top and bottom. """
|
||||||
|
|
@ -170,9 +170,6 @@ class pnand2(pgate.pgate):
|
||||||
self.output_pos = vector(0,
|
self.output_pos = vector(0,
|
||||||
0.5 * (pmos1_pos.y + nmos1_pos.y + self.nmos.active_height))
|
0.5 * (pmos1_pos.y + nmos1_pos.y + self.nmos.active_height))
|
||||||
|
|
||||||
# This will help with the wells
|
|
||||||
self.well_pos = self.output_pos
|
|
||||||
|
|
||||||
def add_well_contacts(self):
|
def add_well_contacts(self):
|
||||||
"""
|
"""
|
||||||
Add n/p well taps to the layout and connect to supplies
|
Add n/p well taps to the layout and connect to supplies
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ class pnand3(pgate.pgate):
|
||||||
self.place_ptx()
|
self.place_ptx()
|
||||||
self.connect_rails()
|
self.connect_rails()
|
||||||
self.add_well_contacts()
|
self.add_well_contacts()
|
||||||
self.extend_wells(self.well_pos)
|
self.extend_wells()
|
||||||
self.route_inputs()
|
self.route_inputs()
|
||||||
self.route_output()
|
self.route_output()
|
||||||
|
|
||||||
|
|
@ -102,10 +102,8 @@ class pnand3(pgate.pgate):
|
||||||
nmos = factory.create(module_type="ptx", tx_type="nmos")
|
nmos = factory.create(module_type="ptx", tx_type="nmos")
|
||||||
extra_contact_space = max(-nmos.get_pin("D").by(), 0)
|
extra_contact_space = max(-nmos.get_pin("D").by(), 0)
|
||||||
# This is a poly-to-poly of a flipped cell
|
# This is a poly-to-poly of a flipped cell
|
||||||
self.top_bottom_space = max(0.5 * self.m1_width + self.m1_space \
|
self.top_bottom_space = max(0.5 * self.m1_width + self.m1_space + extra_contact_space,
|
||||||
+ extra_contact_space,
|
self.poly_extend_active + self.poly_space)
|
||||||
self.poly_extend_active,
|
|
||||||
self.poly_space)
|
|
||||||
|
|
||||||
def route_supply_rails(self):
|
def route_supply_rails(self):
|
||||||
""" Add vdd/gnd rails to the top and bottom. """
|
""" Add vdd/gnd rails to the top and bottom. """
|
||||||
|
|
@ -179,9 +177,6 @@ class pnand3(pgate.pgate):
|
||||||
# This will help with the wells and the input/output placement
|
# This will help with the wells and the input/output placement
|
||||||
self.output_pos = vector(0, 0.5*self.height)
|
self.output_pos = vector(0, 0.5*self.height)
|
||||||
|
|
||||||
# This should be placed at the top of the NMOS well
|
|
||||||
self.well_pos = self.output_pos
|
|
||||||
|
|
||||||
def add_well_contacts(self):
|
def add_well_contacts(self):
|
||||||
""" Add n/p well taps to the layout and connect to supplies """
|
""" Add n/p well taps to the layout and connect to supplies """
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ class pnor2(pgate.pgate):
|
||||||
self.place_ptx()
|
self.place_ptx()
|
||||||
self.connect_rails()
|
self.connect_rails()
|
||||||
self.add_well_contacts()
|
self.add_well_contacts()
|
||||||
self.extend_wells(self.well_pos)
|
self.extend_wells()
|
||||||
self.route_inputs()
|
self.route_inputs()
|
||||||
self.route_output()
|
self.route_output()
|
||||||
|
|
||||||
|
|
@ -168,9 +168,6 @@ class pnor2(pgate.pgate):
|
||||||
self.output_pos = vector(0,
|
self.output_pos = vector(0,
|
||||||
0.5 * (pmos1_pos.y + nmos1_pos.y + self.nmos.active_height))
|
0.5 * (pmos1_pos.y + nmos1_pos.y + self.nmos.active_height))
|
||||||
|
|
||||||
# This will help with the wells
|
|
||||||
self.well_pos = self.output_pos
|
|
||||||
|
|
||||||
def add_well_contacts(self):
|
def add_well_contacts(self):
|
||||||
""" Add n/p well taps to the layout and connect to supplies """
|
""" Add n/p well taps to the layout and connect to supplies """
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
import contact
|
import contact
|
||||||
import design
|
import design
|
||||||
import debug
|
import debug
|
||||||
from tech import drc, parameter
|
from tech import parameter
|
||||||
from vector import vector
|
from vector import vector
|
||||||
from globals import OPTS
|
from globals import OPTS
|
||||||
from sram_factory import factory
|
from sram_factory import factory
|
||||||
|
|
|
||||||
|
|
@ -6,14 +6,13 @@
|
||||||
#All rights reserved.
|
#All rights reserved.
|
||||||
#
|
#
|
||||||
import design
|
import design
|
||||||
from tech import drc, parameter, spice
|
from tech import parameter
|
||||||
import debug
|
import debug
|
||||||
import math
|
|
||||||
from tech import drc
|
|
||||||
from vector import vector
|
from vector import vector
|
||||||
from globals import OPTS
|
from globals import OPTS
|
||||||
from sram_factory import factory
|
from sram_factory import factory
|
||||||
|
|
||||||
|
|
||||||
class pwrite_driver(design.design):
|
class pwrite_driver(design.design):
|
||||||
"""
|
"""
|
||||||
The pwrite_driver is two tristate inverters that drive the bitlines.
|
The pwrite_driver is two tristate inverters that drive the bitlines.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue