mirror of https://github.com/VLSIDA/OpenRAM.git
DRC and LVS fixes for pinv_dec
This commit is contained in:
parent
443b8fbe23
commit
33a32101c9
|
|
@ -27,7 +27,8 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout):
|
|||
# If we have a separate lvs directory, then all the lvs files
|
||||
# should be in there (all or nothing!)
|
||||
lvs_dir = OPTS.openram_tech + "lvs_lib/"
|
||||
if os.path.exists(lvs_dir):
|
||||
# Calibre will do the scaling in s8
|
||||
if os.path.exists(lvs_dir): # and OPTS.lvs_exe[0]!="calibre":
|
||||
self.lvs_file = lvs_dir + name + ".sp"
|
||||
else:
|
||||
self.lvs_file = self.sp_file
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ class dff_buf(design.design):
|
|||
q_pin = self.dff_inst.get_pin("Q")
|
||||
a1_pin = self.inv1_inst.get_pin("A")
|
||||
mid1 = vector(a1_pin.cx(), q_pin.cy())
|
||||
self.add_path(q_pin.layer, [q_pin.center(), mid1, a1_pin.center()])
|
||||
self.add_path(q_pin.layer, [q_pin.center(), mid1, a1_pin.center()], width=q_pin.height())
|
||||
self.add_via_stack_center(from_layer=a1_pin.layer,
|
||||
to_layer=q_pin.layer,
|
||||
offset=a1_pin.center())
|
||||
|
|
@ -177,8 +177,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_nonpref_pitch, 0)
|
||||
q_pos = mid_pos - vector(0, self.m2_pitch)
|
||||
mid_pos = dout_pin.center() + vector(self.m2_nonpref_pitch, 0)
|
||||
q_pos = mid_pos - vector(0, 2 * self.m2_nonpref_pitch)
|
||||
self.add_layout_pin_rect_center(text="Q",
|
||||
layer="m2",
|
||||
offset=q_pos)
|
||||
|
|
@ -187,7 +187,7 @@ class dff_buf(design.design):
|
|||
to_layer="m2",
|
||||
offset=q_pos)
|
||||
|
||||
qb_pos = self.mid_qb_pos + vector(0, self.m2_pitch)
|
||||
qb_pos = self.mid_qb_pos + vector(0, 2 * self.m2_nonpref_pitch)
|
||||
self.add_layout_pin_rect_center(text="Qb",
|
||||
layer="m2",
|
||||
offset=qb_pos)
|
||||
|
|
|
|||
|
|
@ -109,15 +109,15 @@ class pinv_dec(pinv.pinv):
|
|||
self.add_rect(layer="pwell",
|
||||
offset=ll,
|
||||
width=ur.x - ll.x,
|
||||
height=self.height - ll.y)
|
||||
height=self.height - ll.y + 0.5 * self.pwell_contact.height + self.well_enclose_active)
|
||||
|
||||
if "nwell" in layer:
|
||||
ll = self.pmos_inst.ll() - self.pmos_inst.mod.active_offset
|
||||
ur = self.pmos_inst.ur() + self.pmos_inst.mod.active_offset
|
||||
self.add_rect(layer="nwell",
|
||||
offset=ll - vector(self.nwell_enclose_active, 0),
|
||||
width=ur.x - ll.x + self.nwell_enclose_active,
|
||||
height=self.height - ll.y + 2 * self.nwell_enclose_active)
|
||||
offset=ll,
|
||||
width=ur.x - ll.x,
|
||||
height=self.height - ll.y + 0.5 * self.nwell_contact.height + self.well_enclose_active)
|
||||
|
||||
def place_ptx(self):
|
||||
"""
|
||||
|
|
@ -125,15 +125,14 @@ class pinv_dec(pinv.pinv):
|
|||
|
||||
# offset so that the input contact is over from the left edge by poly spacing
|
||||
x_offset = self.nmos.active_offset.y + contact.poly_contact.width + self.poly_space
|
||||
# center the transistor in the y-dimension
|
||||
# bottom of the transistor in the y-dimension
|
||||
y_offset = self.nmos.width + self.active_space
|
||||
self.nmos_pos = vector(x_offset, y_offset)
|
||||
self.nmos_inst.place(self.nmos_pos)
|
||||
self.nmos_inst.place(self.nmos_pos,
|
||||
rotate=270)
|
||||
# place PMOS so it is half a poly spacing down from the top
|
||||
xoffset = self.nmos_inst.height + 2 * self.poly_extend_active + 2 * self.well_extend_active + drc("pwell_to_nwell")
|
||||
self.pmos_pos = self.nmos_pos + vector(xoffset, 0)
|
||||
xoffset = self.nmos_inst.rx() + 2 * self.poly_extend_active + 2 * self.well_extend_active + drc("pwell_to_nwell")
|
||||
self.pmos_pos = vector(xoffset, y_offset)
|
||||
self.pmos_inst.place(self.pmos_pos,
|
||||
rotate=270)
|
||||
|
||||
|
|
@ -142,6 +141,31 @@ class pinv_dec(pinv.pinv):
|
|||
nmos_drain_pos = self.nmos_inst.get_pin("D").center()
|
||||
self.output_pos = vector(0.5 * (pmos_drain_pos.x + nmos_drain_pos.x), nmos_drain_pos.y)
|
||||
|
||||
if OPTS.tech_name == "s8":
|
||||
self.add_implants()
|
||||
|
||||
def add_implants(self):
|
||||
"""
|
||||
Add top-to-bottom implants for adjacency issues in s8.
|
||||
"""
|
||||
# Route to the bottom
|
||||
ll = (self.nmos_inst.ll() - vector(2 * [self.implant_enclose_active])).scale(1, 0)
|
||||
# Don't route to the top
|
||||
ur = self.nmos_inst.ur() + vector(self.implant_enclose_active, 0)
|
||||
self.add_rect("nimplant",
|
||||
ll,
|
||||
ur.x - ll.x,
|
||||
ur.y - ll.y)
|
||||
|
||||
# Route to the bottom
|
||||
ll = (self.pmos_inst.ll() - vector(2 * [self.implant_enclose_active])).scale(1, 0)
|
||||
# Don't route to the top
|
||||
ur = self.pmos_inst.ur() + vector(self.implant_enclose_active, 0)
|
||||
self.add_rect("pimplant",
|
||||
ll,
|
||||
ur.x - ll.x,
|
||||
ur.y - ll.y)
|
||||
|
||||
def route_outputs(self):
|
||||
"""
|
||||
Route the output (drains) together.
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import os
|
|||
from globals import OPTS
|
||||
from pgate import pgate
|
||||
|
||||
|
||||
class ptx(design.design):
|
||||
"""
|
||||
This module generates gds and spice of a parametrically NMOS or
|
||||
|
|
@ -24,6 +25,10 @@ class ptx(design.design):
|
|||
given width. Total width is therefore mults*width. Options allow
|
||||
you to connect the fingered gates and active for parallel devices.
|
||||
The add_*_contact option tells which layer to bring source/drain up to.
|
||||
|
||||
ll, ur, width and height refer to the active area.
|
||||
Wells and poly may extend beyond this.
|
||||
|
||||
"""
|
||||
def __init__(self,
|
||||
name="",
|
||||
|
|
@ -221,15 +226,13 @@ class ptx(design.design):
|
|||
well_width_rule)
|
||||
self.well_height = max(self.active_height + 2 * self.well_enclose_active,
|
||||
well_width_rule)
|
||||
# We are going to shift the 0,0, so include that in the width and height
|
||||
self.height = self.well_height - self.active_offset.y
|
||||
self.width = self.well_width - self.active_offset.x
|
||||
else:
|
||||
# The well is not included in the height and width
|
||||
self.height = self.poly_height
|
||||
self.width = self.active_width
|
||||
self.well_height = self.height
|
||||
self.well_width = self.width
|
||||
|
||||
# We are going to shift the 0,0, so include that in the width and height
|
||||
self.height = self.active_height
|
||||
self.width = self.active_width
|
||||
|
||||
# This is the center of the first active contact offset (centered vertically)
|
||||
self.contact_offset = self.active_offset + vector(0.5 * self.active_contact.width,
|
||||
|
|
@ -353,18 +356,18 @@ class ptx(design.design):
|
|||
"""
|
||||
Adding the diffusion (active region = diffusion region)
|
||||
"""
|
||||
self.add_rect(layer="active",
|
||||
offset=self.active_offset,
|
||||
width=self.active_width,
|
||||
height=self.active_height)
|
||||
self.active = self.add_rect(layer="active",
|
||||
offset=self.active_offset,
|
||||
width=self.active_width,
|
||||
height=self.active_height)
|
||||
# If the implant must enclose the active, shift offset
|
||||
# and increase width/height
|
||||
enclose_width = self.implant_enclose_active
|
||||
enclose_offset = [enclose_width] * 2
|
||||
self.add_rect(layer="{}implant".format(self.implant_type),
|
||||
offset=self.active_offset - enclose_offset,
|
||||
width=self.active_width + 2 * enclose_width,
|
||||
height=self.active_height + 2 * enclose_width)
|
||||
self.implant = self.add_rect(layer="{}implant".format(self.implant_type),
|
||||
offset=self.active_offset - enclose_offset,
|
||||
width=self.active_width + 2 * enclose_width,
|
||||
height=self.active_height + 2 * enclose_width)
|
||||
|
||||
def add_well_implant(self):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -21,6 +21,11 @@ class pinv_dec_1x_test(openram_test):
|
|||
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||
globals.init_openram(config_file)
|
||||
|
||||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_r_ports = 1
|
||||
OPTS.num_w_ports = 0
|
||||
globals.setup_bitcell()
|
||||
|
||||
debug.info(2, "Checking 1x size decoder inverter")
|
||||
tx = factory.create(module_type="pinv_dec", size=1)
|
||||
self.local_check(tx)
|
||||
|
|
|
|||
Loading…
Reference in New Issue