mirror of https://github.com/VLSIDA/OpenRAM.git
Changed the analytical delay model to accept multiport options. Little substance to the values generated.
This commit is contained in:
parent
6efe0f56c2
commit
98a00f985b
|
|
@ -884,3 +884,19 @@ class pbitcell(design.design):
|
|||
Q_bar_pos = self.inverter_pmos_right.get_pin("S").center()
|
||||
vdd_pos = self.inverter_pmos_right.get_pin("D").center()
|
||||
self.add_path("metal1", [Q_bar_pos, vdd_pos])
|
||||
|
||||
def analytical_delay(self, slew, load=0, swing = 0.5):
|
||||
#FIXME: Delay copied exactly over from bitcell
|
||||
from tech import spice
|
||||
r = spice["min_tx_r"]*3
|
||||
c_para = spice["min_tx_drain_c"]
|
||||
result = self.cal_delay_with_rc(r = r, c = c_para+load, slew = slew, swing = swing)
|
||||
return result
|
||||
|
||||
def analytical_power(self, proc, vdd, temp, load):
|
||||
"""Bitcell power in nW. Only characterizes leakage."""
|
||||
from tech import spice
|
||||
leakage = spice["bitcell_leakage"]
|
||||
dynamic = 0 #temporary
|
||||
total_power = self.return_power(dynamic, leakage)
|
||||
return total_power
|
||||
|
|
@ -807,46 +807,74 @@ class delay(simulation):
|
|||
#Add test cycle of read/write port pair. One port could have been used already, but the other has not.
|
||||
self.gen_test_cycles_one_port(cur_read_port, cur_write_port)
|
||||
|
||||
def analytical_delay(self,sram, slews, loads):
|
||||
def analytical_delay(self, slews, loads):
|
||||
""" Return the analytical model results for the SRAM.
|
||||
"""
|
||||
debug.check(OPTS.num_rw_ports < 2 and OPTS.num_w_ports < 1 and OPTS.num_r_ports < 1 ,
|
||||
"Analytical characterization does not currently support multiport.")
|
||||
if OPTS.num_rw_ports > 1 or OPTS.num_w_ports > 0 and OPTS.num_r_ports > 0:
|
||||
debug.warning("Analytical characterization results are not supported for multiport.")
|
||||
|
||||
delay_lh = []
|
||||
delay_hl = []
|
||||
slew_lh = []
|
||||
slew_hl = []
|
||||
power = self.analytical_power(slews, loads)
|
||||
port_data = self.get_empty_measure_data_dict()
|
||||
for slew in slews:
|
||||
for load in loads:
|
||||
self.set_load_slew(load,slew)
|
||||
bank_delay = sram.analytical_delay(self.vdd_voltage, self.slew,self.load)
|
||||
# Convert from ps to ns
|
||||
delay_lh.append(bank_delay.delay/1e3)
|
||||
delay_hl.append(bank_delay.delay/1e3)
|
||||
slew_lh.append(bank_delay.slew/1e3)
|
||||
slew_hl.append(bank_delay.slew/1e3)
|
||||
bank_delay = self.sram.analytical_delay(self.vdd_voltage, self.slew,self.load)
|
||||
for port in range(self.total_ports):
|
||||
for mname in self.delay_meas_names+self.power_meas_names:
|
||||
if "power" in mname:
|
||||
port_data[port][mname].append(power.dynamic)
|
||||
elif "delay" in mname:
|
||||
port_data[port][mname].append(bank_delay[port].delay/1e3)
|
||||
elif "slew" in mname:
|
||||
port_data[port][mname].append(bank_delay[port].slew/1e3)
|
||||
else:
|
||||
debug.error("Measurement name not recognized: {}".format(mname),1)
|
||||
sram_data = { "min_period": 0,
|
||||
"leakage_power": power.leakage}
|
||||
|
||||
return (sram_data,port_data)
|
||||
|
||||
power = sram.analytical_power(self.process, self.vdd_voltage, self.temperature, load)
|
||||
# delay_lh = []
|
||||
# delay_hl = []
|
||||
# slew_lh = []
|
||||
# slew_hl = []
|
||||
# for slew in slews:
|
||||
# for load in loads:
|
||||
# self.set_load_slew(load,slew)
|
||||
# bank_delay = sram.analytical_delay(self.vdd_voltage, self.slew,self.load)
|
||||
# # Convert from ps to ns
|
||||
# delay_lh.append(bank_delay.delay/1e3)
|
||||
# delay_hl.append(bank_delay.delay/1e3)
|
||||
# slew_lh.append(bank_delay.slew/1e3)
|
||||
# slew_hl.append(bank_delay.slew/1e3)
|
||||
|
||||
# power = self.analytical_power()
|
||||
|
||||
# sram_data = { "min_period": 0,
|
||||
# "leakage_power": power.leakage}
|
||||
# port_data = [{"delay_lh": delay_lh,
|
||||
# "delay_hl": delay_hl,
|
||||
# "slew_lh": slew_lh,
|
||||
# "slew_hl": slew_hl,
|
||||
# "read0_power": power.dynamic,
|
||||
# "read1_power": power.dynamic,
|
||||
# "write0_power": power.dynamic,
|
||||
# "write1_power": power.dynamic,
|
||||
# }]
|
||||
# return (sram_data,port_data)
|
||||
|
||||
def analytical_power(self, slews, loads):
|
||||
"""Get the dynamic and leakage power from the SRAM"""
|
||||
#slews unused, only last load is used
|
||||
load = loads[-1]
|
||||
power = self.sram.analytical_power(self.process, self.vdd_voltage, self.temperature, load)
|
||||
#convert from nW to mW
|
||||
power.dynamic /= 1e6
|
||||
power.leakage /= 1e6
|
||||
debug.info(1,"Dynamic Power: {0} mW".format(power.dynamic))
|
||||
debug.info(1,"Leakage Power: {0} mW".format(power.leakage))
|
||||
return power
|
||||
|
||||
sram_data = { "min_period": 0,
|
||||
"leakage_power": power.leakage}
|
||||
port_data = [{"delay_lh": delay_lh,
|
||||
"delay_hl": delay_hl,
|
||||
"slew_lh": slew_lh,
|
||||
"slew_hl": slew_hl,
|
||||
"read0_power": power.dynamic,
|
||||
"read1_power": power.dynamic,
|
||||
"write0_power": power.dynamic,
|
||||
"write1_power": power.dynamic,
|
||||
}]
|
||||
return (sram_data,port_data)
|
||||
|
||||
def gen_data(self):
|
||||
""" Generates the PWL data inputs for a simulation timing test. """
|
||||
for write_port in self.write_index:
|
||||
|
|
|
|||
|
|
@ -482,7 +482,7 @@ class lib:
|
|||
if not hasattr(self,"d"):
|
||||
self.d = delay(self.sram, self.sp_file, self.corner)
|
||||
if self.use_model:
|
||||
char_results = self.d.analytical_delay(self.sram,self.slews,self.loads)
|
||||
char_results = self.d.analytical_delay(self.slews,self.loads)
|
||||
self.char_sram_results, self.char_port_results = char_results
|
||||
else:
|
||||
probe_address = "1" * self.sram.addr_size
|
||||
|
|
|
|||
|
|
@ -927,23 +927,27 @@ class bank(design.design):
|
|||
|
||||
def analytical_delay(self, vdd, slew, load):
|
||||
""" return analytical delay of the bank"""
|
||||
results = []
|
||||
|
||||
decoder_delay = self.row_decoder.analytical_delay(slew, self.wordline_driver.input_load())
|
||||
|
||||
word_driver_delay = self.wordline_driver.analytical_delay(decoder_delay.slew, self.bitcell_array.input_load())
|
||||
|
||||
#FIXME: Array delay is the same for every port.
|
||||
bitcell_array_delay = self.bitcell_array.analytical_delay(word_driver_delay.slew)
|
||||
|
||||
if self.words_per_row > 1:
|
||||
port = 0 #Analytical delay only supports single port
|
||||
column_mux_delay = self.column_mux_array[port].analytical_delay(vdd, bitcell_array_delay.slew,
|
||||
self.sense_amp_array.input_load())
|
||||
else:
|
||||
column_mux_delay = self.return_delay(delay = 0.0, slew=word_driver_delay.slew)
|
||||
|
||||
bl_t_data_out_delay = self.sense_amp_array.analytical_delay(column_mux_delay.slew,
|
||||
self.bitcell_array.output_load())
|
||||
# output load of bitcell_array is set to be only small part of bl for sense amp.
|
||||
#This also essentially creates the same delay for each port. Good structure, no substance
|
||||
for port in range(self.total_ports):
|
||||
if self.words_per_row > 1:
|
||||
column_mux_delay = self.column_mux_array[port].analytical_delay(vdd, bitcell_array_delay.slew,
|
||||
self.sense_amp_array.input_load())
|
||||
else:
|
||||
column_mux_delay = self.return_delay(delay = 0.0, slew=word_driver_delay.slew)
|
||||
|
||||
bl_t_data_out_delay = self.sense_amp_array.analytical_delay(column_mux_delay.slew,
|
||||
self.bitcell_array.output_load())
|
||||
# output load of bitcell_array is set to be only small part of bl for sense amp.
|
||||
results.append(decoder_delay + word_driver_delay + bitcell_array_delay + column_mux_delay + bl_t_data_out_delay)
|
||||
|
||||
result = decoder_delay + word_driver_delay + bitcell_array_delay + column_mux_delay + bl_t_data_out_delay
|
||||
return result
|
||||
return results
|
||||
|
||||
|
|
|
|||
|
|
@ -199,13 +199,21 @@ class bitcell_array(design.design):
|
|||
return total_power
|
||||
|
||||
def gen_wl_wire(self):
|
||||
wl_wire = self.generate_rc_net(int(self.column_size), self.width, drc("minwidth_metal1"))
|
||||
if OPTS.netlist_only:
|
||||
width = 0
|
||||
else:
|
||||
width = self.width
|
||||
wl_wire = self.generate_rc_net(int(self.column_size), width, drc("minwidth_metal1"))
|
||||
wl_wire.wire_c = 2*spice["min_tx_gate_c"] + wl_wire.wire_c # 2 access tx gate per cell
|
||||
return wl_wire
|
||||
|
||||
def gen_bl_wire(self):
|
||||
if OPTS.netlist_only:
|
||||
height = 0
|
||||
else:
|
||||
height = self.height
|
||||
bl_pos = 0
|
||||
bl_wire = self.generate_rc_net(int(self.row_size-bl_pos), self.height, drc("minwidth_metal1"))
|
||||
bl_wire = self.generate_rc_net(int(self.row_size-bl_pos), height, drc("minwidth_metal1"))
|
||||
bl_wire.wire_c =spice["min_tx_drain_c"] + bl_wire.wire_c # 1 access tx d/s per cell
|
||||
return bl_wire
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue