Merge pull request #33 from hznichol/analytical_power

Analytical power
This commit is contained in:
Matt Guthaus 2018-03-02 10:27:21 -08:00 committed by GitHub
commit 2f352c905f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 221 additions and 12 deletions

View File

@ -120,3 +120,10 @@ class design(hierarchy_spice.spice, hierarchy_layout.layout):
for i in self.insts: for i in self.insts:
text+=str(i)+",\n" text+=str(i)+",\n"
return text return text
def analytical_power(self, proc, vdd, temp, load):
""" Get total power of a module """
total_module_power = self.return_power()
for inst in self.insts:
total_module_power += inst.mod.analytical_power(proc, vdd, temp, load)
return total_module_power

View File

@ -214,6 +214,9 @@ class spice(verilog.verilog):
def generate_rc_net(self,lump_num, wire_length, wire_width): def generate_rc_net(self,lump_num, wire_length, wire_width):
return wire_spice_model(lump_num, wire_length, wire_width) return wire_spice_model(lump_num, wire_length, wire_width)
def return_power(self, dynamic=0.0, leakage=0.0):
return power_data(dynamic, leakage)
class delay_data: class delay_data:
""" """
@ -246,6 +249,37 @@ class delay_data:
assert isinstance(other,delay_data) assert isinstance(other,delay_data)
return delay_data(other.delay + self.delay, return delay_data(other.delay + self.delay,
self.slew) self.slew)
class power_data:
"""
This is the power class to represent the power information
Dynamic and leakage power are stored as a single object with this class.
"""
def __init__(self, dynamic=0.0, leakage=0.0):
""" init function support two init method"""
# will take single input as a coordinate
self.dynamic = dynamic
self.leakage = leakage
def __str__(self):
""" override print function output """
return "Power Data: Dynamic "+str(self.dynamic)+", Leakage "+str(self.leakage)+" in nW"
def __add__(self, other):
"""
Override - function (left), for power_data: a+b != b+a
"""
assert isinstance(other,power_data)
return power_data(other.dynamic + self.dynamic,
other.leakage + self.leakage)
def __radd__(self, other):
"""
Override - function (left), for power_data: a+b != b+a
"""
assert isinstance(other,power_data)
return power_data(other.dynamic + self.dynamic,
other.leakage + self.leakage)
class wire_spice_model: class wire_spice_model:

View File

@ -721,17 +721,24 @@ class delay():
delay_hl.append(bank_delay.delay/1e3) delay_hl.append(bank_delay.delay/1e3)
slew_lh.append(bank_delay.slew/1e3) slew_lh.append(bank_delay.slew/1e3)
slew_hl.append(bank_delay.slew/1e3) slew_hl.append(bank_delay.slew/1e3)
power = 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))
data = {"min_period": 0, data = {"min_period": 0,
"delay_lh": delay_lh, "delay_lh": delay_lh,
"delay_hl": delay_hl, "delay_hl": delay_hl,
"slew_lh": slew_lh, "slew_lh": slew_lh,
"slew_hl": slew_hl, "slew_hl": slew_hl,
"read0_power": 0, "read0_power": power.dynamic,
"read1_power": 0, "read1_power": power.dynamic,
"write0_power": 0, "write0_power": power.dynamic,
"write1_power": 0, "write1_power": power.dynamic,
"leakage_power": 0 "leakage_power": power.leakage
} }
return data return data

View File

@ -1228,3 +1228,4 @@ class bank(design.design):
result = msf_addr_delay + decoder_delay + word_driver_delay \ result = msf_addr_delay + decoder_delay + word_driver_delay \
+ bitcell_array_delay + bl_t_data_out_delay + data_t_DATA_delay + bitcell_array_delay + bl_t_data_out_delay + data_t_DATA_delay
return result return result

View File

@ -34,3 +34,11 @@ class bitcell(design.design):
c_para = spice["min_tx_drain_c"] c_para = spice["min_tx_drain_c"]
result = self.cal_delay_with_rc(r = r, c = c_para+load, slew = slew, swing = swing) result = self.cal_delay_with_rc(r = r, c = c_para+load, slew = slew, swing = swing)
return result 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

View File

@ -177,6 +177,25 @@ class bitcell_array(design.design):
#we do not consider the delay over the wire for now #we do not consider the delay over the wire for now
return self.return_delay(cell_delay.delay+wl_to_cell_delay.delay, return self.return_delay(cell_delay.delay+wl_to_cell_delay.delay,
wl_to_cell_delay.slew) wl_to_cell_delay.slew)
def analytical_power(self, proc, vdd, temp, load):
"""Power of Bitcell array and bitline in nW."""
from tech import drc
# Dynamic Power from Bitline
bl_wire = self.gen_bl_wire()
cell_load = 2 * bl_wire.return_input_cap()
bl_swing = 0.1 #This should probably be defined in the tech file or input
freq = spice["default_event_rate"]
bitline_dynamic = bl_swing*cell_load*vdd*vdd*freq #not sure if calculation is correct
#Calculate the bitcell power which currently only includes leakage
cell_power = self.cell.analytical_power(proc, vdd, temp, load)
#Leakage power grows with entire array and bitlines.
total_power = self.return_power(cell_power.dynamic + bitline_dynamic * self.column_size,
cell_power.leakage * self.column_size * self.row_size)
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"]) wl_wire = self.generate_rc_net(int(self.column_size), self.width, drc["minwidth_metal1"])

View File

@ -98,7 +98,7 @@ class control_logic(design.design):
# GAP between main control and replica bitline # GAP between main control and replica bitline
self.replica_bitline_gap = 2*self.m2_pitch self.replica_bitline_gap = 2*self.m2_pitch
def add_modules(self): def add_modules(self):
@ -688,4 +688,4 @@ class control_logic(design.design):
height=pin.height(), height=pin.height(),
width=pin.width()) width=pin.width())

View File

@ -494,6 +494,7 @@ class hierarchical_decoder(design.design):
result = result + z_t_decodeout_delay result = result + z_t_decodeout_delay
return result return result
def input_load(self): def input_load(self):
if self.determine_predecodes(self.num_inputs)[1]==0: if self.determine_predecodes(self.num_inputs)[1]==0:
pre = self.pre2_4 pre = self.pre2_4

View File

@ -55,5 +55,6 @@ class hierarchical_predecode2x4(hierarchical_predecode):
return a_t_b_delay + b_t_z_delay + a_t_out_delay return a_t_b_delay + b_t_z_delay + a_t_out_delay
def input_load(self): def input_load(self):
return self.nand.input_load() return self.nand.input_load()

View File

@ -64,6 +64,5 @@ class hierarchical_predecode3x8(hierarchical_predecode):
return a_t_b_delay + b_t_z_delay + a_t_out_delay return a_t_b_delay + b_t_z_delay + a_t_out_delay
def input_load(self): def input_load(self):
return self.nand.input_load() return self.nand.input_load()

View File

@ -26,4 +26,25 @@ class ms_flop(design.design):
from tech import spice from tech import spice
result = self.return_delay(spice["msflop_delay"], spice["msflop_slew"]) result = self.return_delay(spice["msflop_delay"], spice["msflop_slew"])
return result return result
def analytical_power(self, proc, vdd, temp, load):
"""Returns dynamic and leakage power. Results in nW"""
from tech import spice
c_eff = self.calculate_effective_capacitance(load)
f = spice["default_event_rate"]
power_dyn = c_eff*vdd*vdd*f
power_leak = spice["msflop_leakage"]
total_power = self.return_power(power_dyn, power_leak)
return total_power
def calculate_effective_capacitance(self, load):
"""Computes effective capacitance. Results in fF"""
from tech import spice, parameter
c_load = load
c_para = spice["flop_para_cap"]#ff
transistion_prob = spice["flop_transisition_prob"]
return transistion_prob*(c_load + c_para)

View File

@ -134,3 +134,4 @@ class ms_flop_array(design.design):
def analytical_delay(self, slew, load=0.0): def analytical_delay(self, slew, load=0.0):
return self.ms.analytical_delay(slew=slew, load=load) return self.ms.analytical_delay(slew=slew, load=load)

View File

@ -30,3 +30,8 @@ class sense_amp(design.design):
result = self.cal_delay_with_rc(r = r, c = c_para+load, slew = slew) result = self.cal_delay_with_rc(r = r, c = c_para+load, slew = slew)
return self.return_delay(result.delay, result.slew) return self.return_delay(result.delay, result.slew)
def analytical_power(self, proc, vdd, temp, load):
"""Returns dynamic and leakage power. Results in nW"""
#Power in this module currently not defined. Returns 0 nW (leakage and dynamic).
total_power = self.return_power()
return total_power

View File

@ -117,3 +117,4 @@ class sense_amp_array(design.design):
def analytical_delay(self, slew, load=0.0): def analytical_delay(self, slew, load=0.0):
return self.amp.analytical_delay(slew=slew, load=load) return self.amp.analytical_delay(slew=slew, load=load)

View File

@ -32,7 +32,12 @@ class tri_gate(design.design):
r = spice["min_tx_r"] r = spice["min_tx_r"]
c_para = spice["min_tx_drain_c"] c_para = spice["min_tx_drain_c"]
return self.cal_delay_with_rc(r = r, c = c_para+load, slew = slew) return self.cal_delay_with_rc(r = r, c = c_para+load, slew = slew)
def analytical_power(self, proc, vdd, temp, load):
"""Returns dynamic and leakage power. Results in nW"""
#Power in this module currently not defined. Returns 0 nW (leakage and dynamic).
total_power = self.return_power()
return total_power
def input_load(self): def input_load(self):
return 9*spice["min_tx_gate_c"] return 9*spice["min_tx_gate_c"]

View File

@ -111,3 +111,4 @@ class tri_gate_array(design.design):
def analytical_delay(self, slew, load=0.0): def analytical_delay(self, slew, load=0.0):
return self.tri.analytical_delay(slew = slew, load = load) return self.tri.analytical_delay(slew = slew, load = load)

View File

@ -205,6 +205,7 @@ class wordline_driver(design.design):
net_t_wl = self.inv.analytical_delay(decode_t_net.slew, load) net_t_wl = self.inv.analytical_delay(decode_t_net.slew, load)
return decode_t_net + net_t_wl return decode_t_net + net_t_wl
def input_load(self): def input_load(self):
return self.nand2.input_load() return self.nand2.input_load()

View File

@ -241,3 +241,20 @@ class pinv(pgate.pgate):
r = spice["min_tx_r"]/(self.nmos_size/parameter["min_tx_size"]) r = spice["min_tx_r"]/(self.nmos_size/parameter["min_tx_size"])
c_para = spice["min_tx_drain_c"]*(self.nmos_size/parameter["min_tx_size"])#ff c_para = spice["min_tx_drain_c"]*(self.nmos_size/parameter["min_tx_size"])#ff
return self.cal_delay_with_rc(r = r, c = c_para+load, slew = slew) return self.cal_delay_with_rc(r = r, c = c_para+load, slew = slew)
def analytical_power(self, proc, vdd, temp, load):
"""Returns dynamic and leakage power. Results in nW"""
c_eff = self.calculate_effective_capacitance(load)
freq = spice["default_event_rate"]
power_dyn = c_eff*vdd*vdd*freq
power_leak = spice["inv_leakage"]
total_power = self.return_power(power_dyn, power_leak)
return total_power
def calculate_effective_capacitance(self, load):
"""Computes effective capacitance. Results in fF"""
c_load = load
c_para = spice["min_tx_drain_c"]*(self.nmos_size/parameter["min_tx_size"])#ff
transistion_prob = spice["inv_transisition_prob"]
return transistion_prob*(c_load + c_para)

View File

@ -213,3 +213,20 @@ class pnand2(pgate.pgate):
r = spice["min_tx_r"]/(self.nmos_size/parameter["min_tx_size"]) r = spice["min_tx_r"]/(self.nmos_size/parameter["min_tx_size"])
c_para = spice["min_tx_drain_c"]*(self.nmos_size/parameter["min_tx_size"])#ff c_para = spice["min_tx_drain_c"]*(self.nmos_size/parameter["min_tx_size"])#ff
return self.cal_delay_with_rc(r = r, c = c_para+load, slew = slew) return self.cal_delay_with_rc(r = r, c = c_para+load, slew = slew)
def analytical_power(self, proc, vdd, temp, load):
"""Returns dynamic and leakage power. Results in nW"""
c_eff = self.calculate_effective_capacitance(load)
freq = spice["default_event_rate"]
power_dyn = c_eff*vdd*vdd*freq
power_leak = spice["nand2_leakage"]
total_power = self.return_power(power_dyn, power_leak)
return total_power
def calculate_effective_capacitance(self, load):
"""Computes effective capacitance. Results in fF"""
c_load = load
c_para = spice["min_tx_drain_c"]*(self.nmos_size/parameter["min_tx_size"])#ff
transistion_prob = spice["nand2_transisition_prob"]
return transistion_prob*(c_load + c_para)

View File

@ -233,3 +233,20 @@ class pnand3(pgate.pgate):
r = spice["min_tx_r"]/(self.nmos_size/parameter["min_tx_size"]) r = spice["min_tx_r"]/(self.nmos_size/parameter["min_tx_size"])
c_para = spice["min_tx_drain_c"]*(self.nmos_size/parameter["min_tx_size"])#ff c_para = spice["min_tx_drain_c"]*(self.nmos_size/parameter["min_tx_size"])#ff
return self.cal_delay_with_rc(r = r, c = c_para+load, slew = slew) return self.cal_delay_with_rc(r = r, c = c_para+load, slew = slew)
def analytical_power(self, proc, vdd, temp, load):
"""Returns dynamic and leakage power. Results in nW"""
c_eff = self.calculate_effective_capacitance(load)
freq = spice["default_event_rate"]
power_dyn = c_eff*vdd*vdd*freq
power_leak = spice["nand3_leakage"]
total_power = self.return_power(power_dyn, power_leak)
return total_power
def calculate_effective_capacitance(self, load):
"""Computes effective capacitance. Results in fF"""
c_load = load
c_para = spice["min_tx_drain_c"]*(self.nmos_size/parameter["min_tx_size"])#ff
transistion_prob = spice["nand3_transisition_prob"]
return transistion_prob*(c_load + c_para)

View File

@ -223,3 +223,21 @@ class pnor2(pgate.pgate):
r = spice["min_tx_r"]/(self.nmos_size/parameter["min_tx_size"]) r = spice["min_tx_r"]/(self.nmos_size/parameter["min_tx_size"])
c_para = spice["min_tx_drain_c"]*(self.nmos_size/parameter["min_tx_size"])#ff c_para = spice["min_tx_drain_c"]*(self.nmos_size/parameter["min_tx_size"])#ff
return self.cal_delay_with_rc(r = r, c = c_para+load, slew = slew) return self.cal_delay_with_rc(r = r, c = c_para+load, slew = slew)
def analytical_power(self, proc, vdd, temp, load):
"""Returns dynamic and leakage power. Results in nW"""
c_eff = self.calculate_effective_capacitance(load)
freq = spice["default_event_rate"]
power_dyn = c_eff*vdd*vdd*freq
power_leak = spice["nor2_leakage"]
total_power = self.return_power(power_dyn, power_leak)
return total_power
def calculate_effective_capacitance(self, load):
"""Computes effective capacitance. Results in fF"""
c_load = load
c_para = spice["min_tx_drain_c"]*(self.nmos_size/parameter["min_tx_size"])#ff
transistion_prob = spice["nor2_transisition_prob"]
return transistion_prob*(c_load + c_para)

View File

@ -1015,7 +1015,6 @@ class sram(design.design):
""" LH and HL are the same in analytical model. """ """ LH and HL are the same in analytical model. """
return self.bank.analytical_delay(slew,load) return self.bank.analytical_delay(slew,load)
def save_output(self): def save_output(self):
""" Save all the output files while reporting time to do it as well. """ """ Save all the output files while reporting time to do it as well. """

View File

@ -283,6 +283,21 @@ spice["dff_delay"] = 20.5 # DFF Clk-to-q delay in ps
spice["dff_slew"] = 13.1 # DFF output slew in ps w/ no load spice["dff_slew"] = 13.1 # DFF output slew in ps w/ no load
spice["dff_in_cap"] = 0.2091 # Input capacitance of ms_flop (Din) [Femto-farad] spice["dff_in_cap"] = 0.2091 # Input capacitance of ms_flop (Din) [Femto-farad]
# analytical power parameters, many values are temporary
spice["bitcell_leakage"] = 1 # Leakage power of a single bitcell in nW
spice["inv_leakage"] = 1 # Leakage power of inverter in nW
spice["nand2_leakage"] = 1 # Leakage power of 2-input nand in nW
spice["nand3_leakage"] = 1 # Leakage power of 3-input nand in nW
spice["nor2_leakage"] = 1 # Leakage power of 2-input nor in nW
spice["msflop_leakage"] = 1 # Leakage power of flop in nW
spice["flop_para_cap"] = 2 # Parasitic Output capacitance in fF
spice["default_event_rate"] = 100 # Default event activity of every gate. MHz
spice["flop_transisition_prob"] = .5 # Transition probability of inverter.
spice["inv_transisition_prob"] = .5 # Transition probability of inverter.
spice["nand2_transisition_prob"] = .1875 # Transition probability of 2-input nand.
spice["nand3_transisition_prob"] = .1094 # Transition probability of 3-input nand.
spice["nor2_transisition_prob"] = .1875 # Transition probability of 2-input nor.
################################################### ###################################################
##END Spice Simulation Parameters ##END Spice Simulation Parameters

View File

@ -246,7 +246,21 @@ spice["dff_delay"] = 20.5 # DFF Clk-to-q delay in ps
spice["dff_slew"] = 13.1 # DFF output slew in ps w/ no load spice["dff_slew"] = 13.1 # DFF output slew in ps w/ no load
spice["dff_in_cap"] = 9.8242 # Input capacitance of ms_flop (Din) [Femto-farad] spice["dff_in_cap"] = 9.8242 # Input capacitance of ms_flop (Din) [Femto-farad]
# analytical power parameters, many values are temporary
spice["bitcell_leakage"] = 1 # Leakage power of a single bitcell in nW
spice["inv_leakage"] = 1 # Leakage power of inverter in nW
spice["nand2_leakage"] = 1 # Leakage power of 2-input nand in nW
spice["nand3_leakage"] = 1 # Leakage power of 3-input nand in nW
spice["nor2_leakage"] = 1 # Leakage power of 2-input nor in nW
spice["msflop_leakage"] = 1 # Leakage power of flop in nW
spice["flop_para_cap"] = 2 # Parasitic Output capacitance in fF
spice["default_event_rate"] = 100 # Default event activity of every gate. MHz
spice["flop_transisition_prob"] = .5 # Transition probability of inverter.
spice["inv_transisition_prob"] = .5 # Transition probability of inverter.
spice["nand2_transisition_prob"] = .1875 # Transition probability of 2-input nand.
spice["nand3_transisition_prob"] = .1094 # Transition probability of 3-input nand.
spice["nor2_transisition_prob"] = .1875 # Transition probability of 2-input nor.
################################################### ###################################################
##END Spice Simulation Parameters ##END Spice Simulation Parameters
################################################### ###################################################