mirror of https://github.com/VLSIDA/OpenRAM.git
Fix single finger ptx bugs.
This commit is contained in:
parent
6207f2157c
commit
0214cfb48e
|
|
@ -512,7 +512,7 @@ class bank(design.design):
|
||||||
|
|
||||||
bank_sel_line_pos = vector(xoffset_bank_sel + 0.5*self.m2_width, self.min_point)
|
bank_sel_line_pos = vector(xoffset_bank_sel + 0.5*self.m2_width, self.min_point)
|
||||||
bank_sel_pin_pos=vector(self.left_vdd_x_offset, self.min_point)
|
bank_sel_pin_pos=vector(self.left_vdd_x_offset, self.min_point)
|
||||||
self.add_center_layout_pin_segment(text="bank_sel",
|
self.add_layout_pin_center_segment(text="bank_sel",
|
||||||
layer="metal3",
|
layer="metal3",
|
||||||
start=bank_sel_pin_pos,
|
start=bank_sel_pin_pos,
|
||||||
end=bank_sel_line_pos)
|
end=bank_sel_line_pos)
|
||||||
|
|
@ -629,7 +629,7 @@ class bank(design.design):
|
||||||
offset=logic_pos,
|
offset=logic_pos,
|
||||||
rotate=90)
|
rotate=90)
|
||||||
|
|
||||||
self.add_center_layout_pin_segment(text=input_name,
|
self.add_layout_pin_center_segment(text=input_name,
|
||||||
layer="metal3",
|
layer="metal3",
|
||||||
start=input_pos,
|
start=input_pos,
|
||||||
end=logic_pos)
|
end=logic_pos)
|
||||||
|
|
|
||||||
|
|
@ -174,7 +174,7 @@ class layout:
|
||||||
new_name = pin.name
|
new_name = pin.name
|
||||||
self.add_layout_pin(new_name, pin.layer, pin.ll(), pin.width(), pin.height())
|
self.add_layout_pin(new_name, pin.layer, pin.ll(), pin.width(), pin.height())
|
||||||
|
|
||||||
def add_center_layout_pin_segment(self, text, layer, start, end):
|
def add_layout_pin_center_segment(self, text, layer, start, end):
|
||||||
""" Creates a path like pin with center-line convention """
|
""" Creates a path like pin with center-line convention """
|
||||||
|
|
||||||
debug.check(start.x==end.x or start.y==end.y,"Cannot have a non-manhatten layout pin.")
|
debug.check(start.x==end.x or start.y==end.y,"Cannot have a non-manhatten layout pin.")
|
||||||
|
|
@ -198,7 +198,7 @@ class layout:
|
||||||
|
|
||||||
return self.add_layout_pin(text, layer, ll_offset, width, height)
|
return self.add_layout_pin(text, layer, ll_offset, width, height)
|
||||||
|
|
||||||
def add_center_layout_pin_rect(self, text, layer, offset, width=None, height=None):
|
def add_layout_pin_center_rect(self, text, layer, offset, width=None, height=None):
|
||||||
""" Creates a path like pin with center-line convention """
|
""" Creates a path like pin with center-line convention """
|
||||||
if width==None:
|
if width==None:
|
||||||
width=drc["minwidth_{0}".format(layer)]
|
width=drc["minwidth_{0}".format(layer)]
|
||||||
|
|
|
||||||
|
|
@ -142,6 +142,7 @@ class pinv(design.design):
|
||||||
connect_poly=True,
|
connect_poly=True,
|
||||||
connect_active=True)
|
connect_active=True)
|
||||||
self.add_mod(self.nmos)
|
self.add_mod(self.nmos)
|
||||||
|
|
||||||
self.pmos = ptx(width=self.pmos_width,
|
self.pmos = ptx(width=self.pmos_width,
|
||||||
mults=self.tx_mults,
|
mults=self.tx_mults,
|
||||||
tx_type="pmos",
|
tx_type="pmos",
|
||||||
|
|
@ -151,12 +152,12 @@ class pinv(design.design):
|
||||||
|
|
||||||
def add_supply_rails(self):
|
def add_supply_rails(self):
|
||||||
""" Add vdd/gnd rails to the top and bottom. """
|
""" Add vdd/gnd rails to the top and bottom. """
|
||||||
self.add_center_layout_pin_rect(text="gnd",
|
self.add_layout_pin_center_rect(text="gnd",
|
||||||
layer="metal1",
|
layer="metal1",
|
||||||
offset=vector(0.5*self.width,0),
|
offset=vector(0.5*self.width,0),
|
||||||
width=self.width)
|
width=self.width)
|
||||||
|
|
||||||
self.add_center_layout_pin_rect(text="vdd",
|
self.add_layout_pin_center_rect(text="vdd",
|
||||||
layer="metal1",
|
layer="metal1",
|
||||||
offset=vector(0.5*self.width,self.height),
|
offset=vector(0.5*self.width,self.height),
|
||||||
width=self.width)
|
width=self.width)
|
||||||
|
|
@ -168,7 +169,6 @@ class pinv(design.design):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# place PMOS so it is half a poly spacing down from the top
|
# place PMOS so it is half a poly spacing down from the top
|
||||||
# Source should overlap rail if it is fingered!
|
|
||||||
pmos_position = vector(0,self.height-self.pmos.height-0.5*drc["poly_to_poly"])
|
pmos_position = vector(0,self.height-self.pmos.height-0.5*drc["poly_to_poly"])
|
||||||
self.pmos_inst=self.add_inst(name="pinv_pmos",
|
self.pmos_inst=self.add_inst(name="pinv_pmos",
|
||||||
mod=self.pmos,
|
mod=self.pmos,
|
||||||
|
|
@ -176,7 +176,6 @@ class pinv(design.design):
|
||||||
self.connect_inst(["Z", "A", "vdd", "vdd"])
|
self.connect_inst(["Z", "A", "vdd", "vdd"])
|
||||||
|
|
||||||
# place NMOS so that it is half a poly spacing up from the bottom
|
# place NMOS so that it is half a poly spacing up from the bottom
|
||||||
# Source should overlap rail if it is fingered!
|
|
||||||
nmos_position = vector(0,self.nmos.height+0.5*drc["poly_to_poly"])
|
nmos_position = vector(0,self.nmos.height+0.5*drc["poly_to_poly"])
|
||||||
self.nmos_inst=self.add_inst(name="pinv_nmos",
|
self.nmos_inst=self.add_inst(name="pinv_nmos",
|
||||||
mod=self.nmos,
|
mod=self.nmos,
|
||||||
|
|
@ -256,28 +255,28 @@ class pinv(design.design):
|
||||||
nmos_gate_pin = self.nmos_inst.get_pin("G")
|
nmos_gate_pin = self.nmos_inst.get_pin("G")
|
||||||
pmos_gate_pin = self.pmos_inst.get_pin("G")
|
pmos_gate_pin = self.pmos_inst.get_pin("G")
|
||||||
|
|
||||||
# Pick point in center of NMOS and connect down to PMOS
|
# Pick point on the left of NMOS and connect down to PMOS
|
||||||
nmos_gate_pos = nmos_gate_pin.ll() + vector(0.5*drc["minwidth_poly"],0)
|
nmos_gate_pos = nmos_gate_pin.ll() + vector(0.5*drc["minwidth_poly"],0)
|
||||||
pmos_gate_pos = vector(nmos_gate_pos.x,pmos_gate_pin.bc().y)
|
pmos_gate_pos = vector(nmos_gate_pos.x,pmos_gate_pin.bc().y)
|
||||||
self.add_path("poly",[nmos_gate_pos,pmos_gate_pos])
|
self.add_path("poly",[nmos_gate_pos,pmos_gate_pos])
|
||||||
|
|
||||||
# The midpoint of the vertical poly gate
|
# Add the via to the cell midpoint along the gate
|
||||||
mid_gate_offset = vector(nmos_gate_pos.x,self.middle_position.y)
|
left_gate_offset = vector(nmos_gate_pin.lx(),self.middle_position.y)
|
||||||
contact_offset = mid_gate_offset - vector(0.5*self.poly_contact.height,0)
|
contact_offset = left_gate_offset - vector(0.5*self.poly_contact.height,0)
|
||||||
self.add_center_contact(layers=("poly", "contact", "metal1"),
|
self.add_center_contact(layers=("poly", "contact", "metal1"),
|
||||||
offset=contact_offset,
|
offset=contact_offset,
|
||||||
rotate=90)
|
rotate=90)
|
||||||
self.add_center_layout_pin_segment(text="A",
|
self.add_layout_pin_center_segment(text="A",
|
||||||
layer="metal1",
|
layer="metal1",
|
||||||
start=mid_gate_offset.scale(0,1),
|
start=left_gate_offset.scale(0,1),
|
||||||
end=mid_gate_offset)
|
end=left_gate_offset)
|
||||||
|
|
||||||
# This is to ensure that the contact is connected to the gate
|
# This is to ensure that the contact is connected to the gate
|
||||||
mid_point = contact_offset.scale(0.5,1)+mid_gate_offset.scale(0.5,0)
|
mid_point = contact_offset.scale(0.5,1)+left_gate_offset.scale(0.5,0)
|
||||||
self.add_center_rect(layer="poly",
|
self.add_center_rect(layer="poly",
|
||||||
offset=mid_point,
|
offset=mid_point,
|
||||||
height=self.poly_contact.first_layer_width,
|
height=self.poly_contact.first_layer_width,
|
||||||
width=mid_gate_offset.x-contact_offset.x)
|
width=left_gate_offset.x-contact_offset.x)
|
||||||
|
|
||||||
|
|
||||||
def route_output_drain(self):
|
def route_output_drain(self):
|
||||||
|
|
@ -299,7 +298,7 @@ class pinv(design.design):
|
||||||
if self.route_output == True:
|
if self.route_output == True:
|
||||||
# This extends the output to the edge of the cell
|
# This extends the output to the edge of the cell
|
||||||
output_offset = mid_drain_offset.scale(0,1) + vector(self.width,0)
|
output_offset = mid_drain_offset.scale(0,1) + vector(self.width,0)
|
||||||
self.add_center_layout_pin_segment(text="Z",
|
self.add_layout_pin_center_segment(text="Z",
|
||||||
layer="metal1",
|
layer="metal1",
|
||||||
start=mid_drain_offset,
|
start=mid_drain_offset,
|
||||||
end=output_offset)
|
end=output_offset)
|
||||||
|
|
@ -375,8 +374,8 @@ class pinv(design.design):
|
||||||
# Only if they don't overlap already
|
# Only if they don't overlap already
|
||||||
if gnd_pin.uy() < nmos_source_pin.by():
|
if gnd_pin.uy() < nmos_source_pin.by():
|
||||||
self.add_rect(layer="metal1",
|
self.add_rect(layer="metal1",
|
||||||
offset=nmos__pin.ll(),
|
offset=nmos_source_pin.ll(),
|
||||||
height=nmos_source_pin.by()-gnd_pin.uy(),
|
height=-1*nmos_source_pin.by(),
|
||||||
width=nmos_source_pin.width())
|
width=nmos_source_pin.width())
|
||||||
|
|
||||||
pmos_source_pin = self.pmos_inst.get_pin("S")
|
pmos_source_pin = self.pmos_inst.get_pin("S")
|
||||||
|
|
|
||||||
|
|
@ -47,9 +47,6 @@ class ptx(design.design):
|
||||||
# but this may be uncommented for debug purposes
|
# but this may be uncommented for debug purposes
|
||||||
#self.DRC()
|
#self.DRC()
|
||||||
|
|
||||||
def add_pins(self):
|
|
||||||
"""Adds pins for spice netlist"""
|
|
||||||
self.add_pin_list(["D", "G", "S", "B"])
|
|
||||||
|
|
||||||
def create_layout(self):
|
def create_layout(self):
|
||||||
"""Calls all functions related to the generation of the layout"""
|
"""Calls all functions related to the generation of the layout"""
|
||||||
|
|
@ -60,7 +57,7 @@ class ptx(design.design):
|
||||||
self.add_active_contacts()
|
self.add_active_contacts()
|
||||||
|
|
||||||
def create_spice(self):
|
def create_spice(self):
|
||||||
self.add_pins()
|
self.add_pin_list(["D", "G", "S", "B"])
|
||||||
|
|
||||||
self.spice.append("\n.SUBCKT {0} {1}".format(self.name,
|
self.spice.append("\n.SUBCKT {0} {1}".format(self.name,
|
||||||
" ".join(self.pins)))
|
" ".join(self.pins)))
|
||||||
|
|
@ -160,7 +157,7 @@ class ptx(design.design):
|
||||||
and we will add a single horizontal connection.
|
and we will add a single horizontal connection.
|
||||||
"""
|
"""
|
||||||
# Nothing to do if there's one poly gate
|
# Nothing to do if there's one poly gate
|
||||||
if len(poly_positions) == 1:
|
if len(poly_positions)<2:
|
||||||
return
|
return
|
||||||
|
|
||||||
# The width of the poly is from the left-most to right-most poly gate
|
# The width of the poly is from the left-most to right-most poly gate
|
||||||
|
|
@ -190,24 +187,24 @@ class ptx(design.design):
|
||||||
# This is the width of a contact to extend the ends of the pin
|
# This is the width of a contact to extend the ends of the pin
|
||||||
end_offset = vector(self.active_contact.second_layer_width/2,0)
|
end_offset = vector(self.active_contact.second_layer_width/2,0)
|
||||||
|
|
||||||
if source_positions: # if not an empty set
|
if len(source_positions)>1:
|
||||||
self.remove_layout_pin("S") # remove the individual connections
|
self.remove_layout_pin("S") # remove the individual connections
|
||||||
# Add each vertical segment
|
# Add each vertical segment
|
||||||
for a in source_positions:
|
for a in source_positions:
|
||||||
self.add_path(("metal1"), [a,a+pin_offset])
|
self.add_path(("metal1"), [a,a+pin_offset])
|
||||||
# Add a single horizontal pin
|
# Add a single horizontal pin
|
||||||
self.add_center_layout_pin_segment(text="S",
|
self.add_layout_pin_center_segment(text="S",
|
||||||
layer="metal1",
|
layer="metal1",
|
||||||
start=source_positions[0]+pin_offset-end_offset,
|
start=source_positions[0]+pin_offset-end_offset,
|
||||||
end=source_positions[-1]+pin_offset+end_offset)
|
end=source_positions[-1]+pin_offset+end_offset)
|
||||||
|
|
||||||
if drain_positions: # if not an empty set
|
if len(drain_positions)>1:
|
||||||
self.remove_layout_pin("D") # remove the individual connections
|
self.remove_layout_pin("D") # remove the individual connections
|
||||||
# Add each vertical segment
|
# Add each vertical segment
|
||||||
for a in drain_positions:
|
for a in drain_positions:
|
||||||
self.add_path(("metal1"), [a,a-pin_offset])
|
self.add_path(("metal1"), [a,a-pin_offset])
|
||||||
# Add a single horizontal pin
|
# Add a single horizontal pin
|
||||||
self.add_center_layout_pin_segment(text="D",
|
self.add_layout_pin_center_segment(text="D",
|
||||||
layer="metal1",
|
layer="metal1",
|
||||||
start=drain_positions[0]-pin_offset-end_offset,
|
start=drain_positions[0]-pin_offset-end_offset,
|
||||||
end=drain_positions[-1]-pin_offset+end_offset)
|
end=drain_positions[-1]-pin_offset+end_offset)
|
||||||
|
|
@ -223,18 +220,16 @@ class ptx(design.design):
|
||||||
poly_positions = []
|
poly_positions = []
|
||||||
|
|
||||||
for i in range(0, self.mults):
|
for i in range(0, self.mults):
|
||||||
if self.connect_poly:
|
# Add this duplicate rectangle in case we remove the pin when joining fingers
|
||||||
# Add the rectangle in case we remove the pin when joining fingers
|
self.add_center_rect(layer="poly",
|
||||||
self.add_center_rect(layer="poly",
|
offset=poly_offset,
|
||||||
offset=poly_offset,
|
height=self.poly_height,
|
||||||
height=self.poly_height,
|
width=self.poly_width)
|
||||||
width=self.poly_width)
|
self.add_layout_pin_center_rect(text="G",
|
||||||
else:
|
layer="poly",
|
||||||
self.add_center_layout_pin_rect(text="G",
|
offset=poly_offset,
|
||||||
layer="poly",
|
height=self.poly_height,
|
||||||
offset=poly_offset,
|
width=self.poly_width)
|
||||||
height=self.poly_height,
|
|
||||||
width=self.poly_width)
|
|
||||||
poly_positions.append(poly_offset)
|
poly_positions.append(poly_offset)
|
||||||
poly_offset = poly_offset + vector(self.poly_pitch,0)
|
poly_offset = poly_offset + vector(self.poly_pitch,0)
|
||||||
|
|
||||||
|
|
@ -306,36 +301,22 @@ class ptx(design.design):
|
||||||
contact=self.add_center_contact(layers=("active", "contact", "metal1"),
|
contact=self.add_center_contact(layers=("active", "contact", "metal1"),
|
||||||
offset=pos,
|
offset=pos,
|
||||||
size=(1, self.num_contacts))
|
size=(1, self.num_contacts))
|
||||||
if self.connect_active:
|
self.add_layout_pin_center_rect(text="S",
|
||||||
# Add this in case the pins get removed when fingers joined
|
layer="metal1",
|
||||||
self.add_center_rect(layer="metal1",
|
offset=pos,
|
||||||
offset=pos,
|
width=contact.second_layer_width,
|
||||||
width=contact.second_layer_width,
|
height=contact.second_layer_height)
|
||||||
height=contact.second_layer_height)
|
|
||||||
else:
|
|
||||||
self.add_center_layout_pin_rect(text="S",
|
|
||||||
layer="metal1",
|
|
||||||
offset=pos,
|
|
||||||
width=contact.second_layer_width,
|
|
||||||
height=contact.second_layer_height)
|
|
||||||
|
|
||||||
|
|
||||||
for pos in drain_positions:
|
for pos in drain_positions:
|
||||||
contact=self.add_center_contact(layers=("active", "contact", "metal1"),
|
contact=self.add_center_contact(layers=("active", "contact", "metal1"),
|
||||||
offset=pos,
|
offset=pos,
|
||||||
size=(1, self.num_contacts))
|
size=(1, self.num_contacts))
|
||||||
if self.connect_active:
|
self.add_layout_pin_center_rect(text="D",
|
||||||
# Add this in case the pins get removed when fingers joined
|
layer="metal1",
|
||||||
self.add_center_rect(layer="metal1",
|
offset=pos,
|
||||||
offset=pos,
|
width=contact.second_layer_width,
|
||||||
width=contact.second_layer_width,
|
height=contact.second_layer_height)
|
||||||
height=contact.second_layer_height)
|
|
||||||
else:
|
|
||||||
self.add_center_layout_pin_rect(text="D",
|
|
||||||
layer="metal1",
|
|
||||||
offset=pos,
|
|
||||||
width=contact.second_layer_width,
|
|
||||||
height=contact.second_layer_height)
|
|
||||||
|
|
||||||
if self.connect_active:
|
if self.connect_active:
|
||||||
self.connect_fingered_active(drain_positions, source_positions)
|
self.connect_fingered_active(drain_positions, source_positions)
|
||||||
|
|
|
||||||
|
|
@ -167,7 +167,7 @@ class wordline_driver(design.design):
|
||||||
input_offset = vector(0,a_pos.y)
|
input_offset = vector(0,a_pos.y)
|
||||||
mid_via_offset = vector(clk_offset.x,a_pos.y) + vector(0.5*drc["minwidth_metal2"]+drc["metal2_to_metal2"]+0.5*m1m2_via.width,0)
|
mid_via_offset = vector(clk_offset.x,a_pos.y) + vector(0.5*drc["minwidth_metal2"]+drc["metal2_to_metal2"]+0.5*m1m2_via.width,0)
|
||||||
# must under the clk line in M1
|
# must under the clk line in M1
|
||||||
self.add_center_layout_pin_segment(text="in[{0}]".format(row),
|
self.add_layout_pin_center_segment(text="in[{0}]".format(row),
|
||||||
layer="metal1",
|
layer="metal1",
|
||||||
start=input_offset,
|
start=input_offset,
|
||||||
end=mid_via_offset)
|
end=mid_via_offset)
|
||||||
|
|
@ -185,7 +185,7 @@ class wordline_driver(design.design):
|
||||||
|
|
||||||
# output each WL on the right
|
# output each WL on the right
|
||||||
wl_offset = inv2_inst.get_pin("Z").rc()
|
wl_offset = inv2_inst.get_pin("Z").rc()
|
||||||
self.add_center_layout_pin_segment(text="wl[{0}]".format(row),
|
self.add_layout_pin_center_segment(text="wl[{0}]".format(row),
|
||||||
layer="metal1",
|
layer="metal1",
|
||||||
start=wl_offset,
|
start=wl_offset,
|
||||||
end=wl_offset-vector(drc["minwidth_metal1"],0))
|
end=wl_offset-vector(drc["minwidth_metal1"],0))
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue