mirror of https://github.com/VLSIDA/OpenRAM.git
Add col addr routing and data routing
This commit is contained in:
parent
0665d51249
commit
7a69fc1bca
|
|
@ -25,7 +25,7 @@ class bank(design.design):
|
||||||
mod_list = ["tri_gate", "bitcell", "decoder", "ms_flop_array", "wordline_driver",
|
mod_list = ["tri_gate", "bitcell", "decoder", "ms_flop_array", "wordline_driver",
|
||||||
"bitcell_array", "sense_amp_array", "precharge_array",
|
"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"]
|
"dff", "bank_select"]
|
||||||
from importlib import reload
|
from importlib import reload
|
||||||
for mod_name in mod_list:
|
for mod_name in mod_list:
|
||||||
config_mod_name = getattr(OPTS, mod_name)
|
config_mod_name = getattr(OPTS, mod_name)
|
||||||
|
|
@ -379,8 +379,8 @@ class bank(design.design):
|
||||||
"""
|
"""
|
||||||
Create a 2:4 or 3:8 column address decoder.
|
Create a 2:4 or 3:8 column address decoder.
|
||||||
"""
|
"""
|
||||||
# Place the col decoder aligned left to row decoder
|
# Place the col decoder right aligned with row decoder
|
||||||
x_off = -(self.row_decoder.width + self.central_bus_width + self.wordline_driver.width)
|
x_off = -(self.central_bus_width + self.wordline_driver.width)
|
||||||
y_off = -(self.col_decoder.height + 2*drc["well_to_well"])
|
y_off = -(self.col_decoder.height + 2*drc["well_to_well"])
|
||||||
self.col_decoder_inst=self.add_inst(name="col_address_decoder",
|
self.col_decoder_inst=self.add_inst(name="col_address_decoder",
|
||||||
mod=self.col_decoder,
|
mod=self.col_decoder,
|
||||||
|
|
@ -402,7 +402,7 @@ class bank(design.design):
|
||||||
if self.col_addr_size == 0:
|
if self.col_addr_size == 0:
|
||||||
return
|
return
|
||||||
elif self.col_addr_size == 1:
|
elif self.col_addr_size == 1:
|
||||||
self.col_decoder = pinvbuf()
|
self.col_decoder = pinvbuf(height=self.mod_dff.height)
|
||||||
self.add_mod(self.col_decoder)
|
self.add_mod(self.col_decoder)
|
||||||
elif self.col_addr_size == 2:
|
elif self.col_addr_size == 2:
|
||||||
self.col_decoder = self.row_decoder.pre2_4
|
self.col_decoder = self.row_decoder.pre2_4
|
||||||
|
|
@ -536,7 +536,7 @@ class bank(design.design):
|
||||||
# The bank is at (0,0), so this is to the left of the y-axis.
|
# The bank is at (0,0), so this is to the left of the y-axis.
|
||||||
# 2 pitches on the right for vias/jogs to access the inputs
|
# 2 pitches on the right for vias/jogs to access the inputs
|
||||||
control_bus_offset = vector(-self.m2_pitch * self.num_control_lines - self.m2_width, 0)
|
control_bus_offset = vector(-self.m2_pitch * self.num_control_lines - self.m2_width, 0)
|
||||||
control_bus_length = self.max_y_offset - self.min_y_offset
|
control_bus_length = self.bitcell_array_inst.uy()
|
||||||
self.bus_xoffset = self.create_vertical_bus(layer="metal2",
|
self.bus_xoffset = self.create_vertical_bus(layer="metal2",
|
||||||
pitch=self.m2_pitch,
|
pitch=self.m2_pitch,
|
||||||
offset=control_bus_offset,
|
offset=control_bus_offset,
|
||||||
|
|
@ -622,7 +622,7 @@ class bank(design.design):
|
||||||
for i in range(self.word_size):
|
for i in range(self.word_size):
|
||||||
data_pin = self.sense_amp_array_inst.get_pin("data[{}]".format(i))
|
data_pin = self.sense_amp_array_inst.get_pin("data[{}]".format(i))
|
||||||
self.add_layout_pin_rect_center(text="DOUT[{}]".format(i),
|
self.add_layout_pin_rect_center(text="DOUT[{}]".format(i),
|
||||||
layer="metal2",
|
layer=data_pin.layer,
|
||||||
offset=data_pin.center(),
|
offset=data_pin.center(),
|
||||||
height=data_pin.height(),
|
height=data_pin.height(),
|
||||||
width=data_pin.width()),
|
width=data_pin.width()),
|
||||||
|
|
@ -632,7 +632,7 @@ class bank(design.design):
|
||||||
for i in range(self.word_size):
|
for i in range(self.word_size):
|
||||||
data_pin = self.tri_gate_array_inst.get_pin("out[{}]".format(i))
|
data_pin = self.tri_gate_array_inst.get_pin("out[{}]".format(i))
|
||||||
self.add_layout_pin_rect_center(text="DOUT[{}]".format(i),
|
self.add_layout_pin_rect_center(text="DOUT[{}]".format(i),
|
||||||
layer="metal2",
|
layer=data_pin.layer,
|
||||||
offset=data_pin.center(),
|
offset=data_pin.center(),
|
||||||
height=data_pin.height(),
|
height=data_pin.height(),
|
||||||
width=data_pin.width()),
|
width=data_pin.width()),
|
||||||
|
|
|
||||||
|
|
@ -38,15 +38,22 @@ class sram_1bank(sram_base):
|
||||||
control_pos.y + self.control_logic.height + self.m1_pitch)
|
control_pos.y + self.control_logic.height + self.m1_pitch)
|
||||||
self.add_row_addr_dff(row_addr_pos)
|
self.add_row_addr_dff(row_addr_pos)
|
||||||
|
|
||||||
|
data_gap = -self.m2_pitch*(self.word_size+1)
|
||||||
|
|
||||||
# Add the column address below the bank under the control
|
# Add the column address below the bank under the control
|
||||||
|
# Keep it aligned with the data flops
|
||||||
if self.col_addr_dff:
|
if self.col_addr_dff:
|
||||||
col_addr_pos = vector(-self.col_addr_dff.width, -1.5*self.col_addr_dff.height)
|
col_addr_pos = vector(self.bank.bank_center.x - self.col_addr_dff.width - self.bank.central_bus_width,
|
||||||
|
data_gap - self.col_addr_dff.height)
|
||||||
self.add_col_addr_dff(col_addr_pos)
|
self.add_col_addr_dff(col_addr_pos)
|
||||||
|
|
||||||
# Add the data flops below the bank
|
# Add the data flops below the bank
|
||||||
# This relies on the center point of the bank:
|
# This relies on the center point of the bank:
|
||||||
# decoder in upper left, bank in upper right, sensing in lower right
|
# decoder in upper left, bank in upper right, sensing in lower right.
|
||||||
data_pos = vector(self.bank.bank_center.x, -1.5*self.data_dff.height)
|
# These flops go below the sensing and leave a gap to channel route to the
|
||||||
|
# sense amps.
|
||||||
|
data_pos = vector(self.bank.bank_center.x,
|
||||||
|
data_gap - self.data_dff.height)
|
||||||
self.add_data_dff(data_pos)
|
self.add_data_dff(data_pos)
|
||||||
|
|
||||||
# two supply rails are already included in the bank, so just 2 here.
|
# two supply rails are already included in the bank, so just 2 here.
|
||||||
|
|
@ -78,8 +85,48 @@ class sram_1bank(sram_base):
|
||||||
""" Route a single bank SRAM """
|
""" Route a single bank SRAM """
|
||||||
|
|
||||||
self.add_layout_pins()
|
self.add_layout_pins()
|
||||||
|
|
||||||
|
self.route_vdd_gnd()
|
||||||
|
|
||||||
|
self.route_clk()
|
||||||
|
|
||||||
# Route the outputs from the control logic module
|
self.route_control_logic()
|
||||||
|
|
||||||
|
self.route_row_addr_dff()
|
||||||
|
|
||||||
|
if self.col_addr_dff:
|
||||||
|
self.route_col_addr_dff()
|
||||||
|
|
||||||
|
self.route_data_dff()
|
||||||
|
|
||||||
|
def route_clk(self):
|
||||||
|
""" Route the clock network """
|
||||||
|
debug.warning("Clock is top-level must connect.")
|
||||||
|
# For now, just have four clock pins for the address (x2), data, and control
|
||||||
|
if self.col_addr_dff:
|
||||||
|
self.copy_layout_pin(self.col_addr_dff_inst, "clk")
|
||||||
|
self.copy_layout_pin(self.row_addr_dff_inst, "clk")
|
||||||
|
self.copy_layout_pin(self.data_dff_inst, "clk")
|
||||||
|
self.copy_layout_pin(self.control_logic_inst, "clk")
|
||||||
|
|
||||||
|
def route_vdd_gnd(self):
|
||||||
|
""" Propagate all vdd/gnd pins up to this level for all modules """
|
||||||
|
|
||||||
|
# These are the instances that every bank has
|
||||||
|
top_instances = [self.bank_inst,
|
||||||
|
self.row_addr_dff_inst,
|
||||||
|
self.data_dff_inst,
|
||||||
|
self.control_logic_inst]
|
||||||
|
if self.col_addr_dff:
|
||||||
|
top_instances.append(self.col_addr_dff_inst)
|
||||||
|
|
||||||
|
|
||||||
|
for inst in top_instances:
|
||||||
|
self.copy_layout_pin(inst, "vdd")
|
||||||
|
self.copy_layout_pin(inst, "gnd")
|
||||||
|
|
||||||
|
def route_control_logic(self):
|
||||||
|
""" Route the outputs from the control logic module """
|
||||||
for n in self.control_logic_outputs:
|
for n in self.control_logic_outputs:
|
||||||
src_pin = self.control_logic_inst.get_pin(n)
|
src_pin = self.control_logic_inst.get_pin(n)
|
||||||
dest_pin = self.bank_inst.get_pin(n)
|
dest_pin = self.bank_inst.get_pin(n)
|
||||||
|
|
@ -89,7 +136,8 @@ class sram_1bank(sram_base):
|
||||||
rotate=90)
|
rotate=90)
|
||||||
|
|
||||||
|
|
||||||
# Connect the output of the row flops to the bank pins
|
def route_row_addr_dff(self):
|
||||||
|
""" Connect the output of the row flops to the bank pins """
|
||||||
for i in range(self.row_addr_size):
|
for i in range(self.row_addr_size):
|
||||||
flop_name = "dout[{}]".format(i)
|
flop_name = "dout[{}]".format(i)
|
||||||
bank_name = "A[{}]".format(i+self.col_addr_size)
|
bank_name = "A[{}]".format(i+self.col_addr_size)
|
||||||
|
|
@ -103,44 +151,44 @@ class sram_1bank(sram_base):
|
||||||
offset=flop_pos,
|
offset=flop_pos,
|
||||||
rotate=90)
|
rotate=90)
|
||||||
|
|
||||||
# Connect the output of the row flops to the bank pins
|
def route_col_addr_dff(self):
|
||||||
for i in range(self.col_addr_size):
|
""" Connect the output of the row flops to the bank pins """
|
||||||
flop_name = "dout[{}]".format(i)
|
|
||||||
bank_name = "A[{}]".format(i)
|
|
||||||
flop_pin = self.col_addr_dff_inst.get_pin(flop_name)
|
|
||||||
bank_pin = self.bank_inst.get_pin(bank_name)
|
|
||||||
flop_pos = flop_pin.center()
|
|
||||||
bank_pos = bank_pin.center()
|
|
||||||
self.add_path("metal3",[flop_pos, bank_pos])
|
|
||||||
self.add_via_center(layers=("metal2","via2","metal3"),
|
|
||||||
offset=flop_pos,
|
|
||||||
rotate=90)
|
|
||||||
self.add_via_center(layers=("metal2","via2","metal3"),
|
|
||||||
offset=bank_pos,
|
|
||||||
rotate=90)
|
|
||||||
|
|
||||||
# Connect the output of the row flops to the bank pins
|
bus_names = ["A[{}]".format(x) for x in range(self.word_size)]
|
||||||
for i in range(self.word_size):
|
col_addr_bus_offsets = self.create_horizontal_bus(layer="metal1",
|
||||||
flop_name = "dout[{}]".format(i)
|
pitch=self.m1_pitch,
|
||||||
bank_name = "BANK_DIN[{}]".format(i)
|
offset=self.col_addr_dff_inst.ul() + vector(0, self.m1_pitch),
|
||||||
flop_pin = self.data_dff_inst.get_pin(flop_name)
|
names=bus_names,
|
||||||
bank_pin = self.bank_inst.get_pin(bank_name)
|
length=self.col_addr_dff_inst.width)
|
||||||
flop_pos = flop_pin.center()
|
|
||||||
bank_pos = bank_pin.center()
|
dff_names = ["dout[{}]".format(x) for x in range(self.col_addr_size)]
|
||||||
mid_pos = vector(bank_pos.x,flop_pos.y)
|
data_dff_map = zip(dff_names, bus_names)
|
||||||
self.add_wire(("metal3","via2","metal2"),[flop_pos, mid_pos,bank_pos])
|
self.connect_horizontal_bus(data_dff_map, self.col_addr_dff_inst, col_addr_bus_offsets)
|
||||||
self.add_via_center(layers=("metal2","via2","metal3"),
|
|
||||||
offset=flop_pos,
|
bank_names = ["A[{}]".format(x) for x in range(self.col_addr_size)]
|
||||||
rotate=90)
|
data_bank_map = zip(bank_names, bus_names)
|
||||||
|
self.connect_horizontal_bus(data_bank_map, self.bank_inst, col_addr_bus_offsets)
|
||||||
|
|
||||||
|
|
||||||
|
def route_data_dff(self):
|
||||||
|
""" Connect the output of the data flops to the write driver """
|
||||||
|
# Create a horizontal bus
|
||||||
|
bus_names = ["data[{}]".format(x) for x in range(self.word_size)]
|
||||||
|
data_bus_offsets = self.create_horizontal_bus(layer="metal1",
|
||||||
|
pitch=self.m1_pitch,
|
||||||
|
offset=self.data_dff_inst.ul() + vector(0, self.m1_pitch),
|
||||||
|
names=bus_names,
|
||||||
|
length=self.data_dff_inst.width)
|
||||||
|
|
||||||
|
|
||||||
|
dff_names = ["dout[{}]".format(x) for x in range(self.word_size)]
|
||||||
|
data_dff_map = zip(dff_names, bus_names)
|
||||||
|
self.connect_horizontal_bus(data_dff_map, self.data_dff_inst, data_bus_offsets)
|
||||||
|
|
||||||
|
bank_names = ["BANK_DIN[{}]".format(x) for x in range(self.word_size)]
|
||||||
|
data_bank_map = zip(bank_names, bus_names)
|
||||||
|
self.connect_horizontal_bus(data_bank_map, self.bank_inst, data_bus_offsets)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# # Connect the clock between the flops and control module
|
|
||||||
# flop_pin = self.addr_dff_inst.get_pin("clk")
|
|
||||||
# ctrl_pin = self.control_logic_inst.get_pin("clk_buf")
|
|
||||||
# flop_pos = flop_pin.uc()
|
|
||||||
# ctrl_pos = ctrl_pin.bc()
|
|
||||||
# mid_ypos = 0.5*(ctrl_pos.y+flop_pos.y)
|
|
||||||
# mid1_pos = vector(flop_pos.x, mid_ypos)
|
|
||||||
# mid2_pos = vector(ctrl_pos.x, mid_ypos)
|
|
||||||
# self.add_wire(("metal1","via1","metal2"),[flop_pin.uc(), mid1_pos, mid2_pos, ctrl_pin.bc()])
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue