Merge branch 'tech_migration' into dev

This commit is contained in:
mrg
2020-06-10 17:09:05 -07:00
22 changed files with 340 additions and 103 deletions
+2 -1
View File
@@ -46,7 +46,8 @@ class pgate(design.design):
# This is the space from a S/D contact to the supply rail
contact_to_vdd_rail_space = 0.5 * self.m1_width + self.m1_space
# This is a poly-to-poly of a flipped cell
poly_to_poly_gate_space = self.poly_extend_active + self.poly_space
poly_to_poly_gate_space = self.poly_extend_active + 0.5 * self.poly_space
self.top_bottom_space = max(contact_to_vdd_rail_space,
poly_to_poly_gate_space)
+24 -18
View File
@@ -9,7 +9,7 @@ import debug
import pgate
from vector import vector
from sram_factory import factory
from tech import layer
class pinvbuf(pgate.pgate):
"""
@@ -111,33 +111,45 @@ class pinvbuf(pgate.pgate):
mirror="MX")
def route_wires(self):
if "li" in layer:
route_stack = self.li_stack
else:
route_stack = self.m1_stack
# inv1 Z to inv2 A
z1_pin = self.inv1_inst.get_pin("Z")
a2_pin = self.inv2_inst.get_pin("A")
mid_point = vector(z1_pin.cx(), a2_pin.cy())
self.add_path("m1", [z1_pin.center(), mid_point, a2_pin.center()])
self.add_path(z1_pin.layer, [z1_pin.center(), mid_point, a2_pin.center()])
self.add_via_stack_center(from_layer=z1_pin.layer,
to_layer=a2_pin.layer,
offset=a2_pin.center())
# inv2 Z to inv3 A
z2_pin = self.inv2_inst.get_pin("Z")
a3_pin = self.inv3_inst.get_pin("A")
mid_point = vector(z2_pin.cx(), a3_pin.cy())
self.add_path("m1", [z2_pin.center(), mid_point, a3_pin.center()])
self.add_path(z2_pin.layer, [z2_pin.center(), mid_point, a3_pin.center()])
self.add_via_stack_center(from_layer=z2_pin.layer,
to_layer=a3_pin.layer,
offset=a3_pin.center())
# inv1 Z to inv4 A (up and over)
z1_pin = self.inv1_inst.get_pin("Z")
a4_pin = self.inv4_inst.get_pin("A")
mid_point = vector(z1_pin.cx(), a4_pin.cy())
self.add_wire(self.m1_stack,
self.add_wire(route_stack,
[z1_pin.center(), mid_point, a4_pin.center()])
self.add_via_center(layers=self.m1_stack,
offset=z1_pin.center())
self.add_via_stack_center(from_layer=z1_pin.layer,
to_layer=route_stack[2],
offset=z1_pin.center())
def add_layout_pins(self):
# Continous vdd rail along with label.
vdd_pin = self.inv1_inst.get_pin("vdd")
self.add_layout_pin(text="vdd",
layer="m1",
layer=vdd_pin.layer,
offset=vdd_pin.ll().scale(0, 1),
width=self.width,
height=vdd_pin.height())
@@ -145,7 +157,7 @@ class pinvbuf(pgate.pgate):
# Continous vdd rail along with label.
gnd_pin = self.inv4_inst.get_pin("gnd")
self.add_layout_pin(text="gnd",
layer="m1",
layer=gnd_pin.layer,
offset=gnd_pin.ll().scale(0, 1),
width=self.width,
height=gnd_pin.height())
@@ -153,31 +165,25 @@ class pinvbuf(pgate.pgate):
# Continous gnd rail along with label.
gnd_pin = self.inv1_inst.get_pin("gnd")
self.add_layout_pin(text="gnd",
layer="m1",
layer=gnd_pin.layer,
offset=gnd_pin.ll().scale(0, 1),
width=self.width,
height=vdd_pin.height())
z_pin = self.inv4_inst.get_pin("Z")
self.add_layout_pin_rect_center(text="Z",
layer="m2",
layer=z_pin.layer,
offset=z_pin.center())
self.add_via_center(layers=self.m1_stack,
offset=z_pin.center())
zb_pin = self.inv3_inst.get_pin("Z")
self.add_layout_pin_rect_center(text="Zb",
layer="m2",
layer=zb_pin.layer,
offset=zb_pin.center())
self.add_via_center(layers=self.m1_stack,
offset=zb_pin.center())
a_pin = self.inv1_inst.get_pin("A")
self.add_layout_pin_rect_center(text="A",
layer="m2",
layer=a_pin.layer,
offset=a_pin.center())
self.add_via_center(layers=self.m1_stack,
offset=a_pin.center())
def determine_clk_buf_stage_efforts(self, external_cout, inp_is_rise=False):
"""Get the stage efforts of the clk -> clk_buf path"""
+3 -3
View File
@@ -177,9 +177,9 @@ class pnand2(pgate.pgate):
# Top of NMOS drain
nmos_pin = self.nmos2_inst.get_pin("D")
bottom_pin_offset = nmos_pin.uy()
self.inputA_yoffset = bottom_pin_offset + self.m1_pitch
bottom_pin = self.nmos2_inst.get_pin("D")
self.inputA_yoffset = max(bottom_pin.uy() + self.m1_pitch,
self.nmos2_inst.uy() + self.poly_to_active)
self.inputB_yoffset = self.inputA_yoffset + self.m3_pitch
+15 -7
View File
@@ -12,7 +12,7 @@ from vector import vector
import logical_effort
from sram_factory import factory
from globals import OPTS
import contact
class pnand3(pgate.pgate):
"""
@@ -209,13 +209,21 @@ class pnand3(pgate.pgate):
def route_inputs(self):
""" Route the A and B and C inputs """
# We can use this pitch because the contacts and overlap won't be adjacent
non_contact_pitch = 0.5 * self.m1_width + self.m1_space + 0.5 * contact.poly_contact.second_layer_height
pmos_drain_bottom = self.pmos1_inst.get_pin("D").by()
self.output_yoffset = pmos_drain_bottom - 0.5 * self.route_layer_width - self.route_layer_space
# This is a more compact offset, but the bottom one works better in the decoders to "center" the pins
# in the height of the gates
self.inputA_yoffset = self.output_yoffset - 0.5 * self.route_layer_width - self.route_layer_space
# self.inputA_yoffset = self.output_yoffset - self.m1_pitch
bottom_pin = self.nmos1_inst.get_pin("D")
# active contact metal to poly contact metal spacing
active_contact_to_poly_contact = bottom_pin.uy() + self.m1_space + 0.5 * contact.poly_contact.second_layer_height
# active diffusion to poly contact spacing
# doesn't use nmos uy because that is calculated using offset + poly height
active_to_poly_contact = self.nmos1_inst.by() + self.nmos1_inst.mod.active_height \
+ self.poly_to_active + 0.5 * contact.poly_contact.first_layer_height
self.inputA_yoffset = max(active_contact_to_poly_contact,
active_to_poly_contact)
self.route_input_gate(self.pmos1_inst,
self.nmos1_inst,
self.inputA_yoffset,
@@ -223,14 +231,14 @@ class pnand3(pgate.pgate):
position="left")
# Put B right on the well line
self.inputB_yoffset = self.inputA_yoffset - self.m1_pitch
self.inputB_yoffset = self.inputA_yoffset + non_contact_pitch
self.route_input_gate(self.pmos2_inst,
self.nmos2_inst,
self.inputB_yoffset,
"B",
position="center")
self.inputC_yoffset = self.inputB_yoffset - self.m1_pitch
self.inputC_yoffset = self.inputB_yoffset + non_contact_pitch
self.route_input_gate(self.pmos3_inst,
self.nmos3_inst,
self.inputC_yoffset,
+2 -6
View File
@@ -149,13 +149,9 @@ class precharge(design.design):
# Compute the other pmos2 location,
# but determining offset to overlap the source and drain pins
overlap_offset = self.pmos.get_pin("D").ll() - self.pmos.get_pin("S").ll()
# This is how much the contact is placed inside the ptx active
contact_xdiff = self.pmos.get_pin("S").lx()
# adds the lower pmos to layout
bl_xoffset = self.bitcell_bl_pin.lx()
self.lower_pmos_position = vector(max(bl_xoffset - contact_xdiff,
self.nwell_enclose_active),
self.lower_pmos_position = vector(self.well_enclose_active + 0.5 * self.m1_width,
self.initial_yoffset)
self.lower_pmos_inst.place(self.lower_pmos_position)
@@ -218,7 +214,7 @@ class precharge(design.design):
# adds the contact from active to metal1
offset_height = self.upper_pmos1_inst.uy() + \
0.5 * contact.active_contact.height + \
contact.active_contact.height + \
self.nwell_extend_active
self.well_contact_pos = self.upper_pmos1_inst.get_pin("D").center().scale(1, 0) + \
vector(0, offset_height)
+3 -16
View File
@@ -205,28 +205,15 @@ class ptx(design.design):
# Poly height must include poly extension over active
self.poly_height = self.tx_width + 2 * self.poly_extend_active
# The active offset is due to the well extension
if "pwell" in layer:
pwell_enclose_active = drc("pwell_enclose_active")
else:
pwell_enclose_active = 0
if "nwell" in layer:
nwell_enclose_active = drc("nwell_enclose_active")
else:
nwell_enclose_active = 0
# Use the max of either so that the poly gates will align properly
well_enclose_active = max(pwell_enclose_active,
nwell_enclose_active)
self.active_offset = vector([well_enclose_active] * 2)
self.active_offset = vector([self.well_enclose_active] * 2)
# Well enclosure of active, ensure minwidth as well
well_name = "{}well".format(self.well_type)
if well_name in layer:
well_width_rule = drc("minwidth_" + well_name)
well_enclose_active = drc(well_name + "_enclose_active")
self.well_width = max(self.active_width + 2 * well_enclose_active,
self.well_width = max(self.active_width + 2 * self.well_enclose_active,
well_width_rule)
self.well_height = max(self.active_height + 2 * well_enclose_active,
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