Move label pins to center like layout pins.

Rework of control logic with vertical poly. Passes DRC/LVS.
Single bank passing DRC.
This commit is contained in:
Matt Guthaus 2018-03-14 17:30:41 -07:00
parent 8ca9ba4244
commit b867e163a6
6 changed files with 560 additions and 612 deletions

View File

@ -282,7 +282,7 @@ class layout(lef.lef):
height=height)
self.add_label(text=text,
layer=layer,
offset=offset)
offset=offset+vector(0.5*width,0.5*height))
def add_label(self, text, layer, offset=[0,0],zoom=-1):

View File

@ -60,6 +60,24 @@ class spice(verilog.verilog):
else:
return self.pin_type[name]
def get_inputs(self):
""" These use pin types to determine pin lists. These
may be over-ridden by submodules that didn't use pin directions yet."""
input_list = []
for pin in self.pins:
if self.pin_type[pin]=="INPUT":
input_list.append(pin)
return input_list
def get_outputs(self):
""" These use pin types to determine pin lists. These
may be over-ridden by submodules that didn't use pin directions yet."""
output_list = []
for pin in self.pins:
if self.pin_type[pin]=="OUTPUT":
output_list.append(pin)
return output_list
def add_mod(self, mod):
"""Adds a subckt/submodule to the subckt hierarchy"""

View File

@ -74,17 +74,19 @@ class bank(design.design):
def add_pins(self):
""" Adding pins for Bank module"""
for i in range(self.word_size):
self.add_pin("DATA[{0}]".format(i))
self.add_pin("DATA[{0}]".format(i),"INOUT")
for i in range(self.addr_size):
self.add_pin("A[{0}]".format(i))
self.add_pin("A[{0}]".format(i),"INPUT")
# For more than one bank, we have a bank select and name
# the signals gated_*.
if self.num_banks > 1:
self.add_pin("bank_sel")
self.add_pin("bank_sel","INPUT")
for pin in ["s_en","w_en","tri_en_bar","tri_en",
"clk_bar","clk_buf","vdd","gnd"]:
self.add_pin(pin)
"clk_buf_bar","clk_buf"]:
self.add_pin(pin,"INPUT")
self.add_pin("vdd","POWER")
self.add_pin("gnd","GROUND")
def route_layout(self):
""" Create routing amoung the modules """
@ -151,7 +153,7 @@ class bank(design.design):
# Number of control lines in the bus
self.num_control_lines = 6
# The order of the control signals on the control bus:
self.input_control_signals = ["clk_buf", "tri_en_bar", "tri_en", "clk_bar", "w_en", "s_en"]
self.input_control_signals = ["clk_buf", "tri_en_bar", "tri_en", "clk_buf_bar", "w_en", "s_en"]
# These will be outputs of the gaters if this is multibank, if not, normal signals.
if self.num_banks > 1:
self.control_signals = ["gated_"+str for str in self.input_control_signals]
@ -259,7 +261,7 @@ class bank(design.design):
for i in range(self.num_cols):
temp.append("bl[{0}]".format(i))
temp.append("br[{0}]".format(i))
temp.extend([self.prefix+"clk_bar", "vdd"])
temp.extend([self.prefix+"clk_buf_bar", "vdd"])
self.connect_inst(temp)
def add_column_mux_array(self):
@ -337,7 +339,7 @@ class bank(design.design):
for i in range(self.word_size):
temp.append("data_in[{0}]".format(i))
temp.append("data_in_bar[{0}]".format(i))
temp.extend([self.prefix+"clk_bar", "vdd", "gnd"])
temp.extend([self.prefix+"clk_buf_bar", "vdd", "gnd"])
self.connect_inst(temp)
def add_tri_gate_array(self):
@ -534,8 +536,8 @@ class bank(design.design):
# Add a vdd and gnd power rail above the array
self.max_point += self.supply_rail_pitch + self.supply_rail_width
self.height = self.max_point - self.min_point
self.width = self.right_vdd_x_offset - self.left_gnd_x_offset + self.supply_rail_width
self.height = ur.y - ll.y + 4*self.supply_rail_pitch
self.width = ur.x - ll.x + 4*self.supply_rail_pitch
@ -894,10 +896,10 @@ class bank(design.design):
# Connection from the central bus to the main control block crosses
# pre-decoder and this connection is in metal3
connection = []
connection.append((self.prefix+"clk_bar", self.msf_data_in_inst.get_pin("clk").lc()))
connection.append((self.prefix+"clk_buf_bar", self.msf_data_in_inst.get_pin("clk").lc()))
connection.append((self.prefix+"tri_en_bar", self.tri_gate_array_inst.get_pin("en_bar").lc()))
connection.append((self.prefix+"tri_en", self.tri_gate_array_inst.get_pin("en").lc()))
connection.append((self.prefix+"clk_bar", self.precharge_array_inst.get_pin("en").lc()))
connection.append((self.prefix+"clk_buf_bar", self.precharge_array_inst.get_pin("en").lc()))
connection.append((self.prefix+"w_en", self.write_driver_array_inst.get_pin("en").lc()))
connection.append((self.prefix+"s_en", self.sense_amp_array_inst.get_pin("en").lc()))

File diff suppressed because it is too large Load Diff

View File

@ -41,8 +41,12 @@ class replica_bitline(design.design):
self.offset_all_coordinates()
self.add_layout_pins()
#self.add_lvs_correspondence_points()
self.width = self.right_gnd_pin.rx() - self.left_gnd_pin.lx()
self.height = self.left_gnd_pin.uy() - self.left_gnd_pin.by()
self.DRC_LVS()
def calculate_module_offsets(self):
@ -124,9 +128,6 @@ class replica_bitline(design.design):
self.connect_inst(["bl[0]", "br[0]"] + ["gnd"]*self.bitcell_loads + ["vdd", "gnd"])
self.height = max(self.rbl_inst.uy(),self.dc_inst.uy()) + self.m2_pitch
self.width = self.rbl_inst.rx() + self.m2_width
@ -209,46 +210,28 @@ class replica_bitline(design.design):
# Route the vdd lines from left to right
# Add via for the delay chain
left_vdd_start = self.dc_inst.ll().scale(1,0) - vector(2*self.m2_pitch,2*self.m2_pitch)
left_vdd_end = vector(left_vdd_start.x, self.rbl_inst.uy()+2*self.m2_pitch)
left_vdd_pin=self.add_layout_pin_center_segment(text="vdd",
layer="metal2",
start=left_vdd_start,
end=left_vdd_end)
self.add_via_center(layers=("metal1", "via1", "metal2"),
offset=left_vdd_start,
rotate=90)
self.add_via_center(layers=("metal1", "via1", "metal2"),
offset=left_vdd_end,
rotate=90)
left_vdd_start = self.dc_inst.ll().scale(1,0)
left_vdd_end = vector(left_vdd_start.x, self.rbl_inst.uy())
self.left_vdd_pin=self.add_layout_pin_center_segment(text="vdd",
layer="metal2",
start=left_vdd_start,
end=left_vdd_end)
# Vdd line to the left of the replica bitline
center_vdd_start = self.rbc_inst.ll() - vector(3*self.m2_pitch,2*self.m2_pitch)
center_vdd_end = vector(center_vdd_start.x, self.rbl_inst.uy()+2*self.m2_pitch)
center_vdd_pin=self.add_layout_pin_center_segment(text="vdd",
layer="metal2",
start=center_vdd_start,
end=center_vdd_end)
self.add_via_center(layers=("metal1", "via1", "metal2"),
offset=center_vdd_start,
rotate=90)
self.add_via_center(layers=("metal1", "via1", "metal2"),
offset=center_vdd_end,
rotate=90)
center_vdd_start = self.rbc_inst.ll() - vector(3*self.m2_pitch,0)
center_vdd_end = vector(center_vdd_start.x, self.rbl_inst.uy())
self.center_vdd_pin=self.add_layout_pin_center_segment(text="vdd",
layer="metal2",
start=center_vdd_start,
end=center_vdd_end)
# Vdd line to the right of the replica bitline
right_vdd_start = self.rbc_inst.lr() + vector(2*self.m2_pitch,-2*self.m2_pitch)
right_vdd_end = vector(right_vdd_start.x, self.rbl_inst.uy()+2*self.m2_pitch)
right_vdd_pin=self.add_layout_pin_center_segment(text="vdd",
layer="metal2",
start=right_vdd_start,
end=right_vdd_end)
self.add_via_center(layers=("metal1", "via1", "metal2"),
offset=right_vdd_start,
rotate=90)
self.add_via_center(layers=("metal1", "via1", "metal2"),
offset=right_vdd_end,
rotate=90)
right_vdd_start = self.rbc_inst.lr() + vector(2*self.m2_pitch,0)
right_vdd_end = vector(right_vdd_start.x, self.rbl_inst.uy())
self.right_vdd_pin=self.add_layout_pin_center_segment(text="vdd",
layer="metal2",
start=right_vdd_start,
end=right_vdd_end)
@ -258,8 +241,8 @@ class replica_bitline(design.design):
for pin in rbl_vdd_pins:
if pin.layer != "metal1":
continue
start = vector(center_vdd_pin.cx(),pin.cy())
end = vector(right_vdd_pin.cx(),pin.cy())
start = vector(self.center_vdd_pin.cx(),pin.cy())
end = vector(self.right_vdd_pin.cx(),pin.cy())
self.add_segment_center(layer="metal1",
start=start,
end=end)
@ -277,7 +260,7 @@ class replica_bitline(design.design):
for pin in dc_vdd_pins:
if pin.layer != "metal1":
continue
start = vector(left_vdd_pin.cx(),pin.cy())
start = vector(self.left_vdd_pin.cx(),pin.cy())
# Note, we don't connect to center because of via conflicts
# with the RBL pins
#end = vector(center_vdd_pin.cx(),pin.cy())
@ -289,15 +272,11 @@ class replica_bitline(design.design):
offset=start,
rotate=90)
# self.add_via_center(layers=("metal1", "via1", "metal2"),
# offset=end,
#rotate=90)
# Add via for the inverter
pin = self.rbl_inv_inst.get_pin("vdd")
start = vector(left_vdd_pin.cx(),pin.cy())
end = vector(center_vdd_pin.cx(),pin.cy())
start = vector(self.left_vdd_pin.cx(),pin.cy())
end = vector(self.center_vdd_pin.cx(),pin.cy())
self.add_segment_center(layer="metal1",
start=start,
end=end)
@ -313,7 +292,7 @@ class replica_bitline(design.design):
# Add via for the RBC
pin = self.rbc_inst.get_pin("vdd")
start = pin.lc()
end = vector(right_vdd_pin.cx(),pin.cy())
end = vector(self.right_vdd_pin.cx(),pin.cy())
self.add_segment_center(layer="metal1",
start=start,
end=end)
@ -321,34 +300,18 @@ class replica_bitline(design.design):
offset=end,
rotate=90)
# Connect the RBL rails at the top and bottom
# Create the RBL rails too
rbl_pins = self.rbl_inst.get_pins("vdd")
for pin in rbl_pins:
if pin.layer != "metal2":
continue
end = vector(pin.cx(),right_vdd_pin.uy())
self.add_segment_center(layer="metal2",
start=pin.uc(),
end=end)
self.add_via_center(layers=("metal1", "via1", "metal2"),
offset=end,
rotate=90)
start = vector(pin.cx(),right_vdd_pin.by())
self.add_segment_center(layer="metal2",
start=pin.bc(),
end=start)
self.add_via_center(layers=("metal1", "via1", "metal2"),
offset=start,
rotate=90)
start = vector(pin.cx(),self.right_vdd_pin.by())
end = vector(pin.cx(),self.right_vdd_pin.uy())
self.add_layout_pin_center_segment(text="vdd",
layer="metal2",
start=start,
end=end)
# Connect the rails at the top and bottom
self.add_segment_center(layer="metal1",
start=left_vdd_end,
end=right_vdd_end)
self.add_segment_center(layer="metal1",
start=left_vdd_start,
end=right_vdd_start)
@ -359,46 +322,28 @@ 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(self.m2_pitch,self.m2_pitch)
left_gnd_start = self.dc_inst.ll().scale(1,0) - vector(self.m2_pitch,0)
left_gnd_end = vector(left_gnd_start.x, self.rbl_inst.uy()+self.m2_pitch)
left_gnd_pin=self.add_layout_pin_center_segment(text="gnd",
layer="metal2",
start=left_gnd_start,
end=left_gnd_end)
self.add_via_center(layers=("metal1", "via1", "metal2"),
offset=left_gnd_start,
rotate=90)
self.add_via_center(layers=("metal1", "via1", "metal2"),
offset=left_gnd_end,
rotate=90)
self.left_gnd_pin=self.add_layout_pin_center_segment(text="gnd",
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,self.m2_pitch)
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_pin=self.add_layout_pin_center_segment(text="gnd",
layer="metal2",
start=center_gnd_start,
end=center_gnd_end)
self.add_via_center(layers=("metal1", "via1", "metal2"),
offset=center_gnd_start,
rotate=90)
self.add_via_center(layers=("metal1", "via1", "metal2"),
offset=center_gnd_end,
rotate=90)
self.center_gnd_pin=self.add_layout_pin_center_segment(text="gnd",
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,-self.m2_pitch)
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_pin=self.add_layout_pin_center_segment(text="gnd",
layer="metal2",
start=right_gnd_start,
end=right_gnd_end)
self.add_via_center(layers=("metal1", "via1", "metal2"),
offset=right_gnd_start,
rotate=90)
self.add_via_center(layers=("metal1", "via1", "metal2"),
offset=right_gnd_end,
rotate=90)
self.right_gnd_pin=self.add_layout_pin_center_segment(text="gnd",
layer="metal2",
start=right_gnd_start,
end=right_gnd_end)
@ -408,8 +353,8 @@ class replica_bitline(design.design):
pin = self.rbl_inst.get_pin(wl)
if pin.layer != "metal1":
continue
start = vector(center_gnd_pin.cx(),pin.cy())
end = vector(right_gnd_pin.cx(),pin.cy())
start = vector(self.center_gnd_pin.cx(),pin.cy())
end = vector(self.right_gnd_pin.cx(),pin.cy())
self.add_segment_center(layer="metal1",
start=start,
end=end)
@ -426,8 +371,8 @@ class replica_bitline(design.design):
for pin in rbl_gnd_pins:
if pin.layer != "metal1":
continue
start = vector(center_gnd_pin.cx(),pin.cy())
end = vector(right_gnd_pin.cx(),pin.cy())
start = vector(self.center_gnd_pin.cx(),pin.cy())
end = vector(self.right_gnd_pin.cx(),pin.cy())
self.add_segment_center(layer="metal1",
start=start,
end=end)
@ -445,10 +390,10 @@ class replica_bitline(design.design):
for pin in dc_gnd_pins:
if pin.layer != "metal1":
continue
start = vector(left_gnd_pin.cx(),pin.cy())
start = vector(self.left_gnd_pin.cx(),pin.cy())
# Note, we don't connect to the center rails because of
# via conflicts with the RBL
#end = vector(center_gnd_pin.cx(),pin.cy())
#end = vector(self.center_gnd_pin.cx(),pin.cy())
end = pin.rc()
self.add_segment_center(layer="metal1",
start=start,
@ -464,8 +409,8 @@ class replica_bitline(design.design):
# Add via for the inverter
# pin = self.rbl_inv_inst.get_pin("gnd")
# start = vector(left_gnd_pin.cx(),pin.cy())
# end = vector(center_gnd_pin.cx(),pin.cy())
# start = vector(self.left_gnd_pin.cx(),pin.cy())
# end = vector(self.center_gnd_pin.cx(),pin.cy())
# self.add_segment_center(layer="metal1",
# start=start,
# end=end)
@ -478,35 +423,18 @@ class replica_bitline(design.design):
# Connect the RBL rails at the top and bottom
# Create RBL rails too
rbl_pins = self.rbl_inst.get_pins("gnd")
for pin in rbl_pins:
if pin.layer != "metal2":
continue
end = vector(pin.cx(),right_gnd_pin.uy())
self.add_segment_center(layer="metal2",
start=pin.uc(),
end=end)
self.add_via_center(layers=("metal1", "via1", "metal2"),
offset=end,
rotate=90)
start = vector(pin.cx(),right_gnd_pin.by())
self.add_segment_center(layer="metal2",
start=pin.bc(),
end=start)
self.add_via_center(layers=("metal1", "via1", "metal2"),
offset=start,
rotate=90)
start = vector(pin.cx(),self.right_gnd_pin.by())
end = vector(pin.cx(),self.right_gnd_pin.uy())
self.add_layout_pin_center_segment(text="gnd",
layer="metal2",
start=start,
end=end)
# Connect the rails at the top and bottom
self.add_segment_center(layer="metal1",
start=left_gnd_end,
end=right_gnd_end)
self.add_segment_center(layer="metal1",
start=left_gnd_start,
end=right_gnd_start)
def add_layout_pins(self):

View File

@ -16,7 +16,6 @@ class sram(design.design):
Dynamically generated SRAM by connecting banks to control logic. The
number of banks should be 1 , 2 or 4
"""
def __init__(self, word_size, num_words, num_banks, name):
c = reload(__import__(OPTS.control_logic))
@ -62,6 +61,7 @@ class sram(design.design):
self.bank_to_bus_distance = 5*self.m3_width
self.compute_sizes()
self.create_modules()
self.add_pins()
self.create_layout()
@ -146,8 +146,8 @@ class sram(design.design):
self.add_pin("ADDR[{0}]".format(i),"INPUT")
# These are used to create the physical pins too
self.control_logic_inputs=["CSb", "WEb", "OEb"]
self.control_logic_outputs=["s_en", "w_en", "tri_en", "tri_en_bar", "clk_bar", "clk_buf"]
self.control_logic_inputs=self.control_logic.get_inputs()
self.control_logic_outputs=self.control_logic.get_outputs()
self.add_pin_list(self.control_logic_inputs + ["clk"],"INPUT")
self.add_pin("vdd","POWER")
@ -156,8 +156,6 @@ class sram(design.design):
def create_layout(self):
""" Layout creation """
self.create_modules()
if self.num_banks == 1:
self.add_single_bank_modules()
self.add_single_bank_pins()
@ -366,7 +364,7 @@ class sram(design.design):
""" Add the horizontal and vertical busses """
# Vertical bus
# The order of the control signals on the control bus:
self.control_bus_names = ["clk_buf", "tri_en_bar", "tri_en", "clk_bar", "w_en", "s_en"]
self.control_bus_names = ["clk_buf", "tri_en_bar", "tri_en", "clk_buf_bar", "w_en", "s_en"]
self.vert_control_bus_positions = self.create_bus(layer="metal2",
pitch=self.m2_pitch,
offset=self.vertical_bus_offset,
@ -430,7 +428,7 @@ class sram(design.design):
def add_two_bank_logic(self):
""" Add the control and MSB logic """
self.add_control_logic(position=self.control_logic_position, rotate=0)
self.add_control_logic(position=self.control_logic_position)
self.msb_address_inst = self.add_inst(name="msb_address",
mod=self.msb_address,
@ -443,7 +441,7 @@ class sram(design.design):
""" Add the control and MSB decode/bank select logic for four banks """
self.add_control_logic(position=self.control_logic_position, rotate=0)
self.add_control_logic(position=self.control_logic_position)
self.msb_address_inst = self.add_inst(name="msb_address",
mod=self.msb_address,
@ -797,8 +795,8 @@ class sram(design.design):
self.control_logic = self.mod_control_logic(num_rows=self.num_rows)
self.add_mod(self.control_logic)
# Create the address and control flops
dff_size = self.addr_size + len(self.control_logic_inputs)
# Create the address and control flops (but not the clk)
dff_size = self.addr_size + len(self.control_logic.get_inputs())-1
self.addr_ctrl_dff = self.mod_dff_array(rows=dff_size, columns=1)
self.add_mod(self.addr_ctrl_dff)
@ -859,7 +857,7 @@ class sram(design.design):
if(self.num_banks > 1):
temp.append("bank_sel[{0}]".format(bank_num))
temp.extend(["s_en", "w_en", "tri_en_bar", "tri_en",
"clk_bar","clk_buf" , "vdd", "gnd"])
"clk_buf_bar","clk_buf" , "vdd", "gnd"])
self.connect_inst(temp)
return bank_inst
@ -904,12 +902,11 @@ class sram(design.design):
return line_positions
def add_control_addr_dff(self, position, rotate=0):
def add_control_addr_dff(self, position):
""" Add and place address and control flops """
self.addr_ctrl_dff_inst = self.add_inst(name="address",
mod=self.addr_ctrl_dff,
offset=position,
rotate=rotate)
mod=self.addr_ctrl_dff,
offset=position)
# inputs, outputs/output/bar
inputs = []
outputs = []
@ -918,18 +915,19 @@ class sram(design.design):
outputs.append("A[{}]".format(i))
for i in self.control_logic_inputs:
if i == "clk":
continue
inputs.append(i)
outputs.append(i+"_s")
self.connect_inst(inputs + outputs + ["clk", "vdd", "gnd"])
def add_control_logic(self, position, rotate):
def add_control_logic(self, position):
""" Add and place control logic """
self.control_logic_inst=self.add_inst(name="control",
mod=self.control_logic,
offset=position,
rotate=rotate)
self.connect_inst(self.control_logic_inputs + ["clk"] + self.control_logic_outputs + ["vdd", "gnd"])
offset=position)
self.connect_inst(self.control_logic_inputs + self.control_logic_outputs + ["vdd", "gnd"])
def add_lvs_correspondence_points(self):
@ -961,12 +959,13 @@ class sram(design.design):
# are not recomputed using instance placement. So, place the control logic such that it aligns
# with the top of the SRAM.
control_gap = 2*self.m3_width
control_pos = vector(-control_gap,
self.bank.height-self.control_logic.width)
self.add_control_logic(position=control_pos, rotate=90)
control_pos = vector(-self.control_logic.width-control_gap,
self.bank.height-self.control_logic.height-3*self.supply_rail_width)
self.add_control_logic(position=control_pos)
addr_pos = vector(self.control_logic_inst.lx(),
2*self.supply_rail_pitch)
# Leave room for the control routes to the left of the flops
addr_pos = vector(self.control_logic_inst.lx() + 4*self.m2_pitch,
3*self.supply_rail_pitch)
self.add_control_addr_dff(addr_pos)
self.width = self.bank.width + self.control_logic.height + control_gap
@ -981,11 +980,13 @@ class sram(design.design):
self.copy_layout_pin(self.bank_inst, "DATA[{}]".format(i))
for i in range(self.addr_size):
self.copy_layout_pin(self.bank_inst, "A[{}]".format(i))
self.copy_layout_pin(self.addr_ctrl_dff_inst, "din[{}]".format(i),"ADDR[{}]".format(i))
for (old,new) in zip(["csb","web","oeb","clk"],["CSb","WEb","OEb","clk"]):
self.copy_layout_pin(self.control_logic_inst, old, new)
ctrl_flops = ["din[{}]".format(i) for i in range(self.addr_size,self.addr_size+3)]
for (old,new) in zip(ctrl_flops,["CSb","WEb","OEb"]):
self.copy_layout_pin(self.addr_ctrl_dff_inst, old, new)
self.copy_layout_pin(self.control_logic_inst, "clk")
self.copy_layout_pin(self.bank_inst, "vdd")
self.copy_layout_pin(self.bank_inst, "gnd")
@ -1046,36 +1047,79 @@ class sram(design.design):
dest_pin = self.bank_inst.get_pin(n)
self.connect_rail_from_left_m2m3(src_pin, dest_pin)
# Find the left-most metal2 rails
leftmost_vdd_rail = None
for vdd_pin in self.bank_inst.get_pins("vdd"):
if vdd_pin.layer != "metal2":
continue
if leftmost_vdd_rail == None or vdd_pin.lx() < leftmost_vdd_rail.lx():
leftmost_vdd_rail = vdd_pin
leftmost_gnd_rail = None
for gnd_pin in self.bank_inst.get_pins("gnd"):
if gnd_pin.layer != "metal2":
continue
if leftmost_gnd_rail == None or gnd_pin.lx() < leftmost_gnd_rail.lx():
leftmost_gnd_rail = gnd_pin
# Expand the ring around the bank
bbox_lr = vector(self.control_logic_inst.lx(), self.bank_inst.by() + 2*self.supply_rail_pitch)
bbox_ur = self.bank_inst.ur() - vector(2*self.supply_rail_pitch, 2*self.supply_rail_pitch)
self.add_power_ring([bbox_lr, bbox_ur])
self.route_single_bank_vdd()
self.route_single_bank_gnd()
src_pins = self.control_logic_inst.get_pins("vdd")
for src_pin in src_pins:
if src_pin.layer != "metal2":
continue
self.connect_rail_from_left_m2m3(src_pin,leftmost_vdd_rail)
src_pins = self.control_logic_inst.get_pins("gnd")
for src_pin in src_pins:
if src_pin.layer != "metal2":
continue
self.add_path("metal2", [src_pin.rc(), vector(leftmost_gnd_rail.cx(), src_pin.cy())])
for i in range(self.addr_size):
flop_name = "dout[{}]".format(i)
bank_name = "A[{}]".format(i)
flop_pin = self.addr_ctrl_dff_inst.get_pin(flop_name)
bank_pin = self.bank_inst.get_pin(bank_name)
flop_pos = flop_pin.center()
bank_pos = bank_pin.lc()
mid_x_pos = 0.5*(flop_pos.x + bank_pos.x)
mid_pos = vector(mid_x_pos - i*self.m2_pitch, flop_pos.y)
self.add_wire(("metal1","via1","metal2"),[flop_pos, mid_pos, bank_pos])
# There should be M1 in the flop already, but just in case
self.add_via_center(layers=("metal1","via1","metal2"),
offset=flop_pos,
rotate=90)
for i in range(3):
flop_name = "dout[{}]".format(self.addr_size+i)
ctrl_name = ["csb","web","oeb"][i]
flop_pin = self.addr_ctrl_dff_inst.get_pin(flop_name)
ctrl_pin = self.control_logic_inst.get_pin(ctrl_name)
flop_pos = flop_pin.center()
ctrl_pos = ctrl_pin.bc()
mid_pos = vector(ctrl_pos.x, flop_pos.y)
self.add_wire(("metal3","via2","metal2"),[flop_pos, mid_pos, ctrl_pos])
self.add_via_center(layers=("metal2","via2","metal3"),
offset=flop_pos,
rotate=90)
def route_single_bank_vdd(self):
""" Route vdd for the control and dff array """
# Route the vdd rails to the LEFT
modules = [ self.control_logic_inst, self.addr_ctrl_dff_inst]
for inst in modules:
for vdd_pin in inst.get_pins("vdd"):
if vdd_pin.layer != "metal1":
continue
vdd_pos = vdd_pin.rc()
left_rail_pos = vector(self.left_vdd_x_center, vdd_pos.y)
self.add_path("metal1", [left_rail_pos, vdd_pos])
self.add_via_center(layers=("metal1", "via1", "metal2"),
offset=left_rail_pos,
size = (1,3),
rotate=90)
def route_single_bank_gnd(self):
""" Route gnd for the control and dff array """
# Route the gnd rails to the LEFT
modules = [ self.control_logic_inst, self.addr_ctrl_dff_inst]
for inst in modules:
for gnd_pin in inst.get_pins("gnd"):
if gnd_pin.layer != "metal1":
continue
gnd_pos = gnd_pin.rc()
left_rail_pos = vector(self.left_gnd_x_center, gnd_pos.y)
self.add_path("metal1", [left_rail_pos, gnd_pos])
self.add_via_center(layers=("metal1", "via1", "metal2"),
offset=left_rail_pos,
size = (1,3),
rotate=90)
def sp_write(self, sp_name):
# Write the entire spice of the object to the file
############################################################