Fix new offset snap problems in wordline drive. Fix ptx multifinger pin bug. Add new add_center_rect function.

This commit is contained in:
Matt Guthaus 2017-10-06 15:30:15 -07:00
parent a9797d12ab
commit 10a8531813
7 changed files with 132 additions and 92 deletions

View File

@ -116,8 +116,19 @@ class layout:
self.objs.append(geometry.rectangle(layerNumber, offset, width, height))
return self.objs[-1]
return None
def add_center_rect(self, layer, start, end):
""" Add a min-width rectangle from centered on the start and end points"""
minwidth_layer = drc["minwidth_{}".format(layer)]
if start.x!=end.x and start.y!=end.y:
debug.error("Nonrectilinear center rect!",-1)
elif start.x!=end.x:
offset = vector(0,0.5*minwidth_layer)
else:
offset = vector(0.5*minwidth_layer,0)
return self.add_rect(layer,start-offset,end.x-start.x,minwidth_layer)
def get_pin(self, text):
""" Return the pin or list of pins """
try:
@ -170,7 +181,7 @@ class layout:
width = max(minwidth_layer,width)
self.add_layout_pin(text, layer, ll_offset, width, height)
return self.add_layout_pin(text, layer, ll_offset, width, height)
def remove_layout_pin(self, text):
"""Delete a labeled pin (or all pins of the same name)"""
@ -192,11 +203,13 @@ class layout:
pin_list = self.pin_map[text]
for pin in pin_list:
if pin == new_pin:
return
return pin
self.pin_map[text].append(new_pin)
except KeyError:
self.pin_map[text] = [new_pin]
return new_pin
def add_label_pin(self, text, layer, offset, width=None, height=None):
"""Create a labeled pin WITHOUT the pin data structure. This is not an
actual pin but a named net so that we can add a correspondence point

View File

@ -36,6 +36,7 @@ class nand_2(design.design):
self.add_pins()
self.create_layout()
print self.pin_map
self.DRC_LVS()
def add_pins(self):

View File

@ -16,6 +16,8 @@ class pin_layout:
self.rect = rect
else:
self.rect = [vector(rect[0]),vector(rect[1])]
# snap the rect to the grid
self.rect = [x.snap_to_grid() for x in self.rect]
# if it's a layer number look up the layer name. this assumes a unique layer number.
if type(layer_name_num)==int:
self.layer = layer.keys()[layer.values().index(layer_name_num)]

View File

@ -156,8 +156,6 @@ class ptx(design.design):
self.poly_connect_index = len(self.objs) - 1
# change the name so it is unique and specifies drain/srouce (p) routed
self.name = self.name + "_p"
def pairwise(self, iterable):
@ -239,11 +237,18 @@ class ptx(design.design):
self.poly_positions = []
# following poly(s)
for i in range(0, self.mults):
self.add_layout_pin(text="G",
layer="poly",
offset=[poly_xoffset, poly_yoffset],
width=self.poly_width,
height=self.poly_height)
if self.connect_poly:
self.add_layout_pin(text="G",
layer="poly",
offset=[poly_xoffset, poly_yoffset],
width=self.poly_width,
height=self.poly_height)
else:
# Add the rectangle in case we remove the pin when joining fingers
self.add_rect(layer="poly",
offset=[poly_xoffset, poly_yoffset],
width=self.poly_width,
height=self.poly_height)
self.poly_positions.append(vector(poly_xoffset, poly_yoffset))
poly_xoffset += self.mults_poly_to_poly + drc["minwidth_poly"]
@ -319,11 +324,18 @@ class ptx(design.design):
offset=offset,
size=(1, self.num_contacts))
# source are even
self.add_layout_pin(text="S",
layer="metal1",
offset=offset+contact.second_layer_position,
width=contact.second_layer_width,
height=contact.second_layer_height)
if self.connect_active:
self.add_layout_pin(text="S",
layer="metal1",
offset=offset+contact.second_layer_position,
width=contact.second_layer_width,
height=contact.second_layer_height)
else:
# Add this in case the pins get removed when fingers joined
self.add_rect(layer="metal1",
offset=offset+contact.second_layer_position,
width=contact.second_layer_width,
height=contact.second_layer_height)
self.active_contact_positions.append(offset)
# middle contact columns
@ -337,12 +349,19 @@ class ptx(design.design):
offset=offset,
size=(1, self.num_contacts))
# source are even, drain are odd
name = "S" if i%2==1 else "D"
self.add_layout_pin(text=name,
layer="metal1",
offset=offset+contact.second_layer_position,
width=contact.second_layer_width,
height=contact.second_layer_height)
if self.connect_active:
name = "S" if i%2==1 else "D"
self.add_layout_pin(text=name,
layer="metal1",
offset=offset+contact.second_layer_position,
width=contact.second_layer_width,
height=contact.second_layer_height)
else:
# Add this in case the pins get removed when fingers joined
self.add_rect(layer="metal1",
offset=offset+contact.second_layer_position,
width=contact.second_layer_width,
height=contact.second_layer_height)
self.active_contact_positions.append(offset)
@ -355,12 +374,19 @@ class ptx(design.design):
offset=offset,
size=(1, self.num_contacts))
# source are even, drain are odd
name = "D" if self.mults%2==1 else "S"
self.add_layout_pin(text=name,
layer="metal1",
offset=offset+contact.second_layer_position,
width=contact.second_layer_width,
height=contact.second_layer_height)
if self.connect_active:
name = "D" if self.mults%2==1 else "S"
self.add_layout_pin(text=name,
layer="metal1",
offset=offset+contact.second_layer_position,
width=contact.second_layer_width,
height=contact.second_layer_height)
else:
self.add_rect(layer="metal1",
offset=offset+contact.second_layer_position,
width=contact.second_layer_width,
height=contact.second_layer_height)
# Add this in case the pins get removed when fingers joined
self.active_contact_positions.append(offset)

View File

@ -51,5 +51,6 @@ class wordline_driver_test(unittest.TestCase):
# instantiate a copy of the class to actually run the test
if __name__ == "__main__":
(OPTS, args) = globals.parse_args()
del sys.argv[1:]
header(__file__, OPTS.tech_name)
unittest.main()

View File

@ -25,7 +25,7 @@ class wire(path):
def create_layout(self):
self.setup_layers()
self.create_rectilinear_route()
self.create_rectilinear()
self.create_vias()
self.create_rectangles()
# wires and paths should not be offset to (0,0)

View File

@ -59,11 +59,11 @@ class wordline_driver(design.design):
def create_layout(self):
# Wordline enable connection
self.add_layout_pin(text="en",
layer="metal2",
offset=[drc["minwidth_metal1"] + 2 * drc["metal1_to_metal1"],0],
width=drc["minwidth_metal2"],
height=self.height)
en_pin=self.add_layout_pin(text="en",
layer="metal2",
offset=[drc["minwidth_metal1"] + 2 * drc["metal1_to_metal1"],0],
width=drc["minwidth_metal2"],
height=self.height)
self.add_layout_pin(text="gnd",
layer="metal1",
@ -113,85 +113,82 @@ class wordline_driver(design.design):
# add inv1 based on the info above
self.add_inst(name=name_inv1,
mod=self.inv,
offset=name_inv1_offset,
mirror=inst_mirror )
inv1_inst=self.add_inst(name=name_inv1,
mod=self.inv,
offset=name_inv1_offset,
mirror=inst_mirror )
self.connect_inst(["en", "en_bar[{0}]".format(row),
"vdd", "gnd"])
# add nand 2
self.add_inst(name=name_nand,
mod=self.nand2,
offset=nand2_offset,
mirror=inst_mirror)
nand_inst=self.add_inst(name=name_nand,
mod=self.nand2,
offset=nand2_offset,
mirror=inst_mirror)
self.connect_inst(["in[{0}]".format(row),
"en_bar[{0}]".format(row),
"net[{0}]".format(row),
"vdd", "gnd"])
# add inv2
self.add_inst(name=name_inv2,
mod=self.inv,
offset=inv2_offset,
mirror=inst_mirror)
inv2_inst=self.add_inst(name=name_inv2,
mod=self.inv,
offset=inv2_offset,
mirror=inst_mirror)
self.connect_inst(["net[{0}]".format(row),
"wl[{0}]".format(row),
"vdd", "gnd"])
# clk connection
clk_offset= vector(drc["minwidth_metal1"] + 2 * drc["metal1_to_metal1"],
y_offset + cell_dir.y * self.inv.get_pin("A").by())
self.add_rect(layer="metal1",
offset=clk_offset,
width=self.x_offset0 - 2*drc["metal1_to_metal1"],
height=cell_dir.y *drc["minwidth_metal1"])
self.add_via(layers=("metal1", "via1", "metal2"),
offset=clk_offset)
# en connection
a_pin = inv1_inst.get_pin("A")
a_pos = a_pin.lc()
clk_offset = vector(en_pin.bc().x,a_pos.y)
self.add_center_rect(layer="metal1",
start=clk_offset,
end=a_pos)
self.add_center_via(layers=("metal1", "via1", "metal2"),
offset=clk_offset)
# first inv to nand2 B
inv_to_nand2B_offset = [self.x_offset1 - drc["minwidth_metal1"],
y_offset + cell_dir.y * self.nand2.get_pin("B").by()]
self.add_rect(layer="metal1",
offset=inv_to_nand2B_offset,
width=drc["minwidth_metal1"],
height=cell_dir.y*inv_nand2B_connection_height)
zl_pos = inv1_inst.get_pin("Z").lc()
zr_pos = inv1_inst.get_pin("Z").rc()
bl_pos = nand_inst.get_pin("B").lc()
br_pos = nand_inst.get_pin("B").rc()
self.add_path("metal1", [zl_pos, zr_pos, bl_pos, br_pos])
# Nand2 out to 2nd inv
nand2_to_2ndinv_offset =[self.x_offset2,
y_offset + cell_dir.y * self.nand2.get_pin("Z").by()]
self.add_rect(layer="metal1",
offset=nand2_to_2ndinv_offset,
width=drc["minwidth_metal1"],
height=cell_dir.y * drc["minwidth_metal1"])
zl_pos = nand_inst.get_pin("Z").lc()
zr_pos = nand_inst.get_pin("Z").rc()
bl_pos = inv2_inst.get_pin("A").lc()
br_pos = inv2_inst.get_pin("A").rc()
self.add_path("metal1", [zl_pos, zr_pos, bl_pos, br_pos])
# connect the decoder input pin to nand2 A
input_offset=vector(0, y_offset + cell_dir.y*self.nand2.get_pin("A").by())
mid_via_offset = vector(clk_offset.x,input_offset.y) + vector(drc["minwidth_metal2"]+drc["metal2_to_metal2"],0)
a_pin = nand_inst.get_pin("A")
a_pos = a_pin.lc()
input_offset = vector(0,a_pos.y)
mid_via_offset = vector(clk_offset.x,a_pos.y) + vector(drc["minwidth_metal2"]+drc["metal2_to_metal2"],0)
# must under the clk line in M1
self.add_layout_pin(text="in[{0}]".format(row),
layer="metal1",
offset=input_offset,
width=mid_via_offset.x+drc["minwidth_metal1"],
height=cell_dir.y*drc["minwidth_metal1"])
self.add_via(layers=("metal1", "via1", "metal2"),
offset=mid_via_offset,
mirror=inst_mirror)
self.add_center_layout_pin(text="in[{0}]".format(row),
layer="metal1",
start=input_offset,
end=mid_via_offset)
m1m2_via=self.add_center_via(layers=("metal1", "via1", "metal2"),
offset=mid_via_offset)
# now connect to the nand2 A
self.add_rect(layer="metal2",
offset=mid_via_offset,
width=self.x_offset1-mid_via_offset.x,
height=cell_dir.y*drc["minwidth_metal2"])
self.add_via(layers=("metal1", "via1", "metal2"),
offset=[self.x_offset1,
y_offset + cell_dir.y * self.nand2.get_pin("A").by()],
rotate=m1tm2_rotate,
mirror=m1tm2_mirror)
self.add_center_rect(layer="metal2",
start=mid_via_offset,
end=a_pos)
self.add_center_via(layers=("metal1", "via1", "metal2"),
offset=a_pos + vector(0.5*m1m2_via.height,0),
rotate=90)
# output each WL on the right
wl_offset = base_offset + self.inv.get_pin("Z").ll().scale(cell_dir)
self.add_layout_pin(text="wl[{0}]".format(row),
layer="metal1",
offset=wl_offset,
width=drc["minwidth_metal1"]*cell_dir.y,
height=drc["minwidth_metal1"]*cell_dir.y)
wl_offset = inv2_inst.get_pin("Z").rc()
self.add_center_layout_pin(text="wl[{0}]".format(row),
layer="metal1",
start=wl_offset,
end=wl_offset-vector(drc["minwidth_metal1"],0))
def delay(self, slew, load=0):