mirror of https://github.com/VLSIDA/OpenRAM.git
Functional tests working with new RBL.
This commit is contained in:
parent
0b13225913
commit
043018e8ba
|
|
@ -71,7 +71,12 @@ class bitcell(design.design):
|
|||
"""Get bl name"""
|
||||
debug.check(port==0,"One port for bitcell only.")
|
||||
return "br"
|
||||
|
||||
|
||||
def get_wl_name(self, port=0):
|
||||
"""Get wl name"""
|
||||
debug.check(port==0,"One port for bitcell only.")
|
||||
return "wl"
|
||||
|
||||
def analytical_power(self, corner, load):
|
||||
"""Bitcell power in nW. Only characterizes leakage."""
|
||||
from tech import spice
|
||||
|
|
|
|||
|
|
@ -104,6 +104,11 @@ class bitcell_1rw_1r(design.design):
|
|||
"""Get bl name by port"""
|
||||
debug.check(port<2,"Two ports for bitcell_1rw_1r only.")
|
||||
return "br{}".format(port)
|
||||
|
||||
def get_wl_name(self, port=0):
|
||||
"""Get wl name by port"""
|
||||
debug.check(port<2,"Two ports for bitcell_1rw_1r only.")
|
||||
return "wl{}".format(port)
|
||||
|
||||
def analytical_power(self, corner, load):
|
||||
"""Bitcell power in nW. Only characterizes leakage."""
|
||||
|
|
|
|||
|
|
@ -103,6 +103,11 @@ class bitcell_1w_1r(design.design):
|
|||
"""Get bl name by port"""
|
||||
return "br{}".format(port)
|
||||
|
||||
def get_wl_name(self, port=0):
|
||||
"""Get wl name by port"""
|
||||
debug.check(port<2,"Two ports for bitcell_1rw_1r only.")
|
||||
return "wl{}".format(port)
|
||||
|
||||
def analytical_power(self, corner, load):
|
||||
"""Bitcell power in nW. Only characterizes leakage."""
|
||||
from tech import spice
|
||||
|
|
|
|||
|
|
@ -902,7 +902,13 @@ class pbitcell(design.design):
|
|||
|
||||
def get_br_name(self, port=0):
|
||||
"""Get bl name by port"""
|
||||
return "br{}".format(port)
|
||||
return "br{}".format(port)
|
||||
|
||||
def get_wl_name(self, port=0):
|
||||
"""Get wl name by port"""
|
||||
debug.check(port<2,"Two ports for bitcell_1rw_1r only.")
|
||||
return "wl{}".format(port)
|
||||
|
||||
|
||||
def analytical_delay(self, corner, slew, load=0, swing = 0.5):
|
||||
parasitic_delay = 1
|
||||
|
|
|
|||
|
|
@ -78,6 +78,9 @@ class bank(design.design):
|
|||
for port in self.read_ports:
|
||||
for bit in range(self.word_size):
|
||||
self.add_pin("dout{0}_{1}".format(port,bit),"OUT")
|
||||
self.add_pin("rbl_bl{0}_{0}".format(port),"OUT")
|
||||
for port in self.read_ports:
|
||||
self.add_pin("rbl_wl{0}_{0}".format(port),"IN")
|
||||
for port in self.write_ports:
|
||||
for bit in range(self.word_size):
|
||||
self.add_pin("din{0}_{1}".format(port,bit),"IN")
|
||||
|
|
@ -108,6 +111,7 @@ class bank(design.design):
|
|||
|
||||
for port in self.all_ports:
|
||||
self.route_bitlines(port)
|
||||
self.route_rbl(port)
|
||||
self.route_port_address(port)
|
||||
self.route_column_address_lines(port)
|
||||
self.route_control_lines(port)
|
||||
|
|
@ -116,6 +120,20 @@ class bank(design.design):
|
|||
|
||||
self.route_supplies()
|
||||
|
||||
def route_rbl(self,port):
|
||||
""" Route the rbl_bl and rbl_wl """
|
||||
|
||||
if self.port_data[port].has_rbl():
|
||||
bl_name = self.bitcell.get_bl_name(port)
|
||||
bl_pin = self.bitcell_array_inst.get_pin("rbl_{0}_{1}".format(bl_name,port))
|
||||
self.add_layout_pin(text="rbl_bl{0}".format(port),
|
||||
layer=bl_pin.layer,
|
||||
offset=bl_pin.ll(),
|
||||
height=bl_pin.height(),
|
||||
width=bl_pin.width())
|
||||
|
||||
|
||||
|
||||
def route_bitlines(self, port):
|
||||
""" Route the bitlines depending on the port type rw, w, or r. """
|
||||
|
||||
|
|
@ -281,13 +299,13 @@ class bank(design.design):
|
|||
self.input_control_signals = []
|
||||
port_num = 0
|
||||
for port in range(OPTS.num_rw_ports):
|
||||
self.input_control_signals.append(["wl_en{}".format(port_num), "w_en{}".format(port_num), "s_en{}".format(port_num), "p_en_bar{}".format(port_num)])
|
||||
self.input_control_signals.append(["wl_en{}".format(port_num), "w_en{}".format(port_num), "s_en{}".format(port_num), "p_en_bar{}".format(port_num), "rbl_wl{}".format(port_num)])
|
||||
port_num += 1
|
||||
for port in range(OPTS.num_w_ports):
|
||||
self.input_control_signals.append(["wl_en{}".format(port_num), "w_en{}".format(port_num)])
|
||||
port_num += 1
|
||||
for port in range(OPTS.num_r_ports):
|
||||
self.input_control_signals.append(["wl_en{}".format(port_num), "s_en{}".format(port_num), "p_en_bar{}".format(port_num)])
|
||||
self.input_control_signals.append(["wl_en{}".format(port_num), "s_en{}".format(port_num), "p_en_bar{}".format(port_num), "rbl_wl{}".format(port_num)])
|
||||
port_num += 1
|
||||
|
||||
# Number of control lines in the bus for each port
|
||||
|
|
@ -904,7 +922,10 @@ class bank(design.design):
|
|||
connection = []
|
||||
if port in self.read_ports:
|
||||
connection.append((self.prefix+"p_en_bar{}".format(port), self.port_data_inst[port].get_pin("p_en_bar").lc()))
|
||||
|
||||
|
||||
if port in self.read_ports:
|
||||
connection.append((self.prefix+"rbl_wl{}".format(port), self.bitcell_array_inst.get_pin("rbl_{0}_{1}".format(self.bitcell.get_wl_name(port),port)).lc()))
|
||||
|
||||
if port in self.write_ports:
|
||||
connection.append((self.prefix+"w_en{}".format(port), self.port_data_inst[port].get_pin("w_en").lc()))
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ class control_logic(design.design):
|
|||
self.num_cols = word_size*words_per_row
|
||||
self.num_words = num_rows*words_per_row
|
||||
|
||||
self.enable_delay_chain_resizing = True
|
||||
self.enable_delay_chain_resizing = False
|
||||
self.inv_parasitic_delay = logical_effort.logical_effort.pinv
|
||||
|
||||
#Determines how much larger the sen delay should be. Accounts for possible error in model.
|
||||
|
|
@ -73,10 +73,8 @@ class control_logic(design.design):
|
|||
|
||||
def add_pins(self):
|
||||
""" Add the pins to the control logic module. """
|
||||
for pin in self.input_list + ["clk"]:
|
||||
self.add_pin(pin,"INPUT")
|
||||
for pin in self.output_list:
|
||||
self.add_pin(pin,"OUTPUT")
|
||||
self.add_pin_list(self.input_list + ["clk"] + self.rbl_list, "INPUT")
|
||||
self.add_pin_list(self.output_list,"OUTPUT")
|
||||
self.add_pin("vdd","POWER")
|
||||
self.add_pin("gnd","GROUND")
|
||||
|
||||
|
|
@ -139,46 +137,48 @@ class control_logic(design.design):
|
|||
height=dff_height)
|
||||
self.add_mod(self.p_en_bar_driver)
|
||||
|
||||
if (self.port_type == "rw") or (self.port_type == "r"):
|
||||
from importlib import reload
|
||||
self.delay_chain_resized = False
|
||||
c = reload(__import__(OPTS.replica_bitline))
|
||||
replica_bitline = getattr(c, OPTS.replica_bitline)
|
||||
bitcell_loads = int(math.ceil(self.num_rows * OPTS.rbl_delay_percentage))
|
||||
#Use a model to determine the delays with that heuristic
|
||||
if OPTS.use_tech_delay_chain_size: #Use tech parameters if set.
|
||||
fanout_list = OPTS.delay_chain_stages*[OPTS.delay_chain_fanout_per_stage]
|
||||
debug.info(1, "Using tech parameters to size delay chain: fanout_list={}".format(fanout_list))
|
||||
self.replica_bitline = factory.create(module_type="replica_bitline",
|
||||
delay_fanout_list=fanout_list,
|
||||
bitcell_loads=bitcell_loads)
|
||||
if self.sram != None: #Calculate model value even for specified sizes
|
||||
self.set_sen_wl_delays()
|
||||
# if (self.port_type == "rw") or (self.port_type == "r"):
|
||||
# from importlib import reload
|
||||
# self.delay_chain_resized = False
|
||||
# c = reload(__import__(OPTS.replica_bitline))
|
||||
# replica_bitline = getattr(c, OPTS.replica_bitline)
|
||||
# bitcell_loads = int(math.ceil(self.num_rows * OPTS.rbl_delay_percentage))
|
||||
# #Use a model to determine the delays with that heuristic
|
||||
# if OPTS.use_tech_delay_chain_size: #Use tech parameters if set.
|
||||
# fanout_list = OPTS.delay_chain_stages*[OPTS.delay_chain_fanout_per_stage]
|
||||
# debug.info(1, "Using tech parameters to size delay chain: fanout_list={}".format(fanout_list))
|
||||
# self.replica_bitline = factory.create(module_type="replica_bitline",
|
||||
# delay_fanout_list=fanout_list,
|
||||
# bitcell_loads=bitcell_loads)
|
||||
# if self.sram != None: #Calculate model value even for specified sizes
|
||||
# self.set_sen_wl_delays()
|
||||
|
||||
else: #Otherwise, use a heuristic and/or model based sizing.
|
||||
#First use a heuristic
|
||||
delay_stages_heuristic, delay_fanout_heuristic = self.get_heuristic_delay_chain_size()
|
||||
self.replica_bitline = factory.create(module_type="replica_bitline",
|
||||
delay_fanout_list=[delay_fanout_heuristic]*delay_stages_heuristic,
|
||||
bitcell_loads=bitcell_loads)
|
||||
#Resize if necessary, condition depends on resizing method
|
||||
if self.sram != None and self.enable_delay_chain_resizing and not self.does_sen_rise_fall_timing_match():
|
||||
#This resizes to match fall and rise delays, can make the delay chain weird sizes.
|
||||
stage_list = self.get_dynamic_delay_fanout_list(delay_stages_heuristic, delay_fanout_heuristic)
|
||||
self.replica_bitline = factory.create(module_type="replica_bitline",
|
||||
delay_fanout_list=stage_list,
|
||||
bitcell_loads=bitcell_loads)
|
||||
# else: #Otherwise, use a heuristic and/or model based sizing.
|
||||
# #First use a heuristic
|
||||
# delay_stages_heuristic, delay_fanout_heuristic = self.get_heuristic_delay_chain_size()
|
||||
# self.replica_bitline = factory.create(module_type="replica_bitline",
|
||||
# delay_fanout_list=[delay_fanout_heuristic]*delay_stages_heuristic,
|
||||
# bitcell_loads=bitcell_loads)
|
||||
# #Resize if necessary, condition depends on resizing method
|
||||
# if self.sram != None and self.enable_delay_chain_resizing and not self.does_sen_rise_fall_timing_match():
|
||||
# #This resizes to match fall and rise delays, can make the delay chain weird sizes.
|
||||
# stage_list = self.get_dynamic_delay_fanout_list(delay_stages_heuristic, delay_fanout_heuristic)
|
||||
# self.replica_bitline = factory.create(module_type="replica_bitline",
|
||||
# delay_fanout_list=stage_list,
|
||||
# bitcell_loads=bitcell_loads)
|
||||
|
||||
#This resizes based on total delay.
|
||||
# delay_stages, delay_fanout = self.get_dynamic_delay_chain_size(delay_stages_heuristic, delay_fanout_heuristic)
|
||||
# self.replica_bitline = factory.create(module_type="replica_bitline",
|
||||
# delay_fanout_list=[delay_fanout]*delay_stages,
|
||||
# bitcell_loads=bitcell_loads)
|
||||
# #This resizes based on total delay.
|
||||
# # delay_stages, delay_fanout = self.get_dynamic_delay_chain_size(delay_stages_heuristic, delay_fanout_heuristic)
|
||||
# # self.replica_bitline = factory.create(module_type="replica_bitline",
|
||||
# # delay_fanout_list=[delay_fanout]*delay_stages,
|
||||
# # bitcell_loads=bitcell_loads)
|
||||
|
||||
self.sen_delay_rise,self.sen_delay_fall = self.get_delays_to_sen() #get the new timing
|
||||
self.delay_chain_resized = True
|
||||
|
||||
self.add_mod(self.replica_bitline)
|
||||
# self.sen_delay_rise,self.sen_delay_fall = self.get_delays_to_sen() #get the new timing
|
||||
# self.delay_chain_resized = True
|
||||
|
||||
self.delay_chain=factory.create(module_type="delay_chain",
|
||||
fanout_list = OPTS.delay_chain_stages*[OPTS.delay_chain_fanout_per_stage])
|
||||
self.add_mod(self.delay_chain)
|
||||
|
||||
def get_heuristic_delay_chain_size(self):
|
||||
"""Use a basic heuristic to determine the size of the delay chain used for the Sense Amp Enable """
|
||||
|
|
@ -312,8 +312,13 @@ class control_logic(design.design):
|
|||
# List of input control signals
|
||||
if self.port_type == "rw":
|
||||
self.input_list = ["csb", "web"]
|
||||
self.rbl_list = ["rbl_bl"]
|
||||
elif self.port_type == "r":
|
||||
self.input_list = ["csb"]
|
||||
self.rbl_list = ["rbl_bl"]
|
||||
else:
|
||||
self.input_list = ["csb"]
|
||||
self.rbl_list = []
|
||||
|
||||
if self.port_type == "rw":
|
||||
self.dff_output_list = ["cs_bar", "cs", "we_bar", "we"]
|
||||
|
|
@ -332,9 +337,9 @@ class control_logic(design.design):
|
|||
|
||||
# Outputs to the bank
|
||||
if self.port_type == "rw":
|
||||
self.output_list = ["s_en", "w_en", "p_en_bar"]
|
||||
self.output_list = ["rbl_wl", "s_en", "w_en", "p_en_bar"]
|
||||
elif self.port_type == "r":
|
||||
self.output_list = ["s_en", "p_en_bar"]
|
||||
self.output_list = ["rbl_wl", "s_en", "p_en_bar"]
|
||||
else:
|
||||
self.output_list = ["w_en"]
|
||||
self.output_list.append("wl_en")
|
||||
|
|
@ -361,11 +366,11 @@ class control_logic(design.design):
|
|||
if (self.port_type == "rw") or (self.port_type == "w"):
|
||||
self.create_wen_row()
|
||||
if self.port_type == "rw":
|
||||
self.create_rbl_in_row()
|
||||
self.create_rbl_row()
|
||||
if (self.port_type == "rw") or (self.port_type == "r"):
|
||||
self.create_pen_row()
|
||||
self.create_sen_row()
|
||||
self.create_rbl()
|
||||
self.create_delay()
|
||||
|
||||
|
||||
def place_instances(self):
|
||||
|
|
@ -395,17 +400,16 @@ class control_logic(design.design):
|
|||
height = self.w_en_inst.uy()
|
||||
control_center_y = self.w_en_inst.uy()
|
||||
row += 1
|
||||
if self.port_type == "rw":
|
||||
self.place_rbl_in_row(row)
|
||||
row += 1
|
||||
if (self.port_type == "rw") or (self.port_type == "r"):
|
||||
self.place_rbl_row(row)
|
||||
row += 1
|
||||
self.place_pen_row(row)
|
||||
row += 1
|
||||
self.place_sen_row(row)
|
||||
row += 1
|
||||
self.place_rbl(row)
|
||||
height = self.rbl_inst.uy()
|
||||
control_center_y = self.rbl_inst.by()
|
||||
self.place_delay(row)
|
||||
height = self.delay_inst.uy()
|
||||
control_center_y = self.delay_inst.by()
|
||||
|
||||
# This offset is used for placement of the control logic in the SRAM level.
|
||||
self.control_logic_center = vector(self.ctrl_dff_inst.rx(), control_center_y)
|
||||
|
|
@ -415,7 +419,7 @@ class control_logic(design.design):
|
|||
# Max of modules or logic rows
|
||||
self.width = max([inst.rx() for inst in self.row_end_inst])
|
||||
if (self.port_type == "rw") or (self.port_type == "r"):
|
||||
self.width = max(self.rbl_inst.rx() , self.width)
|
||||
self.width = max(self.delay_inst.rx() , self.width)
|
||||
self.width += self.m2_pitch
|
||||
|
||||
def route_all(self):
|
||||
|
|
@ -426,7 +430,7 @@ class control_logic(design.design):
|
|||
if (self.port_type == "rw") or (self.port_type == "w"):
|
||||
self.route_wen()
|
||||
if (self.port_type == "rw") or (self.port_type == "r"):
|
||||
self.route_rbl_in()
|
||||
self.route_rbl()
|
||||
self.route_pen()
|
||||
self.route_sen()
|
||||
self.route_clk_buf()
|
||||
|
|
@ -435,24 +439,20 @@ class control_logic(design.design):
|
|||
self.route_supply()
|
||||
|
||||
|
||||
def create_rbl(self):
|
||||
def create_delay(self):
|
||||
""" Create the replica bitline """
|
||||
if self.port_type == "r":
|
||||
input_name = "gated_clk_bar"
|
||||
else:
|
||||
input_name = "rbl_in"
|
||||
self.rbl_inst=self.add_inst(name="replica_bitline",
|
||||
mod=self.replica_bitline)
|
||||
self.connect_inst([input_name, "pre_s_en", "vdd", "gnd"])
|
||||
self.delay_inst=self.add_inst(name="delay_chain",
|
||||
mod=self.delay_chain)
|
||||
self.connect_inst(["rbl_bl", "pre_s_en", "vdd", "gnd"])
|
||||
|
||||
def place_rbl(self,row):
|
||||
def place_delay(self,row):
|
||||
""" Place the replica bitline """
|
||||
y_off = row * self.and2.height + 2*self.m1_pitch
|
||||
|
||||
# Add the RBL above the rows
|
||||
# Add to the right of the control rows and routing channel
|
||||
offset = vector(0, y_off)
|
||||
self.rbl_inst.place(offset)
|
||||
self.delay_inst.place(offset)
|
||||
|
||||
|
||||
def create_clk_buf_row(self):
|
||||
|
|
@ -588,44 +588,41 @@ class control_logic(design.design):
|
|||
self.connect_vertical_bus(wlen_map, self.wl_en_inst, self.rail_offsets)
|
||||
self.connect_output(self.wl_en_inst, "Z", "wl_en")
|
||||
|
||||
def create_rbl_in_row(self):
|
||||
def create_rbl_row(self):
|
||||
|
||||
# input: gated_clk_bar, we_bar, output: rbl_in
|
||||
self.rbl_in_inst=self.add_inst(name="and2_rbl_in",
|
||||
self.rbl_inst=self.add_inst(name="and2_rbl",
|
||||
mod=self.and2)
|
||||
self.connect_inst(["gated_clk_bar", "we_bar", "rbl_in", "vdd", "gnd"])
|
||||
self.connect_inst(["gated_clk_bar", "we_bar", "rbl_wl", "vdd", "gnd"])
|
||||
|
||||
def place_rbl_in_row(self,row):
|
||||
def place_rbl_row(self,row):
|
||||
x_off = self.control_x_offset
|
||||
(y_off,mirror)=self.get_offset(row)
|
||||
|
||||
offset = vector(x_off, y_off)
|
||||
self.rbl_in_inst.place(offset, mirror)
|
||||
self.rbl_inst.place(offset, mirror)
|
||||
|
||||
self.row_end_inst.append(self.rbl_in_inst)
|
||||
self.row_end_inst.append(self.rbl_inst)
|
||||
|
||||
def route_rbl_in(self):
|
||||
def route_rbl(self):
|
||||
""" Connect the logic for the rbl_in generation """
|
||||
|
||||
if self.port_type == "rw":
|
||||
input_name = "we_bar"
|
||||
# Connect the NAND gate inputs to the bus
|
||||
rbl_in_map = zip(["A", "B"], ["gated_clk_bar", "we_bar"])
|
||||
self.connect_vertical_bus(rbl_in_map, self.rbl_in_inst, self.rail_offsets)
|
||||
self.connect_vertical_bus(rbl_in_map, self.rbl_inst, self.rail_offsets)
|
||||
|
||||
|
||||
# Connect the output of the precharge enable to the RBL input
|
||||
if self.port_type == "rw":
|
||||
out_pos = self.rbl_in_inst.get_pin("Z").center()
|
||||
else:
|
||||
out_pos = vector(self.rail_offsets["gated_clk_bar"].x, self.rbl_inst.by()-3*self.m2_pitch)
|
||||
in_pos = self.rbl_inst.get_pin("en").center()
|
||||
mid1 = vector(in_pos.x,out_pos.y)
|
||||
self.add_wire(("metal3","via2","metal2"),[out_pos, mid1, in_pos])
|
||||
self.add_via_center(layers=("metal1","via1","metal2"),
|
||||
offset=out_pos)
|
||||
self.add_via_center(layers=("metal2","via2","metal3"),
|
||||
offset=out_pos)
|
||||
#if self.port_type == "rw":
|
||||
# out_pos = self.rbl_in_inst.get_pin("Z").center()
|
||||
#else:
|
||||
# out_pos = vector(self.rail_offsets["gated_clk_bar"].x, self.rbl_inst.by()-3*self.m2_pitch)
|
||||
|
||||
self.copy_layout_pin(self.rbl_inst, "Z", "rbl_wl")
|
||||
|
||||
self.copy_layout_pin(self.delay_inst, "in", "rbl_bl")
|
||||
|
||||
def create_pen_row(self):
|
||||
if self.port_type == "rw":
|
||||
|
|
@ -698,7 +695,7 @@ class control_logic(design.design):
|
|||
|
||||
def route_sen(self):
|
||||
|
||||
out_pos = self.rbl_inst.get_pin("out").bc()
|
||||
out_pos = self.delay_inst.get_pin("out").bc()
|
||||
in_pos = self.s_en_inst.get_pin("A").lc()
|
||||
mid1 = vector(out_pos.x,in_pos.y)
|
||||
self.add_wire(("metal1","via1","metal2"),[out_pos, mid1,in_pos])
|
||||
|
|
@ -817,8 +814,8 @@ class control_logic(design.design):
|
|||
self.add_path("metal1", [row_loc, pin_loc])
|
||||
|
||||
if (self.port_type == "rw") or (self.port_type == "r"):
|
||||
self.copy_layout_pin(self.rbl_inst,"gnd")
|
||||
self.copy_layout_pin(self.rbl_inst,"vdd")
|
||||
self.copy_layout_pin(self.delay_inst,"gnd")
|
||||
self.copy_layout_pin(self.delay_inst,"vdd")
|
||||
|
||||
self.copy_layout_pin(self.ctrl_dff_inst,"gnd")
|
||||
self.copy_layout_pin(self.ctrl_dff_inst,"vdd")
|
||||
|
|
@ -844,7 +841,7 @@ class control_logic(design.design):
|
|||
# height=pin.height(),
|
||||
# width=pin.width())
|
||||
|
||||
pin=self.rbl_inst.get_pin("out")
|
||||
pin=self.delay_inst.get_pin("out")
|
||||
self.add_label_pin(text="out",
|
||||
layer=pin.layer,
|
||||
offset=pin.ll(),
|
||||
|
|
|
|||
|
|
@ -427,3 +427,8 @@ class replica_bitcell_array(design.design):
|
|||
bitcell_wl_cin = self.cell.get_wl_cin()
|
||||
total_cin = bitcell_wl_cin * self.column_size
|
||||
return total_cin
|
||||
|
||||
def graph_exclude_bits(self, targ_row, targ_col):
|
||||
"""Excludes bits in column from being added to graph except target"""
|
||||
self.bitcell_array.graph_exclude_bits(targ_row, targ_col)
|
||||
|
||||
|
|
|
|||
|
|
@ -43,11 +43,11 @@ class options(optparse.Values):
|
|||
###################
|
||||
# Optimization options
|
||||
###################
|
||||
rbl_delay_percentage = .5 #Approximate percentage of delay compared to bitlines
|
||||
rbl_delay_percentage = 0.5 #Approximate percentage of delay compared to bitlines
|
||||
|
||||
# Allow manual adjustment of the delay chain over automatic
|
||||
use_tech_delay_chain_size = False
|
||||
delay_chain_stages = 4
|
||||
delay_chain_stages = 5
|
||||
delay_chain_fanout_per_stage = 3
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -243,6 +243,8 @@ class sram_1bank(sram_base):
|
|||
# The clock gets routed separately and is not a part of the bank
|
||||
if "clk" in signal:
|
||||
continue
|
||||
if signal.startswith("rbl"):
|
||||
continue
|
||||
src_pin = self.control_logic_insts[port].get_pin(signal)
|
||||
dest_pin = self.bank_inst.get_pin(signal+"{}".format(port))
|
||||
self.connect_rail_from_left_m2m3(src_pin, dest_pin)
|
||||
|
|
@ -364,4 +366,4 @@ class sram_1bank(sram_base):
|
|||
#Sanity check in case it was forgotten
|
||||
if inst_name.find('x') != 0:
|
||||
inst_name = 'x'+inst_name
|
||||
return self.bank_inst.mod.get_cell_name(inst_name+'.x'+self.bank_inst.name, row, col)
|
||||
return self.bank_inst.mod.get_cell_name(inst_name+'.x'+self.bank_inst.name, row, col)
|
||||
|
|
|
|||
|
|
@ -283,8 +283,7 @@ class sram_base(design, verilog, lef):
|
|||
# Create the bank module (up to four are instantiated)
|
||||
from bank import bank
|
||||
self.bank = bank(self.sram_config,
|
||||
name="bank",
|
||||
num_ports=len(self.all_ports))
|
||||
name="bank")
|
||||
self.add_mod(self.bank)
|
||||
|
||||
# Create bank decoder
|
||||
|
|
@ -331,6 +330,10 @@ class sram_base(design, verilog, lef):
|
|||
for port in self.read_ports:
|
||||
for bit in range(self.word_size):
|
||||
temp.append("DOUT{0}[{1}]".format(port,bit))
|
||||
for port in self.read_ports:
|
||||
temp.append("rbl_bl{0}".format(port))
|
||||
for port in self.read_ports:
|
||||
temp.append("rbl_wl{0}".format(port))
|
||||
for port in self.write_ports:
|
||||
for bit in range(self.word_size):
|
||||
temp.append("BANK_DIN{0}[{1}]".format(port,bit))
|
||||
|
|
@ -465,8 +468,12 @@ class sram_base(design, verilog, lef):
|
|||
if port in self.readwrite_ports:
|
||||
temp.append("web{}".format(port))
|
||||
temp.append("clk{}".format(port))
|
||||
if port in self.read_ports:
|
||||
temp.append("rbl_bl{}".format(port))
|
||||
|
||||
# Ouputs
|
||||
if port in self.read_ports:
|
||||
temp.append("rbl_wl{}".format(port))
|
||||
if port in self.read_ports:
|
||||
temp.append("s_en{}".format(port))
|
||||
if port in self.write_ports:
|
||||
|
|
|
|||
|
|
@ -53,8 +53,6 @@ class psram_1bank_2mux_1rw_1r_1w_func_test(openram_test):
|
|||
|
||||
corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
|
||||
f = functional(s.s, tempspice, corner)
|
||||
d = delay(s.s, tempspice, corner)
|
||||
feasible_period = self.find_feasible_test_period(d, s.s, f.load, f.slew)
|
||||
|
||||
f.num_cycles = 10
|
||||
(fail, error) = f.run()
|
||||
|
|
|
|||
|
|
@ -53,8 +53,6 @@ class psram_1bank_4mux_func_test(openram_test):
|
|||
|
||||
corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
|
||||
f = functional(s.s, tempspice, corner)
|
||||
d = delay(s.s, tempspice, corner)
|
||||
feasible_period = self.find_feasible_test_period(d, s.s, f.load, f.slew)
|
||||
|
||||
f.num_cycles = 10
|
||||
(fail, error) = f.run()
|
||||
|
|
|
|||
|
|
@ -53,8 +53,6 @@ class psram_1bank_8mux_func_test(openram_test):
|
|||
|
||||
corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
|
||||
f = functional(s.s, tempspice, corner)
|
||||
d = delay(s.s, tempspice, corner)
|
||||
feasible_period = self.find_feasible_test_period(d, s.s, f.load, f.slew)
|
||||
|
||||
f.num_cycles = 10
|
||||
(fail, error) = f.run()
|
||||
|
|
|
|||
|
|
@ -53,8 +53,6 @@ class psram_1bank_nomux_func_test(openram_test):
|
|||
|
||||
corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
|
||||
f = functional(s.s, tempspice, corner)
|
||||
d = delay(s.s, tempspice, corner)
|
||||
feasible_period = self.find_feasible_test_period(d, s.s, f.load, f.slew)
|
||||
|
||||
f.num_cycles = 10
|
||||
(fail, error) = f.run()
|
||||
|
|
|
|||
|
|
@ -45,11 +45,9 @@ class sram_1bank_2mux_func_test(openram_test):
|
|||
|
||||
corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
|
||||
f = functional(s.s, tempspice, corner)
|
||||
d = delay(s.s, tempspice, corner)
|
||||
feasible_period = self.find_feasible_test_period(d, s.s, f.load, f.slew)
|
||||
|
||||
f.num_cycles = 10
|
||||
(fail, error) = f.run(feasible_period)
|
||||
(fail, error) = f.run()
|
||||
self.assertTrue(fail,error)
|
||||
|
||||
globals.end_openram()
|
||||
|
|
|
|||
|
|
@ -45,8 +45,6 @@ class sram_1bank_4mux_func_test(openram_test):
|
|||
|
||||
corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
|
||||
f = functional(s.s, tempspice, corner)
|
||||
d = delay(s.s, tempspice, corner)
|
||||
feasible_period = self.find_feasible_test_period(d, s.s, f.load, f.slew)
|
||||
|
||||
f.num_cycles = 10
|
||||
(fail, error) = f.run()
|
||||
|
|
|
|||
|
|
@ -48,8 +48,6 @@ class sram_1bank_8mux_func_test(openram_test):
|
|||
|
||||
corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
|
||||
f = functional(s.s, tempspice, corner)
|
||||
d = delay(s.s, tempspice, corner)
|
||||
feasible_period = self.find_feasible_test_period(d, s.s, f.load, f.slew)
|
||||
|
||||
f.num_cycles = 10
|
||||
(fail, error) = f.run()
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ class openram_test(unittest.TestCase):
|
|||
self.fail("LVS mismatch: {}".format(a.name))
|
||||
|
||||
# For debug...
|
||||
#import pdb; pdb.set_trace()
|
||||
import pdb; pdb.set_trace()
|
||||
if OPTS.purge_temp:
|
||||
self.cleanup()
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue