Single banks working with new RBL

This commit is contained in:
mrg 2019-07-11 14:47:27 -07:00
parent b841fd7ce3
commit 0b13225913
10 changed files with 176 additions and 107 deletions

View File

@ -62,12 +62,14 @@ class bitcell(design.design):
column_pins = ["br"] column_pins = ["br"]
return column_pins return column_pins
def get_bl_name(self): def get_bl_name(self, port=0):
"""Get bl name""" """Get bl name"""
debug.check(port==0,"One port for bitcell only.")
return "bl" return "bl"
def get_br_name(self): def get_br_name(self, port=0):
"""Get bl name""" """Get bl name"""
debug.check(port==0,"One port for bitcell only.")
return "br" return "br"
def analytical_power(self, corner, load): def analytical_power(self, corner, load):
@ -96,4 +98,4 @@ class bitcell(design.design):
def build_graph(self, graph, inst_name, port_nets): def build_graph(self, graph, inst_name, port_nets):
"""Adds edges based on inputs/outputs. Overrides base class function.""" """Adds edges based on inputs/outputs. Overrides base class function."""
self.add_graph_edges(graph, port_nets) self.add_graph_edges(graph, port_nets)

View File

@ -97,10 +97,12 @@ class bitcell_1rw_1r(design.design):
def get_bl_name(self, port=0): def get_bl_name(self, port=0):
"""Get bl name by port""" """Get bl name by port"""
debug.check(port<2,"Two ports for bitcell_1rw_1r only.")
return "bl{}".format(port) return "bl{}".format(port)
def get_br_name(self, port=0): def get_br_name(self, port=0):
"""Get bl name by port""" """Get bl name by port"""
debug.check(port<2,"Two ports for bitcell_1rw_1r only.")
return "br{}".format(port) return "br{}".format(port)
def analytical_power(self, corner, load): def analytical_power(self, corner, load):

View File

@ -26,17 +26,18 @@ class bank(design.design):
This can create up to two ports in any combination: rw, w, r. 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 self.sram_config = sram_config
sram_config.set_local_config(self) sram_config.set_local_config(self)
self.num_ports = num_ports
if name == "": if name == "":
name = "bank_{0}_{1}".format(self.word_size, self.num_words) name = "bank_{0}_{1}".format(self.word_size, self.num_words)
design.design.__init__(self, name) design.design.__init__(self, name)
debug.info(2, "create sram of size {0} with {1} words".format(self.word_size,self.num_words)) 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, # 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 # so this prefix will be added to all of the input signals to create
# the internal gated signals. # the internal gated signals.
@ -47,7 +48,6 @@ class bank(design.design):
self.create_netlist() self.create_netlist()
if not OPTS.netlist_only: if not OPTS.netlist_only:
debug.check(len(self.all_ports)<=2,"Bank layout cannot handle more than two ports.")
self.create_layout() self.create_layout()
self.add_boundary() 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 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) # 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 # 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 # 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() self.compute_instance_port0_offsets()
if len(self.all_ports)==2: if len(self.all_ports)==2:
@ -179,7 +179,10 @@ class bank(design.design):
# LOWER RIGHT QUADRANT # LOWER RIGHT QUADRANT
# Below the bitcell array # 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 # UPPER LEFT QUADRANT
# To the left of the bitcell array # To the left of the bitcell array
@ -219,12 +222,12 @@ class bank(design.design):
# UPPER LEFT QUADRANT # UPPER LEFT QUADRANT
# Above the bitcell array # 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 # LOWER RIGHT QUADRANT
# To the left of the bitcell array # To the left of the bitcell array
x_offset = self.bitcell_array_right + self.port_address.width + self.m2_gap 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 # UPPER RIGHT QUADRANT
# Place the col decoder right aligned with wordline driver # 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.br_names = self.bitcell.list_all_br_names()
self.wl_names = self.bitcell.list_all_wl_names() self.wl_names = self.bitcell.list_all_wl_names()
self.bitline_names = self.bitcell.list_all_bitline_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 = [] self.port_data = []
for port in self.all_ports: for port in self.all_ports:
@ -342,7 +339,32 @@ class bank(design.design):
cols=self.num_cols, cols=self.num_cols,
rows=self.num_rows) rows=self.num_rows)
self.add_mod(self.port_address) 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): if(self.num_banks > 1):
self.bank_select = factory.create(module_type="bank_select") self.bank_select = factory.create(module_type="bank_select")
self.add_mod(self.bank_select) self.add_mod(self.bank_select)
@ -357,15 +379,16 @@ class bank(design.design):
temp = [] temp = []
for col in range(self.num_cols): for col in range(self.num_cols):
for bitline in self.bitline_names: for bitline in self.bitline_names:
temp.append(bitline+"_{0}".format(col)) temp.append("{0}_{1}".format(bitline,col))
for col in range(self.num_ports): for rbl in range(self.num_rbl):
for bitline in self.bitline_names: 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 row in range(self.num_rows):
for wordline in self.wl_names: for wordline in self.wl_names:
temp.append(wordline+"_{0}".format(row)) temp.append("{0}_{1}".format(wordline,row))
for wordline in self.wl_names: for rbl in range(self.num_rbl):
temp.append("replica_"+wordline) for wordline in self.wl_names:
temp.append("rbl_{0}_{1}".format(wordline,rbl))
temp.append("vdd") temp.append("vdd")
temp.append("gnd") temp.append("gnd")
self.connect_inst(temp) self.connect_inst(temp)
@ -385,9 +408,9 @@ class bank(design.design):
mod=self.port_data[port]) mod=self.port_data[port])
temp = [] temp = []
if port in self.read_ports: if self.port_data[port].has_rbl():
temp.append("rbl_{0}".format(self.bl_names[port])) temp.append("rbl_{0}_{1}".format(self.bl_names[port],self.rbl_indices[port]))
temp.append("rbl_{0}".format(self.br_names[port])) temp.append("rbl_{0}_{1}".format(self.br_names[port],self.rbl_indices[port]))
for col in range(self.num_cols): for col in range(self.num_cols):
temp.append("{0}_{1}".format(self.bl_names[port],col)) temp.append("{0}_{1}".format(self.bl_names[port],col))
temp.append("{0}_{1}".format(self.br_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("addr{0}_{1}".format(port,bit+self.col_addr_size))
temp.append("wl_en{0}".format(port)) temp.append("wl_en{0}".format(port))
for row in range(self.num_rows): 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"]) temp.extend(["vdd", "gnd"])
self.connect_inst(temp) self.connect_inst(temp)
@ -452,7 +475,7 @@ class bank(design.design):
# The address flop and decoder are aligned in the x coord. # The address flop and decoder are aligned in the x coord.
for port in self.all_ports: for port in self.all_ports:
if port%2 == 1: if port%2:
mirror = "MY" mirror = "MY"
else: else:
mirror = "R0" mirror = "R0"
@ -612,7 +635,7 @@ class bank(design.design):
# 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[0] - self.m2_width, self.min_y_offset) 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 # 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", self.bus_xoffset[0] = self.create_bus(layer="metal2",
pitch=self.m2_pitch, pitch=self.m2_pitch,
offset=control_bus_offset, offset=control_bus_offset,
@ -624,7 +647,7 @@ class bank(design.design):
# Port 1 # Port 1
if len(self.all_ports)==2: if len(self.all_ports)==2:
# The other control bus is routed up to two pitches above the bitcell array # 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, control_bus_offset = vector(self.bitcell_array_right,
self.max_y_offset - control_bus_length) self.max_y_offset - control_bus_length)
@ -640,12 +663,20 @@ class bank(design.design):
def route_port_data_to_bitcell_array(self, port): def route_port_data_to_bitcell_array(self, port):
""" Routing of BL and BR between port data and bitcell array """ """ Routing of BL and BR between port data and bitcell array """
# Connect the regular bitlines
inst2 = self.port_data_inst[port] inst2 = self.port_data_inst[port]
inst1 = self.bitcell_array_inst inst1 = self.bitcell_array_inst
inst1_bl_name = self.bl_names[port]+"_{}" inst1_bl_name = self.bl_names[port]+"_{}"
inst1_br_name = self.br_names[port]+"_{}" inst1_br_name = self.br_names[port]+"_{}"
self.connect_bitlines(inst1=inst1, inst2=inst2, num_bits=self.num_cols, self.connect_bitlines(inst1=inst1, inst2=inst2, num_bits=self.num_cols,
inst1_bl_name=inst1_bl_name, inst1_br_name=inst1_br_name) 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): def route_port_data_out(self, port):
@ -705,12 +736,9 @@ class bank(design.design):
route_map = list(zip(bottom_names, top_names)) route_map = list(zip(bottom_names, top_names))
self.create_horizontal_channel_route(route_map, offset) self.create_horizontal_channel_route(route_map, offset)
def connect_bitline(self, inst1, inst2, inst1_name, inst2_name):
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. Connect two pins of two modules.
This assumes that they have sufficient space to create a jog This assumes that they have sufficient space to create a jog
in the middle between the two modules (if needed). in the middle between the two modules (if needed).
""" """
@ -718,23 +746,34 @@ class bank(design.design):
# determine top and bottom automatically. # determine top and bottom automatically.
# since they don't overlap, we can just check the bottom y coordinate. # since they don't overlap, we can just check the bottom y coordinate.
if inst1.by() < inst2.by(): if inst1.by() < inst2.by():
(bottom_inst, bottom_bl_name, bottom_br_name) = (inst1, inst1_bl_name, inst1_br_name) (bottom_inst, bottom_name) = (inst1, inst1_name)
(top_inst, top_bl_name, top_br_name) = (inst2, inst2_bl_name, inst2_br_name) (top_inst, top_name) = (inst2, inst2_name)
else: else:
(bottom_inst, bottom_bl_name, bottom_br_name) = (inst2, inst2_bl_name, inst2_br_name) (bottom_inst, bottom_name) = (inst2, inst2_name)
(top_inst, top_bl_name, top_br_name) = (inst1, inst1_bl_name, inst1_br_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): for col in range(num_bits):
bottom_bl = bottom_inst.get_pin(bottom_bl_name.format(col)).uc() self.connect_bitline(inst1, inst2, inst1_bl_name.format(col), inst2_bl_name.format(col))
bottom_br = bottom_inst.get_pin(bottom_br_name.format(col)).uc() self.connect_bitline(inst1, inst2, inst1_br_name.format(col), inst2_br_name.format(col))
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])
def route_port_address(self, port): def route_port_address(self, port):

View File

@ -15,6 +15,7 @@ from globals import OPTS
class port_data(design.design): class port_data(design.design):
""" """
Create the data port (column mux, sense amps, write driver, etc.) for the given port number. 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=""): def __init__(self, sram_config, port, name=""):
@ -71,12 +72,12 @@ class port_data(design.design):
def add_pins(self): def add_pins(self):
""" Adding pins for port address module""" """ Adding pins for port address module"""
if self.port in self.read_ports or self.col_addr_size>0: if self.has_rbl():
self.add_pin("rbl_"+self.bl_names[self.port],"INOUT") self.add_pin("rbl_bl","INOUT")
self.add_pin("rbl_"+self.br_names[self.port],"INOUT") self.add_pin("rbl_br","INOUT")
for bit in range(self.num_cols): for bit in range(self.num_cols):
self.add_pin(self.bl_names[self.port]+"_{0}".format(bit),"INOUT") self.add_pin("bl_{0}".format(bit),"INOUT")
self.add_pin(self.br_names[self.port]+"_{0}".format(bit),"INOUT") self.add_pin("br_{0}".format(bit),"INOUT")
if self.port in self.read_ports: if self.port in self.read_ports:
for bit in range(self.word_size): for bit in range(self.word_size):
self.add_pin("dout_{}".format(bit),"OUTPUT") 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_sense_amp_to_column_mux_or_precharge_array(self.port)
self.route_column_mux_to_precharge_array(self.port) self.route_column_mux_to_precharge_array(self.port)
else: 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_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): def route_supplies(self):
""" Propagate all vdd/gnd pins up to this level for all modules """ """ 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) mod=self.precharge_array)
temp = [] temp = []
temp.append("rbl_"+self.bl_names[self.port]) if self.has_rbl() and self.port==0:
temp.append("rbl_"+self.br_names[self.port]) temp.append("rbl_bl")
temp.append("rbl_br")
for bit in range(self.num_cols): for bit in range(self.num_cols):
temp.append(self.bl_names[self.port]+"_{0}".format(bit)) temp.append("bl_{0}".format(bit))
temp.append(self.br_names[self.port]+"_{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"]) temp.extend(["p_en_bar", "vdd"])
self.connect_inst(temp) self.connect_inst(temp)
@ -234,13 +240,13 @@ class port_data(design.design):
temp = [] temp = []
for col in range(self.num_cols): for col in range(self.num_cols):
temp.append(self.bl_names[self.port]+"_{0}".format(col)) temp.append("bl_{0}".format(col))
temp.append(self.br_names[self.port]+"_{0}".format(col)) temp.append("br_{0}".format(col))
for word in range(self.words_per_row): for word in range(self.words_per_row):
temp.append("sel_{}".format(word)) temp.append("sel_{}".format(word))
for bit in range(self.word_size): for bit in range(self.word_size):
temp.append(self.bl_names[self.port]+"_out_{0}".format(bit)) temp.append("bl_out_{0}".format(bit))
temp.append(self.br_names[self.port]+"_out_{0}".format(bit)) temp.append("br_out_{0}".format(bit))
temp.append("gnd") temp.append("gnd")
self.connect_inst(temp) self.connect_inst(temp)
@ -263,11 +269,11 @@ class port_data(design.design):
for bit in range(self.word_size): for bit in range(self.word_size):
temp.append("dout_{}".format(bit)) temp.append("dout_{}".format(bit))
if self.words_per_row == 1: if self.words_per_row == 1:
temp.append(self.bl_names[self.port]+"_{0}".format(bit)) temp.append("bl_{0}".format(bit))
temp.append(self.br_names[self.port]+"_{0}".format(bit)) temp.append("br_{0}".format(bit))
else: else:
temp.append(self.bl_names[self.port]+"_out_{0}".format(bit)) temp.append("bl_out_{0}".format(bit))
temp.append(self.br_names[self.port]+"_out_{0}".format(bit)) temp.append("br_out_{0}".format(bit))
temp.extend(["s_en", "vdd", "gnd"]) temp.extend(["s_en", "vdd", "gnd"])
self.connect_inst(temp) self.connect_inst(temp)
@ -288,11 +294,11 @@ class port_data(design.design):
temp.append("din_{}".format(bit)) temp.append("din_{}".format(bit))
for bit in range(self.word_size): for bit in range(self.word_size):
if (self.words_per_row == 1): if (self.words_per_row == 1):
temp.append(self.bl_names[self.port]+"_{0}".format(bit)) temp.append("bl_{0}".format(bit))
temp.append(self.br_names[self.port]+"_{0}".format(bit)) temp.append("br_{0}".format(bit))
else: else:
temp.append(self.bl_names[self.port]+"_out_{0}".format(bit)) temp.append("bl_out_{0}".format(bit))
temp.append(self.br_names[self.port]+"_out_{0}".format(bit)) temp.append("br_out_{0}".format(bit))
temp.extend(["w_en", "vdd", "gnd"]) temp.extend(["w_en", "vdd", "gnd"])
self.connect_inst(temp) self.connect_inst(temp)
@ -314,7 +320,7 @@ class port_data(design.design):
vertical_port_order.append(self.write_driver_array_inst) vertical_port_order.append(self.write_driver_array_inst)
# Add one column for the the RBL # 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 x_offset = self.bitcell.width
else: else:
x_offset = 0 x_offset = 0
@ -334,8 +340,10 @@ class port_data(design.design):
self.sense_amp_offset = vertical_port_offsets[2] self.sense_amp_offset = vertical_port_offsets[2]
self.column_mux_offset = vertical_port_offsets[1] self.column_mux_offset = vertical_port_offsets[1]
self.precharge_offset = vertical_port_offsets[0] self.precharge_offset = vertical_port_offsets[0]
if self.precharge_offset: # Shift the precharge left if port 0
self.precharge_offset -= vector(x_offset,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 inst1 = self.column_mux_array_inst
inst2 = self.precharge_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): 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 = self.precharge_array_inst
inst1_bl_name = "bl_{}" inst1_bl_name = "bl_{}"
inst1_br_name = "br_{}" 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, 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): def route_bitline_pins(self):
""" Add the bitline pins for the given port """ """ 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, "bl_0", "rbl_bl")
self.copy_layout_pin(self.precharge_array_inst, "br_0", "rbl_br") 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): for bit in range(self.num_cols):
if self.port in self.read_ports: if self.precharge_array_inst:
self.copy_layout_pin(self.precharge_array_inst, "bl_{}".format(bit+1), "bl_{}".format(bit)) 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+1), "br_{}".format(bit)) self.copy_layout_pin(self.precharge_array_inst, "br_{}".format(bit+bit_offset), "br_{}".format(bit))
elif self.column_mux_array_inst: # 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, "bl_{}".format(bit))
self.copy_layout_pin(self.column_mux_array_inst, "br_{}".format(bit)) # self.copy_layout_pin(self.column_mux_array_inst, "br_{}".format(bit))
else: else:
self.copy_layout_pin(self.write_driver_array_inst, "bl_{}".format(bit)) self.copy_layout_pin(self.write_driver_array_inst, "bl_{}".format(bit))
self.copy_layout_pin(self.write_driver_array_inst, "br_{}".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""" """Precharge adds a loop between bitlines, can be excluded to reduce complexity"""
if self.precharge_array_inst: if self.precharge_array_inst:
self.graph_inst_exclude.add(self.precharge_array_inst) self.graph_inst_exclude.add(self.precharge_array_inst)
def has_rbl(self):
return self.port in self.read_ports

View File

@ -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")] self.bl_names = [x for x in self.bitcell_array.pins if x.startswith("b")]
# These are the non-indexed names # 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_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_cell_bl_names = ["dummy_"+x for x in self.cell.list_all_bitline_names()]
self.dummy_row_bl_names = self.bl_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]) 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) # Left port WLs (one dummy for each port when we allow >1 port)
for bit in range(self.left_rbl): 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 # Regular WLs
self.replica_col_wl_names.extend(self.wl_names) self.replica_col_wl_names.extend(self.wl_names)
# Right port WLs (one dummy for each port when we allow >1 port) # 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): 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]) 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 # 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_bl_names = []
self.replica_wl_names = [] self.replica_wl_names = []
for bit in range(self.left_rbl+self.right_rbl): 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_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] 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] 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]): 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) 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, self.add_layout_pin(text=name,
layer=pin.layer, layer=pin.layer,
offset=pin.ll().scale(1,0), offset=pin.ll().scale(1,0),

View File

@ -55,9 +55,9 @@ class port_data_test(openram_test):
self.local_check(a) self.local_check(a)
OPTS.bitcell = "bitcell_1w_1r" OPTS.bitcell = "bitcell_1w_1r"
OPTS.num_rw_ports = 1 OPTS.num_rw_ports = 0
OPTS.num_r_ports = 1 OPTS.num_r_ports = 1
OPTS.num_w_ports = 0 OPTS.num_w_ports = 1
c.num_words=16 c.num_words=16
c.words_per_row=1 c.words_per_row=1

View File

@ -32,7 +32,7 @@ class single_bank_1rw_1r_test(openram_test):
factory.reset() factory.reset()
c.recompute_sizes() c.recompute_sizes()
debug.info(1, "No column mux") 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) self.local_check(a)
c.num_words=32 c.num_words=32
@ -40,7 +40,7 @@ class single_bank_1rw_1r_test(openram_test):
factory.reset() factory.reset()
c.recompute_sizes() c.recompute_sizes()
debug.info(1, "Two way column mux") 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) self.local_check(a)
c.num_words=64 c.num_words=64
@ -48,7 +48,7 @@ class single_bank_1rw_1r_test(openram_test):
factory.reset() factory.reset()
c.recompute_sizes() c.recompute_sizes()
debug.info(1, "Four way column mux") 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) self.local_check(a)
c.word_size=2 c.word_size=2
@ -57,7 +57,7 @@ class single_bank_1rw_1r_test(openram_test):
factory.reset() factory.reset()
c.recompute_sizes() c.recompute_sizes()
debug.info(1, "Eight way column mux") 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) self.local_check(a)
globals.end_openram() globals.end_openram()

View File

@ -32,7 +32,7 @@ class single_bank_1w_1r_test(openram_test):
factory.reset() factory.reset()
c.recompute_sizes() c.recompute_sizes()
debug.info(1, "No column mux") 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) self.local_check(a)
c.num_words=32 c.num_words=32
@ -40,7 +40,7 @@ class single_bank_1w_1r_test(openram_test):
factory.reset() factory.reset()
c.recompute_sizes() c.recompute_sizes()
debug.info(1, "Two way column mux") 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) self.local_check(a)
c.num_words=64 c.num_words=64
@ -48,7 +48,7 @@ class single_bank_1w_1r_test(openram_test):
factory.reset() factory.reset()
c.recompute_sizes() c.recompute_sizes()
debug.info(1, "Four way column mux") 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) self.local_check(a)
c.word_size=2 c.word_size=2
@ -57,7 +57,7 @@ class single_bank_1w_1r_test(openram_test):
factory.reset() factory.reset()
c.recompute_sizes() c.recompute_sizes()
debug.info(1, "Eight way column mux") 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) self.local_check(a)
globals.end_openram() globals.end_openram()

View File

@ -28,7 +28,7 @@ class single_bank_test(openram_test):
factory.reset() factory.reset()
c.recompute_sizes() c.recompute_sizes()
debug.info(1, "No column mux") 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) self.local_check(a)
c.num_words=32 c.num_words=32
@ -36,7 +36,7 @@ class single_bank_test(openram_test):
factory.reset() factory.reset()
c.recompute_sizes() c.recompute_sizes()
debug.info(1, "Two way column mux") 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) self.local_check(a)
c.num_words=64 c.num_words=64
@ -44,7 +44,7 @@ class single_bank_test(openram_test):
factory.reset() factory.reset()
c.recompute_sizes() c.recompute_sizes()
debug.info(1, "Four way column mux") 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) self.local_check(a)
c.word_size=2 c.word_size=2
@ -53,7 +53,7 @@ class single_bank_test(openram_test):
factory.reset() factory.reset()
c.recompute_sizes() c.recompute_sizes()
debug.info(1, "Eight way column mux") 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) self.local_check(a)
globals.end_openram() globals.end_openram()

View File

@ -6,7 +6,8 @@ equate class {-circuit1 pfet} {-circuit2 p}
flatten class {-circuit1 dummy_cell_6t} flatten class {-circuit1 dummy_cell_6t}
flatten class {-circuit1 dummy_cell_1rw_1r} flatten class {-circuit1 dummy_cell_1rw_1r}
flatten class {-circuit1 dummy_cell_1w_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 nfet} remove as ad ps pd
property {-circuit1 pfet} remove as ad ps pd property {-circuit1 pfet} remove as ad ps pd
property {-circuit2 n} remove as ad ps pd property {-circuit2 n} remove as ad ps pd