mirror of https://github.com/VLSIDA/OpenRAM.git
Merge branch 'dev' into add_wmask
This commit is contained in:
commit
9409f60237
|
|
@ -835,6 +835,7 @@ class delay(simulation):
|
|||
Checks the measurements which represent the internal storage voltages
|
||||
at the end of the read cycle.
|
||||
"""
|
||||
success = False
|
||||
for polarity, meas_list in self.bit_meas.items():
|
||||
for meas in meas_list:
|
||||
val = meas.retrieve_measure()
|
||||
|
|
@ -855,12 +856,11 @@ class delay(simulation):
|
|||
elif (meas_cycle == sram_op.WRITE_ONE and polarity == bit_polarity.INVERTING) or\
|
||||
(meas_cycle == sram_op.WRITE_ZERO and polarity == bit_polarity.NONINVERTING):
|
||||
success = val < self.vdd_voltage/2
|
||||
else:
|
||||
success = False
|
||||
if not success:
|
||||
debug.info(1,("Wrong value detected on probe bit during read/write cycle. "
|
||||
"Check writes and control logic for bugs.\n measure={}, op={}, "
|
||||
"bit_storage={}, V(bit)={}").format(meas.name, meas_cycle.name, polarity.name,val))
|
||||
|
||||
return success
|
||||
|
||||
def check_bitline_meas(self, v_discharged_bl, v_charged_bl):
|
||||
|
|
|
|||
|
|
@ -25,9 +25,6 @@ class simulation():
|
|||
self.word_size = self.sram.word_size
|
||||
self.addr_size = self.sram.addr_size
|
||||
self.write_size = self.sram.write_size
|
||||
self.num_cols = self.sram.num_cols
|
||||
self.num_rows = self.sram.num_rows
|
||||
self.num_banks = self.sram.num_banks
|
||||
self.sp_file = spfile
|
||||
|
||||
self.all_ports = self.sram.all_ports
|
||||
|
|
@ -262,19 +259,21 @@ class simulation():
|
|||
t_current+self.period)
|
||||
elif op == "partial_write":
|
||||
comment = "\tWriting (partial) {0} to address {1} with mask bit {2} (from port {3}) during cycle {4} ({5}ns - {6}ns)".format(word,
|
||||
addr,
|
||||
wmask,
|
||||
port,
|
||||
int(t_current / self.period),
|
||||
t_current,
|
||||
t_current + self.period)
|
||||
addr,
|
||||
wmask,
|
||||
port,
|
||||
int(t_current / self.period),
|
||||
t_current,
|
||||
t_current + self.period)
|
||||
else:
|
||||
comment = "\tReading {0} from address {1} (from port {2}) during cycle {3} ({4}ns - {5}ns)".format(word,
|
||||
addr,
|
||||
port,
|
||||
int(t_current/self.period),
|
||||
t_current,
|
||||
t_current+self.period)
|
||||
addr,
|
||||
port,
|
||||
int(t_current/self.period),
|
||||
t_current,
|
||||
t_current+self.period)
|
||||
|
||||
|
||||
return comment
|
||||
|
||||
def gen_pin_names(self, port_signal_names, port_info, abits, dbits):
|
||||
|
|
|
|||
|
|
@ -84,8 +84,6 @@ class bank(design.design):
|
|||
self.add_pin("dout{0}_{1}".format(port,bit),"OUTPUT")
|
||||
for port in self.read_ports:
|
||||
self.add_pin(self.bitcell_array.get_rbl_bl_name(self.port_rbl_map[port]),"OUTPUT")
|
||||
for port in self.read_ports:
|
||||
self.add_pin(self.bitcell_array.get_rbl_wl_name(self.port_rbl_map[port]),"INPUT")
|
||||
for port in self.write_ports:
|
||||
for bit in range(self.word_size):
|
||||
self.add_pin("din{0}_{1}".format(port,bit),"INPUT")
|
||||
|
|
@ -306,13 +304,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), "rbl_wl{}".format(port_num)])
|
||||
self.input_control_signals.append(["w_en{}".format(port_num), "s_en{}".format(port_num), "p_en_bar{}".format(port_num), "wl_en{}".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), "p_en_bar{}".format(port_num)])
|
||||
self.input_control_signals.append(["w_en{}".format(port_num), "p_en_bar{}".format(port_num), "wl_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), "rbl_wl{}".format(port_num)])
|
||||
self.input_control_signals.append(["s_en{}".format(port_num), "p_en_bar{}".format(port_num), "wl_en{}".format(port_num)])
|
||||
port_num += 1
|
||||
|
||||
# Number of control lines in the bus for each port
|
||||
|
|
@ -422,9 +420,9 @@ class bank(design.design):
|
|||
for row in range(self.num_rows):
|
||||
for wordline in self.wl_names:
|
||||
temp.append("{0}_{1}".format(wordline,row))
|
||||
for rbl in range(self.num_rbl):
|
||||
rbl_wl_name=self.bitcell_array.get_rbl_wl_name(rbl)
|
||||
temp.append(rbl_wl_name)
|
||||
for port in self.all_ports:
|
||||
if self.port_data[port].has_rbl():
|
||||
temp.append("wl_en{0}".format(port))
|
||||
temp.append("vdd")
|
||||
temp.append("gnd")
|
||||
self.connect_inst(temp)
|
||||
|
|
@ -947,7 +945,7 @@ class bank(design.design):
|
|||
|
||||
if port in self.read_ports:
|
||||
rbl_wl_name = self.bitcell_array.get_rbl_wl_name(self.port_rbl_map[port])
|
||||
connection.append((self.prefix+"rbl_wl{}".format(port), self.bitcell_array_inst.get_pin(rbl_wl_name).lc()))
|
||||
connection.append((self.prefix+"wl_en{}".format(port), self.bitcell_array_inst.get_pin(rbl_wl_name).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()))
|
||||
|
|
@ -967,10 +965,10 @@ class bank(design.design):
|
|||
control_signal = self.prefix+"wl_en{}".format(port)
|
||||
if port%2:
|
||||
pin_pos = self.port_address_inst[port].get_pin("wl_en").uc()
|
||||
mid_pos = pin_pos + vector(0,self.m2_gap) # to route down to the top of the bus
|
||||
mid_pos = pin_pos + vector(0,2*self.m2_gap) # to route down to the top of the bus
|
||||
else:
|
||||
pin_pos = self.port_address_inst[port].get_pin("wl_en").bc()
|
||||
mid_pos = pin_pos - vector(0,self.m2_gap) # to route down to the top of the bus
|
||||
mid_pos = pin_pos - vector(0,2*self.m2_gap) # to route down to the top of the bus
|
||||
control_x_offset = self.bus_xoffset[port][control_signal].x
|
||||
control_pos = vector(control_x_offset, mid_pos.y)
|
||||
self.add_wire(("metal1","via1","metal2"),[pin_pos, mid_pos, control_pos])
|
||||
|
|
|
|||
|
|
@ -77,12 +77,12 @@ class bitcell_array(design.design):
|
|||
column_list = self.cell.get_all_bitline_names()
|
||||
for col in range(self.column_size):
|
||||
for cell_column in column_list:
|
||||
self.add_pin(cell_column+"_{0}".format(col))
|
||||
self.add_pin(cell_column+"_{0}".format(col), "INOUT")
|
||||
for row in range(self.row_size):
|
||||
for cell_row in row_list:
|
||||
self.add_pin(cell_row+"_{0}".format(row))
|
||||
self.add_pin("vdd")
|
||||
self.add_pin("gnd")
|
||||
self.add_pin(cell_row+"_{0}".format(row), "INPUT")
|
||||
self.add_pin("vdd", "POWER")
|
||||
self.add_pin("gnd", "GROUND")
|
||||
|
||||
def add_modules(self):
|
||||
""" Add the modules used in this design """
|
||||
|
|
|
|||
|
|
@ -101,17 +101,23 @@ class control_logic(design.design):
|
|||
self.add_mod(self.rbl_driver)
|
||||
|
||||
|
||||
# clk_buf drives a flop for every address and control bit
|
||||
# clk_buf drives a flop for every address
|
||||
addr_flops = math.log(self.num_words,2) + math.log(self.words_per_row,2)
|
||||
# plus data flops and control flops
|
||||
num_flops = addr_flops + self.word_size + self.num_control_signals
|
||||
# each flop internally has a FO 5 approximately
|
||||
# plus about 5 fanouts for the control logic
|
||||
# each flop internally has a FO 4 approximately
|
||||
clock_fanout = 4*(math.log(self.num_words,2) + math.log(self.words_per_row,2) \
|
||||
+ self.num_control_signals) + 5
|
||||
clock_fanout = 5*num_flops + 5
|
||||
self.clk_buf_driver = factory.create(module_type="pdriver",
|
||||
fanout=clock_fanout,
|
||||
height=dff_height)
|
||||
|
||||
self.add_mod(self.clk_buf_driver)
|
||||
|
||||
# We will use the maximum since this same value is used to size the wl_en
|
||||
# and the p_en_bar drivers
|
||||
max_fanout = max(self.num_rows,self.num_cols)
|
||||
|
||||
# wl_en drives every row in the bank
|
||||
self.wl_en_driver = factory.create(module_type="pdriver",
|
||||
fanout=self.num_rows,
|
||||
|
|
@ -132,14 +138,16 @@ class control_logic(design.design):
|
|||
|
||||
# used to generate inverted signals with low fanout
|
||||
self.inv = factory.create(module_type="pinv",
|
||||
size=1,
|
||||
height=dff_height)
|
||||
size=1,
|
||||
height=dff_height)
|
||||
self.add_mod(self.inv)
|
||||
|
||||
# p_en_bar drives every column in the bitcell array
|
||||
# but it is sized the same as the wl_en driver with
|
||||
# prepended 3 inverter stages to guarantee it is slower and odd polarity
|
||||
self.p_en_bar_driver = factory.create(module_type="pdriver",
|
||||
neg_polarity=True,
|
||||
fanout=self.num_cols,
|
||||
neg_polarity=True,
|
||||
height=dff_height)
|
||||
self.add_mod(self.p_en_bar_driver)
|
||||
|
||||
|
|
@ -184,6 +192,7 @@ class control_logic(design.design):
|
|||
# self.sen_delay_rise,self.sen_delay_fall = self.get_delays_to_sen() #get the new timing
|
||||
# self.delay_chain_resized = True
|
||||
|
||||
debug.check(OPTS.delay_chain_stages%2, "Must use odd number of delay chain stages for inverting delay chain.")
|
||||
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)
|
||||
|
|
@ -345,9 +354,9 @@ class control_logic(design.design):
|
|||
|
||||
# Outputs to the bank
|
||||
if self.port_type == "rw":
|
||||
self.output_list = ["rbl_wl", "s_en", "w_en"]
|
||||
self.output_list = ["s_en", "w_en"]
|
||||
elif self.port_type == "r":
|
||||
self.output_list = ["rbl_wl", "s_en"]
|
||||
self.output_list = ["s_en"]
|
||||
else:
|
||||
self.output_list = ["w_en"]
|
||||
self.output_list.append("p_en_bar")
|
||||
|
|
@ -375,7 +384,6 @@ class control_logic(design.design):
|
|||
if (self.port_type == "rw") or (self.port_type == "w"):
|
||||
self.create_wen_row()
|
||||
if (self.port_type == "rw") or (self.port_type == "r"):
|
||||
self.create_rbl_row()
|
||||
self.create_sen_row()
|
||||
self.create_delay()
|
||||
self.create_pen_row()
|
||||
|
|
@ -409,9 +417,6 @@ class control_logic(design.design):
|
|||
height = self.w_en_gate_inst.uy()
|
||||
control_center_y = self.w_en_gate_inst.uy()
|
||||
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
|
||||
if (self.port_type == "rw") or (self.port_type == "r"):
|
||||
|
|
@ -440,7 +445,6 @@ 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()
|
||||
self.route_sen()
|
||||
self.route_pen()
|
||||
self.route_clk_buf()
|
||||
|
|
@ -595,42 +599,15 @@ class control_logic(design.design):
|
|||
|
||||
def route_wlen(self):
|
||||
wlen_map = zip(["A"], ["gated_clk_bar"])
|
||||
self.connect_vertical_bus(wlen_map, self.wl_en_inst, self.rail_offsets)
|
||||
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_row(self):
|
||||
|
||||
self.rbl_inst=self.add_inst(name="rbl_driver",
|
||||
mod=self.rbl_driver)
|
||||
# input: gated_clk_bar, output: rbl_wl
|
||||
self.connect_inst(["gated_clk_bar", "rbl_wl", "vdd", "gnd"])
|
||||
|
||||
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_inst.place(offset, mirror)
|
||||
|
||||
self.row_end_inst.append(self.rbl_inst)
|
||||
|
||||
def route_rbl(self):
|
||||
""" Connect the logic for the rbl_in generation """
|
||||
|
||||
rbl_in_map = zip(["A"], ["gated_clk_bar"])
|
||||
self.connect_vertical_bus(rbl_in_map, self.rbl_inst, self.rail_offsets)
|
||||
self.connect_output(self.rbl_inst, "Z", "rbl_wl")
|
||||
|
||||
# Input from RBL goes to the delay line for futher delay
|
||||
self.copy_layout_pin(self.delay_inst, "in", "rbl_bl")
|
||||
|
||||
def create_pen_row(self):
|
||||
input_name = "gated_clk_buf"
|
||||
|
||||
# input: pre_p_en, output: p_en_bar
|
||||
# input: gated_clk_bar, output: p_en_bar
|
||||
self.p_en_bar_inst=self.add_inst(name="inv_p_en_bar",
|
||||
mod=self.p_en_bar_driver)
|
||||
self.connect_inst([input_name, "p_en_bar", "vdd", "gnd"])
|
||||
self.connect_inst(["gated_clk_buf", "p_en_bar", "vdd", "gnd"])
|
||||
|
||||
|
||||
def place_pen_row(self,row):
|
||||
|
|
@ -689,6 +666,10 @@ class control_logic(design.design):
|
|||
self.add_wire(("metal1","via1","metal2"),[out_pos, mid1,in_pos])
|
||||
|
||||
self.connect_output(self.s_en_gate_inst, "Z", "s_en")
|
||||
|
||||
# Input from RBL goes to the delay line for futher delay
|
||||
self.copy_layout_pin(self.delay_inst, "in", "rbl_bl")
|
||||
|
||||
|
||||
|
||||
def create_wen_row(self):
|
||||
|
|
|
|||
|
|
@ -57,10 +57,10 @@ class delay_chain(design.design):
|
|||
|
||||
def add_pins(self):
|
||||
""" Add the pins of the delay chain"""
|
||||
self.add_pin("in")
|
||||
self.add_pin("out")
|
||||
self.add_pin("vdd")
|
||||
self.add_pin("gnd")
|
||||
self.add_pin("in", "INPUT")
|
||||
self.add_pin("out", "OUTPUT")
|
||||
self.add_pin("vdd", "POWER")
|
||||
self.add_pin("gnd", "GROUND")
|
||||
|
||||
def add_modules(self):
|
||||
self.inv = factory.create(module_type="pinv", route_output=False)
|
||||
|
|
|
|||
|
|
@ -54,13 +54,13 @@ class dff_array(design.design):
|
|||
def add_pins(self):
|
||||
for row in range(self.rows):
|
||||
for col in range(self.columns):
|
||||
self.add_pin(self.get_din_name(row,col))
|
||||
self.add_pin(self.get_din_name(row,col), "INPUT")
|
||||
for row in range(self.rows):
|
||||
for col in range(self.columns):
|
||||
self.add_pin(self.get_dout_name(row,col))
|
||||
self.add_pin("clk")
|
||||
self.add_pin("vdd")
|
||||
self.add_pin("gnd")
|
||||
self.add_pin(self.get_dout_name(row,col), "OUTPUT")
|
||||
self.add_pin("clk", "INPUT")
|
||||
self.add_pin("vdd", "POWER")
|
||||
self.add_pin("gnd", "GROUND")
|
||||
|
||||
def create_dff_array(self):
|
||||
self.dff_insts={}
|
||||
|
|
|
|||
|
|
@ -75,12 +75,12 @@ class dff_buf(design.design):
|
|||
|
||||
|
||||
def add_pins(self):
|
||||
self.add_pin("D")
|
||||
self.add_pin("Q")
|
||||
self.add_pin("Qb")
|
||||
self.add_pin("clk")
|
||||
self.add_pin("vdd")
|
||||
self.add_pin("gnd")
|
||||
self.add_pin("D", "INPUT")
|
||||
self.add_pin("Q", "OUTPUT")
|
||||
self.add_pin("Qb", "OUTPUT")
|
||||
self.add_pin("clk", "INPUT")
|
||||
self.add_pin("vdd", "POWER")
|
||||
self.add_pin("gnd", "GROUND")
|
||||
|
||||
def create_instances(self):
|
||||
self.dff_inst=self.add_inst(name="dff_buf_dff",
|
||||
|
|
|
|||
|
|
@ -55,14 +55,14 @@ class dff_buf_array(design.design):
|
|||
def add_pins(self):
|
||||
for row in range(self.rows):
|
||||
for col in range(self.columns):
|
||||
self.add_pin(self.get_din_name(row,col))
|
||||
self.add_pin(self.get_din_name(row,col), "INPUT")
|
||||
for row in range(self.rows):
|
||||
for col in range(self.columns):
|
||||
self.add_pin(self.get_dout_name(row,col))
|
||||
self.add_pin(self.get_dout_bar_name(row,col))
|
||||
self.add_pin("clk")
|
||||
self.add_pin("vdd")
|
||||
self.add_pin("gnd")
|
||||
self.add_pin(self.get_dout_name(row,col), "OUTPUT")
|
||||
self.add_pin(self.get_dout_bar_name(row,col), "OUTPUT")
|
||||
self.add_pin("clk", "INPUT")
|
||||
self.add_pin("vdd", "POWER")
|
||||
self.add_pin("gnd", "GROUND")
|
||||
|
||||
def add_modules(self):
|
||||
self.dff = factory.create(module_type="dff_buf",
|
||||
|
|
|
|||
|
|
@ -59,14 +59,14 @@ class dff_inv_array(design.design):
|
|||
def add_pins(self):
|
||||
for row in range(self.rows):
|
||||
for col in range(self.columns):
|
||||
self.add_pin(self.get_din_name(row,col))
|
||||
self.add_pin(self.get_din_name(row,col), "INPUT")
|
||||
for row in range(self.rows):
|
||||
for col in range(self.columns):
|
||||
self.add_pin(self.get_dout_name(row,col))
|
||||
self.add_pin(self.get_dout_bar_name(row,col))
|
||||
self.add_pin("clk")
|
||||
self.add_pin("vdd")
|
||||
self.add_pin("gnd")
|
||||
self.add_pin(self.get_dout_name(row,col), "OUTPUT")
|
||||
self.add_pin(self.get_dout_bar_name(row,col), "OUTPUT")
|
||||
self.add_pin("clk", "INPUT")
|
||||
self.add_pin("vdd", "POWER")
|
||||
self.add_pin("gnd", "GROUND")
|
||||
|
||||
def create_dff_array(self):
|
||||
self.dff_insts={}
|
||||
|
|
|
|||
|
|
@ -70,12 +70,12 @@ class dummy_array(design.design):
|
|||
column_list = self.cell.get_all_bitline_names()
|
||||
for col in range(self.column_size):
|
||||
for cell_column in column_list:
|
||||
self.add_pin(cell_column+"_{0}".format(col))
|
||||
self.add_pin(cell_column+"_{0}".format(col), "INOUT")
|
||||
for row in range(self.row_size):
|
||||
for cell_row in row_list:
|
||||
self.add_pin(cell_row+"_{0}".format(row))
|
||||
self.add_pin("vdd")
|
||||
self.add_pin("gnd")
|
||||
self.add_pin(cell_row+"_{0}".format(row), "INPUT")
|
||||
self.add_pin("vdd", "POWER")
|
||||
self.add_pin("gnd", "GROUND")
|
||||
|
||||
def add_modules(self):
|
||||
""" Add the modules used in this design """
|
||||
|
|
|
|||
|
|
@ -231,12 +231,12 @@ class hierarchical_decoder(design.design):
|
|||
""" Add the module pins """
|
||||
|
||||
for i in range(self.num_inputs):
|
||||
self.add_pin("addr_{0}".format(i))
|
||||
self.add_pin("addr_{0}".format(i), "INPUT")
|
||||
|
||||
for j in range(self.rows):
|
||||
self.add_pin("decode_{0}".format(j))
|
||||
self.add_pin("vdd")
|
||||
self.add_pin("gnd")
|
||||
self.add_pin("decode_{0}".format(j), "OUTPUT")
|
||||
self.add_pin("vdd", "POWER")
|
||||
self.add_pin("gnd", "GROUND")
|
||||
|
||||
|
||||
def create_pre_decoder(self):
|
||||
|
|
|
|||
|
|
@ -26,11 +26,11 @@ class hierarchical_predecode(design.design):
|
|||
|
||||
def add_pins(self):
|
||||
for k in range(self.number_of_inputs):
|
||||
self.add_pin("in_{0}".format(k))
|
||||
self.add_pin("in_{0}".format(k), "INPUT")
|
||||
for i in range(self.number_of_outputs):
|
||||
self.add_pin("out_{0}".format(i))
|
||||
self.add_pin("vdd")
|
||||
self.add_pin("gnd")
|
||||
self.add_pin("out_{0}".format(i), "OUTPUT")
|
||||
self.add_pin("vdd", "POWER")
|
||||
self.add_pin("gnd", "GROUND")
|
||||
|
||||
def add_modules(self):
|
||||
""" Add the INV and NAND gate modules """
|
||||
|
|
|
|||
|
|
@ -35,10 +35,11 @@ class precharge_array(design.design):
|
|||
def add_pins(self):
|
||||
"""Adds pins for spice file"""
|
||||
for i in range(self.columns):
|
||||
self.add_pin("bl_{0}".format(i))
|
||||
self.add_pin("br_{0}".format(i))
|
||||
self.add_pin("en_bar")
|
||||
self.add_pin("vdd")
|
||||
# These are outputs from the precharge only
|
||||
self.add_pin("bl_{0}".format(i), "OUTPUT")
|
||||
self.add_pin("br_{0}".format(i), "OUTPUT")
|
||||
self.add_pin("en_bar", "INPUT")
|
||||
self.add_pin("vdd", "POWER")
|
||||
|
||||
def create_netlist(self):
|
||||
self.add_modules()
|
||||
|
|
@ -115,4 +116,4 @@ class precharge_array(design.design):
|
|||
#Assume single port
|
||||
precharge_en_cin = self.pc_cell.get_en_cin()
|
||||
return precharge_en_cin*self.columns
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -55,14 +55,15 @@ class replica_column(design.design):
|
|||
def add_pins(self):
|
||||
|
||||
for bl_name in self.cell.get_all_bitline_names():
|
||||
self.add_pin("{0}_{1}".format(bl_name,0))
|
||||
# In the replica column, these are only outputs!
|
||||
self.add_pin("{0}_{1}".format(bl_name,0), "OUTPUT")
|
||||
|
||||
for row in range(self.total_size):
|
||||
for wl_name in self.cell.get_all_wl_names():
|
||||
self.add_pin("{0}_{1}".format(wl_name,row))
|
||||
self.add_pin("{0}_{1}".format(wl_name,row), "INPUT")
|
||||
|
||||
self.add_pin("vdd")
|
||||
self.add_pin("gnd")
|
||||
self.add_pin("vdd", "POWER")
|
||||
self.add_pin("gnd", "GROUND")
|
||||
|
||||
def add_modules(self):
|
||||
self.replica_cell = factory.create(module_type="replica_bitcell")
|
||||
|
|
|
|||
|
|
@ -55,12 +55,12 @@ class sense_amp_array(design.design):
|
|||
|
||||
def add_pins(self):
|
||||
for i in range(0,self.word_size):
|
||||
self.add_pin("data_{0}".format(i))
|
||||
self.add_pin("bl_{0}".format(i))
|
||||
self.add_pin("br_{0}".format(i))
|
||||
self.add_pin("en")
|
||||
self.add_pin("vdd")
|
||||
self.add_pin("gnd")
|
||||
self.add_pin("data_{0}".format(i), "OUTPUT")
|
||||
self.add_pin("bl_{0}".format(i), "INPUT")
|
||||
self.add_pin("br_{0}".format(i), "INPUT")
|
||||
self.add_pin("en", "INPUT")
|
||||
self.add_pin("vdd", "POWER")
|
||||
self.add_pin("gnd", "GROUND")
|
||||
|
||||
def add_modules(self):
|
||||
self.amp = factory.create(module_type="sense_amp")
|
||||
|
|
|
|||
|
|
@ -50,13 +50,13 @@ class wordline_driver(design.design):
|
|||
def add_pins(self):
|
||||
# inputs to wordline_driver.
|
||||
for i in range(self.rows):
|
||||
self.add_pin("in_{0}".format(i))
|
||||
self.add_pin("in_{0}".format(i), "INPUT")
|
||||
# Outputs from wordline_driver.
|
||||
for i in range(self.rows):
|
||||
self.add_pin("wl_{0}".format(i))
|
||||
self.add_pin("en")
|
||||
self.add_pin("vdd")
|
||||
self.add_pin("gnd")
|
||||
self.add_pin("wl_{0}".format(i), "OUTPUT")
|
||||
self.add_pin("en", "INPUT")
|
||||
self.add_pin("vdd", "POWER")
|
||||
self.add_pin("gnd", "GROUND")
|
||||
|
||||
|
||||
def add_modules(self):
|
||||
|
|
|
|||
|
|
@ -59,17 +59,17 @@ class write_driver_array(design.design):
|
|||
|
||||
def add_pins(self):
|
||||
for i in range(self.word_size):
|
||||
self.add_pin("data_{0}".format(i))
|
||||
self.add_pin("data_{0}".format(i), "INPUT")
|
||||
for i in range(self.word_size):
|
||||
self.add_pin("bl_{0}".format(i))
|
||||
self.add_pin("br_{0}".format(i))
|
||||
self.add_pin("bl_{0}".format(i), "OUTPUT")
|
||||
self.add_pin("br_{0}".format(i), "OUTPUT")
|
||||
if self.write_size != None:
|
||||
for i in range(self.num_wmasks):
|
||||
self.add_pin("en_{}".format(i))
|
||||
self.add_pin("en_{}".format(i), "INPUT")
|
||||
else:
|
||||
self.add_pin("en")
|
||||
self.add_pin("vdd")
|
||||
self.add_pin("gnd")
|
||||
self.add_pin("en", "INPUT")
|
||||
self.add_pin("vdd", "POWER")
|
||||
self.add_pin("gnd", "GROUND")
|
||||
|
||||
def add_modules(self):
|
||||
self.driver = factory.create(module_type="write_driver")
|
||||
|
|
|
|||
|
|
@ -51,8 +51,8 @@ class options(optparse.Values):
|
|||
|
||||
# Allow manual adjustment of the delay chain over automatic
|
||||
use_tech_delay_chain_size = False
|
||||
delay_chain_stages = 5
|
||||
delay_chain_fanout_per_stage = 3
|
||||
delay_chain_stages = 9
|
||||
delay_chain_fanout_per_stage = 4
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -47,11 +47,11 @@ class pand2(pgate.pgate):
|
|||
self.DRC_LVS()
|
||||
|
||||
def add_pins(self):
|
||||
self.add_pin("A")
|
||||
self.add_pin("B")
|
||||
self.add_pin("Z")
|
||||
self.add_pin("vdd")
|
||||
self.add_pin("gnd")
|
||||
self.add_pin("A", "INPUT")
|
||||
self.add_pin("B", "INPUT")
|
||||
self.add_pin("Z", "OUTPUT")
|
||||
self.add_pin("vdd", "POWER")
|
||||
self.add_pin("gnd", "GROUND")
|
||||
|
||||
def create_insts(self):
|
||||
self.nand_inst=self.add_inst(name="pand2_nand",
|
||||
|
|
|
|||
|
|
@ -42,10 +42,10 @@ class pbuf(pgate.pgate):
|
|||
self.add_layout_pins()
|
||||
|
||||
def add_pins(self):
|
||||
self.add_pin("A")
|
||||
self.add_pin("Z")
|
||||
self.add_pin("vdd")
|
||||
self.add_pin("gnd")
|
||||
self.add_pin("A", "INPUT")
|
||||
self.add_pin("Z", "OUTPUT")
|
||||
self.add_pin("vdd", "POWER")
|
||||
self.add_pin("gnd", "GROUND")
|
||||
|
||||
def create_modules(self):
|
||||
# Shield the cap, but have at least a stage effort of 4
|
||||
|
|
|
|||
|
|
@ -53,15 +53,15 @@ class pdriver(pgate.pgate):
|
|||
elif not self.neg_polarity and (self.num_stages%2):
|
||||
self.num_stages += 1
|
||||
|
||||
self.size_list = []
|
||||
# compute sizes backwards from the fanout
|
||||
fanout_prev = self.fanout
|
||||
for x in range(self.num_stages):
|
||||
fanout_prev = max(round(fanout_prev/self.stage_effort),1)
|
||||
self.size_list.append(fanout_prev)
|
||||
self.size_list = []
|
||||
# compute sizes backwards from the fanout
|
||||
fanout_prev = self.fanout
|
||||
for x in range(self.num_stages):
|
||||
fanout_prev = max(round(fanout_prev/self.stage_effort),1)
|
||||
self.size_list.append(fanout_prev)
|
||||
|
||||
# reverse the sizes to be from input to output
|
||||
self.size_list.reverse()
|
||||
# reverse the sizes to be from input to output
|
||||
self.size_list.reverse()
|
||||
|
||||
|
||||
def create_netlist(self):
|
||||
|
|
@ -81,10 +81,10 @@ class pdriver(pgate.pgate):
|
|||
|
||||
|
||||
def add_pins(self):
|
||||
self.add_pin("A")
|
||||
self.add_pin("Z")
|
||||
self.add_pin("vdd")
|
||||
self.add_pin("gnd")
|
||||
self.add_pin("A", "INPUT")
|
||||
self.add_pin("Z", "OUTPUT")
|
||||
self.add_pin("vdd", "POWER")
|
||||
self.add_pin("gnd", "GROUND")
|
||||
|
||||
def add_modules(self):
|
||||
self.inv_list = []
|
||||
|
|
@ -178,7 +178,7 @@ class pdriver(pgate.pgate):
|
|||
return self.inv_list[0].input_load()
|
||||
|
||||
def analytical_delay(self, corner, slew, load=0.0):
|
||||
"""Calculate the analytical delay of INV1 -> ... -> INVn"""
|
||||
""" Calculate the analytical delay of INV1 -> ... -> INVn """
|
||||
|
||||
cout_list = []
|
||||
for prev_inv,inv in zip(self.inv_list, self.inv_list[1:]):
|
||||
|
|
@ -198,9 +198,12 @@ class pdriver(pgate.pgate):
|
|||
|
||||
return delay
|
||||
|
||||
|
||||
def get_sizes(self):
|
||||
""" Return the relative sizes of the buffers """
|
||||
return self.size_list
|
||||
|
||||
def get_stage_efforts(self, external_cout, inp_is_rise=False):
|
||||
"""Get the stage efforts of the A -> Z path"""
|
||||
""" Get the stage efforts of the A -> Z path """
|
||||
cout_list = []
|
||||
for prev_inv,inv in zip(self.inv_list, self.inv_list[1:]):
|
||||
cout_list.append(inv.get_cin())
|
||||
|
|
@ -217,5 +220,5 @@ class pdriver(pgate.pgate):
|
|||
return stage_effort_list
|
||||
|
||||
def get_cin(self):
|
||||
"""Returns the relative capacitance of the input"""
|
||||
""" Returns the relative capacitance of the input """
|
||||
return self.inv_list[0].get_cin()
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ class pinv(pgate.pgate):
|
|||
def add_pins(self):
|
||||
""" Adds pins for spice netlist """
|
||||
pin_list = ["A", "Z", "vdd", "gnd"]
|
||||
dir_list = ['INPUT', 'OUTPUT', 'POWER', 'GROUND']
|
||||
dir_list = ["INPUT", "OUTPUT", "POWER", "GROUND"]
|
||||
self.add_pin_list(pin_list, dir_list)
|
||||
|
||||
|
||||
|
|
@ -300,4 +300,4 @@ class pinv(pgate.pgate):
|
|||
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ class pnand2(pgate.pgate):
|
|||
def add_pins(self):
|
||||
""" Adds pins for spice netlist """
|
||||
pin_list = ["A", "B", "Z", "vdd", "gnd"]
|
||||
dir_list = ['INPUT', 'INPUT', 'OUTPUT', 'POWER', 'GROUND']
|
||||
dir_list = ["INPUT", "INPUT", "OUTPUT", "POWER", "GROUND"]
|
||||
self.add_pin_list(pin_list, dir_list)
|
||||
|
||||
|
||||
|
|
@ -281,4 +281,4 @@ class pnand2(pgate.pgate):
|
|||
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ class pnand3(pgate.pgate):
|
|||
def add_pins(self):
|
||||
""" Adds pins for spice netlist """
|
||||
pin_list = ["A", "B", "C", "Z", "vdd", "gnd"]
|
||||
dir_list = ['INPUT', 'INPUT', 'INPUT', 'OUTPUT', 'POWER', 'GROUND']
|
||||
dir_list = ["INPUT", "INPUT", "INPUT", "OUTPUT", "POWER", "GROUND"]
|
||||
self.add_pin_list(pin_list, dir_list)
|
||||
|
||||
def create_netlist(self):
|
||||
|
|
@ -283,4 +283,4 @@ class pnand3(pgate.pgate):
|
|||
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ class pnor2(pgate.pgate):
|
|||
def add_pins(self):
|
||||
""" Adds pins for spice netlist """
|
||||
pin_list = ["A", "B", "Z", "vdd", "gnd"]
|
||||
dir_list = ['INPUT', 'INPUT', 'OUTPUT', 'INOUT', 'INOUT']
|
||||
dir_list = ["INPUT", "INPUT", "OUTPUT", "INOUT", "INOUT"]
|
||||
self.add_pin_list(pin_list, dir_list)
|
||||
|
||||
def create_netlist(self):
|
||||
|
|
@ -242,4 +242,4 @@ class pnor2(pgate.pgate):
|
|||
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ class precharge(design.design):
|
|||
self.connect_to_bitlines()
|
||||
|
||||
def add_pins(self):
|
||||
self.add_pin_list(["bl", "br", "en_bar", "vdd"])
|
||||
self.add_pin_list(["bl", "br", "en_bar", "vdd"], ["OUTPUT", "OUTPUT", "INPUT", "POWER"])
|
||||
|
||||
def add_ptx(self):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -341,8 +341,6 @@ class sram_base(design, verilog, lef):
|
|||
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))
|
||||
|
|
@ -506,9 +504,6 @@ class sram_base(design, verilog, lef):
|
|||
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:
|
||||
|
|
@ -530,7 +525,10 @@ class sram_base(design, verilog, lef):
|
|||
in_pos = src_pin.rc()
|
||||
else:
|
||||
in_pos = src_pin.lc()
|
||||
out_pos = dest_pin.center()
|
||||
if src_pin.cy() < dest_pin.cy():
|
||||
out_pos = dest_pin.bc()
|
||||
else:
|
||||
out_pos = dest_pin.uc()
|
||||
|
||||
# move horizontal first
|
||||
self.add_wire(("metal3","via2","metal2"),[in_pos, vector(out_pos.x,in_pos.y),out_pos])
|
||||
|
|
|
|||
|
|
@ -61,7 +61,6 @@ class sram_config:
|
|||
self.tentative_num_rows = self.num_bits_per_bank / (self.words_per_row*self.word_size)
|
||||
self.words_per_row = self.amend_words_per_row(self.tentative_num_rows, self.words_per_row)
|
||||
|
||||
debug.info(1,"Words per row: {}".format(self.words_per_row))
|
||||
self.recompute_sizes()
|
||||
|
||||
def recompute_sizes(self):
|
||||
|
|
@ -71,6 +70,8 @@ class sram_config:
|
|||
SRAM for testing.
|
||||
"""
|
||||
|
||||
debug.info(1,"Recomputing with words per row: {}".format(self.words_per_row))
|
||||
|
||||
# If the banks changed
|
||||
self.num_words_per_bank = self.num_words/self.num_banks
|
||||
self.num_bits_per_bank = self.word_size*self.num_words_per_bank
|
||||
|
|
@ -78,12 +79,16 @@ class sram_config:
|
|||
# Fix the number of columns and rows
|
||||
self.num_cols = int(self.words_per_row*self.word_size)
|
||||
self.num_rows = int(self.num_words_per_bank/self.words_per_row)
|
||||
debug.info(1,"Rows: {} Cols: {}".format(self.num_rows,self.num_cols))
|
||||
|
||||
# Compute the address and bank sizes
|
||||
self.row_addr_size = int(log(self.num_rows, 2))
|
||||
self.col_addr_size = int(log(self.words_per_row, 2))
|
||||
self.bank_addr_size = self.col_addr_size + self.row_addr_size
|
||||
self.addr_size = self.bank_addr_size + int(log(self.num_banks, 2))
|
||||
debug.info(1,"Row addr size: {}".format(self.row_addr_size)
|
||||
+ " Col addr size: {}".format(self.col_addr_size)
|
||||
+ " Bank addr size: {}".format(self.bank_addr_size))
|
||||
|
||||
|
||||
def estimate_words_per_row(self,tentative_num_cols, word_size):
|
||||
|
|
|
|||
|
|
@ -61,27 +61,27 @@ class timing_sram_test(openram_test):
|
|||
data.update(port_data[0])
|
||||
|
||||
if OPTS.tech_name == "freepdk45":
|
||||
golden_data = {'delay_hl': [0.2179763],
|
||||
'delay_lh': [0.2179763],
|
||||
'leakage_power': 0.0025727,
|
||||
'min_period': 0.527,
|
||||
'read0_power': [0.4479132],
|
||||
'read1_power': [0.422467],
|
||||
'slew_hl': [0.0988916],
|
||||
'slew_lh': [0.0988916],
|
||||
'write0_power': [0.4976688],
|
||||
'write1_power': [0.4605285]}
|
||||
golden_data = {'delay_hl': [0.2181231],
|
||||
'delay_lh': [0.2181231],
|
||||
'leakage_power': 0.0025453999999999997,
|
||||
'min_period': 0.781,
|
||||
'read0_power': [0.34664159999999994],
|
||||
'read1_power': [0.32656349999999995],
|
||||
'slew_hl': [0.21136519999999998],
|
||||
'slew_lh': [0.21136519999999998],
|
||||
'write0_power': [0.37980179999999997],
|
||||
'write1_power': [0.3532026]}
|
||||
elif OPTS.tech_name == "scn4m_subm":
|
||||
golden_data = {'delay_hl': [1.4119000000000002],
|
||||
'delay_lh': [1.4119000000000002],
|
||||
'leakage_power': 0.027366399999999996,
|
||||
'min_period': 3.125,
|
||||
'read0_power': [14.7569],
|
||||
'read1_power': [14.008800000000003],
|
||||
'slew_hl': [0.7314153],
|
||||
'slew_lh': [0.7314153],
|
||||
'write0_power': [16.700500000000005],
|
||||
'write1_power': [15.214100000000002]}
|
||||
golden_data = {'delay_hl': [1.4082],
|
||||
'delay_lh': [1.4082],
|
||||
'leakage_power': 0.0267388,
|
||||
'min_period': 4.688,
|
||||
'read0_power': [11.5255],
|
||||
'read1_power': [10.9406],
|
||||
'slew_hl': [1.2979],
|
||||
'slew_lh': [1.2979],
|
||||
'write0_power': [12.9458],
|
||||
'write1_power': [11.7444]}
|
||||
else:
|
||||
self.assertTrue(False) # other techs fail
|
||||
# Check if no too many or too few results
|
||||
|
|
|
|||
|
|
@ -54,27 +54,27 @@ class timing_sram_test(openram_test):
|
|||
data.update(port_data[0])
|
||||
|
||||
if OPTS.tech_name == "freepdk45":
|
||||
golden_data = {'delay_hl': [0.2265453],
|
||||
'delay_lh': [0.2265453],
|
||||
'leakage_power': 0.003688569,
|
||||
'min_period': 0.547,
|
||||
'read0_power': [0.4418831],
|
||||
'read1_power': [0.41914969999999996],
|
||||
'slew_hl': [0.103665],
|
||||
'slew_lh': [0.103665],
|
||||
'write0_power': [0.48889660000000007],
|
||||
'write1_power': [0.4419755]}
|
||||
golden_data = {'delay_hl': [0.22609590000000002],
|
||||
'delay_lh': [0.22609590000000002],
|
||||
'leakage_power': 0.003317743,
|
||||
'min_period': 0.859,
|
||||
'read0_power': [0.3271056],
|
||||
'read1_power': [0.3064244],
|
||||
'slew_hl': [0.2153979],
|
||||
'slew_lh': [0.2153979],
|
||||
'write0_power': [0.3532067],
|
||||
'write1_power': [0.3381259]}
|
||||
elif OPTS.tech_name == "scn4m_subm":
|
||||
golden_data = {'delay_hl': [1.710243],
|
||||
'delay_lh': [1.710243],
|
||||
'leakage_power': 0.06079017,
|
||||
'min_period': 3.75,
|
||||
'read0_power': [14.046140000000001],
|
||||
'read1_power': [13.52625],
|
||||
'slew_hl': [0.7730236],
|
||||
'slew_lh': [0.7730236],
|
||||
'write0_power': [15.86152],
|
||||
'write1_power': [14.612160000000001]}
|
||||
golden_data = {'delay_hl': [1.709791],
|
||||
'delay_lh': [1.709791],
|
||||
'leakage_power': 0.06803324999999999,
|
||||
'min_period': 7.812,
|
||||
'read0_power': [7.9499070000000005],
|
||||
'read1_power': [7.619662999999999],
|
||||
'slew_hl': [1.390261],
|
||||
'slew_lh': [1.390261],
|
||||
'write0_power': [8.913003],
|
||||
'write1_power': [8.166687000000001]}
|
||||
else:
|
||||
self.assertTrue(False) # other techs fail
|
||||
|
||||
|
|
|
|||
|
|
@ -37,8 +37,8 @@ class psram_1bank_2mux_func_test(openram_test):
|
|||
reload(characterizer)
|
||||
from characterizer import functional, delay
|
||||
from sram_config import sram_config
|
||||
c = sram_config(word_size=4,
|
||||
num_words=64,
|
||||
c = sram_config(word_size=2,
|
||||
num_words=32,
|
||||
num_banks=1)
|
||||
c.words_per_row=2
|
||||
c.recompute_sizes()
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ class psram_1bank_4mux_func_test(openram_test):
|
|||
reload(characterizer)
|
||||
from characterizer import functional, delay
|
||||
from sram_config import sram_config
|
||||
c = sram_config(word_size=4,
|
||||
c = sram_config(word_size=2,
|
||||
num_words=256,
|
||||
num_banks=1)
|
||||
c.words_per_row=4
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ class psram_1bank_nomux_func_test(openram_test):
|
|||
reload(characterizer)
|
||||
from characterizer import functional, delay
|
||||
from sram_config import sram_config
|
||||
c = sram_config(word_size=4,
|
||||
c = sram_config(word_size=2,
|
||||
num_words=32,
|
||||
num_banks=1)
|
||||
c.words_per_row=1
|
||||
|
|
|
|||
Loading…
Reference in New Issue