mirror of https://github.com/VLSIDA/OpenRAM.git
Connect bank supply rings in sram.py.
This commit is contained in:
parent
0c203c1c7e
commit
4205a6a700
|
|
@ -21,7 +21,8 @@ class bank(design.design):
|
|||
|
||||
mod_list = ["tri_gate", "bitcell", "decoder", "ms_flop_array", "wordline_driver",
|
||||
"bitcell_array", "sense_amp_array", "precharge_array",
|
||||
"column_mux_array", "write_driver_array", "tri_gate_array"]
|
||||
"column_mux_array", "write_driver_array", "tri_gate_array",
|
||||
"bank_select"]
|
||||
for mod_name in mod_list:
|
||||
config_mod_name = getattr(OPTS, mod_name)
|
||||
class_file = reload(__import__(config_mod_name))
|
||||
|
|
@ -50,11 +51,13 @@ class bank(design.design):
|
|||
self.create_modules()
|
||||
self.add_modules()
|
||||
self.setup_layout_constraints()
|
||||
self.route_power_ring(self.core_bbox)
|
||||
|
||||
if self.num_banks > 1:
|
||||
self.add_bank_select()
|
||||
|
||||
self.route_layout()
|
||||
|
||||
# Add and route the bank select logic
|
||||
if(self.num_banks > 1):
|
||||
self.add_bank_select()
|
||||
|
||||
# Can remove the following, but it helps for debug!
|
||||
self.add_lvs_correspondence_points()
|
||||
|
|
@ -72,7 +75,7 @@ class bank(design.design):
|
|||
|
||||
# For more than one bank, we have a bank select and name
|
||||
# the signals gated_*.
|
||||
if(self.num_banks > 1):
|
||||
if self.num_banks > 1:
|
||||
self.add_pin("bank_sel")
|
||||
for pin in ["s_en","w_en","tri_en_bar","tri_en",
|
||||
"clk_bar","clk_buf","vdd","gnd"]:
|
||||
|
|
@ -80,7 +83,6 @@ class bank(design.design):
|
|||
|
||||
def route_layout(self):
|
||||
""" Create routing amoung the modules """
|
||||
self.route_power_ring(self.core_bbox)
|
||||
self.create_central_bus()
|
||||
self.route_precharge_to_bitcell_array()
|
||||
self.route_sense_amp_to_trigate()
|
||||
|
|
@ -91,6 +93,9 @@ class bank(design.design):
|
|||
self.route_msf_address()
|
||||
self.route_control_lines()
|
||||
self.add_control_pins()
|
||||
if self.num_banks > 1:
|
||||
self.route_bank_select()
|
||||
|
||||
self.route_vdd_supply()
|
||||
self.route_gnd_supply()
|
||||
|
||||
|
|
@ -108,7 +113,7 @@ class bank(design.design):
|
|||
self.column_mux_height = 0
|
||||
if self.col_addr_size > 1: # size 1 is from addr FF
|
||||
self.add_column_decoder()
|
||||
|
||||
|
||||
self.add_sense_amp_array()
|
||||
self.add_write_driver_array()
|
||||
self.add_msf_data_in()
|
||||
|
|
@ -139,7 +144,7 @@ class bank(design.design):
|
|||
# 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"]
|
||||
# These will be outputs of the gaters if this is multibank
|
||||
if self.num_banks>1:
|
||||
if self.num_banks > 1:
|
||||
self.control_signals = ["gated_"+str for str in self.input_control_signals]
|
||||
else:
|
||||
self.control_signals = self.input_control_signals
|
||||
|
|
@ -177,7 +182,7 @@ class bank(design.design):
|
|||
self.precharge_array = self.mod_precharge_array(columns=self.num_cols)
|
||||
self.add_mod(self.precharge_array)
|
||||
|
||||
if(self.col_addr_size > 0):
|
||||
if self.col_addr_size > 0:
|
||||
self.column_mux_array = self.mod_column_mux_array(columns=self.num_cols,
|
||||
word_size=self.word_size)
|
||||
self.add_mod(self.column_mux_array)
|
||||
|
|
@ -213,6 +218,10 @@ class bank(design.design):
|
|||
|
||||
self.inv = pinv()
|
||||
self.add_mod(self.inv)
|
||||
|
||||
if(self.num_banks > 1):
|
||||
self.bank_select = self.mod_bank_select()
|
||||
self.add_mod(self.bank_select)
|
||||
|
||||
|
||||
def add_bitcell_array(self):
|
||||
|
|
@ -452,133 +461,37 @@ class bank(design.design):
|
|||
temp.extend(["vdd", "gnd"])
|
||||
self.connect_inst(temp)
|
||||
|
||||
|
||||
def add_bank_select(self):
|
||||
"""Create a bank select signal that is combined with an array of
|
||||
NOR+INV gates to gate the control signals in case of multiple
|
||||
banks are created in upper level SRAM module
|
||||
"""
|
||||
""" Instantiate the bank select logic. """
|
||||
xoffset = self.left_vdd_x_offset + self.supply_rail_pitch
|
||||
# extra space to allow vias
|
||||
yoffset = self.min_point + 2*self.supply_rail_pitch + self.m1_space
|
||||
self.bank_select_pos = vector(xoffset,yoffset)
|
||||
self.bank_select_inst = self.add_inst(name="bank_select",
|
||||
mod=self.bank_select,
|
||||
offset=self.bank_select_pos)
|
||||
|
||||
# 4x Inverter
|
||||
self.inv4x = pinv(4)
|
||||
self.add_mod(self.inv4x)
|
||||
|
||||
self.nor2 = pnor2()
|
||||
self.add_mod(self.nor2)
|
||||
|
||||
self.nand2 = pnand2()
|
||||
self.add_mod(self.nand2)
|
||||
|
||||
# left of gnd rail is the "bus start"
|
||||
bus_start = self.start_of_right_central_bus - self.m2_space
|
||||
xoffset_nand = bus_start - self.nand2.width - self.inv4x.width - drc["pwell_to_nwell"]
|
||||
xoffset_nor = bus_start - self.nor2.width - self.inv4x.width - drc["pwell_to_nwell"]
|
||||
xoffset_inv = bus_start - self.inv4x.width
|
||||
xoffset_bank_sel_inv = xoffset_nor - self.inv.width - 3*self.m2_pitch
|
||||
xoffset_inputs = xoffset_bank_sel_inv - 6*self.m2_pitch
|
||||
|
||||
# bank select inverter
|
||||
self.bank_select_inv_position = vector(xoffset_bank_sel_inv,
|
||||
self.min_point)
|
||||
# bank select inverter (must be made unique if more than one OR)
|
||||
bank_sel_inv=self.add_inst(name="bank_sel_inv",
|
||||
mod=self.inv,
|
||||
offset=[xoffset_bank_sel_inv,self.min_point])
|
||||
self.connect_inst(["bank_sel", "bank_sel_bar", "vdd", "gnd"])
|
||||
|
||||
# bank_sel is vertical wire
|
||||
bank_sel_inv_pin = bank_sel_inv.get_pin("A")
|
||||
xoffset_bank_sel = bank_sel_inv_pin.lx()
|
||||
bank_sel_line_pos = vector(xoffset_bank_sel, self.min_point)
|
||||
bank_sel_line_end = vector(xoffset_bank_sel, self.decoder_min_point-self.m2_pitch)
|
||||
self.add_path("metal2", [bank_sel_line_pos,bank_sel_line_end])
|
||||
self.add_via_center(layers=("metal1","via1","metal2"),
|
||||
offset=bank_sel_inv_pin.lc())
|
||||
|
||||
# Route the pin to the left edge as well
|
||||
bank_sel_pin_pos=vector(self.left_vdd_x_offset, self.min_point)
|
||||
bank_sel_pin_end=vector(bank_sel_line_pos.x, bank_sel_pin_pos.y)
|
||||
self.add_layout_pin_center_segment(text="bank_sel",
|
||||
layer="metal3",
|
||||
start=bank_sel_pin_pos,
|
||||
end=bank_sel_pin_end)
|
||||
self.add_via_center(layers=("metal2","via2","metal3"),
|
||||
offset=bank_sel_pin_end,
|
||||
rotate=90)
|
||||
|
||||
# bank_sel_bar is vertical wire
|
||||
bank_sel_bar_pin = bank_sel_inv.get_pin("Z")
|
||||
xoffset_bank_sel_bar = bank_sel_bar_pin.rx()
|
||||
self.add_label_pin(text="bank_sel_bar",
|
||||
layer="metal2",
|
||||
offset=vector(xoffset_bank_sel_bar, self.min_point),
|
||||
height=2*self.inv.height)
|
||||
self.add_via_center(layers=("metal1","via1","metal2"),
|
||||
offset=bank_sel_bar_pin.rc())
|
||||
|
||||
temp = []
|
||||
for i in range(self.num_control_lines):
|
||||
input_name = self.input_control_signals[i]
|
||||
gated_name = self.control_signals[i]
|
||||
name_nand = "nand_{}".format(input_name)
|
||||
name_nor = "nor_{}".format(input_name)
|
||||
name_inv = "inv_{}".format(input_name)
|
||||
temp.append(self.input_control_signals[i])
|
||||
for i in range(self.num_control_lines):
|
||||
temp.append(self.control_signals[i])
|
||||
temp.extend(["vdd", "gnd"])
|
||||
self.connect_inst(temp)
|
||||
|
||||
y_offset = self.min_point + self.inv.height * i
|
||||
if i%2:
|
||||
y_offset += self.inv.height
|
||||
mirror = "MX"
|
||||
else:
|
||||
mirror = ""
|
||||
|
||||
# These require OR (nor2+inv) gates since they are active low.
|
||||
# (writes occur on clk low)
|
||||
if input_name in ("clk_buf", "tri_en_bar"):
|
||||
|
||||
logic_inst=self.add_inst(name=name_nor,
|
||||
mod=self.nor2,
|
||||
offset=[xoffset_nor, y_offset],
|
||||
mirror=mirror)
|
||||
self.connect_inst([input_name,
|
||||
"bank_sel_bar",
|
||||
gated_name+"_temp_bar",
|
||||
"vdd",
|
||||
"gnd"])
|
||||
xoffset_bank_signal = xoffset_bank_sel_bar
|
||||
|
||||
|
||||
# the rest are AND (nand2+inv) gates
|
||||
else:
|
||||
logic_inst=self.add_inst(name=name_nand,
|
||||
mod=self.nand2,
|
||||
offset=[xoffset_nand, y_offset],
|
||||
mirror=mirror)
|
||||
bank_sel_signal = "bank_sel"
|
||||
self.connect_inst([input_name,
|
||||
"bank_sel",
|
||||
gated_name+"_temp_bar",
|
||||
"vdd",
|
||||
"gnd"])
|
||||
xoffset_bank_signal = xoffset_bank_sel
|
||||
|
||||
# They all get inverters on the output
|
||||
inv_inst=self.add_inst(name=name_inv,
|
||||
mod=self.inv4x,
|
||||
offset=[xoffset_inv, y_offset],
|
||||
mirror=mirror)
|
||||
self.connect_inst([gated_name+"_temp_bar",
|
||||
gated_name,
|
||||
"vdd",
|
||||
"gnd"])
|
||||
|
||||
|
||||
# Connect the logic output to inverter input
|
||||
pre = logic_inst.get_pin("Z").lc()
|
||||
out_position = logic_inst.get_pin("Z").rc() + vector(0.5*self.m1_width,0)
|
||||
in_position = inv_inst.get_pin("A").lc() + vector(0.5*self.m1_width,0)
|
||||
post = inv_inst.get_pin("A").rc()
|
||||
self.add_path("metal1", [pre, out_position, in_position, post])
|
||||
def route_bank_select(self):
|
||||
""" Route the bank select logic. """
|
||||
for input_name in self.input_control_signals+["bank_sel"]:
|
||||
in_pos = self.bank_select_inst.get_pin(input_name).lc()
|
||||
self.add_layout_pin_center_segment(text=input_name,
|
||||
layer="metal3",
|
||||
start=vector(self.left_gnd_x_offset,in_pos.y),
|
||||
end=in_pos)
|
||||
|
||||
for gated_name in self.control_signals:
|
||||
# Connect the inverter output to the central bus
|
||||
out_pos = inv_inst.get_pin("Z").rc()
|
||||
out_pos = self.bank_select_inst.get_pin(gated_name).rc()
|
||||
bus_pos = vector(self.central_line_xoffset[gated_name], out_pos.y)
|
||||
self.add_path("metal3",[out_pos, bus_pos])
|
||||
self.add_via_center(layers=("metal2", "via2", "metal3"),
|
||||
|
|
@ -590,50 +503,7 @@ class bank(design.design):
|
|||
self.add_via_center(layers=("metal2", "via2", "metal3"),
|
||||
offset=out_pos,
|
||||
rotate=90)
|
||||
|
||||
# Connect the logic B input to bank_sel/bank_sel_bar
|
||||
logic_pos = logic_inst.get_pin("B").lc() - vector(0.5*contact.m1m2.height,0)
|
||||
input_pos = vector(xoffset_bank_signal,logic_pos.y)
|
||||
self.add_path("metal2",[logic_pos, input_pos])
|
||||
self.add_via_center(layers=("metal1", "via1", "metal2"),
|
||||
offset=logic_pos,
|
||||
rotate=90)
|
||||
|
||||
|
||||
# Connect the logic A input to the input pin
|
||||
logic_pos = logic_inst.get_pin("A").lc()
|
||||
input_pos = vector(self.left_vdd_x_offset,logic_pos.y)
|
||||
self.add_via_center(layers=("metal1", "via1", "metal2"),
|
||||
offset=logic_pos,
|
||||
rotate=90)
|
||||
self.add_via_center(layers=("metal2", "via2", "metal3"),
|
||||
offset=logic_pos,
|
||||
rotate=90)
|
||||
self.add_layout_pin_center_segment(text=input_name,
|
||||
layer="metal3",
|
||||
start=input_pos,
|
||||
end=logic_pos)
|
||||
|
||||
|
||||
|
||||
# Add vdd/gnd supply rails
|
||||
gnd_pin = inv_inst.get_pin("gnd")
|
||||
left_gnd_pos = vector(self.left_gnd_x_center, gnd_pos.cy())
|
||||
self.add_path("metal1",[left_gnd_pos, gnd_pos.rc()])
|
||||
self.add_via_center(layers=("metal1", "via1", "metal2"),
|
||||
offset=left_gnd_pos,
|
||||
size = (1,3),
|
||||
rotate=90)
|
||||
|
||||
vdd_pin = inv_inst.get_pin("vdd")
|
||||
left_vdd_pos = vector(self.left_vdd_x_center, vdd_pin.cy())
|
||||
self.add_path("metal1",[left_vdd_pos, vdd_pin.rc()])
|
||||
self.add_via_center(layers=("metal1", "via1", "metal2"),
|
||||
offset=left_vdd_pos,
|
||||
size = (1,3),
|
||||
rotate=90)
|
||||
|
||||
|
||||
|
||||
|
||||
def setup_layout_constraints(self):
|
||||
""" Calculating layout constraints, width, height etc """
|
||||
|
|
@ -653,7 +523,7 @@ class bank(design.design):
|
|||
if self.num_banks>1:
|
||||
# The control gating logic is below the decoder
|
||||
# Min of the control gating logic and tri gate.
|
||||
self.min_point = min(self.decoder_min_point - self.num_control_lines * self.bitcell.height, tri_gate_min_point)
|
||||
self.min_point = min(self.decoder_min_point - self.bank_select.height, tri_gate_min_point)
|
||||
else:
|
||||
# Just the min of the decoder logic logic and tri gate.
|
||||
self.min_point = min(self.decoder_min_point, addr_min_point, tri_gate_min_point)
|
||||
|
|
@ -961,30 +831,6 @@ class bank(design.design):
|
|||
self.add_path("metal1", [driver_wl_pos, mid1, mid2, bitcell_wl_pos])
|
||||
|
||||
|
||||
# route the gnd rails, add contact to rail as well
|
||||
for gnd_pin in self.wordline_driver_inst.get_pins("gnd"):
|
||||
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)
|
||||
|
||||
# route the vdd rails
|
||||
for vdd_pin in self.wordline_driver_inst.get_pins("vdd"):
|
||||
vdd_pos = vdd_pin.rc()
|
||||
left_rail_pos = vector(self.left_vdd_x_center, vdd_pos.y)
|
||||
right_rail_pos = vector(self.right_vdd_x_center, vdd_pos.y)
|
||||
self.add_path("metal1", [left_rail_pos, right_rail_pos])
|
||||
self.add_via_center(layers=("metal1", "via1", "metal2"),
|
||||
offset=left_rail_pos,
|
||||
size = (1,3),
|
||||
rotate=90)
|
||||
self.add_via_center(layers=("metal1", "via1", "metal2"),
|
||||
offset=right_rail_pos,
|
||||
size = (1,3),
|
||||
rotate=90)
|
||||
|
||||
|
||||
|
||||
|
|
@ -1237,9 +1083,11 @@ class bank(design.design):
|
|||
def route_vdd_supply(self):
|
||||
""" Route vdd for the precharge, sense amp, write_driver, data FF, tristate """
|
||||
|
||||
for inst in [self.precharge_array_inst, self.sense_amp_array_inst,
|
||||
self.write_driver_array_inst, self.msf_data_in_inst,
|
||||
self.tri_gate_array_inst]:
|
||||
# Route the vdd rails to the RIGHT
|
||||
modules = [self.precharge_array_inst, self.sense_amp_array_inst,
|
||||
self.write_driver_array_inst, self.msf_data_in_inst,
|
||||
self.tri_gate_array_inst]
|
||||
for inst in modules:
|
||||
for vdd_pin in inst.get_pins("vdd"):
|
||||
self.add_rect(layer="metal1",
|
||||
offset=vdd_pin.ll(),
|
||||
|
|
@ -1250,12 +1098,39 @@ class bank(design.design):
|
|||
offset=via_position,
|
||||
size = (1,3),
|
||||
rotate=90)
|
||||
|
||||
# Route the vdd rails to the LEFT
|
||||
for vdd_pin in self.wordline_driver_inst.get_pins("vdd"):
|
||||
vdd_pos = vdd_pin.rc()
|
||||
left_rail_pos = vector(self.left_vdd_x_center, vdd_pos.y)
|
||||
right_rail_pos = vector(self.right_vdd_x_center, vdd_pos.y)
|
||||
self.add_path("metal1", [left_rail_pos, right_rail_pos])
|
||||
self.add_via_center(layers=("metal1", "via1", "metal2"),
|
||||
offset=left_rail_pos,
|
||||
size = (1,3),
|
||||
rotate=90)
|
||||
self.add_via_center(layers=("metal1", "via1", "metal2"),
|
||||
offset=right_rail_pos,
|
||||
size = (1,3),
|
||||
rotate=90)
|
||||
|
||||
if self.num_banks>1:
|
||||
for vdd_pin in self.bank_select_inst.get_pins("vdd"):
|
||||
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_gnd_supply(self):
|
||||
""" Route gnd for the precharge, sense amp, write_driver, data FF, tristate """
|
||||
""" Route gnd rails"""
|
||||
# Route the gnd rails to the RIGHT
|
||||
# precharge is connected by abutment
|
||||
for inst in [ self.tri_gate_array_inst, self.sense_amp_array_inst, self.msf_data_in_inst, self.write_driver_array_inst]:
|
||||
modules = [ self.tri_gate_array_inst, self.sense_amp_array_inst, self.msf_data_in_inst, self.write_driver_array_inst]
|
||||
for inst in modules:
|
||||
for gnd_pin in inst.get_pins("gnd"):
|
||||
if gnd_pin.layer != "metal1":
|
||||
continue
|
||||
|
|
@ -1269,6 +1144,20 @@ class bank(design.design):
|
|||
size = (1,3),
|
||||
rotate=90)
|
||||
|
||||
# Route the gnd rails to the LEFT
|
||||
modules = [self.wordline_driver_inst]
|
||||
if self.num_banks>1:
|
||||
modules.append(self.bank_select_inst)
|
||||
for inst in modules:
|
||||
for gnd_pin in inst.get_pins("gnd"):
|
||||
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 add_control_pins(self):
|
||||
""" Add the control signal input pins """
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@ class bank_select(design.design):
|
|||
for i in range(self.num_control_lines):
|
||||
gated_name = self.control_signals[i]
|
||||
self.add_pin(gated_name)
|
||||
self.add_pin("vdd")
|
||||
self.add_pin("gnd")
|
||||
|
||||
self.create_modules()
|
||||
self.calculate_module_offsets()
|
||||
|
|
@ -61,26 +63,26 @@ class bank_select(design.design):
|
|||
self.m1_pitch = contact.m1m2.height + max(self.m1_space,self.m2_space)
|
||||
self.m2_pitch = contact.m2m3.height + max(self.m2_space,self.m3_space)
|
||||
|
||||
# left of gnd rail is the "bus start"
|
||||
self.xoffset_nand = self.inv4x.width + 2*self.m2_pitch + drc["pwell_to_nwell"]
|
||||
self.xoffset_nor = self.inv4x.width + 2*self.m2_pitch + drc["pwell_to_nwell"]
|
||||
self.xoffset_inv = max(self.xoffset_nand + self.nand2.width, self.xoffset_nor + self.nor2.width)
|
||||
self.xoffset_bank_sel_inv = 0
|
||||
self.xoffset_inputs = 0
|
||||
|
||||
# Above the bottom rails (plus a pitch to allow vias)
|
||||
self.yoffset_minpoint = self.m1_pitch
|
||||
self.yoffset_maxpoint = self.num_control_lines * self.inv.height
|
||||
# Include the M1 pitches for the supply rails and spacing
|
||||
self.height = self.yoffset_maxpoint + 2*self.m1_pitch
|
||||
self.width = self.xoffset_inv + self.inv4x.width
|
||||
|
||||
def add_modules(self):
|
||||
|
||||
# bank select inverter
|
||||
self.bank_select_inv_position = vector(self.xoffset_bank_sel_inv,
|
||||
self.yoffset_minpoint)
|
||||
self.bank_select_inv_position = vector(self.xoffset_bank_sel_inv, 0)
|
||||
|
||||
# bank select inverter (must be made unique if more than one OR)
|
||||
self.bank_sel_inv=self.add_inst(name="bank_sel_inv",
|
||||
mod=self.inv,
|
||||
offset=[self.xoffset_bank_sel_inv, self.yoffset_minpoint])
|
||||
offset=[self.xoffset_bank_sel_inv, 0])
|
||||
self.connect_inst(["bank_sel", "bank_sel_bar", "vdd", "gnd"])
|
||||
|
||||
self.logic_inst = []
|
||||
|
|
@ -92,7 +94,7 @@ class bank_select(design.design):
|
|||
name_nor = "nor_{}".format(input_name)
|
||||
name_inv = "inv_{}".format(input_name)
|
||||
|
||||
y_offset = self.yoffset_minpoint + self.inv.height * i
|
||||
y_offset = self.inv.height * i
|
||||
if i%2:
|
||||
y_offset += self.inv.height
|
||||
mirror = "MX"
|
||||
|
|
@ -143,14 +145,14 @@ class bank_select(design.design):
|
|||
# bank_sel is vertical wire
|
||||
bank_sel_inv_pin = self.bank_sel_inv.get_pin("A")
|
||||
xoffset_bank_sel = bank_sel_inv_pin.lx()
|
||||
bank_sel_line_pos = vector(xoffset_bank_sel, self.yoffset_minpoint)
|
||||
bank_sel_line_pos = vector(xoffset_bank_sel, 0)
|
||||
bank_sel_line_end = vector(xoffset_bank_sel, self.yoffset_maxpoint)
|
||||
self.add_path("metal2", [bank_sel_line_pos, bank_sel_line_end])
|
||||
self.add_via_center(layers=("metal1","via1","metal2"),
|
||||
offset=bank_sel_inv_pin.lc())
|
||||
|
||||
# Route the pin to the left edge as well
|
||||
bank_sel_pin_pos=vector(0, self.yoffset_minpoint)
|
||||
bank_sel_pin_pos=vector(0, 0)
|
||||
bank_sel_pin_end=vector(bank_sel_line_pos.x, bank_sel_pin_pos.y)
|
||||
self.add_layout_pin_center_segment(text="bank_sel",
|
||||
layer="metal3",
|
||||
|
|
@ -165,7 +167,7 @@ class bank_select(design.design):
|
|||
xoffset_bank_sel_bar = bank_sel_bar_pin.rx()
|
||||
self.add_label_pin(text="bank_sel_bar",
|
||||
layer="metal2",
|
||||
offset=vector(xoffset_bank_sel_bar, self.yoffset_minpoint),
|
||||
offset=vector(xoffset_bank_sel_bar, 0),
|
||||
height=2*self.inv.height)
|
||||
self.add_via_center(layers=("metal1","via1","metal2"),
|
||||
offset=bank_sel_bar_pin.rc())
|
||||
|
|
|
|||
279
compiler/sram.py
279
compiler/sram.py
|
|
@ -68,7 +68,7 @@ class sram(design.design):
|
|||
# Can remove the following, but it helps for debug!
|
||||
self.add_lvs_correspondence_points()
|
||||
|
||||
self.offset_all_coordinates()
|
||||
#self.offset_all_coordinates()
|
||||
sizes = self.find_highest_coords()
|
||||
self.width = sizes[0]
|
||||
self.height = sizes[1]
|
||||
|
|
@ -175,10 +175,12 @@ class sram(design.design):
|
|||
def add_four_bank_modules(self):
|
||||
""" Adds the modules and the buses to the top level """
|
||||
|
||||
self.compute_four_bank_offsets()
|
||||
self.compute_bus_sizes()
|
||||
|
||||
self.add_four_banks()
|
||||
|
||||
self.compute_four_bank_offsets()
|
||||
|
||||
self.add_busses()
|
||||
|
||||
self.add_four_bank_logic()
|
||||
|
|
@ -190,10 +192,12 @@ class sram(design.design):
|
|||
def add_two_bank_modules(self):
|
||||
""" Adds the modules and the buses to the top level """
|
||||
|
||||
self.compute_two_bank_offsets()
|
||||
self.compute_bus_sizes()
|
||||
|
||||
self.add_two_banks()
|
||||
|
||||
self.compute_two_bank_offsets()
|
||||
|
||||
self.add_busses()
|
||||
|
||||
self.add_two_bank_logic()
|
||||
|
|
@ -233,7 +237,6 @@ class sram(design.design):
|
|||
self.add_path("metal3",[pin_pos,rail_pos])
|
||||
self.add_via_center(("metal2","via2","metal3"),rail_pos)
|
||||
|
||||
|
||||
|
||||
def route_four_banks(self):
|
||||
""" Route all of the signals for the four bank SRAM. """
|
||||
|
|
@ -274,7 +277,7 @@ class sram(design.design):
|
|||
self.add_via_center(("metal2","via2","metal3"),rail_pos)
|
||||
|
||||
|
||||
self.route_bank_supply_rails(bottom_banks=[2,3])
|
||||
self.route_bank_supply_rails(left_banks=[0,2], bottom_banks=[2,3])
|
||||
|
||||
|
||||
|
||||
|
|
@ -310,16 +313,14 @@ class sram(design.design):
|
|||
# The main difference is that the four bank SRAM has the data bus in the middle of the four banks
|
||||
# as opposed to the top of the banks.
|
||||
|
||||
self.compute_bus_sizes()
|
||||
|
||||
# In 4 bank SRAM, the height is determined by the bank decoder and address flop
|
||||
self.vertical_bus_height = 2*self.bank.height + 4*self.bank_to_bus_distance + self.data_bus_height \
|
||||
+ self.supply_bus_height + self.msb_decoder.height + self.msb_address.width
|
||||
# The address bus extends down through the power rails, but control and bank_sel bus don't
|
||||
self.addr_bus_height = self.vertical_bus_height + 2*self.power_rail_pitch
|
||||
self.addr_bus_height = self.vertical_bus_height
|
||||
|
||||
self.vertical_bus_offset = vector(self.bank.width + self.bank_to_bus_distance, 2*self.power_rail_pitch)
|
||||
self.data_bus_offset = vector(0, 2*self.power_rail_pitch + self.bank.height + self.bank_to_bus_distance)
|
||||
self.vertical_bus_offset = vector(self.bank.width + self.bank_to_bus_distance, 0)
|
||||
self.data_bus_offset = vector(0, self.bank.height + self.bank_to_bus_distance)
|
||||
self.supply_bus_offset = vector(0, self.data_bus_offset.y + self.data_bus_height + self.bank.height + 2*self.bank_to_bus_distance)
|
||||
self.control_bus_offset = vector(0, self.supply_bus_offset.y + self.supply_bus_height)
|
||||
self.bank_sel_bus_offset = self.vertical_bus_offset + vector(self.m2_pitch*self.control_size,0)
|
||||
|
|
@ -330,7 +331,7 @@ class sram(design.design):
|
|||
|
||||
# Bank select flops get put to the right of control logic above bank1 and the buses
|
||||
# Leave a pitch to get the vdd rails up to M2
|
||||
self.msb_address_position = vector(max(self.bank.width + self.vertical_bus_width + 2*self.bank_to_bus_distance, self.control_logic.width),
|
||||
self.msb_address_position = vector(self.bank_inst[1].lx() + 3*self.supply_rail_pitch,
|
||||
self.supply_bus_offset.y + self.supply_bus_height + 2*self.m1_pitch + self.msb_address.width)
|
||||
|
||||
# Decoder goes above the MSB address flops, and is flipped in Y
|
||||
|
|
@ -341,15 +342,13 @@ class sram(design.design):
|
|||
def compute_two_bank_offsets(self):
|
||||
""" Compute the overall offsets for a two bank SRAM """
|
||||
|
||||
self.compute_bus_sizes()
|
||||
|
||||
# In 2 bank SRAM, the height is determined by the control bus which is higher than the msb address
|
||||
self.vertical_bus_height = self.bank.height + 2*self.bank_to_bus_distance + self.data_bus_height + self.control_bus_height
|
||||
# The address bus extends down through the power rails, but control and bank_sel bus don't
|
||||
self.addr_bus_height = self.vertical_bus_height + 2*self.power_rail_pitch
|
||||
self.addr_bus_height = self.vertical_bus_height
|
||||
|
||||
self.vertical_bus_offset = vector(self.bank.width + self.bank_to_bus_distance, 2*self.power_rail_pitch)
|
||||
self.data_bus_offset = vector(0, 2*self.power_rail_pitch + self.bank.height + self.bank_to_bus_distance)
|
||||
self.vertical_bus_offset = vector(self.bank.width + self.bank_to_bus_distance, 0)
|
||||
self.data_bus_offset = vector(0, self.bank.height + self.bank_to_bus_distance)
|
||||
self.supply_bus_offset = vector(0, self.data_bus_offset.y + self.data_bus_height)
|
||||
self.control_bus_offset = vector(0, self.supply_bus_offset.y + self.supply_bus_height)
|
||||
self.bank_sel_bus_offset = self.vertical_bus_offset + vector(self.m2_pitch*self.control_size,0)
|
||||
|
|
@ -360,7 +359,7 @@ class sram(design.design):
|
|||
|
||||
# Bank select flops get put to the right of control logic above bank1 and the buses
|
||||
# Leave a pitch to get the vdd rails up to M2
|
||||
self.msb_address_position = vector(max(self.bank.width + self.vertical_bus_width + 2*self.bank_to_bus_distance,self.control_logic.width),
|
||||
self.msb_address_position = vector(self.bank_inst[1].lx() + 3*self.supply_rail_pitch,
|
||||
self.supply_bus_offset.y+self.supply_bus_height + 2*self.m1_pitch + self.msb_address.width)
|
||||
|
||||
def add_busses(self):
|
||||
|
|
@ -419,7 +418,7 @@ class sram(design.design):
|
|||
pitch=self.m1_pitch,
|
||||
offset=self.supply_bus_offset+vector(0,self.m1_pitch),
|
||||
names=["gnd"],
|
||||
length=self.supply_bus_width-2*self.power_rail_width,
|
||||
length=self.supply_bus_width,
|
||||
vertical=False))
|
||||
self.horz_control_bus_positions.update(self.create_bus(layer="metal1",
|
||||
pitch=self.m1_pitch,
|
||||
|
|
@ -497,13 +496,11 @@ class sram(design.design):
|
|||
self.add_via_center(("metal2","via2","metal3"),rail_pos)
|
||||
|
||||
|
||||
self.route_bank_supply_rails(bottom_banks=[0,1])
|
||||
self.route_bank_supply_rails(left_banks=[0], bottom_banks=[0,1])
|
||||
|
||||
|
||||
def route_double_msb_address(self):
|
||||
""" Route two MSB address bits and the bank decoder for 4-bank SRAM """
|
||||
|
||||
|
||||
|
||||
# connect the MSB flops to the address input bus
|
||||
for i in [0,1]:
|
||||
|
|
@ -551,68 +548,107 @@ class sram(design.design):
|
|||
self.add_wire(("metal1","via1","metal2"),[msb_pin_pos,out_pos,up_pos,in_pos])
|
||||
self.add_via_center(("metal1","via1","metal2"),in_pos)
|
||||
self.add_via_center(("metal1","via1","metal2"),msb_pin_pos,rotate=90)
|
||||
|
||||
self.route_double_msb_address_supplies()
|
||||
|
||||
def route_double_msb_address_supplies(self):
|
||||
""" Route the vdd/gnd bits of the 2-bit bank decoder. """
|
||||
|
||||
# Route the right-most vdd/gnd of the right upper bank to the top of the decoder
|
||||
vdd_pins = self.bank_inst[1].get_pins("vdd")
|
||||
highest_x = None
|
||||
for bank_vdd_pin in vdd_pins:
|
||||
if highest_x == None or bank_vdd_pin.lx()>highest_x:
|
||||
highest_x = bank_vdd_pin.lx()
|
||||
bank_vdd_pos = bank_vdd_pin.ul()
|
||||
# Route to top
|
||||
self.add_rect(layer="metal1",
|
||||
offset=bank_vdd_pos,
|
||||
height=self.height-bank_vdd_pos.y,
|
||||
width=bank_vdd_pin.width())
|
||||
left_bank_vdd_pin = None
|
||||
right_bank_vdd_pin = None
|
||||
for vdd_pin in vdd_pins:
|
||||
if vdd_pin.layer != "metal2":
|
||||
continue
|
||||
if left_bank_vdd_pin == None or vdd_pin.lx()<left_bank_vdd_pin.lx():
|
||||
left_bank_vdd_pin = vdd_pin
|
||||
if right_bank_vdd_pin == None or vdd_pin.lx()>right_bank_vdd_pin.lx():
|
||||
right_bank_vdd_pin = vdd_pin
|
||||
# Route to top
|
||||
self.add_rect(layer="metal2",
|
||||
offset=vdd_pin.ul(),
|
||||
height=self.height-vdd_pin.uy(),
|
||||
width=vdd_pin.width())
|
||||
|
||||
gnd_pins = self.bank_inst[1].get_pins("gnd")
|
||||
highest_x = None
|
||||
for bank_gnd_pin in gnd_pins:
|
||||
if highest_x == None or bank_gnd_pin.lx()>highest_x:
|
||||
highest_x = bank_gnd_pin.lx()
|
||||
bank_gnd_pos = bank_gnd_pin.ul()
|
||||
# Route to top
|
||||
self.add_rect(layer="metal2",
|
||||
offset=bank_gnd_pos,
|
||||
height=self.height-bank_gnd_pos.y,
|
||||
width=bank_gnd_pin.width())
|
||||
left_bank_gnd_pin = None
|
||||
right_bank_gnd_pin = None
|
||||
for gnd_pin in gnd_pins:
|
||||
if gnd_pin.layer != "metal2":
|
||||
continue
|
||||
if left_bank_gnd_pin == None or gnd_pin.lx()<left_bank_gnd_pin.lx():
|
||||
left_bank_gnd_pin = gnd_pin
|
||||
if right_bank_gnd_pin == None or gnd_pin.lx()>right_bank_gnd_pin.lx():
|
||||
right_bank_gnd_pin = gnd_pin
|
||||
# Route to top
|
||||
self.add_rect(layer="metal2",
|
||||
offset=gnd_pin.ul(),
|
||||
height=self.height-gnd_pin.uy(),
|
||||
width=gnd_pin.width())
|
||||
|
||||
# Connect bank decoder vdd/gnd supplies using the previous bank_vdd_pos and bank_gnd_pos
|
||||
# Connect bank decoder vdd/gnd supplies using the previous bank pins
|
||||
vdd_pins = self.msb_decoder_inst.get_pins("vdd")
|
||||
for vdd_pin in vdd_pins:
|
||||
if vdd_pin.layer != "metal1": continue
|
||||
vdd_pos = vdd_pin.rc()
|
||||
rail_pos = vector(bank_vdd_pos.x+bank_vdd_pin.width(),vdd_pos.y)
|
||||
self.add_path("metal1",[vdd_pos,rail_pos])
|
||||
if vdd_pin.layer != "metal1":
|
||||
continue
|
||||
rail1_pos = vector(left_bank_vdd_pin.cx(),vdd_pin.cy())
|
||||
rail2_pos = vector(right_bank_vdd_pin.cx(),vdd_pin.cy())
|
||||
self.add_path("metal1",[rail1_pos,rail2_pos])
|
||||
self.add_via_center(layers=("metal1","via1","metal2"),
|
||||
offset=rail1_pos,
|
||||
rotate=90,
|
||||
size=[1,3])
|
||||
self.add_via_center(layers=("metal1","via1","metal2"),
|
||||
offset=rail2_pos,
|
||||
rotate=90,
|
||||
size=[1,3])
|
||||
gnd_pins = self.msb_decoder_inst.get_pins("gnd")
|
||||
for gnd_pin in gnd_pins:
|
||||
if gnd_pin.layer != "metal1": continue
|
||||
gnd_pos = gnd_pin.rc()
|
||||
rail_pos = vector(bank_gnd_pos.x+bank_gnd_pin.width(),gnd_pos.y)
|
||||
self.add_path("metal1",[gnd_pos,rail_pos])
|
||||
self.add_via(("metal1","via1","metal2"),rail_pos- vector(0,0.5*self.m1_width),rotate=90,size=[1,3])
|
||||
if gnd_pin.layer != "metal1":
|
||||
continue
|
||||
rail1_pos = vector(left_bank_gnd_pin.cx(),gnd_pin.cy())
|
||||
rail2_pos = vector(right_bank_gnd_pin.cx(),gnd_pin.cy())
|
||||
self.add_path("metal1",[rail1_pos,rail2_pos])
|
||||
self.add_via_center(layers=("metal1","via1","metal2"),
|
||||
offset=rail1_pos,
|
||||
rotate=90,
|
||||
size=[1,3])
|
||||
self.add_via_center(layers=("metal1","via1","metal2"),
|
||||
offset=rail2_pos,
|
||||
rotate=90,
|
||||
size=[1,3])
|
||||
|
||||
# connect the bank MSB flop supplies
|
||||
vdd_pins = self.msb_address_inst.get_pins("vdd")
|
||||
# vdd pins go down to the rail
|
||||
for vdd_pin in vdd_pins:
|
||||
if vdd_pin.layer != "metal1": continue
|
||||
if vdd_pin.layer != "metal1":
|
||||
continue
|
||||
vdd_pos = vdd_pin.bc()
|
||||
down_pos = vdd_pos - vector(0,self.m1_pitch)
|
||||
rail_pos = vector(vdd_pos.x,self.horz_control_bus_positions["vdd"].y)
|
||||
self.add_path("metal1",[vdd_pos,down_pos])
|
||||
self.add_via_center(("metal1","via1","metal2"),down_pos,rotate=90)
|
||||
self.add_via_center(layers=("metal1","via1","metal2"),
|
||||
offset=down_pos,
|
||||
rotate=90)
|
||||
self.add_path("metal2",[down_pos,rail_pos])
|
||||
self.add_via_center(("metal1","via1","metal2"),rail_pos)
|
||||
self.add_via_center(layers=("metal1","via1","metal2"),
|
||||
offset=rail_pos)
|
||||
# gnd pins go right to the rail
|
||||
gnd_pins = self.msb_address_inst.get_pins("gnd")
|
||||
for gnd_pin in gnd_pins:
|
||||
if gnd_pin.layer != "metal2": continue
|
||||
gnd_pos = gnd_pin.rc()
|
||||
rail_pos = vector(bank_gnd_pos.x+bank_gnd_pin.width(),gnd_pos.y)
|
||||
self.add_path("metal1",[gnd_pos,rail_pos])
|
||||
self.add_via_center(("metal1","via1","metal2"),gnd_pos,rotate=90)
|
||||
self.add_via(("metal1","via1","metal2"),rail_pos- vector(0,0.5*self.m1_width),rotate=90,size=[1,3])
|
||||
if gnd_pin.layer != "metal2":
|
||||
continue
|
||||
rail1_pos = vector(left_bank_gnd_pin.cx(),gnd_pin.cy())
|
||||
self.add_path("metal1",[rail1_pos,gnd_pin.lc()])
|
||||
self.add_via_center(layers=("metal1","via1","metal2"),
|
||||
offset=gnd_pin.lc(),
|
||||
rotate=90)
|
||||
self.add_via_center(layers=("metal1","via1","metal2"),
|
||||
offset=rail1_pos,
|
||||
rotate=90,
|
||||
size=[1,3])
|
||||
|
||||
def route_single_msb_address(self):
|
||||
""" Route one MSB address bit for 2-bank SRAM """
|
||||
|
|
@ -681,65 +717,65 @@ class sram(design.design):
|
|||
|
||||
|
||||
|
||||
def route_bank_supply_rails(self, bottom_banks):
|
||||
def route_bank_supply_rails(self, left_banks, bottom_banks):
|
||||
""" Create rails at bottom. Connect veritcal rails to top and bottom. """
|
||||
|
||||
self.add_layout_pin(text="gnd",
|
||||
layer="metal1",
|
||||
offset=vector(0,0),
|
||||
height=self.power_rail_width,
|
||||
width=self.width)
|
||||
|
||||
self.add_layout_pin(text="vdd",
|
||||
layer="metal1",
|
||||
offset=vector(0,self.power_rail_pitch),
|
||||
height=self.power_rail_width,
|
||||
width=self.width)
|
||||
for i in left_banks:
|
||||
vdd_pins = self.bank_inst[i].get_pins("vdd")
|
||||
for vdd_pin in vdd_pins:
|
||||
if vdd_pin.layer != "metal1":
|
||||
continue
|
||||
self.add_layout_pin(text="vdd",
|
||||
layer=vdd_pin.layer,
|
||||
offset=vdd_pin.ll(),
|
||||
height=vdd_pin.height(),
|
||||
width=self.width)
|
||||
|
||||
gnd_pins = self.bank_inst[i].get_pins("gnd")
|
||||
for gnd_pin in gnd_pins:
|
||||
if gnd_pin.layer != "metal1":
|
||||
continue
|
||||
self.add_layout_pin(text="gnd",
|
||||
layer=gnd_pin.layer,
|
||||
offset=gnd_pin.ll(),
|
||||
height=gnd_pin.height(),
|
||||
width=self.width)
|
||||
|
||||
|
||||
|
||||
# route bank vertical rails to bottom
|
||||
for i in bottom_banks:
|
||||
vdd_pins = self.bank_inst[i].get_pins("vdd")
|
||||
for vdd_pin in vdd_pins:
|
||||
vdd_pos = vdd_pin.ul()
|
||||
# Route to bottom
|
||||
self.add_rect(layer="metal2",
|
||||
offset=vector(vdd_pos.x,self.power_rail_pitch),
|
||||
height=self.horz_control_bus_positions["vdd"].y-self.power_rail_pitch,
|
||||
if vdd_pin.layer != "metal2":
|
||||
continue
|
||||
# Route from bottom to top
|
||||
self.add_rect(layer=vdd_pin.layer,
|
||||
offset=vdd_pin.ll(),
|
||||
height=self.horz_control_bus_positions["vdd"].y,
|
||||
width=vdd_pin.width())
|
||||
# Add vias at top
|
||||
rail_pos = vector(vdd_pin.ur().x,self.horz_control_bus_positions["vdd"].y)
|
||||
self.add_via(layers=("metal1","via1","metal2"),
|
||||
offset=rail_pos - vector(0,0.5*self.m1_width),
|
||||
rotate=90,
|
||||
size=[1,3])
|
||||
# Add vias at bottom
|
||||
rail_pos = vector(vdd_pin.lr().x,self.power_rail_pitch)
|
||||
self.add_via(layers=("metal1","via1","metal2"),
|
||||
rail_pos = vector(vdd_pin.cx(),self.horz_control_bus_positions["vdd"].y)
|
||||
self.add_via_center(layers=("metal1","via1","metal2"),
|
||||
offset=rail_pos,
|
||||
rotate=90,
|
||||
size=[2,3])
|
||||
size=[1,3])
|
||||
|
||||
gnd_pins = self.bank_inst[i].get_pins("gnd")
|
||||
for gnd_pin in gnd_pins:
|
||||
gnd_pos = gnd_pin.ul()
|
||||
# Route to bottom
|
||||
self.add_rect(layer="metal2",
|
||||
offset=vector(gnd_pos.x,0),
|
||||
height=self.horz_control_bus_positions["gnd"].y, # route to the top bank
|
||||
if gnd_pin.layer != "metal2":
|
||||
continue
|
||||
# Route from bottom to top
|
||||
self.add_rect(layer=gnd_pin.layer,
|
||||
offset=gnd_pin.ll(),
|
||||
height=self.horz_control_bus_positions["gnd"].y,
|
||||
width=gnd_pin.width())
|
||||
# Add vias at top
|
||||
right_rail_pos = vector(gnd_pin.ur().x,self.horz_control_bus_positions["gnd"].y)
|
||||
self.add_via(layers=("metal1","via1","metal2"),
|
||||
offset=right_rail_pos - vector(0,0.5*self.m1_width),
|
||||
rail_pos = vector(gnd_pin.cx(),self.horz_control_bus_positions["gnd"].y)
|
||||
self.add_via_center(layers=("metal1","via1","metal2"),
|
||||
offset=rail_pos,
|
||||
rotate=90,
|
||||
size=[1,3])
|
||||
# Add vias at bottom
|
||||
right_rail_pos = vector(gnd_pin.lr().x,0)
|
||||
self.add_via(layers=("metal2","via2","metal3"),
|
||||
offset=right_rail_pos,
|
||||
rotate=90,
|
||||
size=[2,3])
|
||||
size=[1,3])
|
||||
|
||||
|
||||
|
||||
|
|
@ -775,9 +811,9 @@ class sram(design.design):
|
|||
|
||||
self.bank_count = 0
|
||||
|
||||
self.power_rail_width = self.bank.vdd_rail_width
|
||||
self.supply_rail_width = self.bank.supply_rail_width
|
||||
# Leave some extra space for the pitch
|
||||
self.power_rail_pitch = self.bank.vdd_rail_width + 2*self.m3_space
|
||||
self.supply_rail_pitch = self.bank.supply_rail_pitch
|
||||
|
||||
|
||||
|
||||
|
|
@ -897,12 +933,13 @@ class sram(design.design):
|
|||
|
||||
# No orientation or offset
|
||||
self.bank_inst = self.add_bank(0, [0, 0], 1, 1)
|
||||
|
||||
# Control logic is placed to the left of the blank even with the
|
||||
# decoder bottom. A small gap is in the x-dimension.
|
||||
|
||||
# 3/5/18 MRG: Cannot reference positions inside submodules because boundaries
|
||||
# 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
|
||||
pos = vector(-control_gap,
|
||||
self.bank.row_decoder_inst.by() + 2*self.m3_width)
|
||||
self.bank.height-self.control_logic.width)
|
||||
self.add_control_logic(position=pos,
|
||||
rotate=90)
|
||||
|
||||
|
|
@ -930,7 +967,7 @@ class sram(design.design):
|
|||
def add_two_banks(self):
|
||||
# Placement of bank 0 (left)
|
||||
bank_position_0 = vector(self.bank.width,
|
||||
self.bank.height + 2*self.power_rail_pitch)
|
||||
self.bank.height)
|
||||
self.bank_inst=[self.add_bank(0, bank_position_0, -1, -1)]
|
||||
|
||||
# Placement of bank 1 (right)
|
||||
|
|
@ -943,7 +980,7 @@ class sram(design.design):
|
|||
|
||||
# Placement of bank 0 (upper left)
|
||||
bank_position_0 = vector(self.bank.width,
|
||||
self.bank.height + self.data_bus_height + 2*self.bank_to_bus_distance + 2*self.power_rail_pitch)
|
||||
self.bank.height + self.data_bus_height + 2*self.bank_to_bus_distance)
|
||||
self.bank_inst=[self.add_bank(0, bank_position_0, 1, -1)]
|
||||
|
||||
# Placement of bank 1 (upper right)
|
||||
|
|
@ -952,7 +989,7 @@ class sram(design.design):
|
|||
self.bank_inst.append(self.add_bank(1, bank_position_1, 1, 1))
|
||||
|
||||
# Placement of bank 2 (bottom left)
|
||||
y_off = self.bank.height + 2*self.power_rail_pitch
|
||||
y_off = self.bank.height
|
||||
bank_position_2 = vector(bank_position_0.x, y_off)
|
||||
self.bank_inst.append(self.add_bank(2, bank_position_2, -1, -1))
|
||||
|
||||
|
|
@ -983,19 +1020,33 @@ 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
|
||||
|
||||
|
||||
src_pins = self.control_logic_inst.get_pins("vdd")
|
||||
for src_pin in src_pins:
|
||||
if src_pin.layer != "metal2":
|
||||
continue
|
||||
dest_pin = self.bank_inst.get_pins("vdd")[1]
|
||||
self.connect_rail_from_left_m2m1(src_pin,dest_pin)
|
||||
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
|
||||
dest_pin = self.bank_inst.get_pin("gnd")
|
||||
self.connect_rail_from_left_m2m3(src_pin,dest_pin)
|
||||
self.add_path("metal2", [src_pin.rc(), vector(leftmost_gnd_rail.cx(), src_pin.cy())])
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue