Clean up and generalize layer rules.

Convert metalN to mN.
Generalize helper constants in modules for
space, width, enclose, etc.
Use layer stacks whever possible.
Try to remove drc() calls in liu of helper constants.
This commit is contained in:
Matt Guthaus
2019-12-17 11:03:36 -08:00
parent a79d03fef4
commit ed28b4983b
52 changed files with 604 additions and 578 deletions
+3 -3
View File
@@ -76,14 +76,14 @@ class pand2(pgate.pgate):
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("metal1",
self.add_path("m1",
[z1_pin.center(), mid1_point, mid2_point, a2_pin.center()])
def add_layout_pins(self):
# Continous vdd rail along with label.
vdd_pin = self.inv_inst.get_pin("vdd")
self.add_layout_pin(text="vdd",
layer="metal1",
layer="m1",
offset=vdd_pin.ll().scale(0, 1),
width=self.width,
height=vdd_pin.height())
@@ -91,7 +91,7 @@ class pand2(pgate.pgate):
# Continous gnd rail along with label.
gnd_pin = self.inv_inst.get_pin("gnd")
self.add_layout_pin(text="gnd",
layer="metal1",
layer="m1",
offset=gnd_pin.ll().scale(0, 1),
width=self.width,
height=vdd_pin.height())
+3 -3
View File
@@ -76,14 +76,14 @@ class pand3(pgate.pgate):
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("metal1",
self.add_path("m1",
[z1_pin.center(), mid1_point, mid2_point, a2_pin.center()])
def add_layout_pins(self):
# Continous vdd rail along with label.
vdd_pin = self.inv_inst.get_pin("vdd")
self.add_layout_pin(text="vdd",
layer="metal1",
layer="m1",
offset=vdd_pin.ll().scale(0, 1),
width=self.width,
height=vdd_pin.height())
@@ -91,7 +91,7 @@ class pand3(pgate.pgate):
# Continous gnd rail along with label.
gnd_pin = self.inv_inst.get_pin("gnd")
self.add_layout_pin(text="gnd",
layer="metal1",
layer="m1",
offset=gnd_pin.ll().scale(0, 1),
width=self.width,
height=vdd_pin.height())
+3 -3
View File
@@ -78,13 +78,13 @@ class pbuf(pgate.pgate):
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("metal1", [z1_pin.center(), mid_point, a2_pin.center()])
self.add_path("m1", [z1_pin.center(), mid_point, a2_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="metal1",
layer="m1",
offset=vdd_pin.ll().scale(0, 1),
width=self.width,
height=vdd_pin.height())
@@ -92,7 +92,7 @@ class pbuf(pgate.pgate):
# Continous gnd rail along with label.
gnd_pin = self.inv1_inst.get_pin("gnd")
self.add_layout_pin(text="gnd",
layer="metal1",
layer="m1",
offset=gnd_pin.ll().scale(0, 1),
width=self.width,
height=vdd_pin.height())
+3 -3
View File
@@ -140,7 +140,7 @@ class pdriver(pgate.pgate):
z_inst_list.append(self.inv_inst_list[x].get_pin("Z"))
a_inst_list.append(self.inv_inst_list[x + 1].get_pin("A"))
mid_point = vector(z_inst_list[x].cx(), a_inst_list[x].cy())
self.add_path("metal1",
self.add_path("m1",
[z_inst_list[x].center(), mid_point,
a_inst_list[x].center()])
@@ -148,7 +148,7 @@ class pdriver(pgate.pgate):
# Continous vdd rail along with label.
vdd_pin = self.inv_inst_list[0].get_pin("vdd")
self.add_layout_pin(text="vdd",
layer="metal1",
layer="m1",
offset=vdd_pin.ll().scale(0, 1),
width=self.width,
height=vdd_pin.height())
@@ -156,7 +156,7 @@ class pdriver(pgate.pgate):
# Continous gnd rail along with label.
gnd_pin = self.inv_inst_list[0].get_pin("gnd")
self.add_layout_pin(text="gnd",
layer="metal1",
layer="m1",
offset=gnd_pin.ll().scale(0, 1),
width=self.width,
height=vdd_pin.height())
+6 -6
View File
@@ -59,7 +59,7 @@ class pgate(design.design):
debug.error("Invalid supply name.", -1)
if abs(height) > 0:
self.add_rect(layer="metal1",
self.add_rect(layer="m1",
offset=source_pin.ll(),
height=height,
width=source_pin.width())
@@ -120,7 +120,7 @@ class pgate(design.design):
directions=directions)
self.add_layout_pin_rect_center(text=name,
layer="metal1",
layer="m1",
offset=contact_offset,
width=contact_m1_width,
height=contact_m1_height)
@@ -172,7 +172,7 @@ class pgate(design.design):
# To the right a spacing away from the pmos right active edge
contact_xoffset = pmos_pos.x + pmos.active_width \
+ drc("active_to_body_active")
+ self.active_space
# Must be at least an well enclosure of active down
# from the top of the well
@@ -189,7 +189,7 @@ class pgate(design.design):
directions=("H", "V"),
implant_type="n",
well_type="n")
self.add_rect_center(layer="metal1",
self.add_rect_center(layer="m1",
offset=contact_offset + vector(0, 0.5 * (self.height-contact_offset.y)),
width=self.nwell_contact.mod.second_layer_width,
height=self.height - contact_offset.y)
@@ -227,7 +227,7 @@ class pgate(design.design):
# To the right a spacing away from the nmos right active edge
contact_xoffset = nmos_pos.x + nmos.active_width \
+ drc("active_to_body_active")
+ self.active_space
# Must be at least an well enclosure of active up
# from the bottom of the well
contact_yoffset = max(nmos_pos.y,
@@ -243,7 +243,7 @@ class pgate(design.design):
directions=("H", "V"),
implant_type="p",
well_type="p")
self.add_rect_center(layer="metal1",
self.add_rect_center(layer="m1",
offset=contact_offset.scale(1,0.5),
width=self.pwell_contact.mod.second_layer_width,
height=contact_offset.y)
+8 -8
View File
@@ -96,14 +96,14 @@ class pinv(pgate.pgate):
tx_height = nmos.poly_height + pmos.poly_height
# rotated m1 pitch or poly to active spacing
min_channel = max(contact.poly.width + self.m1_space,
contact.poly.width + 2 * drc("poly_to_active"))
contact.poly.width + 2 * self.poly_to_active)
# This is the extra space needed to ensure DRC rules
# to the active contacts
extra_contact_space = max(-nmos.get_pin("D").by(), 0)
# 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,
drc("poly_extend_active"), self.poly_space)
self.poly_extend_active, self.poly_space)
total_height = tx_height + min_channel + 2 * self.top_bottom_space
debug.check(self.height > total_height,
"Cell height {0} too small for simple min height {1}.".format(self.height,
@@ -153,7 +153,7 @@ class pinv(pgate.pgate):
# the well width is determined the multi-finger PMOS device width plus
# the well contact width and half well enclosure on both sides
self.well_width = self.pmos.active_width + self.pmos.active_contact.width \
+ drc("active_to_body_active") + 2*drc("well_enclosure_active")
+ self.active_space + 2*self.well_enclose_active
self.width = self.well_width
# Height is an input parameter, so it is not recomputed.
@@ -178,12 +178,12 @@ class pinv(pgate.pgate):
def route_supply_rails(self):
""" Add vdd/gnd rails to the top and bottom. """
self.add_layout_pin_rect_center(text="gnd",
layer="metal1",
layer="m1",
offset=vector(0.5 * self.width, 0),
width=self.width)
self.add_layout_pin_rect_center(text="vdd",
layer="metal1",
layer="m1",
offset=vector(0.5 * self.width, self.height),
width=self.width)
@@ -238,7 +238,7 @@ class pinv(pgate.pgate):
# Pick point at right most of NMOS and connect down to PMOS
nmos_drain_pos = nmos_drain_pin.bc()
pmos_drain_pos = vector(nmos_drain_pos.x, pmos_drain_pin.uc().y)
self.add_path("metal1", [nmos_drain_pos, pmos_drain_pos])
self.add_path("m1", [nmos_drain_pos, pmos_drain_pos])
# Remember the mid for the output
mid_drain_offset = vector(nmos_drain_pos.x, self.output_pos.y)
@@ -247,13 +247,13 @@ class pinv(pgate.pgate):
# This extends the output to the edge of the cell
output_offset = mid_drain_offset.scale(0, 1) + vector(self.width, 0)
self.add_layout_pin_segment_center(text="Z",
layer="metal1",
layer="m1",
start=mid_drain_offset,
end=output_offset)
else:
# This leaves the output as an internal pin (min sized)
self.add_layout_pin_rect_center(text="Z",
layer="metal1",
layer="m1",
offset=mid_drain_offset \
+ vector(0.5 * self.m1_width, 0))
+8 -8
View File
@@ -114,13 +114,13 @@ class pinvbuf(pgate.pgate):
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("metal1", [z1_pin.center(), mid_point, a2_pin.center()])
self.add_path("m1", [z1_pin.center(), mid_point, 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("metal1", [z2_pin.center(), mid_point, a3_pin.center()])
self.add_path("m1", [z2_pin.center(), mid_point, a3_pin.center()])
# inv1 Z to inv4 A (up and over)
z1_pin = self.inv1_inst.get_pin("Z")
@@ -136,7 +136,7 @@ class pinvbuf(pgate.pgate):
# Continous vdd rail along with label.
vdd_pin = self.inv1_inst.get_pin("vdd")
self.add_layout_pin(text="vdd",
layer="metal1",
layer="m1",
offset=vdd_pin.ll().scale(0, 1),
width=self.width,
height=vdd_pin.height())
@@ -144,7 +144,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="metal1",
layer="m1",
offset=gnd_pin.ll().scale(0, 1),
width=self.width,
height=gnd_pin.height())
@@ -152,28 +152,28 @@ 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="metal1",
layer="m1",
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="metal2",
layer="m2",
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="metal2",
layer="m2",
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="metal2",
layer="m2",
offset=a_pin.center())
self.add_via_center(layers=self.m1_stack,
offset=a_pin.center())
+7 -7
View File
@@ -99,8 +99,8 @@ class pnand2(pgate.pgate):
# Two PMOS devices and a well contact. Separation between each.
# Enclosure space on the sides.
self.well_width = 2 * self.pmos.active_width + contact.active.width \
+ 2 * drc("active_to_body_active") \
+ 2 * drc("well_enclosure_active")
+ 2 * self.active_space \
+ 2 * self.well_enclose_active
self.width = self.well_width
# Height is an input parameter, so it is not recomputed.
@@ -110,17 +110,17 @@ class pnand2(pgate.pgate):
extra_contact_space = max(-self.nmos.get_pin("D").by(), 0)
# 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,
drc("poly_extend_active"), self.poly_space)
self.poly_extend_active, self.poly_space)
def route_supply_rails(self):
""" Add vdd/gnd rails to the top and bottom. """
self.add_layout_pin_rect_center(text="gnd",
layer="metal1",
layer="m1",
offset=vector(0.5*self.width, 0),
width=self.width)
self.add_layout_pin_rect_center(text="vdd",
layer="metal1",
layer="m1",
offset=vector(0.5 * self.width, self.height),
width=self.width)
@@ -235,13 +235,13 @@ class pnand2(pgate.pgate):
offset=out_offset)
# PMOS1 to mid-drain to NMOS2 drain
self.add_path("metal2",
self.add_path("m2",
[top_pin_offset, mid1_offset, out_offset,
mid2_offset, bottom_pin_offset])
# This extends the output to the edge of the cell
self.add_layout_pin_rect_center(text="Z",
layer="metal1",
layer="m1",
offset=out_offset,
width=contact.m1m2.first_layer_height,
height=contact.m1m2.first_layer_width)
+8 -8
View File
@@ -92,7 +92,7 @@ class pnand3(pgate.pgate):
# Two PMOS devices and a well contact. Separation between each.
# Enclosure space on the sides.
self.well_width = 3 * self.pmos.active_width + self.pmos.active_contact.width \
+ 2 * drc("active_to_body_active") + 2 * drc("well_enclosure_active") \
+ 2 * self.active_space + 2 * self.well_enclose_active \
- self.overlap_offset.x
self.width = self.well_width
# Height is an input parameter, so it is not recomputed.
@@ -107,18 +107,18 @@ class pnand3(pgate.pgate):
# 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,
drc("poly_extend_active"),
self.poly_extend_active,
self.poly_space)
def route_supply_rails(self):
""" Add vdd/gnd rails to the top and bottom. """
self.add_layout_pin_rect_center(text="gnd",
layer="metal1",
layer="m1",
offset=vector(0.5 * self.width, 0),
width=self.width)
self.add_layout_pin_rect_center(text="vdd",
layer="metal1",
layer="m1",
offset=vector(0.5 * self.width, self.height),
width=self.width)
@@ -205,7 +205,7 @@ class pnand3(pgate.pgate):
self.m1_space + 0.5 *contact.poly.width + 0.5 * self.m1_width)
active_spacing = max(self.m1_space,
0.5 * contact.poly.first_layer_width + drc("poly_to_active"))
0.5 * contact.poly.first_layer_width + self.poly_to_active)
inputC_yoffset = self.nmos3_pos.y + self.nmos.active_height + active_spacing
self.route_input_gate(self.pmos3_inst,
self.nmos3_inst,
@@ -245,16 +245,16 @@ class pnand3(pgate.pgate):
offset=nmos3_pin.center())
# PMOS3 and NMOS3 are drain aligned
self.add_path("metal2", [pmos3_pin.bc(), nmos3_pin.uc()])
self.add_path("m2", [pmos3_pin.bc(), nmos3_pin.uc()])
# Route in the A input track (top track)
mid_offset = vector(nmos3_pin.center().x, self.inputA_yoffset)
self.add_path("metal2", [pmos1_pin.bc(), mid_offset, nmos3_pin.uc()])
self.add_path("m2", [pmos1_pin.bc(), mid_offset, nmos3_pin.uc()])
# This extends the output to the edge of the cell
self.add_via_center(layers=self.m1_stack,
offset=mid_offset)
self.add_layout_pin_rect_center(text="Z",
layer="metal1",
layer="m1",
offset=mid_offset,
width=contact.m1m2.first_layer_width,
height=contact.m1m2.first_layer_height)
+8 -9
View File
@@ -97,9 +97,8 @@ class pnor2(pgate.pgate):
# Enclosure space on the sides.
self.well_width = 2 * self.pmos.active_width \
+ self.pmos.active_contact.width \
+ 2 * drc("active_to_body_active") \
+ 2 * drc("well_enclosure_active")
+ 2 * self.active_space \
+ 2 * self.well_enclose_active
self.width = self.well_width
# Height is an input parameter, so it is not recomputed.
@@ -108,18 +107,18 @@ class pnor2(pgate.pgate):
extra_contact_space = max(-self.nmos.get_pin("D").by(), 0)
# 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,
drc("poly_extend_active"),
self.poly_extend_active,
self.poly_space)
def route_supply_rails(self):
""" Add vdd/gnd rails to the top and bottom. """
self.add_layout_pin_rect_center(text="gnd",
layer="metal1",
layer="m1",
offset=vector(0.5 * self.width, 0),
width=self.width)
self.add_layout_pin_rect_center(text="vdd",
layer="metal1",
layer="m1",
offset=vector(0.5 * self.width, self.height),
width=self.width)
@@ -226,15 +225,15 @@ class pnor2(pgate.pgate):
mid3_offset = mid2_offset + vector(self.m2_width, 0)
# PMOS1 to mid-drain to NMOS2 drain
self.add_path("metal2",
self.add_path("m2",
[pmos_pin.bc(), mid2_offset, mid3_offset])
self.add_path("metal2",
self.add_path("m2",
[nmos_pin.rc(), mid1_offset, mid2_offset])
# This extends the output to the edge of the cell
self.add_via_center(layers=self.m1_stack,
offset=mid3_offset)
self.add_layout_pin_rect_center(text="Z",
layer="metal1",
layer="m1",
offset=mid3_offset,
width=contact.m1m2.first_layer_height,
height=contact.m1m2.first_layer_width)
+8 -8
View File
@@ -72,7 +72,7 @@ class precharge(design.design):
# Adds the rail across the width of the cell
vdd_position = vector(0.5 * self.width, self.height)
self.add_rect_center(layer="metal1",
self.add_rect_center(layer="m1",
offset=vdd_position,
width=self.width,
height=self.m1_width)
@@ -80,7 +80,7 @@ class precharge(design.design):
pmos_pin = self.upper_pmos2_inst.get_pin("S")
# center of vdd rail
pmos_vdd_pos = vector(pmos_pin.cx(), vdd_position.y)
self.add_path("metal1", [pmos_pin.uc(), pmos_vdd_pos])
self.add_path("m1", [pmos_pin.uc(), pmos_vdd_pos])
# Add vdd pin above the transistor
self.add_power_pin("vdd", pmos_pin.center(), vertical=True)
@@ -164,7 +164,7 @@ class precharge(design.design):
# adds the en rail on metal1
self.add_layout_pin_segment_center(text="en_bar",
layer="metal1",
layer="m1",
start=offset.scale(0, 1),
end=offset.scale(0, 1) + vector(self.width, 0))
@@ -176,7 +176,7 @@ class precharge(design.design):
# adds the contact from active to metal1
well_contact_pos = self.upper_pmos1_inst.get_pin("D").center().scale(1, 0) \
+ vector(0, self.upper_pmos1_inst.uy() + contact.well.height / 2 \
+ drc("well_extend_active"))
+ self.well_extend_active)
self.add_via_center(layers=self.active_stack,
offset=well_contact_pos,
implant_type="n",
@@ -200,7 +200,7 @@ class precharge(design.design):
offset = vector(self.bitcell.get_pin(self.bitcell_bl).cx(), 0) \
- vector(0.5 * self.m2_width, 0)
self.bl_pin = self.add_layout_pin(text="bl",
layer="metal2",
layer="m2",
offset=offset,
height=self.height)
@@ -208,7 +208,7 @@ class precharge(design.design):
offset = vector(self.bitcell.get_pin(self.bitcell_br).cx(), 0) \
- vector(0.5 * self.m2_width, 0)
self.br_pin = self.add_layout_pin(text="br",
layer="metal2",
layer="m2",
offset=offset,
height=self.height)
@@ -258,7 +258,7 @@ class precharge(design.design):
left_pos = vector(min(pmos_pin.cx(), bit_pin.cx()), pmos_pin.cy())
right_pos = vector(max(pmos_pin.cx(), bit_pin.cx()), pmos_pin.cy())
self.add_path("metal1", [left_pos, right_pos] )
self.add_path("m1", [left_pos, right_pos] )
def connect_pmos_m2(self, pmos_pin, bit_pin):
"""
@@ -268,7 +268,7 @@ class precharge(design.design):
left_pos = vector(min(pmos_pin.cx(), bit_pin.cx()), pmos_pin.cy())
right_pos = vector(max(pmos_pin.cx(), bit_pin.cx()), pmos_pin.cy())
self.add_path("metal2", [left_pos, right_pos], self.bl_contact.height)
self.add_path("m2", [left_pos, right_pos], self.bl_contact.height)
def get_en_cin(self):
"""Get the relative capacitance of the enable in the precharge cell"""
+4 -4
View File
@@ -73,7 +73,7 @@ class ptristate_inv(pgate.pgate):
# Two PMOS devices and a well contact. Separation between each.
# Enclosure space on the sides.
self.well_width = 2 * self.pmos.active_width + drc("well_enclosure_active")
self.well_width = 2 * self.pmos.active_width + self.well_enclose_active
# Add an extra space because we route the output on the right of the S/D
self.width = self.well_width + 0.5 * self.m1_space
@@ -101,12 +101,12 @@ class ptristate_inv(pgate.pgate):
def route_supply_rails(self):
""" Add vdd/gnd rails to the top and bottom. """
self.add_layout_pin_rect_center(text="gnd",
layer="metal1",
layer="m1",
offset=vector(0.5 * self.width, 0),
width=self.width)
self.add_layout_pin_rect_center(text="vdd",
layer="metal1",
layer="m1",
offset=vector(0.5 * self.width, self.height),
width=self.width)
@@ -181,7 +181,7 @@ class ptristate_inv(pgate.pgate):
pmos_drain_pos = pmos_drain_pin.ur()
self.add_layout_pin(text="out",
layer="metal1",
layer="m1",
offset=nmos_drain_pos,
height=pmos_drain_pos.y - nmos_drain_pos.y)
+13 -13
View File
@@ -91,8 +91,8 @@ class ptx(design.design):
# " ".join(self.pins)))
# Just make a guess since these will actually
# be decided in the layout later.
area_sd = 2.5 * drc("minwidth_poly") * self.tx_width
perimeter_sd = 2 * drc("minwidth_poly") + 2 * self.tx_width
area_sd = 2.5 * self.poly_width * self.tx_width
perimeter_sd = 2 * self.poly_width + 2 * self.tx_width
main_str = "M{{0}} {{1}} {0} m={1} w={2}u l={3}u ".format(spice[self.tx_type],
self.mults,
self.tx_width,
@@ -136,7 +136,7 @@ class ptx(design.design):
self.contact_pitch = 2 * self.contact_to_gate + self.contact_width + self.poly_width
# The enclosure of an active contact. Not sure about second term.
active_enclose_contact = max(drc("active_enclosure_contact"),
active_enclose_contact = max(self.active_enclose_contact,
(self.active_width - self.contact_width) / 2)
# This is the distance from the edge of poly to the contacted end of active
@@ -180,11 +180,11 @@ class ptx(design.design):
# Min area results are just flagged for now.
debug.check(self.active_width * self.active_height >= drc("minarea_active"),
debug.check(self.active_width * self.active_height >= self.minarea_active,
"Minimum active area violated.")
# We do not want to increase the poly dimensions to fix
# an area problem as it would cause an LVS issue.
debug.check(self.poly_width * self.poly_height >= drc("minarea_poly"),
debug.check(self.poly_width * self.poly_height >= self.minarea_poly,
"Minimum poly area violated.")
def connect_fingered_poly(self, poly_positions):
@@ -219,7 +219,7 @@ class ptx(design.design):
layer="poly",
offset=poly_offset,
width=poly_width,
height=drc("minwidth_poly"))
height=self.poly_width)
def connect_fingered_active(self, drain_positions, source_positions):
@@ -249,12 +249,12 @@ class ptx(design.design):
self.remove_layout_pin("S") # remove the individual connections
# Add each vertical segment
for a in source_positions:
self.add_path(("metal1"),
self.add_path(("m1"),
[a, a + pin_offset.scale(source_dir,
source_dir)])
# Add a single horizontal pin
self.add_layout_pin_segment_center(text="S",
layer="metal1",
layer="m1",
start=source_positions[0] + source_offset - end_offset,
end=source_positions[-1] + source_offset + end_offset)
@@ -263,10 +263,10 @@ class ptx(design.design):
self.remove_layout_pin("D") # remove the individual connections
# Add each vertical segment
for a in drain_positions:
self.add_path(("metal1"), [a,a+drain_offset])
self.add_path(("m1"), [a,a+drain_offset])
# Add a single horizontal pin
self.add_layout_pin_segment_center(text="D",
layer="metal1",
layer="m1",
start=drain_positions[0] + drain_offset - end_offset,
end=drain_positions[-1] + drain_offset + end_offset)
@@ -313,7 +313,7 @@ class ptx(design.design):
height=self.active_height)
# If the implant must enclose the active, shift offset
# and increase width/height
enclose_width = drc("implant_enclosure_active")
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,
@@ -380,7 +380,7 @@ class ptx(design.design):
implant_type=self.implant_type,
well_type=self.well_type)
self.add_layout_pin_rect_center(text="S",
layer="metal1",
layer="m1",
offset=pos,
width=contact.mod.second_layer_width,
height=contact.mod.second_layer_height)
@@ -394,7 +394,7 @@ class ptx(design.design):
implant_type=self.implant_type,
well_type=self.well_type)
self.add_layout_pin_rect_center(text="D",
layer="metal1",
layer="m1",
offset=pos,
width=contact.mod.second_layer_width,
height=contact.mod.second_layer_height)
+29 -29
View File
@@ -131,26 +131,26 @@ class pwrite_driver(design.design):
bl_xoffset = left_x
bl_out=vector(bl_xoffset, self.height)
bl_in=self.bl_inst.get_pin("out").center()
self.add_via_center(layers=("metal1","via1","metal2"),
self.add_via_center(layers=self.m1_stack,
offset=bl_in)
bl_mid = vector(bl_out.x,bl_in.y)
self.add_path("metal2", [bl_in, bl_mid, bl_out])
self.add_path("m2", [bl_in, bl_mid, bl_out])
self.add_layout_pin_rect_center(text="bl",
layer="metal2",
layer="m2",
offset=bl_out)
br_xoffset = right_x
br_out=vector(br_xoffset, self.height)
br_in=self.br_inst.get_pin("out").center()
self.add_via_center(layers=("metal1","via1","metal2"),
self.add_via_center(layers=self.m1_stack,
offset=br_in)
br_mid = vector(br_out.x,br_in.y)
self.add_path("metal2", [br_in, br_mid, br_out])
self.add_path("m2", [br_in, br_mid, br_out])
self.add_layout_pin_rect_center(text="br",
layer="metal2",
layer="m2",
offset=br_out)
#br_xoffset = b.get_pin("br".cx()
@@ -162,19 +162,19 @@ class pwrite_driver(design.design):
track_xoff = self.get_m2_track(1)
din_loc = self.din_inst.get_pin("A").center()
self.add_via_stack("metal1", "metal2", din_loc)
self.add_via_stack("m1", "m2", din_loc)
din_track = vector(track_xoff,din_loc.y)
br_in = self.br_inst.get_pin("in").center()
self.add_via_stack("metal1", "metal2", br_in)
self.add_via_stack("m1", "m2", br_in)
br_track = vector(track_xoff,br_in.y)
din_in = vector(track_xoff,0)
self.add_path("metal2", [din_in, din_track, din_loc, din_track, br_track, br_in])
self.add_path("m2", [din_in, din_track, din_loc, din_track, br_track, br_in])
self.add_layout_pin_rect_center(text="din",
layer="metal2",
layer="m2",
offset=din_in)
def route_din_bar(self):
@@ -183,19 +183,19 @@ class pwrite_driver(design.design):
track_xoff = self.get_m4_track(self.din_bar_track)
din_bar_in = self.din_inst.get_pin("Z").center()
self.add_via_stack("metal1", "metal3", din_bar_in)
self.add_via_stack("m1", "m3", din_bar_in)
din_bar_track = vector(track_xoff,din_bar_in.y)
bl_in = self.bl_inst.get_pin("in").center()
self.add_via_stack("metal1", "metal3", bl_in)
self.add_via_stack("m1", "m3", bl_in)
bl_track = vector(track_xoff,bl_in.y)
din_in = vector(track_xoff,0)
self.add_wire(("metal3","via3","metal4"), [din_bar_in, din_bar_track, bl_track, bl_in])
self.add_wire(self.m3_stack, [din_bar_in, din_bar_track, bl_track, bl_in])
self.add_layout_pin_rect_center(text="din",
layer="metal4",
layer="m4",
offset=din_in)
@@ -206,22 +206,22 @@ class pwrite_driver(design.design):
# This M2 pitch is a hack since the A and Z pins align horizontally
en_bar_loc = self.en_inst.get_pin("Z").uc()
en_bar_track = vector(track_xoff, en_bar_loc.y)
self.add_via_stack("metal1", "metal3", en_bar_loc)
self.add_via_stack("m1", "m3", en_bar_loc)
# This is a U route to the right down then left
bl_en_loc = self.bl_inst.get_pin("en_bar").center()
bl_en_track = vector(track_xoff, bl_en_loc.y)
self.add_via_stack("metal1", "metal3", bl_en_loc)
self.add_via_stack("m1", "m3", bl_en_loc)
br_en_loc = self.br_inst.get_pin("en_bar").center()
br_en_track = vector(track_xoff, bl_en_loc.y)
self.add_via_stack("metal1", "metal3", br_en_loc)
self.add_via_stack("m1", "m3", br_en_loc)
# L shape
self.add_wire(("metal3","via3","metal4"),
self.add_wire(self.m3_stack,
[en_bar_loc, en_bar_track, bl_en_track])
# U shape
self.add_wire(("metal3","via3","metal4"),
self.add_wire(self.m3_stack,
[bl_en_loc, bl_en_track, br_en_track, br_en_loc])
@@ -233,30 +233,30 @@ class pwrite_driver(design.design):
# The en pin will be over the vdd rail
vdd_yloc = self.en_inst.get_pin("vdd").cy()
self.add_layout_pin_segment_center(text="en",
layer="metal3",
layer="m3",
start=vector(0,vdd_yloc),
end=vector(self.width,vdd_yloc))
en_loc = self.en_inst.get_pin("A").center()
en_rail = vector(en_loc.x, vdd_yloc)
self.add_via_stack("metal1", "metal2", en_loc)
self.add_path("metal2", [en_loc, en_rail])
self.add_via_stack("metal2", "metal3", en_rail)
self.add_via_stack("m1", "m2", en_loc)
self.add_path("m2", [en_loc, en_rail])
self.add_via_stack("m2", "m3", en_rail)
# Start point in the track on the pin rail
en_track = vector(track_xoff, vdd_yloc)
self.add_via_stack("metal3", "metal4", en_track)
self.add_via_stack("m3", "m4", en_track)
# This is a U route to the right down then left
bl_en_loc = self.bl_inst.get_pin("en").center()
bl_en_track = vector(track_xoff, bl_en_loc.y)
self.add_via_stack("metal1", "metal3", bl_en_loc)
self.add_via_stack("m1", "m3", bl_en_loc)
br_en_loc = self.br_inst.get_pin("en").center()
br_en_track = vector(track_xoff, bl_en_loc.y)
self.add_via_stack("metal1", "metal3", br_en_loc)
self.add_via_stack("m1", "m3", br_en_loc)
# U shape
self.add_wire(("metal3","via3","metal4"),
self.add_wire(self.m3_stack,
[en_track, bl_en_track, bl_en_loc, bl_en_track, br_en_track, br_en_loc])
@@ -284,7 +284,7 @@ class pwrite_driver(design.design):
# Continous vdd rail along with label.
vdd_pin=inst.get_pin("vdd")
self.add_layout_pin(text="vdd",
layer="metal1",
layer="m1",
offset=vdd_pin.ll().scale(0,1),
width=self.width,
height=vdd_pin.height())
@@ -292,7 +292,7 @@ class pwrite_driver(design.design):
# Continous gnd rail along with label.
gnd_pin=inst.get_pin("gnd")
self.add_layout_pin(text="gnd",
layer="metal1",
layer="m1",
offset=gnd_pin.ll().scale(0,1),
width=self.width,
height=vdd_pin.height())
+9 -9
View File
@@ -65,21 +65,21 @@ class single_level_column_mux(pgate.pgate):
# bl and br
self.add_layout_pin(text="bl",
layer="metal2",
layer="m2",
offset=bl_pos + vector(0, self.height - self.pin_height),
height=self.pin_height)
self.add_layout_pin(text="br",
layer="metal2",
layer="m2",
offset=br_pos + vector(0, self.height - self.pin_height),
height=self.pin_height)
# bl_out and br_out
self.add_layout_pin(text="bl_out",
layer="metal2",
layer="m2",
offset=bl_pos,
height=self.pin_height)
self.add_layout_pin(text="br_out",
layer="metal2",
layer="m2",
offset=br_pos,
height=self.pin_height)
@@ -141,7 +141,7 @@ class single_level_column_mux(pgate.pgate):
# bl -> nmos_upper/D on metal1
# bl_out -> nmos_upper/S on metal2
self.add_path("metal1",
self.add_path("m1",
[bl_pin.ll(), vector(nmos_upper_d_pin.cx(), bl_pin.by()),
nmos_upper_d_pin.center()])
# halfway up, move over
@@ -149,12 +149,12 @@ class single_level_column_mux(pgate.pgate):
+ nmos_upper_s_pin.bc().scale(0, 0.4)
mid2 = bl_out_pin.uc().scale(0, 0.4) \
+ nmos_upper_s_pin.bc().scale(1, 0.4)
self.add_path("metal2",
self.add_path("m2",
[bl_out_pin.uc(), mid1, mid2, nmos_upper_s_pin.bc()])
# br -> nmos_lower/D on metal2
# br_out -> nmos_lower/S on metal1
self.add_path("metal1",
self.add_path("m1",
[br_out_pin.uc(),
vector(nmos_lower_s_pin.cx(), br_out_pin.uy()),
nmos_lower_s_pin.center()])
@@ -163,7 +163,7 @@ class single_level_column_mux(pgate.pgate):
+ nmos_lower_d_pin.uc().scale(0,0.5)
mid2 = br_pin.bc().scale(0,0.5) \
+ nmos_lower_d_pin.uc().scale(1,0.5)
self.add_path("metal2",
self.add_path("m2",
[br_pin.bc(), mid1, mid2, nmos_lower_d_pin.uc()])
def add_wells(self):
@@ -186,7 +186,7 @@ class single_level_column_mux(pgate.pgate):
self.add_via_center(layers=self.m2_stack,
offset=active_pos)
self.add_layout_pin_rect_center(text="gnd",
layer="metal3",
layer="m3",
offset=active_pos)
# Add well enclosure over all the tx and contact