mirror of https://github.com/VLSIDA/OpenRAM.git
Single banks working with new RBL
This commit is contained in:
parent
b841fd7ce3
commit
0b13225913
|
|
@ -62,12 +62,14 @@ class bitcell(design.design):
|
|||
column_pins = ["br"]
|
||||
return column_pins
|
||||
|
||||
def get_bl_name(self):
|
||||
def get_bl_name(self, port=0):
|
||||
"""Get bl name"""
|
||||
debug.check(port==0,"One port for bitcell only.")
|
||||
return "bl"
|
||||
|
||||
def get_br_name(self):
|
||||
def get_br_name(self, port=0):
|
||||
"""Get bl name"""
|
||||
debug.check(port==0,"One port for bitcell only.")
|
||||
return "br"
|
||||
|
||||
def analytical_power(self, corner, load):
|
||||
|
|
@ -96,4 +98,4 @@ class bitcell(design.design):
|
|||
|
||||
def build_graph(self, graph, inst_name, port_nets):
|
||||
"""Adds edges based on inputs/outputs. Overrides base class function."""
|
||||
self.add_graph_edges(graph, port_nets)
|
||||
self.add_graph_edges(graph, port_nets)
|
||||
|
|
|
|||
|
|
@ -97,10 +97,12 @@ class bitcell_1rw_1r(design.design):
|
|||
|
||||
def get_bl_name(self, port=0):
|
||||
"""Get bl name by port"""
|
||||
debug.check(port<2,"Two ports for bitcell_1rw_1r only.")
|
||||
return "bl{}".format(port)
|
||||
|
||||
def get_br_name(self, port=0):
|
||||
"""Get bl name by port"""
|
||||
debug.check(port<2,"Two ports for bitcell_1rw_1r only.")
|
||||
return "br{}".format(port)
|
||||
|
||||
def analytical_power(self, corner, load):
|
||||
|
|
|
|||
|
|
@ -26,17 +26,18 @@ class bank(design.design):
|
|||
This can create up to two ports in any combination: rw, w, r.
|
||||
"""
|
||||
|
||||
def __init__(self, sram_config, num_ports, name=""):
|
||||
def __init__(self, sram_config, name=""):
|
||||
|
||||
self.sram_config = sram_config
|
||||
sram_config.set_local_config(self)
|
||||
self.num_ports = num_ports
|
||||
|
||||
if name == "":
|
||||
name = "bank_{0}_{1}".format(self.word_size, self.num_words)
|
||||
design.design.__init__(self, name)
|
||||
debug.info(2, "create sram of size {0} with {1} words".format(self.word_size,self.num_words))
|
||||
|
||||
debug.check(len(self.all_ports)<=2,"Bank layout cannot handle more than two ports.")
|
||||
|
||||
# The local control signals are gated when we have bank select logic,
|
||||
# so this prefix will be added to all of the input signals to create
|
||||
# the internal gated signals.
|
||||
|
|
@ -47,7 +48,6 @@ class bank(design.design):
|
|||
|
||||
self.create_netlist()
|
||||
if not OPTS.netlist_only:
|
||||
debug.check(len(self.all_ports)<=2,"Bank layout cannot handle more than two ports.")
|
||||
self.create_layout()
|
||||
self.add_boundary()
|
||||
|
||||
|
|
@ -155,11 +155,11 @@ class bank(design.design):
|
|||
self.bitcell_array_right = self.bitcell_array.width + self.m1_width + self.m2_gap
|
||||
|
||||
# These are the offsets of the main array (excluding dummy and replica rows/cols)
|
||||
self.main_bitcell_array_top = self.bitcell_array_top - (self.num_ports*self.bitcell.height)
|
||||
self.main_bitcell_array_top = self.bitcell_array.bitcell_array_inst.uy()
|
||||
# Just past the dummy column
|
||||
self.main_bitcell_array_left = self.bitcell.width
|
||||
self.main_bitcell_array_left = self.bitcell_array.bitcell_array_inst.lx()
|
||||
# Just past the dummy row and replica row
|
||||
self.main_bitcell_array_bottom = 2*self.bitcell.height
|
||||
self.main_bitcell_array_bottom = self.bitcell_array.bitcell_array_inst.by()
|
||||
|
||||
self.compute_instance_port0_offsets()
|
||||
if len(self.all_ports)==2:
|
||||
|
|
@ -179,7 +179,10 @@ class bank(design.design):
|
|||
|
||||
# LOWER RIGHT QUADRANT
|
||||
# Below the bitcell array
|
||||
self.port_data_offsets[port] = vector(self.main_bitcell_array_left,0)
|
||||
if self.port_data[port].has_rbl():
|
||||
self.port_data_offsets[port] = vector(self.main_bitcell_array_left - self.bitcell_array.cell.width,0)
|
||||
else:
|
||||
self.port_data_offsets[port] = vector(self.main_bitcell_array_left,0)
|
||||
|
||||
# UPPER LEFT QUADRANT
|
||||
# To the left of the bitcell array
|
||||
|
|
@ -219,12 +222,12 @@ class bank(design.design):
|
|||
|
||||
# UPPER LEFT QUADRANT
|
||||
# Above the bitcell array
|
||||
self.port_data_offsets[port] = vector(0,self.bitcell_array_top)
|
||||
self.port_data_offsets[port] = vector(self.main_bitcell_array_left, self.bitcell_array_top)
|
||||
|
||||
# LOWER RIGHT QUADRANT
|
||||
# To the left of the bitcell array
|
||||
x_offset = self.bitcell_array_right + self.port_address.width + self.m2_gap
|
||||
self.port_address_offsets[port] = vector(x_offset,self.main_bitcell_array_top)
|
||||
self.port_address_offsets[port] = vector(x_offset,self.main_bitcell_array_bottom)
|
||||
|
||||
# UPPER RIGHT QUADRANT
|
||||
# Place the col decoder right aligned with wordline driver
|
||||
|
|
@ -322,12 +325,6 @@ class bank(design.design):
|
|||
self.br_names = self.bitcell.list_all_br_names()
|
||||
self.wl_names = self.bitcell.list_all_wl_names()
|
||||
self.bitline_names = self.bitcell.list_all_bitline_names()
|
||||
|
||||
self.bitcell_array = factory.create(module_type="replica_bitcell_array",
|
||||
cols=self.num_cols,
|
||||
rows=self.num_rows,
|
||||
num_ports=self.num_ports)
|
||||
self.add_mod(self.bitcell_array)
|
||||
|
||||
self.port_data = []
|
||||
for port in self.all_ports:
|
||||
|
|
@ -342,7 +339,32 @@ class bank(design.design):
|
|||
cols=self.num_cols,
|
||||
rows=self.num_rows)
|
||||
self.add_mod(self.port_address)
|
||||
|
||||
|
||||
|
||||
# The number of replica lines depends on the port configuration
|
||||
rbl_num = [self.read_ports.count(p) for p in self.all_ports]
|
||||
if len(rbl_num)<2:
|
||||
rbl_num.append(0)
|
||||
self.num_rbl = sum(rbl_num)
|
||||
# The indices always start at 0
|
||||
self.rbl_indices = []
|
||||
index = 0
|
||||
for num in rbl_num:
|
||||
if num>0:
|
||||
self.rbl_indices.append(index)
|
||||
index += 1
|
||||
else:
|
||||
self.rbl_indices.append(-1)
|
||||
|
||||
|
||||
self.bitcell_array = factory.create(module_type="replica_bitcell_array",
|
||||
cols=self.num_cols,
|
||||
rows=self.num_rows,
|
||||
left_rbl=rbl_num[0],
|
||||
right_rbl=rbl_num[1])
|
||||
self.add_mod(self.bitcell_array)
|
||||
|
||||
|
||||
if(self.num_banks > 1):
|
||||
self.bank_select = factory.create(module_type="bank_select")
|
||||
self.add_mod(self.bank_select)
|
||||
|
|
@ -357,15 +379,16 @@ class bank(design.design):
|
|||
temp = []
|
||||
for col in range(self.num_cols):
|
||||
for bitline in self.bitline_names:
|
||||
temp.append(bitline+"_{0}".format(col))
|
||||
for col in range(self.num_ports):
|
||||
temp.append("{0}_{1}".format(bitline,col))
|
||||
for rbl in range(self.num_rbl):
|
||||
for bitline in self.bitline_names:
|
||||
temp.append("replica_"+bitline+"_{0}".format(col))
|
||||
temp.append("rbl_{0}_{1}".format(bitline,rbl))
|
||||
for row in range(self.num_rows):
|
||||
for wordline in self.wl_names:
|
||||
temp.append(wordline+"_{0}".format(row))
|
||||
for wordline in self.wl_names:
|
||||
temp.append("replica_"+wordline)
|
||||
temp.append("{0}_{1}".format(wordline,row))
|
||||
for rbl in range(self.num_rbl):
|
||||
for wordline in self.wl_names:
|
||||
temp.append("rbl_{0}_{1}".format(wordline,rbl))
|
||||
temp.append("vdd")
|
||||
temp.append("gnd")
|
||||
self.connect_inst(temp)
|
||||
|
|
@ -385,9 +408,9 @@ class bank(design.design):
|
|||
mod=self.port_data[port])
|
||||
|
||||
temp = []
|
||||
if port in self.read_ports:
|
||||
temp.append("rbl_{0}".format(self.bl_names[port]))
|
||||
temp.append("rbl_{0}".format(self.br_names[port]))
|
||||
if self.port_data[port].has_rbl():
|
||||
temp.append("rbl_{0}_{1}".format(self.bl_names[port],self.rbl_indices[port]))
|
||||
temp.append("rbl_{0}_{1}".format(self.br_names[port],self.rbl_indices[port]))
|
||||
for col in range(self.num_cols):
|
||||
temp.append("{0}_{1}".format(self.bl_names[port],col))
|
||||
temp.append("{0}_{1}".format(self.br_names[port],col))
|
||||
|
|
@ -435,7 +458,7 @@ class bank(design.design):
|
|||
temp.append("addr{0}_{1}".format(port,bit+self.col_addr_size))
|
||||
temp.append("wl_en{0}".format(port))
|
||||
for row in range(self.num_rows):
|
||||
temp.append(self.wl_names[port]+"_{0}".format(row))
|
||||
temp.append("{0}_{1}".format(self.wl_names[port],row))
|
||||
temp.extend(["vdd", "gnd"])
|
||||
self.connect_inst(temp)
|
||||
|
||||
|
|
@ -452,7 +475,7 @@ class bank(design.design):
|
|||
# The address flop and decoder are aligned in the x coord.
|
||||
|
||||
for port in self.all_ports:
|
||||
if port%2 == 1:
|
||||
if port%2:
|
||||
mirror = "MY"
|
||||
else:
|
||||
mirror = "R0"
|
||||
|
|
@ -612,7 +635,7 @@ class bank(design.design):
|
|||
# 2 pitches on the right for vias/jogs to access the inputs
|
||||
control_bus_offset = vector(-self.m2_pitch * self.num_control_lines[0] - self.m2_width, self.min_y_offset)
|
||||
# The control bus is routed up to two pitches below the bitcell array
|
||||
control_bus_length = -2*self.m1_pitch - self.min_y_offset
|
||||
control_bus_length = self.main_bitcell_array_bottom - self.min_y_offset - 2*self.m1_pitch
|
||||
self.bus_xoffset[0] = self.create_bus(layer="metal2",
|
||||
pitch=self.m2_pitch,
|
||||
offset=control_bus_offset,
|
||||
|
|
@ -624,7 +647,7 @@ class bank(design.design):
|
|||
# Port 1
|
||||
if len(self.all_ports)==2:
|
||||
# The other control bus is routed up to two pitches above the bitcell array
|
||||
control_bus_length = self.max_y_offset - self.bitcell_array_top - 2*self.m1_pitch
|
||||
control_bus_length = self.max_y_offset - self.main_bitcell_array_top - 2*self.m1_pitch
|
||||
control_bus_offset = vector(self.bitcell_array_right,
|
||||
self.max_y_offset - control_bus_length)
|
||||
|
||||
|
|
@ -640,12 +663,20 @@ class bank(design.design):
|
|||
def route_port_data_to_bitcell_array(self, port):
|
||||
""" Routing of BL and BR between port data and bitcell array """
|
||||
|
||||
# Connect the regular bitlines
|
||||
inst2 = self.port_data_inst[port]
|
||||
inst1 = self.bitcell_array_inst
|
||||
inst1_bl_name = self.bl_names[port]+"_{}"
|
||||
inst1_br_name = self.br_names[port]+"_{}"
|
||||
|
||||
self.connect_bitlines(inst1=inst1, inst2=inst2, num_bits=self.num_cols,
|
||||
inst1_bl_name=inst1_bl_name, inst1_br_name=inst1_br_name)
|
||||
|
||||
# Connect the replica bitlines
|
||||
if self.port_data[port].has_rbl():
|
||||
self.connect_bitline(inst1, inst2, "rbl_{0}_{1}".format(self.bitcell.get_bl_name(port),self.rbl_indices[port]), "rbl_bl")
|
||||
self.connect_bitline(inst1, inst2, "rbl_{0}_{1}".format(self.bitcell.get_br_name(port),self.rbl_indices[port]), "rbl_br")
|
||||
|
||||
|
||||
|
||||
def route_port_data_out(self, port):
|
||||
|
|
@ -705,12 +736,9 @@ class bank(design.design):
|
|||
route_map = list(zip(bottom_names, top_names))
|
||||
self.create_horizontal_channel_route(route_map, offset)
|
||||
|
||||
|
||||
def connect_bitlines(self, inst1, inst2, num_bits,
|
||||
inst1_bl_name="bl_{}", inst1_br_name="br_{}",
|
||||
inst2_bl_name="bl_{}", inst2_br_name="br_{}"):
|
||||
def connect_bitline(self, inst1, inst2, inst1_name, inst2_name):
|
||||
"""
|
||||
Connect the bl and br of two modules.
|
||||
Connect two pins of two modules.
|
||||
This assumes that they have sufficient space to create a jog
|
||||
in the middle between the two modules (if needed).
|
||||
"""
|
||||
|
|
@ -718,23 +746,34 @@ class bank(design.design):
|
|||
# determine top and bottom automatically.
|
||||
# since they don't overlap, we can just check the bottom y coordinate.
|
||||
if inst1.by() < inst2.by():
|
||||
(bottom_inst, bottom_bl_name, bottom_br_name) = (inst1, inst1_bl_name, inst1_br_name)
|
||||
(top_inst, top_bl_name, top_br_name) = (inst2, inst2_bl_name, inst2_br_name)
|
||||
(bottom_inst, bottom_name) = (inst1, inst1_name)
|
||||
(top_inst, top_name) = (inst2, inst2_name)
|
||||
else:
|
||||
(bottom_inst, bottom_bl_name, bottom_br_name) = (inst2, inst2_bl_name, inst2_br_name)
|
||||
(top_inst, top_bl_name, top_br_name) = (inst1, inst1_bl_name, inst1_br_name)
|
||||
(bottom_inst, bottom_name) = (inst2, inst2_name)
|
||||
(top_inst, top_name) = (inst1, inst1_name)
|
||||
|
||||
bottom_pin = bottom_inst.get_pin(bottom_name)
|
||||
top_pin = top_inst.get_pin(top_name)
|
||||
debug.check(bottom_pin.layer == top_pin.layer, "Pin layers do not match.")
|
||||
|
||||
bottom_loc = bottom_pin.uc()
|
||||
top_loc = top_pin.bc()
|
||||
|
||||
yoffset = 0.5*(top_loc.y+bottom_loc.y)
|
||||
self.add_path(top_pin.layer,[bottom_loc, vector(bottom_loc.x,yoffset),
|
||||
vector(top_loc.x,yoffset), top_loc])
|
||||
|
||||
|
||||
def connect_bitlines(self, inst1, inst2, num_bits,
|
||||
inst1_bl_name="bl_{}", inst1_br_name="br_{}",
|
||||
inst2_bl_name="bl_{}", inst2_br_name="br_{}"):
|
||||
"""
|
||||
Connect the bl and br of two modules.
|
||||
"""
|
||||
|
||||
for col in range(num_bits):
|
||||
bottom_bl = bottom_inst.get_pin(bottom_bl_name.format(col)).uc()
|
||||
bottom_br = bottom_inst.get_pin(bottom_br_name.format(col)).uc()
|
||||
top_bl = top_inst.get_pin(top_bl_name.format(col)).bc()
|
||||
top_br = top_inst.get_pin(top_br_name.format(col)).bc()
|
||||
|
||||
yoffset = 0.5*(top_bl.y+bottom_bl.y)
|
||||
self.add_path("metal2",[bottom_bl, vector(bottom_bl.x,yoffset),
|
||||
vector(top_bl.x,yoffset), top_bl])
|
||||
self.add_path("metal2",[bottom_br, vector(bottom_br.x,yoffset),
|
||||
vector(top_br.x,yoffset), top_br])
|
||||
self.connect_bitline(inst1, inst2, inst1_bl_name.format(col), inst2_bl_name.format(col))
|
||||
self.connect_bitline(inst1, inst2, inst1_br_name.format(col), inst2_br_name.format(col))
|
||||
|
||||
|
||||
def route_port_address(self, port):
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ from globals import OPTS
|
|||
class port_data(design.design):
|
||||
"""
|
||||
Create the data port (column mux, sense amps, write driver, etc.) for the given port number.
|
||||
Port 0 always has the RBL on the left while port 1 is on the right.
|
||||
"""
|
||||
|
||||
def __init__(self, sram_config, port, name=""):
|
||||
|
|
@ -71,12 +72,12 @@ class port_data(design.design):
|
|||
|
||||
def add_pins(self):
|
||||
""" Adding pins for port address module"""
|
||||
if self.port in self.read_ports or self.col_addr_size>0:
|
||||
self.add_pin("rbl_"+self.bl_names[self.port],"INOUT")
|
||||
self.add_pin("rbl_"+self.br_names[self.port],"INOUT")
|
||||
if self.has_rbl():
|
||||
self.add_pin("rbl_bl","INOUT")
|
||||
self.add_pin("rbl_br","INOUT")
|
||||
for bit in range(self.num_cols):
|
||||
self.add_pin(self.bl_names[self.port]+"_{0}".format(bit),"INOUT")
|
||||
self.add_pin(self.br_names[self.port]+"_{0}".format(bit),"INOUT")
|
||||
self.add_pin("bl_{0}".format(bit),"INOUT")
|
||||
self.add_pin("br_{0}".format(bit),"INOUT")
|
||||
if self.port in self.read_ports:
|
||||
for bit in range(self.word_size):
|
||||
self.add_pin("dout_{}".format(bit),"OUTPUT")
|
||||
|
|
@ -124,9 +125,10 @@ class port_data(design.design):
|
|||
self.route_sense_amp_to_column_mux_or_precharge_array(self.port)
|
||||
self.route_column_mux_to_precharge_array(self.port)
|
||||
else:
|
||||
# write_driver -> (column_mux) -> bitcell_array
|
||||
# write_driver -> (column_mux -> precharge) -> bitcell_array
|
||||
self.route_write_driver_in(self.port)
|
||||
self.route_write_driver_to_column_mux_or_bitcell_array(self.port)
|
||||
self.route_write_driver_to_column_mux_or_bitcell_array(self.port)
|
||||
self.route_column_mux_to_precharge_array(self.port)
|
||||
|
||||
def route_supplies(self):
|
||||
""" Propagate all vdd/gnd pins up to this level for all modules """
|
||||
|
|
@ -213,11 +215,15 @@ class port_data(design.design):
|
|||
mod=self.precharge_array)
|
||||
|
||||
temp = []
|
||||
temp.append("rbl_"+self.bl_names[self.port])
|
||||
temp.append("rbl_"+self.br_names[self.port])
|
||||
if self.has_rbl() and self.port==0:
|
||||
temp.append("rbl_bl")
|
||||
temp.append("rbl_br")
|
||||
for bit in range(self.num_cols):
|
||||
temp.append(self.bl_names[self.port]+"_{0}".format(bit))
|
||||
temp.append(self.br_names[self.port]+"_{0}".format(bit))
|
||||
temp.append("bl_{0}".format(bit))
|
||||
temp.append("br_{0}".format(bit))
|
||||
if self.has_rbl() and self.port==1:
|
||||
temp.append("rbl_bl")
|
||||
temp.append("rbl_br")
|
||||
temp.extend(["p_en_bar", "vdd"])
|
||||
self.connect_inst(temp)
|
||||
|
||||
|
|
@ -234,13 +240,13 @@ class port_data(design.design):
|
|||
|
||||
temp = []
|
||||
for col in range(self.num_cols):
|
||||
temp.append(self.bl_names[self.port]+"_{0}".format(col))
|
||||
temp.append(self.br_names[self.port]+"_{0}".format(col))
|
||||
temp.append("bl_{0}".format(col))
|
||||
temp.append("br_{0}".format(col))
|
||||
for word in range(self.words_per_row):
|
||||
temp.append("sel_{}".format(word))
|
||||
for bit in range(self.word_size):
|
||||
temp.append(self.bl_names[self.port]+"_out_{0}".format(bit))
|
||||
temp.append(self.br_names[self.port]+"_out_{0}".format(bit))
|
||||
temp.append("bl_out_{0}".format(bit))
|
||||
temp.append("br_out_{0}".format(bit))
|
||||
temp.append("gnd")
|
||||
self.connect_inst(temp)
|
||||
|
||||
|
|
@ -263,11 +269,11 @@ class port_data(design.design):
|
|||
for bit in range(self.word_size):
|
||||
temp.append("dout_{}".format(bit))
|
||||
if self.words_per_row == 1:
|
||||
temp.append(self.bl_names[self.port]+"_{0}".format(bit))
|
||||
temp.append(self.br_names[self.port]+"_{0}".format(bit))
|
||||
temp.append("bl_{0}".format(bit))
|
||||
temp.append("br_{0}".format(bit))
|
||||
else:
|
||||
temp.append(self.bl_names[self.port]+"_out_{0}".format(bit))
|
||||
temp.append(self.br_names[self.port]+"_out_{0}".format(bit))
|
||||
temp.append("bl_out_{0}".format(bit))
|
||||
temp.append("br_out_{0}".format(bit))
|
||||
|
||||
temp.extend(["s_en", "vdd", "gnd"])
|
||||
self.connect_inst(temp)
|
||||
|
|
@ -288,11 +294,11 @@ class port_data(design.design):
|
|||
temp.append("din_{}".format(bit))
|
||||
for bit in range(self.word_size):
|
||||
if (self.words_per_row == 1):
|
||||
temp.append(self.bl_names[self.port]+"_{0}".format(bit))
|
||||
temp.append(self.br_names[self.port]+"_{0}".format(bit))
|
||||
temp.append("bl_{0}".format(bit))
|
||||
temp.append("br_{0}".format(bit))
|
||||
else:
|
||||
temp.append(self.bl_names[self.port]+"_out_{0}".format(bit))
|
||||
temp.append(self.br_names[self.port]+"_out_{0}".format(bit))
|
||||
temp.append("bl_out_{0}".format(bit))
|
||||
temp.append("br_out_{0}".format(bit))
|
||||
temp.extend(["w_en", "vdd", "gnd"])
|
||||
self.connect_inst(temp)
|
||||
|
||||
|
|
@ -314,7 +320,7 @@ class port_data(design.design):
|
|||
vertical_port_order.append(self.write_driver_array_inst)
|
||||
|
||||
# Add one column for the the RBL
|
||||
if self.port in self.read_ports:
|
||||
if self.has_rbl() and self.port==0:
|
||||
x_offset = self.bitcell.width
|
||||
else:
|
||||
x_offset = 0
|
||||
|
|
@ -334,8 +340,10 @@ class port_data(design.design):
|
|||
self.sense_amp_offset = vertical_port_offsets[2]
|
||||
self.column_mux_offset = vertical_port_offsets[1]
|
||||
self.precharge_offset = vertical_port_offsets[0]
|
||||
if self.precharge_offset:
|
||||
self.precharge_offset -= vector(x_offset,0)
|
||||
# Shift the precharge left if port 0
|
||||
if self.precharge_offset and self.port==0:
|
||||
self.precharge_offset -= vector(x_offset,0)
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -382,8 +390,11 @@ class port_data(design.design):
|
|||
|
||||
inst1 = self.column_mux_array_inst
|
||||
inst2 = self.precharge_array_inst
|
||||
self.connect_bitlines(inst1, inst2, self.num_cols, inst2_start_bit=1)
|
||||
|
||||
if self.has_rbl() and self.port==0:
|
||||
self.connect_bitlines(inst1, inst2, self.num_cols, inst2_start_bit=1)
|
||||
else:
|
||||
self.connect_bitlines(inst1, inst2, self.num_cols)
|
||||
|
||||
|
||||
|
||||
def route_sense_amp_to_column_mux_or_precharge_array(self, port):
|
||||
|
|
@ -401,7 +412,10 @@ class port_data(design.design):
|
|||
inst1 = self.precharge_array_inst
|
||||
inst1_bl_name = "bl_{}"
|
||||
inst1_br_name = "br_{}"
|
||||
start_bit=1
|
||||
if self.has_rbl() and self.port==0:
|
||||
start_bit=1
|
||||
else:
|
||||
start_bit=0
|
||||
|
||||
|
||||
self.channel_route_bitlines(inst1=inst1, inst2=inst2, num_bits=self.word_size,
|
||||
|
|
@ -437,17 +451,25 @@ class port_data(design.design):
|
|||
def route_bitline_pins(self):
|
||||
""" Add the bitline pins for the given port """
|
||||
|
||||
if self.port in self.read_ports:
|
||||
if self.has_rbl() and self.port==0:
|
||||
self.copy_layout_pin(self.precharge_array_inst, "bl_0", "rbl_bl")
|
||||
self.copy_layout_pin(self.precharge_array_inst, "br_0", "rbl_br")
|
||||
bit_offset=1
|
||||
elif self.has_rbl() and self.port==1:
|
||||
self.copy_layout_pin(self.precharge_array_inst, "bl_{}".format(self.num_cols), "rbl_bl")
|
||||
self.copy_layout_pin(self.precharge_array_inst, "br_{}".format(self.num_cols), "rbl_br")
|
||||
bit_offset=0
|
||||
else:
|
||||
bit_offset=0
|
||||
|
||||
|
||||
for bit in range(self.num_cols):
|
||||
if self.port in self.read_ports:
|
||||
self.copy_layout_pin(self.precharge_array_inst, "bl_{}".format(bit+1), "bl_{}".format(bit))
|
||||
self.copy_layout_pin(self.precharge_array_inst, "br_{}".format(bit+1), "br_{}".format(bit))
|
||||
elif self.column_mux_array_inst:
|
||||
self.copy_layout_pin(self.column_mux_array_inst, "bl_{}".format(bit))
|
||||
self.copy_layout_pin(self.column_mux_array_inst, "br_{}".format(bit))
|
||||
if self.precharge_array_inst:
|
||||
self.copy_layout_pin(self.precharge_array_inst, "bl_{}".format(bit+bit_offset), "bl_{}".format(bit))
|
||||
self.copy_layout_pin(self.precharge_array_inst, "br_{}".format(bit+bit_offset), "br_{}".format(bit))
|
||||
# elif self.column_mux_array_inst:
|
||||
# self.copy_layout_pin(self.column_mux_array_inst, "bl_{}".format(bit))
|
||||
# self.copy_layout_pin(self.column_mux_array_inst, "br_{}".format(bit))
|
||||
else:
|
||||
self.copy_layout_pin(self.write_driver_array_inst, "bl_{}".format(bit))
|
||||
self.copy_layout_pin(self.write_driver_array_inst, "br_{}".format(bit))
|
||||
|
|
@ -528,3 +550,6 @@ class port_data(design.design):
|
|||
"""Precharge adds a loop between bitlines, can be excluded to reduce complexity"""
|
||||
if self.precharge_array_inst:
|
||||
self.graph_inst_exclude.add(self.precharge_array_inst)
|
||||
|
||||
def has_rbl(self):
|
||||
return self.port in self.read_ports
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ class replica_bitcell_array(design.design):
|
|||
self.bl_names = [x for x in self.bitcell_array.pins if x.startswith("b")]
|
||||
|
||||
# These are the non-indexed names
|
||||
self.replica_cell_wl_names = ["replica_"+x for x in self.cell.list_all_wl_names()]
|
||||
self.replica_cell_wl_names = ["rbl_"+x for x in self.cell.list_all_wl_names()]
|
||||
self.dummy_cell_wl_names = ["dummy_"+x for x in self.cell.list_all_wl_names()]
|
||||
self.dummy_cell_bl_names = ["dummy_"+x for x in self.cell.list_all_bitline_names()]
|
||||
self.dummy_row_bl_names = self.bl_names
|
||||
|
|
@ -136,12 +136,12 @@ class replica_bitcell_array(design.design):
|
|||
self.replica_col_wl_names.extend(["{0}_bot".format(x) for x in self.dummy_cell_wl_names])
|
||||
# Left port WLs (one dummy for each port when we allow >1 port)
|
||||
for bit in range(self.left_rbl):
|
||||
self.replica_col_wl_names.extend(["replica_{0}_{1}".format(x,bit) for x in self.cell.list_all_wl_names()])
|
||||
self.replica_col_wl_names.extend(["rbl_{0}_{1}".format(x,bit) for x in self.cell.list_all_wl_names()])
|
||||
# Regular WLs
|
||||
self.replica_col_wl_names.extend(self.wl_names)
|
||||
# Right port WLs (one dummy for each port when we allow >1 port)
|
||||
for bit in range(self.left_rbl,self.left_rbl+self.right_rbl):
|
||||
self.replica_col_wl_names.extend(["replica_{0}_{1}".format(x,bit) for x in self.cell.list_all_wl_names()])
|
||||
self.replica_col_wl_names.extend(["rbl_{0}_{1}".format(x,bit) for x in self.cell.list_all_wl_names()])
|
||||
self.replica_col_wl_names.extend(["{0}_top".format(x) for x in self.dummy_cell_wl_names])
|
||||
|
||||
# Left/right dummy columns are connected identically to the replica column
|
||||
|
|
@ -155,7 +155,7 @@ class replica_bitcell_array(design.design):
|
|||
self.replica_bl_names = []
|
||||
self.replica_wl_names = []
|
||||
for bit in range(self.left_rbl+self.right_rbl):
|
||||
self.replica_bl_names_list[bit] = ["replica_{0}_{1}".format(x,bit) for x in self.cell.list_all_bitline_names()]
|
||||
self.replica_bl_names_list[bit] = ["rbl_{0}_{1}".format(x,bit) for x in self.cell.list_all_bitline_names()]
|
||||
self.replica_bl_names.extend(self.replica_bl_names_list[bit])
|
||||
|
||||
self.replica_wl_names_list[bit] = ["{0}_{1}".format(x,bit) for x in self.replica_cell_wl_names]
|
||||
|
|
@ -320,7 +320,7 @@ class replica_bitcell_array(design.design):
|
|||
inst = self.replica_col_inst[bit]
|
||||
for (pin_name, bl_name) in zip(self.cell.list_all_bitline_names(),self.replica_bl_names_list[bit]):
|
||||
pin = inst.get_pin(pin_name)
|
||||
name = "replica_{0}_{1}".format(pin_name,bit)
|
||||
name = "rbl_{0}_{1}".format(pin_name,bit)
|
||||
self.add_layout_pin(text=name,
|
||||
layer=pin.layer,
|
||||
offset=pin.ll().scale(1,0),
|
||||
|
|
|
|||
|
|
@ -55,9 +55,9 @@ class port_data_test(openram_test):
|
|||
self.local_check(a)
|
||||
|
||||
OPTS.bitcell = "bitcell_1w_1r"
|
||||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_rw_ports = 0
|
||||
OPTS.num_r_ports = 1
|
||||
OPTS.num_w_ports = 0
|
||||
OPTS.num_w_ports = 1
|
||||
|
||||
c.num_words=16
|
||||
c.words_per_row=1
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ class single_bank_1rw_1r_test(openram_test):
|
|||
factory.reset()
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "No column mux")
|
||||
a = factory.create(module_type="bank", sram_config=c, num_ports=2)
|
||||
a = factory.create(module_type="bank", sram_config=c)
|
||||
self.local_check(a)
|
||||
|
||||
c.num_words=32
|
||||
|
|
@ -40,7 +40,7 @@ class single_bank_1rw_1r_test(openram_test):
|
|||
factory.reset()
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "Two way column mux")
|
||||
a = factory.create(module_type="bank", sram_config=c, num_ports=2)
|
||||
a = factory.create(module_type="bank", sram_config=c)
|
||||
self.local_check(a)
|
||||
|
||||
c.num_words=64
|
||||
|
|
@ -48,7 +48,7 @@ class single_bank_1rw_1r_test(openram_test):
|
|||
factory.reset()
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "Four way column mux")
|
||||
a = factory.create(module_type="bank", sram_config=c, num_ports=2)
|
||||
a = factory.create(module_type="bank", sram_config=c)
|
||||
self.local_check(a)
|
||||
|
||||
c.word_size=2
|
||||
|
|
@ -57,7 +57,7 @@ class single_bank_1rw_1r_test(openram_test):
|
|||
factory.reset()
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "Eight way column mux")
|
||||
a = factory.create(module_type="bank", sram_config=c, num_ports=2)
|
||||
a = factory.create(module_type="bank", sram_config=c)
|
||||
self.local_check(a)
|
||||
|
||||
globals.end_openram()
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ class single_bank_1w_1r_test(openram_test):
|
|||
factory.reset()
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "No column mux")
|
||||
a = factory.create(module_type="bank", sram_config=c, num_ports=2)
|
||||
a = factory.create(module_type="bank", sram_config=c)
|
||||
self.local_check(a)
|
||||
|
||||
c.num_words=32
|
||||
|
|
@ -40,7 +40,7 @@ class single_bank_1w_1r_test(openram_test):
|
|||
factory.reset()
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "Two way column mux")
|
||||
a = factory.create(module_type="bank", sram_config=c, num_ports=2)
|
||||
a = factory.create(module_type="bank", sram_config=c)
|
||||
self.local_check(a)
|
||||
|
||||
c.num_words=64
|
||||
|
|
@ -48,7 +48,7 @@ class single_bank_1w_1r_test(openram_test):
|
|||
factory.reset()
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "Four way column mux")
|
||||
a = factory.create(module_type="bank", sram_config=c, num_ports=2)
|
||||
a = factory.create(module_type="bank", sram_config=c)
|
||||
self.local_check(a)
|
||||
|
||||
c.word_size=2
|
||||
|
|
@ -57,7 +57,7 @@ class single_bank_1w_1r_test(openram_test):
|
|||
factory.reset()
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "Eight way column mux")
|
||||
a = factory.create(module_type="bank", sram_config=c, num_ports=2)
|
||||
a = factory.create(module_type="bank", sram_config=c)
|
||||
self.local_check(a)
|
||||
|
||||
globals.end_openram()
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ class single_bank_test(openram_test):
|
|||
factory.reset()
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "No column mux")
|
||||
a = factory.create("bank", sram_config=c, num_ports=1)
|
||||
a = factory.create("bank", sram_config=c)
|
||||
self.local_check(a)
|
||||
|
||||
c.num_words=32
|
||||
|
|
@ -36,7 +36,7 @@ class single_bank_test(openram_test):
|
|||
factory.reset()
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "Two way column mux")
|
||||
a = factory.create("bank", sram_config=c, num_ports=1)
|
||||
a = factory.create("bank", sram_config=c)
|
||||
self.local_check(a)
|
||||
|
||||
c.num_words=64
|
||||
|
|
@ -44,7 +44,7 @@ class single_bank_test(openram_test):
|
|||
factory.reset()
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "Four way column mux")
|
||||
a = factory.create("bank", sram_config=c, num_ports=1)
|
||||
a = factory.create("bank", sram_config=c)
|
||||
self.local_check(a)
|
||||
|
||||
c.word_size=2
|
||||
|
|
@ -53,7 +53,7 @@ class single_bank_test(openram_test):
|
|||
factory.reset()
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "Eight way column mux")
|
||||
a = factory.create("bank", sram_config=c, num_ports=1)
|
||||
a = factory.create("bank", sram_config=c)
|
||||
self.local_check(a)
|
||||
|
||||
globals.end_openram()
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@ equate class {-circuit1 pfet} {-circuit2 p}
|
|||
flatten class {-circuit1 dummy_cell_6t}
|
||||
flatten class {-circuit1 dummy_cell_1rw_1r}
|
||||
flatten class {-circuit1 dummy_cell_1w_1r}
|
||||
flatten class {-circuit1 dummy_pbitcell}
|
||||
flatten class {-circuit1 pbitcell_0}
|
||||
flatten class {-circuit1 pbitcell_1}
|
||||
property {-circuit1 nfet} remove as ad ps pd
|
||||
property {-circuit1 pfet} remove as ad ps pd
|
||||
property {-circuit2 n} remove as ad ps pd
|
||||
|
|
|
|||
Loading…
Reference in New Issue