mirror of
https://github.com/VLSIDA/OpenRAM.git
synced 2026-09-04 00:40:09 +02:00
Rewrite add_contact to use layer directions.
This commit is contained in:
committed by
Matt Guthaus
parent
c1411f4227
commit
be20408fb2
@@ -800,14 +800,11 @@ class bank(design.design):
|
||||
bus_pos = vector(self.bus_xoffset[port][name].x, out_pos.y)
|
||||
self.add_path("metal3",[out_pos, bus_pos])
|
||||
self.add_via_center(layers=("metal2", "via2", "metal3"),
|
||||
offset=bus_pos,
|
||||
rotate=90)
|
||||
offset=bus_pos)
|
||||
self.add_via_center(layers=("metal1", "via1", "metal2"),
|
||||
offset=out_pos,
|
||||
rotate=90)
|
||||
offset=out_pos)
|
||||
self.add_via_center(layers=("metal2", "via2", "metal3"),
|
||||
offset=out_pos,
|
||||
rotate=90)
|
||||
offset=out_pos)
|
||||
|
||||
|
||||
def setup_routing_constraints(self):
|
||||
@@ -1197,8 +1194,7 @@ class bank(design.design):
|
||||
control_pos = vector(self.bus_xoffset[port][control_signal].x ,pin_pos.y)
|
||||
self.add_path("metal1", [control_pos, pin_pos])
|
||||
self.add_via_center(layers=("metal1", "via1", "metal2"),
|
||||
offset=control_pos,
|
||||
rotate=90)
|
||||
offset=control_pos)
|
||||
|
||||
# clk to wordline_driver
|
||||
control_signal = self.prefix+"wl_en{}".format(port)
|
||||
@@ -1212,8 +1208,7 @@ class bank(design.design):
|
||||
control_pos = vector(control_x_offset, mid_pos.y)
|
||||
self.add_wire(("metal1","via1","metal2"),[pin_pos, mid_pos, control_pos])
|
||||
self.add_via_center(layers=("metal1", "via1", "metal2"),
|
||||
offset=control_pos,
|
||||
rotate=90)
|
||||
offset=control_pos)
|
||||
|
||||
def analytical_delay(self, corner, slew, load, port):
|
||||
""" return analytical delay of the bank. This will track the clock to output path"""
|
||||
|
||||
@@ -213,7 +213,7 @@ class bank_select(design.design):
|
||||
end=bank_sel_pin_end)
|
||||
self.add_via_center(layers=("metal2","via2","metal3"),
|
||||
offset=bank_sel_pin_end,
|
||||
rotate=90)
|
||||
directions=("H","H"))
|
||||
|
||||
# bank_sel_bar is vertical wire
|
||||
bank_sel_bar_pin = self.bank_sel_inv.get_pin("Z")
|
||||
@@ -252,7 +252,7 @@ class bank_select(design.design):
|
||||
self.add_path("metal2",[logic_pos, input_pos])
|
||||
self.add_via_center(layers=("metal1", "via1", "metal2"),
|
||||
offset=logic_pos,
|
||||
rotate=90)
|
||||
directions=("H","H"))
|
||||
|
||||
|
||||
# Connect the logic A input to the input pin
|
||||
@@ -260,10 +260,10 @@ class bank_select(design.design):
|
||||
input_pos = vector(0,logic_pos.y)
|
||||
self.add_via_center(layers=("metal1", "via1", "metal2"),
|
||||
offset=logic_pos,
|
||||
rotate=90)
|
||||
directions=("H","H"))
|
||||
self.add_via_center(layers=("metal2", "via2", "metal3"),
|
||||
offset=logic_pos,
|
||||
rotate=90)
|
||||
directions=("H","H"))
|
||||
self.add_layout_pin_segment_center(text=input_name,
|
||||
layer="metal3",
|
||||
start=input_pos,
|
||||
@@ -295,10 +295,10 @@ class bank_select(design.design):
|
||||
pin_pos = vector(xoffset, supply_pin.cy())
|
||||
self.add_via_center(layers=("metal1", "via1", "metal2"),
|
||||
offset=pin_pos,
|
||||
rotate=90)
|
||||
directions=("H","H"))
|
||||
self.add_via_center(layers=("metal2", "via2", "metal3"),
|
||||
offset=pin_pos,
|
||||
rotate=90)
|
||||
directions=("H","H"))
|
||||
self.add_layout_pin_rect_center(text=n,
|
||||
layer="metal3",
|
||||
offset=pin_pos)
|
||||
|
||||
@@ -128,7 +128,7 @@ class bitcell_array(design.design):
|
||||
inst = self.cell_inst[row,col]
|
||||
for pin_name in ["vdd", "gnd"]:
|
||||
for pin in inst.get_pins(pin_name):
|
||||
self.add_power_pin(pin_name, pin.center(), 0, pin.layer)
|
||||
self.add_power_pin(name=pin_name, loc=pin.center(), vertical=True, start_layer=pin.layer)
|
||||
|
||||
def analytical_delay(self, corner, slew, load):
|
||||
"""Returns relative delay of the bitline in the bitcell array"""
|
||||
|
||||
@@ -615,11 +615,9 @@ class control_logic(design.design):
|
||||
mid1 = vector(in_pos.x,out_pos.y)
|
||||
self.add_wire(("metal3","via2","metal2"),[out_pos, mid1, in_pos])
|
||||
self.add_via_center(layers=("metal1","via1","metal2"),
|
||||
offset=out_pos,
|
||||
rotate=90)
|
||||
offset=out_pos)
|
||||
self.add_via_center(layers=("metal2","via2","metal3"),
|
||||
offset=out_pos,
|
||||
rotate=90)
|
||||
offset=out_pos)
|
||||
|
||||
def create_pen_row(self):
|
||||
if self.port_type == "rw":
|
||||
@@ -759,8 +757,7 @@ class control_logic(design.design):
|
||||
rail_pos = vector(self.rail_offsets["clk_buf"].x, mid_pos.y)
|
||||
self.add_wire(("metal1","via1","metal2"),[in_pos, mid_pos, rail_pos])
|
||||
self.add_via_center(layers=("metal1","via1","metal2"),
|
||||
offset=rail_pos,
|
||||
rotate=90)
|
||||
offset=rail_pos)
|
||||
|
||||
self.copy_layout_pin(self.ctrl_dff_inst, "din_0", "csb")
|
||||
if (self.port_type == "rw"):
|
||||
|
||||
@@ -213,11 +213,9 @@ class hierarchical_decoder(design.design):
|
||||
""" Route a vertical M2 coordinate to another vertical M2 coordinate to the predecode inputs """
|
||||
|
||||
self.add_via_center(layers=("metal2", "via2", "metal3"),
|
||||
offset=input_offset,
|
||||
rotate=90)
|
||||
offset=input_offset)
|
||||
self.add_via_center(layers=("metal2", "via2", "metal3"),
|
||||
offset=output_offset,
|
||||
rotate=90)
|
||||
offset=output_offset)
|
||||
self.add_path(("metal3"), [input_offset, output_offset])
|
||||
|
||||
|
||||
@@ -575,8 +573,7 @@ class hierarchical_decoder(design.design):
|
||||
rail_pos = vector(self.predecode_rails[rail_name].x,pin.lc().y)
|
||||
self.add_path("metal1", [rail_pos, pin.lc()])
|
||||
self.add_via_center(layers=("metal1", "via1", "metal2"),
|
||||
offset=rail_pos,
|
||||
rotate=90)
|
||||
offset=rail_pos)
|
||||
|
||||
|
||||
def route_predecode_rail_m3(self, rail_name, pin):
|
||||
@@ -586,12 +583,10 @@ class hierarchical_decoder(design.design):
|
||||
mid_point = vector(pin.cx(), pin.cy()+self.inv.height/2)
|
||||
rail_pos = vector(self.predecode_rails[rail_name].x,mid_point.y)
|
||||
self.add_via_center(layers=("metal1", "via1", "metal2"),
|
||||
offset=pin.center(),
|
||||
rotate=90)
|
||||
offset=pin.center())
|
||||
self.add_wire(("metal3","via2","metal2"), [rail_pos, mid_point, pin.uc()])
|
||||
self.add_via_center(layers=("metal2", "via2", "metal3"),
|
||||
offset=rail_pos,
|
||||
rotate=90)
|
||||
offset=rail_pos)
|
||||
|
||||
|
||||
def analytical_delay(self, corner, slew, load = 0.0):
|
||||
|
||||
@@ -178,11 +178,9 @@ class hierarchical_predecode(design.design):
|
||||
a_pos = vector(self.decode_rails[a_pin].x,y_offset)
|
||||
self.add_path("metal1",[in_pos, a_pos])
|
||||
self.add_via_center(layers = ("metal1", "via1", "metal2"),
|
||||
offset=[self.input_rails[in_pin].x, y_offset],
|
||||
rotate=90)
|
||||
offset=[self.input_rails[in_pin].x, y_offset])
|
||||
self.add_via_center(layers = ("metal1", "via1", "metal2"),
|
||||
offset=[self.decode_rails[a_pin].x, y_offset],
|
||||
rotate=90)
|
||||
offset=[self.decode_rails[a_pin].x, y_offset])
|
||||
|
||||
def route_output_inverters(self):
|
||||
"""
|
||||
@@ -223,8 +221,7 @@ class hierarchical_predecode(design.design):
|
||||
rail_pos = vector(self.decode_rails[out_pin].x,y_offset)
|
||||
self.add_path("metal1", [inv_out_pos, right_pos, vector(right_pos.x, y_offset), rail_pos])
|
||||
self.add_via_center(layers = ("metal1", "via1", "metal2"),
|
||||
offset=rail_pos,
|
||||
rotate=90)
|
||||
offset=rail_pos)
|
||||
|
||||
|
||||
#route input
|
||||
@@ -232,8 +229,7 @@ class hierarchical_predecode(design.design):
|
||||
in_pos = vector(self.input_rails[in_pin].x,inv_in_pos.y)
|
||||
self.add_path("metal1", [in_pos, inv_in_pos])
|
||||
self.add_via_center(layers=("metal1", "via1", "metal2"),
|
||||
offset=in_pos,
|
||||
rotate=90)
|
||||
offset=in_pos)
|
||||
|
||||
|
||||
def route_nand_to_rails(self):
|
||||
@@ -254,8 +250,8 @@ class hierarchical_predecode(design.design):
|
||||
rail_pos = vector(self.decode_rails[rail_pin].x, pin_pos.y)
|
||||
self.add_path("metal1", [rail_pos, pin_pos])
|
||||
self.add_via_center(layers=("metal1", "via1", "metal2"),
|
||||
offset=rail_pos,
|
||||
rotate=90)
|
||||
offset=rail_pos)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -39,8 +39,8 @@ class replica_bitline(design.design):
|
||||
#self.add_lvs_correspondence_points()
|
||||
|
||||
# Extra pitch on top and right
|
||||
self.width = self.rbl_inst.rx() - self.dc_inst.lx() + self.m2_pitch
|
||||
self.height = max(self.rbl_inst.uy(), self.dc_inst.uy()) + self.m3_pitch
|
||||
self.width = self.replica_column_inst.rx() - self.delay_chain_inst.lx() + self.m2_pitch
|
||||
self.height = max(self.replica_column_inst.uy(), self.delay_chain_inst.uy()) + self.m3_pitch
|
||||
|
||||
self.DRC_LVS()
|
||||
|
||||
@@ -111,12 +111,12 @@ class replica_bitline(design.design):
|
||||
self.connect_inst(["vdd", "delayed_en", "bl0_0", "vdd"])
|
||||
# add the well and poly contact
|
||||
|
||||
self.dc_inst=self.add_inst(name="delay_chain",
|
||||
mod=self.delay_chain)
|
||||
self.delay_chain_inst=self.add_inst(name="delay_chain",
|
||||
mod=self.delay_chain)
|
||||
self.connect_inst(["en", "delayed_en", "vdd", "gnd"])
|
||||
|
||||
self.rbc_inst=self.add_inst(name="bitcell",
|
||||
mod=self.replica_bitcell)
|
||||
self.replica_cell_inst=self.add_inst(name="bitcell",
|
||||
mod=self.replica_bitcell)
|
||||
temp = []
|
||||
for port in self.all_ports:
|
||||
temp.append("bl{}_0".format(port))
|
||||
@@ -127,8 +127,8 @@ class replica_bitline(design.design):
|
||||
temp.append("gnd")
|
||||
self.connect_inst(temp)
|
||||
|
||||
self.rbl_inst=self.add_inst(name="load",
|
||||
mod=self.rbl)
|
||||
self.replica_column_inst=self.add_inst(name="load",
|
||||
mod=self.rbl)
|
||||
|
||||
temp = []
|
||||
for port in self.all_ports:
|
||||
@@ -153,12 +153,12 @@ class replica_bitline(design.design):
|
||||
|
||||
self.tx_inst.place(self.access_tx_offset)
|
||||
|
||||
self.dc_inst.place(self.delay_chain_offset)
|
||||
self.delay_chain_inst.place(self.delay_chain_offset)
|
||||
|
||||
self.rbc_inst.place(offset=self.bitcell_offset,
|
||||
self.replica_cell_inst.place(offset=self.bitcell_offset,
|
||||
mirror="MX")
|
||||
|
||||
self.rbl_inst.place(self.rbl_offset)
|
||||
self.replica_column_inst.place(self.rbl_offset)
|
||||
|
||||
|
||||
def route(self):
|
||||
@@ -172,7 +172,7 @@ class replica_bitline(design.design):
|
||||
# Connect the WL and gnd pins directly to the center and right gnd rails
|
||||
for row in range(self.bitcell_loads):
|
||||
wl = self.wl_list[0]+"_{}".format(row)
|
||||
pin = self.rbl_inst.get_pin(wl)
|
||||
pin = self.replica_column_inst.get_pin(wl)
|
||||
|
||||
# Route the connection to the right so that it doesn't interfere with the cells
|
||||
# Wordlines may be close to each other when tiled, so gnd connections are routed in opposite directions
|
||||
@@ -188,7 +188,7 @@ class replica_bitline(design.design):
|
||||
|
||||
# for multiport, need to short wordlines to each other so they all connect to gnd.
|
||||
wl_last = self.wl_list[-1]+"_{}".format(row)
|
||||
pin_last = self.rbl_inst.get_pin(wl_last)
|
||||
pin_last = self.replica_column_inst.get_pin(wl_last)
|
||||
self.short_wordlines(pin, pin_last, "right", False, row, vector(self.m3_pitch,0))
|
||||
|
||||
def short_wordlines(self, wl_pin_a, wl_pin_b, pin_side, is_replica_cell, cell_row=0, offset_x_vec=None):
|
||||
@@ -229,10 +229,10 @@ class replica_bitline(design.design):
|
||||
for port in self.all_ports:
|
||||
if is_replica_cell:
|
||||
wl = self.wl_list[port]
|
||||
pin = self.rbc_inst.get_pin(wl)
|
||||
pin = self.replica_cell_inst.get_pin(wl)
|
||||
else:
|
||||
wl = self.wl_list[port]+"_{}".format(cell_row)
|
||||
pin = self.rbl_inst.get_pin(wl)
|
||||
pin = self.replica_column_inst.get_pin(wl)
|
||||
|
||||
if pin_side == "left":
|
||||
self.add_path("metal1", [pin.lc()-correct_x, pin.lc()])
|
||||
@@ -245,8 +245,8 @@ class replica_bitline(design.design):
|
||||
""" Propagate all vdd/gnd pins up to this level for all modules """
|
||||
|
||||
# These are the instances that every bank has
|
||||
top_instances = [self.rbl_inst,
|
||||
self.dc_inst]
|
||||
top_instances = [self.replica_column_inst,
|
||||
self.delay_chain_inst]
|
||||
for inst in top_instances:
|
||||
self.copy_layout_pin(inst, "vdd")
|
||||
self.copy_layout_pin(inst, "gnd")
|
||||
@@ -257,11 +257,11 @@ class replica_bitline(design.design):
|
||||
pin = self.rbl_inv_inst.get_pin("vdd")
|
||||
self.add_power_pin("vdd", pin.lc())
|
||||
|
||||
pin=self.rbc_inst.get_pin("vdd")
|
||||
self.add_power_pin("vdd", pin.center(), 0, pin.layer)
|
||||
for pin in self.replica_cell_inst.get_pins("vdd"):
|
||||
self.add_power_pin(name="vdd", loc=pin.center(), vertical=True, start_layer=pin.layer)
|
||||
|
||||
for pin in self.rbc_inst.get_pins("gnd"):
|
||||
self.add_power_pin("gnd", pin.center())
|
||||
for pin in self.replica_cell_inst.get_pins("gnd"):
|
||||
self.add_power_pin("gnd", pin.center(), vertical=True, start_layer=pin.layer)
|
||||
|
||||
|
||||
|
||||
@@ -275,10 +275,10 @@ class replica_bitline(design.design):
|
||||
poly_offset = poly_pin.uc()
|
||||
# This centers the contact above the poly by one pitch
|
||||
contact_offset = poly_offset + vector(0,self.m2_pitch)
|
||||
self.add_contact_center(layers=("poly", "contact", "metal1"),
|
||||
offset=contact_offset)
|
||||
self.add_contact_center(layers=("metal1", "via1", "metal2"),
|
||||
offset=contact_offset)
|
||||
self.add_via_center(layers=("poly", "contact", "metal1"),
|
||||
offset=contact_offset)
|
||||
self.add_via_center(layers=("metal1", "via1", "metal2"),
|
||||
offset=contact_offset)
|
||||
self.add_segment_center(layer="poly",
|
||||
start=poly_offset,
|
||||
end=contact_offset)
|
||||
@@ -289,12 +289,12 @@ class replica_bitline(design.design):
|
||||
# height=self.delay_chain_offset.y-nwell_offset.y)
|
||||
|
||||
# 2. Route delay chain output to access tx gate
|
||||
delay_en_offset = self.dc_inst.get_pin("out").bc()
|
||||
delay_en_offset = self.delay_chain_inst.get_pin("out").bc()
|
||||
self.add_path("metal2", [delay_en_offset,contact_offset])
|
||||
|
||||
# 3. Route the contact of previous route to the bitcell WL
|
||||
# route bend of previous net to bitcell WL
|
||||
wl_offset = self.rbc_inst.get_pin(self.wl_list[0]).lc()
|
||||
wl_offset = self.replica_cell_inst.get_pin(self.wl_list[0]).lc()
|
||||
wl_mid1 = wl_offset - vector(1.5*drc("minwidth_metal1"), 0)
|
||||
wl_mid2 = vector(wl_mid1.x, contact_offset.y)
|
||||
#xmid_point= 0.5*(wl_offset.x+contact_offset.x)
|
||||
@@ -305,8 +305,8 @@ class replica_bitline(design.design):
|
||||
# 4. Short wodlines if multiport
|
||||
wl = self.wl_list[0]
|
||||
wl_last = self.wl_list[-1]
|
||||
pin = self.rbc_inst.get_pin(wl)
|
||||
pin_last = self.rbc_inst.get_pin(wl_last)
|
||||
pin = self.replica_cell_inst.get_pin(wl)
|
||||
pin_last = self.replica_cell_inst.get_pin(wl_last)
|
||||
x_offset = self.short_wordlines(pin, pin_last, "left", True)
|
||||
|
||||
#correct = vector(0.5*drc("minwidth_metal1"), 0)
|
||||
@@ -315,7 +315,7 @@ class replica_bitline(design.design):
|
||||
# DRAIN ROUTE
|
||||
# Route the drain to the vdd rail
|
||||
drain_offset = self.tx_inst.get_pin("D").center()
|
||||
self.add_power_pin("vdd", drain_offset, rotate=0)
|
||||
self.add_power_pin("vdd", drain_offset, vertical=True)
|
||||
|
||||
# SOURCE ROUTE
|
||||
# Route the drain to the RBL inverter input
|
||||
@@ -325,7 +325,7 @@ class replica_bitline(design.design):
|
||||
|
||||
# Route the connection of the source route to the RBL bitline (left)
|
||||
# Via will go halfway down from the bitcell
|
||||
bl_offset = self.rbc_inst.get_pin(self.bl_list[0]).bc()
|
||||
bl_offset = self.replica_cell_inst.get_pin(self.bl_list[0]).bc()
|
||||
# Route down a pitch so we can use M2 routing
|
||||
bl_down_offset = bl_offset - vector(0, self.m2_pitch)
|
||||
self.add_path("metal2",[source_offset, bl_down_offset, bl_offset])
|
||||
@@ -344,12 +344,12 @@ class replica_bitline(design.design):
|
||||
def route_vdd(self):
|
||||
""" Route all signals connected to vdd """
|
||||
|
||||
self.copy_layout_pin(self.dc_inst,"vdd")
|
||||
self.copy_layout_pin(self.rbc_inst,"vdd")
|
||||
self.copy_layout_pin(self.delay_chain_inst,"vdd")
|
||||
self.copy_layout_pin(self.replica_cell_inst,"vdd")
|
||||
|
||||
# Connect the WL and vdd pins directly to the center and right vdd rails
|
||||
# Connect RBL vdd pins to center and right rails
|
||||
rbl_vdd_pins = self.rbl_inst.get_pins("vdd")
|
||||
rbl_vdd_pins = self.replica_column_inst.get_pins("vdd")
|
||||
for pin in rbl_vdd_pins:
|
||||
if pin.layer != "metal1":
|
||||
continue
|
||||
@@ -360,11 +360,9 @@ class replica_bitline(design.design):
|
||||
start=start,
|
||||
end=end)
|
||||
self.add_via_center(layers=("metal1", "via1", "metal2"),
|
||||
offset=start,
|
||||
rotate=90)
|
||||
offset=start)
|
||||
self.add_via_center(layers=("metal1", "via1", "metal2"),
|
||||
offset=end,
|
||||
rotate=90)
|
||||
offset=end)
|
||||
|
||||
# Add via for the inverter
|
||||
pin = self.rbl_inv_inst.get_pin("vdd")
|
||||
@@ -374,38 +372,34 @@ class replica_bitline(design.design):
|
||||
start=start,
|
||||
end=end)
|
||||
self.add_via_center(layers=("metal1", "via1", "metal2"),
|
||||
offset=start,
|
||||
rotate=90)
|
||||
offset=start)
|
||||
|
||||
self.add_via_center(layers=("metal1", "via1", "metal2"),
|
||||
offset=end,
|
||||
rotate=90)
|
||||
offset=end)
|
||||
|
||||
|
||||
# Add via for the RBC
|
||||
pin = self.rbc_inst.get_pin("vdd")
|
||||
pin = self.replica_cell_inst.get_pin("vdd")
|
||||
start = pin.lc()
|
||||
end = vector(self.right_vdd_pin.cx(),pin.cy())
|
||||
self.add_segment_center(layer="metal1",
|
||||
start=start,
|
||||
end=end)
|
||||
self.add_via_center(layers=("metal1", "via1", "metal2"),
|
||||
offset=end,
|
||||
rotate=90)
|
||||
offset=end)
|
||||
|
||||
# Create the RBL rails too
|
||||
rbl_pins = self.rbl_inst.get_pins("vdd")
|
||||
rbl_pins = self.replica_column_inst.get_pins("vdd")
|
||||
for pin in rbl_pins:
|
||||
if pin.layer != "metal1":
|
||||
continue
|
||||
# If above the delay line, route the full width
|
||||
left = vector(self.left_vdd_pin.cx(),pin.cy())
|
||||
center = vector(self.center_vdd_pin.cx(),pin.cy())
|
||||
if pin.cy() > self.dc_inst.uy() + self.m1_pitch:
|
||||
if pin.cy() > self.delay_chain_inst.uy() + self.m1_pitch:
|
||||
start = left
|
||||
self.add_via_center(layers=("metal1", "via1", "metal2"),
|
||||
offset=left,
|
||||
rotate=90)
|
||||
offset=left)
|
||||
else:
|
||||
start = center
|
||||
end = vector(self.right_vdd_pin.cx()+0.5*self.m1_width,pin.cy())
|
||||
@@ -425,22 +419,22 @@ class replica_bitline(design.design):
|
||||
# Route the gnd lines from left to right
|
||||
|
||||
# Add via for the delay chain
|
||||
left_gnd_start = self.dc_inst.ll().scale(1,0) - vector(2*self.m2_pitch,0)
|
||||
left_gnd_end = vector(left_gnd_start.x, self.rbl_inst.uy()+self.m2_pitch)
|
||||
left_gnd_start = self.delay_chain_inst.ll().scale(1,0) - vector(2*self.m2_pitch,0)
|
||||
left_gnd_end = vector(left_gnd_start.x, self.replica_column_inst.uy()+self.m2_pitch)
|
||||
self.left_gnd_pin=self.add_segment_center(layer="metal2",
|
||||
start=left_gnd_start,
|
||||
end=left_gnd_end)
|
||||
|
||||
# Gnd line to the left of the replica bitline
|
||||
center_gnd_start = self.rbc_inst.ll().scale(1,0) - vector(2*self.m2_pitch,0)
|
||||
center_gnd_end = vector(center_gnd_start.x, self.rbl_inst.uy()+self.m2_pitch)
|
||||
center_gnd_start = self.replica_cell_inst.ll().scale(1,0) - vector(2*self.m2_pitch,0)
|
||||
center_gnd_end = vector(center_gnd_start.x, self.replica_column_inst.uy()+self.m2_pitch)
|
||||
self.center_gnd_pin=self.add_segment_center(layer="metal2",
|
||||
start=center_gnd_start,
|
||||
end=center_gnd_end)
|
||||
|
||||
# Gnd line to the right of the replica bitline
|
||||
right_gnd_start = self.rbc_inst.lr().scale(1,0) + vector(self.m2_pitch,0)
|
||||
right_gnd_end = vector(right_gnd_start.x, self.rbl_inst.uy()+self.m2_pitch)
|
||||
right_gnd_start = self.replica_cell_inst.lr().scale(1,0) + vector(self.m2_pitch,0)
|
||||
right_gnd_end = vector(right_gnd_start.x, self.replica_column_inst.uy()+self.m2_pitch)
|
||||
self.right_gnd_pin=self.add_segment_center(layer="metal2",
|
||||
start=right_gnd_start,
|
||||
end=right_gnd_end)
|
||||
@@ -450,13 +444,13 @@ class replica_bitline(design.design):
|
||||
# Connect the WL and gnd pins directly to the center and right gnd rails
|
||||
for row in range(self.bitcell_loads):
|
||||
wl = self.wl_list[0]+"_{}".format(row)
|
||||
pin = self.rbl_inst.get_pin(wl)
|
||||
pin = self.replica_column_inst.get_pin(wl)
|
||||
if pin.layer != "metal1":
|
||||
continue
|
||||
# If above the delay line, route the full width
|
||||
left = vector(self.left_gnd_pin.cx(),pin.cy())
|
||||
center = vector(self.center_gnd_pin.cx(),pin.cy())
|
||||
if pin.cy() > self.dc_inst.uy() + self.m1_pitch:
|
||||
if pin.cy() > self.delay_chain_inst.uy() + self.m1_pitch:
|
||||
start = left
|
||||
else:
|
||||
start = center
|
||||
@@ -467,47 +461,41 @@ class replica_bitline(design.design):
|
||||
end=end)
|
||||
if start == left:
|
||||
self.add_via_center(layers=("metal1", "via1", "metal2"),
|
||||
offset=left,
|
||||
rotate=90)
|
||||
offset=left)
|
||||
self.add_via_center(layers=("metal1", "via1", "metal2"),
|
||||
offset=center,
|
||||
rotate=90)
|
||||
offset=center)
|
||||
self.add_via_center(layers=("metal1", "via1", "metal2"),
|
||||
offset=end,
|
||||
rotate=90)
|
||||
offset=end)
|
||||
|
||||
|
||||
rbl_gnd_pins = self.rbl_inst.get_pins("gnd")
|
||||
# Add L shapes to each vertical gnd rail
|
||||
for pin in rbl_gnd_pins:
|
||||
if pin.layer != "metal1":
|
||||
continue
|
||||
# If above the delay line, route the full width
|
||||
left = vector(self.left_gnd_pin.cx(),pin.cy())
|
||||
center = vector(self.center_gnd_pin.cx(),pin.cy())
|
||||
if pin.cy() > self.dc_inst.uy() + self.m1_pitch:
|
||||
start = left
|
||||
else:
|
||||
start = center
|
||||
end = vector(self.right_gnd_pin.cx(),pin.cy())
|
||||
self.add_segment_center(layer="metal1",
|
||||
start=start,
|
||||
end=end)
|
||||
if start == left:
|
||||
self.add_via_center(layers=("metal1", "via1", "metal2"),
|
||||
offset=left,
|
||||
rotate=90)
|
||||
self.add_via_center(layers=("metal1", "via1", "metal2"),
|
||||
offset=center,
|
||||
rotate=90)
|
||||
self.add_via_center(layers=("metal1", "via1", "metal2"),
|
||||
offset=end,
|
||||
rotate=90)
|
||||
# rbl_gnd_pins = self.replica_column_inst.get_pins("gnd")
|
||||
# # Add L shapes to each vertical gnd rail
|
||||
# for pin in rbl_gnd_pins:
|
||||
# if pin.layer != "metal1":
|
||||
# continue
|
||||
# # If above the delay line, route the full width
|
||||
# left = vector(self.left_gnd_pin.cx(),pin.cy())
|
||||
# center = vector(self.center_gnd_pin.cx(),pin.cy())
|
||||
# if pin.cy() > self.delay_chain_inst.uy() + self.m1_pitch:
|
||||
# start = left
|
||||
# else:
|
||||
# start = center
|
||||
# end = vector(self.right_gnd_pin.cx(),pin.cy())
|
||||
# self.add_segment_center(layer="metal1",
|
||||
# start=start,
|
||||
# end=end)
|
||||
# if start == left:
|
||||
# self.add_via_center(layers=("metal1", "via1", "metal2"),
|
||||
# offset=left)
|
||||
# self.add_via_center(layers=("metal1", "via1", "metal2"),
|
||||
# offset=center)
|
||||
# self.add_via_center(layers=("metal1", "via1", "metal2"),
|
||||
# offset=end)
|
||||
|
||||
|
||||
|
||||
# Connect the gnd pins of the delay chain to the left rails
|
||||
dc_gnd_pins = self.dc_inst.get_pins("gnd")
|
||||
dc_gnd_pins = self.delay_chain_inst.get_pins("gnd")
|
||||
for pin in dc_gnd_pins:
|
||||
if pin.layer != "metal1":
|
||||
continue
|
||||
@@ -520,12 +508,10 @@ class replica_bitline(design.design):
|
||||
start=start,
|
||||
end=end)
|
||||
self.add_via_center(layers=("metal1", "via1", "metal2"),
|
||||
offset=start,
|
||||
rotate=90)
|
||||
offset=start)
|
||||
|
||||
# self.add_via_center(layers=("metal1", "via1", "metal2"),
|
||||
# offset=end,
|
||||
#rotate=90)
|
||||
# offset=end)
|
||||
|
||||
|
||||
# Add via for the inverter
|
||||
@@ -536,16 +522,14 @@ class replica_bitline(design.design):
|
||||
# start=start,
|
||||
# end=end)
|
||||
# self.add_via_center(layers=("metal1", "via1", "metal2"),
|
||||
# offset=start,
|
||||
#rotate=90)
|
||||
# offset=start)
|
||||
# self.add_via_center(layers=("metal1", "via1", "metal2"),
|
||||
# offset=end,
|
||||
#rotate=90)
|
||||
# offset=end)
|
||||
|
||||
|
||||
|
||||
# Create RBL rails too
|
||||
rbl_pins = self.rbl_inst.get_pins("gnd")
|
||||
rbl_pins = self.replica_column_inst.get_pins("gnd")
|
||||
for pin in rbl_pins:
|
||||
if pin.layer != "metal2":
|
||||
continue
|
||||
@@ -560,7 +544,7 @@ class replica_bitline(design.design):
|
||||
|
||||
def add_layout_pins(self):
|
||||
""" Route the input and output signal """
|
||||
en_offset = self.dc_inst.get_pin("in").bc()
|
||||
en_offset = self.delay_chain_inst.get_pin("in").bc()
|
||||
self.add_layout_pin_segment_center(text="en",
|
||||
layer="metal2",
|
||||
start=en_offset,
|
||||
@@ -587,7 +571,7 @@ class replica_bitline(design.design):
|
||||
height=pin.height(),
|
||||
width=pin.width())
|
||||
|
||||
pin = self.dc_inst.get_pin("out")
|
||||
pin = self.delay_chain_inst.get_pin("out")
|
||||
self.add_label_pin(text="delayed_en",
|
||||
layer=pin.layer,
|
||||
offset=pin.ll(),
|
||||
|
||||
@@ -131,8 +131,7 @@ class single_level_column_mux_array(design.design):
|
||||
self.add_layout_pin(text="sel_{}".format(j),
|
||||
layer="metal1",
|
||||
offset=offset,
|
||||
width=self.mux.width * self.columns,
|
||||
height=contact.m1m2.width)
|
||||
width=self.mux.width * self.columns)
|
||||
|
||||
def add_vertical_poly_rail(self):
|
||||
""" Connect the poly to the address rails """
|
||||
@@ -149,73 +148,60 @@ class single_level_column_mux_array(design.design):
|
||||
offset = vector(gate_offset.x,self.get_pin("sel_{}".format(sel_index)).cy())
|
||||
# Add the poly contact with a shift to account for the rotation
|
||||
self.add_via_center(layers=("metal1", "contact", "poly"),
|
||||
offset=offset,
|
||||
rotate=90)
|
||||
offset=offset)
|
||||
self.add_path("poly", [offset, gate_offset])
|
||||
|
||||
def route_bitlines(self):
|
||||
""" Connect the output bit-lines to form the appropriate width mux """
|
||||
for j in range(self.columns):
|
||||
bl_offset = self.mux_inst[j].get_pin("bl_out").ll()
|
||||
br_offset = self.mux_inst[j].get_pin("br_out").ll()
|
||||
bl_offset = self.mux_inst[j].get_pin("bl_out").bc()
|
||||
br_offset = self.mux_inst[j].get_pin("br_out").bc()
|
||||
|
||||
bl_out_offset = bl_offset - vector(0,(self.words_per_row+1)*self.m1_pitch)
|
||||
br_out_offset = br_offset - vector(0,(self.words_per_row+2)*self.m1_pitch)
|
||||
|
||||
bl_out_offset_end = bl_out_offset + vector(0,self.route_height)
|
||||
br_out_offset_end = br_out_offset + vector(0,self.route_height)
|
||||
|
||||
if (j % self.words_per_row) == 0:
|
||||
# Create the metal1 to connect the n-way mux output from the pass gate
|
||||
# These will be located below the select lines. Yes, these are M2 width
|
||||
# to ensure vias are enclosed and M1 min width rules.
|
||||
width = contact.m1m2.width + self.mux.width * (self.words_per_row - 1)
|
||||
self.add_rect(layer="metal1",
|
||||
offset=bl_out_offset,
|
||||
width=width,
|
||||
height=drc("minwidth_metal2"))
|
||||
self.add_rect(layer="metal1",
|
||||
offset=br_out_offset,
|
||||
width=width,
|
||||
height=drc("minwidth_metal2"))
|
||||
|
||||
width = self.m2_width + self.mux.width * (self.words_per_row - 1)
|
||||
self.add_path("metal1", [bl_out_offset, bl_out_offset+vector(width,0)])
|
||||
self.add_path("metal1", [br_out_offset, br_out_offset+vector(width,0)])
|
||||
|
||||
# Extend the bitline output rails and gnd downward on the first bit of each n-way mux
|
||||
self.add_layout_pin(text="bl_out_{}".format(int(j/self.words_per_row)),
|
||||
layer="metal2",
|
||||
offset=bl_out_offset.scale(1,0),
|
||||
width=drc('minwidth_metal2'),
|
||||
height=self.route_height)
|
||||
self.add_layout_pin(text="br_out_{}".format(int(j/self.words_per_row)),
|
||||
layer="metal2",
|
||||
offset=br_out_offset.scale(1,0),
|
||||
width=drc('minwidth_metal2'),
|
||||
height=self.route_height)
|
||||
self.add_layout_pin_segment_center(text="bl_out_{}".format(int(j/self.words_per_row)),
|
||||
layer="metal2",
|
||||
start=bl_out_offset,
|
||||
end=bl_out_offset_end)
|
||||
self.add_layout_pin_segment_center(text="br_out_{}".format(int(j/self.words_per_row)),
|
||||
layer="metal2",
|
||||
start=br_out_offset,
|
||||
end=br_out_offset_end)
|
||||
|
||||
|
||||
# This via is on the right of the wire
|
||||
self.add_via(layers=("metal1", "via1", "metal2"),
|
||||
offset=bl_out_offset + vector(contact.m1m2.height,0),
|
||||
rotate=90)
|
||||
self.add_via_center(layers=("metal1", "via1", "metal2"),
|
||||
offset=bl_out_offset)
|
||||
|
||||
# This via is on the left of the wire
|
||||
self.add_via(layers=("metal1", "via1", "metal2"),
|
||||
offset= br_out_offset,
|
||||
rotate=90)
|
||||
self.add_via_center(layers=("metal1", "via1", "metal2"),
|
||||
offset=br_out_offset)
|
||||
|
||||
else:
|
||||
|
||||
self.add_rect(layer="metal2",
|
||||
offset=bl_out_offset,
|
||||
width=drc('minwidth_metal2'),
|
||||
height=self.route_height-bl_out_offset.y)
|
||||
self.add_path("metal2", [ bl_out_offset, bl_out_offset_end])
|
||||
self.add_path("metal2", [ br_out_offset, br_out_offset_end])
|
||||
|
||||
# This via is on the right of the wire
|
||||
self.add_via(layers=("metal1", "via1", "metal2"),
|
||||
offset=bl_out_offset + vector(contact.m1m2.height,0),
|
||||
rotate=90)
|
||||
self.add_rect(layer="metal2",
|
||||
offset=br_out_offset,
|
||||
width=drc('minwidth_metal2'),
|
||||
height=self.route_height-br_out_offset.y)
|
||||
self.add_via_center(layers=("metal1", "via1", "metal2"),
|
||||
offset=bl_out_offset)
|
||||
# This via is on the left of the wire
|
||||
self.add_via(layers=("metal1", "via1", "metal2"),
|
||||
offset= br_out_offset,
|
||||
rotate=90)
|
||||
self.add_via_center(layers=("metal1", "via1", "metal2"),
|
||||
offset=br_out_offset)
|
||||
|
||||
|
||||
def analytical_delay(self, corner, slew, load):
|
||||
from tech import parameter
|
||||
@@ -230,4 +216,4 @@ class single_level_column_mux_array(design.design):
|
||||
from tech import parameter
|
||||
#Bitcell drain load being used to estimate mux NMOS drain load
|
||||
drain_load = logical_effort.convert_farad_to_relative_c(parameter['bitcell_drain_cap'])
|
||||
return drain_load
|
||||
return drain_load
|
||||
|
||||
@@ -81,21 +81,13 @@ class wordline_driver(design.design):
|
||||
(gate_offset, y_dir) = self.get_gate_offset(0, self.inv.height, num)
|
||||
|
||||
# Route both supplies
|
||||
for n in ["vdd", "gnd"]:
|
||||
supply_pin = self.inv2_inst[num].get_pin(n)
|
||||
for name in ["vdd", "gnd"]:
|
||||
supply_pin = self.inv2_inst[num].get_pin(name)
|
||||
|
||||
# Add pins in two locations
|
||||
for xoffset in [a_xoffset, b_xoffset]:
|
||||
pin_pos = vector(xoffset, supply_pin.cy())
|
||||
self.add_via_center(layers=("metal1", "via1", "metal2"),
|
||||
offset=pin_pos,
|
||||
rotate=90)
|
||||
self.add_via_center(layers=("metal2", "via2", "metal3"),
|
||||
offset=pin_pos,
|
||||
rotate=90)
|
||||
self.add_layout_pin_rect_center(text=n,
|
||||
layer="metal3",
|
||||
offset=pin_pos)
|
||||
self.add_power_pin(name, pin_pos)
|
||||
|
||||
|
||||
|
||||
@@ -193,13 +185,14 @@ class wordline_driver(design.design):
|
||||
start=input_offset,
|
||||
end=mid_via_offset)
|
||||
self.add_via_center(layers=("metal1", "via1", "metal2"),
|
||||
offset=mid_via_offset)
|
||||
offset=mid_via_offset,
|
||||
directions=("V","V"))
|
||||
|
||||
# now connect to the nand2 B
|
||||
self.add_path("metal2", [mid_via_offset, b_pos])
|
||||
self.add_via_center(layers=("metal1", "via1", "metal2"),
|
||||
offset=b_pos - vector(0.5*contact.m1m2.height,0),
|
||||
rotate=90)
|
||||
directions=("H","H"))
|
||||
|
||||
|
||||
# output each WL on the right
|
||||
|
||||
Reference in New Issue
Block a user