Added initial version of analytical power esitmation. Loops through instances but power estimate is not accurate.

This commit is contained in:
Hunter Nichols 2018-02-22 19:35:54 -08:00
parent beb7dad9bc
commit 62ad30e741
16 changed files with 333 additions and 77 deletions

View File

@ -125,6 +125,6 @@ class design(hierarchy_spice.spice, hierarchy_layout.layout):
""" Get total power of a module """ """ Get total power of a module """
#print "Getting power for ",self.name," module" #print "Getting power for ",self.name," module"
total_module_power = self.return_power() total_module_power = self.return_power()
# for inst in self.insts: for inst in self.insts:
# total_module_power += self.return_power()#inst.mod.analytical_power(vdd, temp, load) total_module_power += inst.mod.analytical_power(vdd, temp, load)
return total_module_power return total_module_power

View File

@ -270,7 +270,7 @@ class power_data:
Override - function (left), for power_data: a+b != b+a Override - function (left), for power_data: a+b != b+a
""" """
assert isinstance(other,power_data) assert isinstance(other,power_data)
return delay_data(other.dynamic + self.dynamic, return power_data(other.dynamic + self.dynamic,
other.leakage + self.leakage) other.leakage + self.leakage)
def __radd__(self, other): def __radd__(self, other):
@ -278,7 +278,7 @@ class power_data:
Override - function (left), for power_data: a+b != b+a Override - function (left), for power_data: a+b != b+a
""" """
assert isinstance(other,power_data) assert isinstance(other,power_data)
return delay_data(other.dynamic + self.dynamic, return power_data(other.dynamic + self.dynamic,
other.leakage + self.leakage) other.leakage + self.leakage)

View File

@ -35,10 +35,11 @@ class bitcell(design.design):
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, slew, load=0, swing = 0.5): def analytical_power(self, vdd, temp, load):
#Power of the bitcell. Mostly known for leakage, but dynamic can also be factored in. #Power of the bitcell. Mostly known for leakage, but dynamic can also be factored in.
#Only consider leakage power for now. Value defined in tech file rather than calculated. #Only consider leakage power for now. Value defined in tech file rather than calculated.
from tech import spice from tech import spice
leakage = spice["bitcell_leakage"] leakage = spice["bitcell_leakage"]
total_power = leakage dynamic = 0 #temporary
total_power = self.return_power(dynamic, leakage)
return total_power return total_power

View File

@ -178,7 +178,7 @@ class bitcell_array(design.design):
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, slew, load=0): def analytical_power(self, vdd, temp, load):
#This will be pretty bare bones as the power needs to be determined from the dynamic power #This will be pretty bare bones as the power needs to be determined from the dynamic power
#of the word line, leakage power from the cell, and dynamic power of the bitlines as a few #of the word line, leakage power from the cell, and dynamic power of the bitlines as a few
#sources for power. These features are tbd. #sources for power. These features are tbd.
@ -194,10 +194,12 @@ class bitcell_array(design.design):
# hence just use the whole c # hence just use the whole c
bl_swing = 0.1 bl_swing = 0.1
#Calculate the bitcell power which can include leakage as well as bitline dynamic #Calculate the bitcell power which can include leakage as well as bitline dynamic
cell_power = self.cell.analytical_power(slew, cell_load, swing = bl_swing) cell_power = self.cell.analytical_power(vdd, temp, load)
#Leakage power grows with entire array. Dynamic currently not accounted for.
total_power = self.return_power(cell_power.dynamic, cell_power.leakage * self.column_size * self.row_size)
#calculate power for entire array based off a single cell #calculate power for entire array based off a single cell
return cell_power * 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

@ -494,21 +494,21 @@ class hierarchical_decoder(design.design):
result = result + z_t_decodeout_delay result = result + z_t_decodeout_delay
return result return result
def analytical_power(self, slew, load = 0.0): # def analytical_power(self, slew, load = 0.0):
# A -> out # # A -> out
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
nand = self.nand2 # nand = self.nand2
else: # else:
pre = self.pre3_8 # pre = self.pre3_8
nand = self.nand3 # nand = self.nand3
a_t_out_power = pre.analytical_power(slew=slew,load = nand.input_load()) # a_t_out_power = pre.analytical_power(slew=slew,load = nand.input_load())
out_t_z_power = nand.analytical_power(slew, # out_t_z_power = nand.analytical_power(slew,
load = self.inv.input_load()) # load = self.inv.input_load())
z_t_decodeout_power = self.inv.analytical_power(slew, load = load) # z_t_decodeout_power = self.inv.analytical_power(slew, load = load)
return a_t_out_power + out_t_z_power + z_t_decodeout_power # return a_t_out_power + out_t_z_power + z_t_decodeout_power
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:

View File

@ -55,17 +55,17 @@ 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 analytical_power(self, slew, load = 0.0 ): # def analytical_power(self, slew, load = 0.0 ):
# in -> inbar # # in -> inbar
a_t_b_power = self.inv.analytical_power(slew=slew, load=self.nand.input_load()) # a_t_b_power = self.inv.analytical_power(slew=slew, load=self.nand.input_load())
# inbar -> z # # inbar -> z
b_t_z_power = self.nand.analytical_power(slew, load=self.inv.input_load()) # b_t_z_power = self.nand.analytical_power(slew, load=self.inv.input_load())
# Z -> out # # Z -> out
a_t_out_power = self.inv.analytical_power(slew, load=load) # a_t_out_power = self.inv.analytical_power(slew, load=load)
return a_t_b_power + b_t_z_power + a_t_out_power # return a_t_b_power + b_t_z_power + a_t_out_power
def input_load(self): def input_load(self):
return self.nand.input_load() return self.nand.input_load()

View File

@ -63,17 +63,17 @@ 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 analytical_power(self, slew, load = 0.0 ): # def analytical_power(self, slew, load = 0.0 ):
# in -> inbar # # in -> inbar
a_t_b_power = self.inv.analytical_power(slew=slew, load=self.nand.input_load()) # a_t_b_power = self.inv.analytical_power(slew=slew, load=self.nand.input_load())
# inbar -> z # # inbar -> z
b_t_z_power = self.nand.analytical_power(slew, load=self.inv.input_load()) # b_t_z_power = self.nand.analytical_power(slew, load=self.inv.input_load())
# Z -> out # # Z -> out
a_t_out_power = self.inv.analytical_power(slew, load=load) # a_t_out_power = self.inv.analytical_power(slew, load=load)
return a_t_b_power + b_t_z_power + a_t_out_power # return a_t_b_power + b_t_z_power + a_t_out_power
def input_load(self): def input_load(self):
return self.nand.input_load() return self.nand.input_load()

View File

@ -347,11 +347,12 @@ class replica_bitline(design.design):
# def analytical_power(self, vdd, temp, load): # def analytical_power(self, vdd, temp, load):
# #This has yet to be fully determined. # #This has yet to be fully determined.
# print "Instances:" # print self.name," Instances:"
# total_power = 0 # total_power = self.return_power()
# for inst in self.insts: # for inst in self.insts:
# print inst.name," Instance" # print inst.name," Instance"
# #total_power += inst.mod.analytical_power(vdd, temp, load) # total_power += inst.mod.analytical_power(vdd, temp, load)
# print self.name," Instances End"
# #currently, only return flop array power # #currently, only return flop array power
# return total_power # return total_power

View File

@ -30,7 +30,7 @@ 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, slew, load=0.0): def analytical_power(self, vdd, temp, load):
#This is just skeleton code which returns a magic number. The sense amp consumes static #Not sure how to determine this yet. Sense amps return zero power for now
#power during its operation and some dynamic power due to the switching. total_power = self.return_power()
return 2 return total_power

View File

@ -118,5 +118,5 @@ 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)
def analytical_power(self, slew, load=0.0): # def analytical_power(self, slew, load=0.0):
return self.amp.analytical_power(slew=slew, load=load) # return self.amp.analytical_power(slew=slew, load=load)

View File

@ -33,9 +33,10 @@ class tri_gate(design.design):
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, slew, load=0.0): def analytical_power(self, vdd, temp, load):
#Skeleton code for the power of a trigate. Returns magic number for now. #Not sure how to determine this yet. Tri-gates return zero power for now
return 2 total_power = self.return_power()
return total_power
def input_load(self): def input_load(self):

View File

@ -112,5 +112,5 @@ 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)
def analytical_power(self, slew, load=0.0): # def analytical_power(self, slew, load=0.0):
return self.tri.analytical_power(slew = slew, load = load) # return self.tri.analytical_power(slew = slew, load = load)

View File

@ -206,14 +206,14 @@ class wordline_driver(design.design):
return decode_t_net + net_t_wl return decode_t_net + net_t_wl
def analytical_power(self, slew, load=0): # def analytical_power(self, slew, load=0):
# decode -> net # # decode -> net
decode_p_net = self.nand2.analytical_power(slew, self.inv.input_load()) # decode_p_net = self.nand2.analytical_power(slew, self.inv.input_load())
# net -> wl # # net -> wl
net_p_wl = self.inv.analytical_power(slew, load) # net_p_wl = self.inv.analytical_power(slew, load)
return decode_p_net + net_p_wl # return decode_p_net + net_p_wl
def input_load(self): def input_load(self):
return self.nand2.input_load() return self.nand2.input_load()

View File

@ -1015,29 +1015,29 @@ 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 analytical_power(self, vdd, temp, load): # def analytical_power(self, vdd, temp, load):
""" Just a test function for the power.""" # """ Just a test function for the power."""
power_sum = 0; # power_sum = 0;
print "Module Powers" # print "Module Powers"
# for mod in self.mods: # # for mod in self.mods:
# print mod.name," Power: ", mod.analytical_power(slew, load) # # print mod.name," Power: ", mod.analytical_power(slew, load)
# power_sum += mod.analytical_power(slew, load) # # power_sum += mod.analytical_power(slew, load)
# print "Instances:" # # print "Instances:"
# for inst in self.insts: # # for inst in self.insts:
# print inst.name," Instance" # # print inst.name," Instance"
# print "Instances from Modules of Instances:" # # print "Instances from Modules of Instances:"
# for inst in self.insts: # # for inst in self.insts:
# print inst.mod.name," Module" # # print inst.mod.name," Module"
# for mod_inst in inst.mod.insts: # # for mod_inst in inst.mod.insts:
# print mod_inst.name," Instance" # # print mod_inst.name," Instance"
power_sum = self.control_logic.analytical_power(vdd, temp, load) # power_sum = self.control_logic.analytical_power(vdd, temp, load)
return power_sum # return power_sum
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

@ -76,3 +76,254 @@ cell (sram_2_16_1_freepdk45){
dont_touch : true; dont_touch : true;
area : 1756.7563625; area : 1756.7563625;
bus(DATA){
bus_type : DATA;
direction : inout;
max_capacitance : 1.6728;
three_state : "!OEb & !clk";
memory_write(){
address : ADDR;
clocked_on : clk;
}
memory_read(){
address : ADDR;
}
pin(DATA[1:0]){
internal_power(){
when : "OEb & !clk";
rise_power(scalar){
values("Power Data: Dynamic 174266.64, Leakage 423.0 in nW");
}
fall_power(scalar){
values("Power Data: Dynamic 174266.64, Leakage 423.0 in nW");
}
}
timing(){
timing_type : setup_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009");
}
}
timing(){
timing_type : hold_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
}
internal_power(){
when : "!OEb & !clk";
rise_power(scalar){
values("Power Data: Dynamic 174266.64, Leakage 423.0 in nW");
}
fall_power(scalar){
values("Power Data: Dynamic 174266.64, Leakage 423.0 in nW");
}
}
timing(){
timing_sense : non_unate;
related_pin : "clk";
timing_type : falling_edge;
cell_rise(CELL_TABLE) {
values("0.167, 0.168, 0.177",\
"0.167, 0.168, 0.177",\
"0.167, 0.168, 0.177");
}
cell_fall(CELL_TABLE) {
values("0.167, 0.168, 0.177",\
"0.167, 0.168, 0.177",\
"0.167, 0.168, 0.177");
}
rise_transition(CELL_TABLE) {
values("0.006, 0.007, 0.018",\
"0.006, 0.007, 0.018",\
"0.006, 0.007, 0.018");
}
fall_transition(CELL_TABLE) {
values("0.006, 0.007, 0.018",\
"0.006, 0.007, 0.018",\
"0.006, 0.007, 0.018");
}
}
}
}
bus(ADDR){
bus_type : ADDR;
direction : input;
capacitance : 0.2091;
max_transition : 0.04;
fanout_load : 1.000000;
pin(ADDR[6:0]){
timing(){
timing_type : setup_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009");
}
}
timing(){
timing_type : hold_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
}
}
}
pin(CSb){
direction : input;
capacitance : 0.2091;
timing(){
timing_type : setup_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009");
}
}
timing(){
timing_type : hold_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
}
}
pin(OEb){
direction : input;
capacitance : 0.2091;
timing(){
timing_type : setup_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009");
}
}
timing(){
timing_type : hold_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
}
}
pin(WEb){
direction : input;
capacitance : 0.2091;
timing(){
timing_type : setup_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009");
}
}
timing(){
timing_type : hold_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
}
}
pin(clk){
clock : true;
direction : input;
capacitance : 0.2091;
timing(){
timing_type :"min_pulse_width";
related_pin : clk;
rise_constraint(scalar) {
values("0.0");
}
fall_constraint(scalar) {
values("0.0");
}
}
timing(){
timing_type :"minimum_period";
related_pin : clk;
rise_constraint(scalar) {
values("0.0");
}
fall_constraint(scalar) {
values("0.0");
}
}
}
}
}