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()
|
Q_bar_pos = self.inverter_pmos_right.get_pin("S").center()
|
||||||
vdd_pos = self.inverter_pmos_right.get_pin("D").center()
|
vdd_pos = self.inverter_pmos_right.get_pin("D").center()
|
||||||
self.add_path("metal1", [Q_bar_pos, vdd_pos])
|
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.
|
#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)
|
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.
|
""" 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 ,
|
if OPTS.num_rw_ports > 1 or OPTS.num_w_ports > 0 and OPTS.num_r_ports > 0:
|
||||||
"Analytical characterization does not currently support multiport.")
|
debug.warning("Analytical characterization results are not supported for multiport.")
|
||||||
|
|
||||||
delay_lh = []
|
power = self.analytical_power(slews, loads)
|
||||||
delay_hl = []
|
port_data = self.get_empty_measure_data_dict()
|
||||||
slew_lh = []
|
|
||||||
slew_hl = []
|
|
||||||
for slew in slews:
|
for slew in slews:
|
||||||
for load in loads:
|
for load in loads:
|
||||||
self.set_load_slew(load,slew)
|
self.set_load_slew(load,slew)
|
||||||
bank_delay = sram.analytical_delay(self.vdd_voltage, self.slew,self.load)
|
bank_delay = self.sram.analytical_delay(self.vdd_voltage, self.slew,self.load)
|
||||||
# Convert from ps to ns
|
for port in range(self.total_ports):
|
||||||
delay_lh.append(bank_delay.delay/1e3)
|
for mname in self.delay_meas_names+self.power_meas_names:
|
||||||
delay_hl.append(bank_delay.delay/1e3)
|
if "power" in mname:
|
||||||
slew_lh.append(bank_delay.slew/1e3)
|
port_data[port][mname].append(power.dynamic)
|
||||||
slew_hl.append(bank_delay.slew/1e3)
|
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
|
#convert from nW to mW
|
||||||
power.dynamic /= 1e6
|
power.dynamic /= 1e6
|
||||||
power.leakage /= 1e6
|
power.leakage /= 1e6
|
||||||
debug.info(1,"Dynamic Power: {0} mW".format(power.dynamic))
|
debug.info(1,"Dynamic Power: {0} mW".format(power.dynamic))
|
||||||
debug.info(1,"Leakage Power: {0} mW".format(power.leakage))
|
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):
|
def gen_data(self):
|
||||||
""" Generates the PWL data inputs for a simulation timing test. """
|
""" Generates the PWL data inputs for a simulation timing test. """
|
||||||
for write_port in self.write_index:
|
for write_port in self.write_index:
|
||||||
|
|
|
||||||
|
|
@ -482,7 +482,7 @@ class lib:
|
||||||
if not hasattr(self,"d"):
|
if not hasattr(self,"d"):
|
||||||
self.d = delay(self.sram, self.sp_file, self.corner)
|
self.d = delay(self.sram, self.sp_file, self.corner)
|
||||||
if self.use_model:
|
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
|
self.char_sram_results, self.char_port_results = char_results
|
||||||
else:
|
else:
|
||||||
probe_address = "1" * self.sram.addr_size
|
probe_address = "1" * self.sram.addr_size
|
||||||
|
|
|
||||||
|
|
@ -927,23 +927,27 @@ class bank(design.design):
|
||||||
|
|
||||||
def analytical_delay(self, vdd, slew, load):
|
def analytical_delay(self, vdd, slew, load):
|
||||||
""" return analytical delay of the bank"""
|
""" return analytical delay of the bank"""
|
||||||
|
results = []
|
||||||
|
|
||||||
decoder_delay = self.row_decoder.analytical_delay(slew, self.wordline_driver.input_load())
|
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())
|
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)
|
bitcell_array_delay = self.bitcell_array.analytical_delay(word_driver_delay.slew)
|
||||||
|
|
||||||
if self.words_per_row > 1:
|
#This also essentially creates the same delay for each port. Good structure, no substance
|
||||||
port = 0 #Analytical delay only supports single port
|
for port in range(self.total_ports):
|
||||||
column_mux_delay = self.column_mux_array[port].analytical_delay(vdd, bitcell_array_delay.slew,
|
if self.words_per_row > 1:
|
||||||
self.sense_amp_array.input_load())
|
column_mux_delay = self.column_mux_array[port].analytical_delay(vdd, bitcell_array_delay.slew,
|
||||||
else:
|
self.sense_amp_array.input_load())
|
||||||
column_mux_delay = self.return_delay(delay = 0.0, slew=word_driver_delay.slew)
|
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())
|
bl_t_data_out_delay = self.sense_amp_array.analytical_delay(column_mux_delay.slew,
|
||||||
# output load of bitcell_array is set to be only small part of bl for sense amp.
|
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 results
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -199,13 +199,21 @@ class bitcell_array(design.design):
|
||||||
return total_power
|
return total_power
|
||||||
|
|
||||||
def gen_wl_wire(self):
|
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
|
wl_wire.wire_c = 2*spice["min_tx_gate_c"] + wl_wire.wire_c # 2 access tx gate per cell
|
||||||
return wl_wire
|
return wl_wire
|
||||||
|
|
||||||
def gen_bl_wire(self):
|
def gen_bl_wire(self):
|
||||||
|
if OPTS.netlist_only:
|
||||||
|
height = 0
|
||||||
|
else:
|
||||||
|
height = self.height
|
||||||
bl_pos = 0
|
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
|
bl_wire.wire_c =spice["min_tx_drain_c"] + bl_wire.wire_c # 1 access tx d/s per cell
|
||||||
return bl_wire
|
return bl_wire
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue