mirror of https://github.com/VLSIDA/OpenRAM.git
Fix new offset snap problems in wordline drive. Fix ptx multifinger pin bug. Add new add_center_rect function.
This commit is contained in:
parent
a9797d12ab
commit
10a8531813
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
Loading…
Reference in New Issue