mirror of
https://github.com/VLSIDA/OpenRAM.git
synced 2026-09-08 03:43:44 +02:00
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:
@@ -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())
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"""
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user