1015 lines
53 KiB
C++
1015 lines
53 KiB
C++
|
/*****************************************************************************
|
||
|
* McPAT
|
||
|
* SOFTWARE LICENSE AGREEMENT
|
||
|
* Copyright 2012 Hewlett-Packard Development Company, L.P.
|
||
|
* All Rights Reserved
|
||
|
*
|
||
|
* Redistribution and use in source and binary forms, with or without
|
||
|
* modification, are permitted provided that the following conditions are
|
||
|
* met: redistributions of source code must retain the above copyright
|
||
|
* notice, this list of conditions and the following disclaimer;
|
||
|
* redistributions in binary form must reproduce the above copyright
|
||
|
* notice, this list of conditions and the following disclaimer in the
|
||
|
* documentation and/or other materials provided with the distribution;
|
||
|
* neither the name of the copyright holders nor the names of its
|
||
|
* contributors may be used to endorse or promote products derived from
|
||
|
* this software without specific prior written permission.
|
||
|
|
||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.”
|
||
|
*
|
||
|
***************************************************************************/
|
||
|
|
||
|
#include "logic.h"
|
||
|
|
||
|
|
||
|
//selection_logic
|
||
|
selection_logic::selection_logic(
|
||
|
bool _is_default,
|
||
|
int win_entries_,
|
||
|
int issue_width_,
|
||
|
const InputParameter *configure_interface,
|
||
|
enum Device_ty device_ty_,
|
||
|
enum Core_type core_ty_)
|
||
|
//const ParseXML *_XML_interface)
|
||
|
:is_default(_is_default),
|
||
|
win_entries(win_entries_),
|
||
|
issue_width(issue_width_),
|
||
|
device_ty(device_ty_),
|
||
|
core_ty(core_ty_)
|
||
|
{
|
||
|
//uca_org_t result2;
|
||
|
l_ip=*configure_interface;
|
||
|
local_result = init_interface(&l_ip);
|
||
|
//init_tech_params(l_ip.F_sz_um, false);
|
||
|
//win_entries=numIBEntries;//IQentries;
|
||
|
//issue_width=issueWidth;
|
||
|
selection_power();
|
||
|
double sckRation = g_tp.sckt_co_eff;
|
||
|
power.readOp.dynamic *= sckRation;
|
||
|
power.writeOp.dynamic *= sckRation;
|
||
|
power.searchOp.dynamic *= sckRation;
|
||
|
|
||
|
double long_channel_device_reduction = longer_channel_device_reduction(device_ty,core_ty);
|
||
|
power.readOp.longer_channel_leakage = power.readOp.leakage*long_channel_device_reduction;
|
||
|
}
|
||
|
|
||
|
void selection_logic::selection_power()
|
||
|
{//based on cost effective superscalar processor TR pp27-31
|
||
|
double Ctotal, Cor, Cpencode;
|
||
|
int num_arbiter;
|
||
|
double WSelORn, WSelORprequ, WSelPn, WSelPp, WSelEnn, WSelEnp;
|
||
|
|
||
|
//TODO: the 0.8um process data is used.
|
||
|
WSelORn = 12.5 * l_ip.F_sz_um;//this was 10 micron for the 0.8 micron process
|
||
|
WSelORprequ = 50 * l_ip.F_sz_um;//this was 40 micron for the 0.8 micron process
|
||
|
WSelPn = 12.5 * l_ip.F_sz_um;//this was 10mcron for the 0.8 micron process
|
||
|
WSelPp = 18.75 * l_ip.F_sz_um;//this was 15 micron for the 0.8 micron process
|
||
|
WSelEnn = 6.25 * l_ip.F_sz_um;//this was 5 micron for the 0.8 micron process
|
||
|
WSelEnp = 12.5 * l_ip.F_sz_um;//this was 10 micron for the 0.8 micron process
|
||
|
|
||
|
|
||
|
Ctotal=0;
|
||
|
num_arbiter=1;
|
||
|
while(win_entries > 4)
|
||
|
{
|
||
|
win_entries = (int)ceil((double)win_entries / 4.0);
|
||
|
num_arbiter += win_entries;
|
||
|
}
|
||
|
//the 4-input OR logic to generate anyreq
|
||
|
Cor = 4 * drain_C_(WSelORn,NCH,1,1, g_tp.cell_h_def) + drain_C_(WSelORprequ,PCH,1,1, g_tp.cell_h_def);
|
||
|
power.readOp.gate_leakage = cmos_Ig_leakage(WSelORn, WSelORprequ, 4, nor)*g_tp.peri_global.Vdd;
|
||
|
|
||
|
//The total capacity of the 4-bit priority encoder
|
||
|
Cpencode = drain_C_(WSelPn,NCH,1, 1, g_tp.cell_h_def) + drain_C_(WSelPp,PCH,1, 1, g_tp.cell_h_def) +
|
||
|
2*drain_C_(WSelPn,NCH,1, 1, g_tp.cell_h_def) + drain_C_(WSelPp,PCH,2, 1, g_tp.cell_h_def) +
|
||
|
3*drain_C_(WSelPn,NCH,1, 1, g_tp.cell_h_def) + drain_C_(WSelPp,PCH,3, 1, g_tp.cell_h_def) +
|
||
|
4*drain_C_(WSelPn,NCH,1, 1, g_tp.cell_h_def) + drain_C_(WSelPp,PCH,4, 1, g_tp.cell_h_def) +//precompute priority logic
|
||
|
2*4*gate_C(WSelEnn+WSelEnp,20.0)+
|
||
|
4*drain_C_(WSelEnn,NCH,1, 1, g_tp.cell_h_def) + 2*4*drain_C_(WSelEnp,PCH,1, 1, g_tp.cell_h_def)+//enable logic
|
||
|
(2*4+2*3+2*2+2)*gate_C(WSelPn+WSelPp,10.0);//requests signal
|
||
|
|
||
|
Ctotal += issue_width * num_arbiter*(Cor+Cpencode);
|
||
|
|
||
|
power.readOp.dynamic = Ctotal*g_tp.peri_global.Vdd*g_tp.peri_global.Vdd*2;//2 means the abitration signal need to travel round trip
|
||
|
power.readOp.leakage = issue_width * num_arbiter *
|
||
|
(cmos_Isub_leakage(WSelPn, WSelPp, 2, nor)/*approximate precompute with a nor gate*///grant1p
|
||
|
+ cmos_Isub_leakage(WSelPn, WSelPp, 3, nor)//grant2p
|
||
|
+ cmos_Isub_leakage(WSelPn, WSelPp, 4, nor)//grant3p
|
||
|
+ cmos_Isub_leakage(WSelEnn, WSelEnp, 2, nor)*4//enable logic
|
||
|
+ cmos_Isub_leakage(WSelEnn, WSelEnp, 1, inv)*2*3//for each grant there are two inverters, there are 3 grant sIsubnals
|
||
|
)*g_tp.peri_global.Vdd;
|
||
|
power.readOp.gate_leakage = issue_width * num_arbiter *
|
||
|
(cmos_Ig_leakage(WSelPn, WSelPp, 2, nor)/*approximate precompute with a nor gate*///grant1p
|
||
|
+ cmos_Ig_leakage(WSelPn, WSelPp, 3, nor)//grant2p
|
||
|
+ cmos_Ig_leakage(WSelPn, WSelPp, 4, nor)//grant3p
|
||
|
+ cmos_Ig_leakage(WSelEnn, WSelEnp, 2, nor)*4//enable logic
|
||
|
+ cmos_Ig_leakage(WSelEnn, WSelEnp, 1, inv)*2*3//for each grant there are two inverters, there are 3 grant signals
|
||
|
)*g_tp.peri_global.Vdd;
|
||
|
}
|
||
|
|
||
|
|
||
|
dep_resource_conflict_check::dep_resource_conflict_check(
|
||
|
const InputParameter *configure_interface,
|
||
|
const CoreDynParam & dyn_p_,
|
||
|
int compare_bits_,
|
||
|
bool _is_default)
|
||
|
: l_ip(*configure_interface),
|
||
|
coredynp(dyn_p_),
|
||
|
compare_bits(compare_bits_),
|
||
|
is_default(_is_default)
|
||
|
{
|
||
|
Wcompn = 25 * l_ip.F_sz_um;//this was 20.0 micron for the 0.8 micron process
|
||
|
Wevalinvp = 25 * l_ip.F_sz_um;//this was 20.0 micron for the 0.8 micron process
|
||
|
Wevalinvn = 100 * l_ip.F_sz_um;//this was 80.0 mcron for the 0.8 micron process
|
||
|
Wcomppreequ = 50 * l_ip.F_sz_um;//this was 40.0 micron for the 0.8 micron process
|
||
|
WNORn = 6.75 * l_ip.F_sz_um;//this was 5.4 micron for the 0.8 micron process
|
||
|
WNORp = 38.125 * l_ip.F_sz_um;//this was 30.5 micron for the 0.8 micron process
|
||
|
|
||
|
local_result = init_interface(&l_ip);
|
||
|
|
||
|
if (coredynp.core_ty==Inorder)
|
||
|
compare_bits += 16 + 8 + 8;//TODO: opcode bits + log(shared resources) + REG TAG BITS-->opcode comparator
|
||
|
else
|
||
|
compare_bits += 16 + 8 + 8;
|
||
|
|
||
|
conflict_check_power();
|
||
|
double sckRation = g_tp.sckt_co_eff;
|
||
|
power.readOp.dynamic *= sckRation;
|
||
|
power.writeOp.dynamic *= sckRation;
|
||
|
power.searchOp.dynamic *= sckRation;
|
||
|
|
||
|
}
|
||
|
|
||
|
void dep_resource_conflict_check::conflict_check_power()
|
||
|
{
|
||
|
double Ctotal;
|
||
|
int num_comparators;
|
||
|
num_comparators = 3*((coredynp.decodeW) * (coredynp.decodeW)-coredynp.decodeW);//2(N*N-N) is used for source to dest comparison, (N*N-N) is used for dest to dest comparision.
|
||
|
//When decode-width ==1, no dcl logic
|
||
|
|
||
|
Ctotal = num_comparators * compare_cap();
|
||
|
//printf("%i,%s\n",XML_interface->sys.core[0].predictor.predictor_entries,XML_interface->sys.core[0].predictor.prediction_scheme);
|
||
|
|
||
|
power.readOp.dynamic=Ctotal*/*CLOCKRATE*/g_tp.peri_global.Vdd*g_tp.peri_global.Vdd/*AF*/;
|
||
|
power.readOp.leakage=num_comparators*compare_bits*2*simplified_nmos_leakage(Wcompn, false);
|
||
|
|
||
|
double long_channel_device_reduction = longer_channel_device_reduction(Core_device, coredynp.core_ty);
|
||
|
power.readOp.longer_channel_leakage = power.readOp.leakage*long_channel_device_reduction;
|
||
|
power.readOp.gate_leakage=num_comparators*compare_bits*2*cmos_Ig_leakage(Wcompn, 0, 2, nmos);
|
||
|
|
||
|
}
|
||
|
|
||
|
/* estimate comparator power consumption (this comparator is similar
|
||
|
to the tag-match structure in a CAM */
|
||
|
double dep_resource_conflict_check::compare_cap()
|
||
|
{
|
||
|
double c1, c2;
|
||
|
|
||
|
WNORp = WNORp * compare_bits/2.0;//resize the big NOR gate at the DCL according to fan in.
|
||
|
/* bottom part of comparator */
|
||
|
c2 = (compare_bits)*(drain_C_(Wcompn,NCH,1,1, g_tp.cell_h_def)+drain_C_(Wcompn,NCH,2,1, g_tp.cell_h_def))+
|
||
|
drain_C_(Wevalinvp,PCH,1,1, g_tp.cell_h_def) + drain_C_(Wevalinvn,NCH,1,1, g_tp.cell_h_def);
|
||
|
|
||
|
/* top part of comparator */
|
||
|
c1 = (compare_bits)*(drain_C_(Wcompn,NCH,1,1, g_tp.cell_h_def)+drain_C_(Wcompn,NCH,2,1, g_tp.cell_h_def)+
|
||
|
drain_C_(Wcomppreequ,NCH,1,1, g_tp.cell_h_def)) + gate_C(WNORn + WNORp,10.0) +
|
||
|
drain_C_(WNORp,NCH,2,1, g_tp.cell_h_def) + compare_bits*drain_C_(WNORn,NCH,2,1, g_tp.cell_h_def);
|
||
|
return(c1 + c2);
|
||
|
|
||
|
}
|
||
|
|
||
|
void dep_resource_conflict_check::leakage_feedback(double temperature)
|
||
|
{
|
||
|
l_ip.temp = (unsigned int)round(temperature/10.0)*10;
|
||
|
uca_org_t init_result = init_interface(&l_ip); // init_result is dummy
|
||
|
|
||
|
// This is part of conflict_check_power()
|
||
|
int num_comparators = 3*((coredynp.decodeW) * (coredynp.decodeW)-coredynp.decodeW);//2(N*N-N) is used for source to dest comparison, (N*N-N) is used for dest to dest comparision.
|
||
|
power.readOp.leakage=num_comparators*compare_bits*2*simplified_nmos_leakage(Wcompn, false);
|
||
|
|
||
|
double long_channel_device_reduction = longer_channel_device_reduction(Core_device, coredynp.core_ty);
|
||
|
power.readOp.longer_channel_leakage = power.readOp.leakage*long_channel_device_reduction;
|
||
|
power.readOp.gate_leakage=num_comparators*compare_bits*2*cmos_Ig_leakage(Wcompn, 0, 2, nmos);
|
||
|
}
|
||
|
|
||
|
//TODO: add inverter and transmission gate base DFF.
|
||
|
|
||
|
DFFCell::DFFCell(
|
||
|
bool _is_dram,
|
||
|
double _WdecNANDn,
|
||
|
double _WdecNANDp,
|
||
|
double _cell_load,
|
||
|
const InputParameter *configure_interface)
|
||
|
:is_dram(_is_dram),
|
||
|
cell_load(_cell_load),
|
||
|
WdecNANDn(_WdecNANDn),
|
||
|
WdecNANDp(_WdecNANDp)
|
||
|
{//this model is based on the NAND2 based DFF.
|
||
|
l_ip=*configure_interface;
|
||
|
// area.set_area(730*l_ip.F_sz_um*l_ip.F_sz_um);
|
||
|
area.set_area(5*compute_gate_area(NAND, 2,WdecNANDn,WdecNANDp, g_tp.cell_h_def)
|
||
|
+ compute_gate_area(NAND, 2,WdecNANDn,WdecNANDn, g_tp.cell_h_def));
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
double DFFCell::fpfp_node_cap(unsigned int fan_in, unsigned int fan_out)
|
||
|
{
|
||
|
double Ctotal = 0;
|
||
|
//printf("WdecNANDn = %E\n", WdecNANDn);
|
||
|
|
||
|
/* part 1: drain cap of NAND gate */
|
||
|
Ctotal += drain_C_(WdecNANDn, NCH, 2, 1, g_tp.cell_h_def, is_dram) + fan_in * drain_C_(WdecNANDp, PCH, 1, 1, g_tp.cell_h_def, is_dram);
|
||
|
|
||
|
/* part 2: gate cap of NAND gates */
|
||
|
Ctotal += fan_out * gate_C(WdecNANDn + WdecNANDp, 0, is_dram);
|
||
|
|
||
|
return Ctotal;
|
||
|
}
|
||
|
|
||
|
|
||
|
void DFFCell::compute_DFF_cell()
|
||
|
{
|
||
|
double c1, c2, c3, c4, c5, c6;
|
||
|
/* node 5 and node 6 are identical to node 1 in capacitance */
|
||
|
c1 = c5 = c6 = fpfp_node_cap(2, 1);
|
||
|
c2 = fpfp_node_cap(2, 3);
|
||
|
c3 = fpfp_node_cap(3, 2);
|
||
|
c4 = fpfp_node_cap(2, 2);
|
||
|
|
||
|
//cap-load of the clock signal in each Dff, actually the clock signal only connected to one NAND2
|
||
|
clock_cap= 2 * gate_C(WdecNANDn + WdecNANDp, 0, is_dram);
|
||
|
e_switch.readOp.dynamic += (c4 + c1 + c2 + c3 + c5 + c6 + 2*cell_load)*0.5*g_tp.peri_global.Vdd * g_tp.peri_global.Vdd;;
|
||
|
|
||
|
/* no 1/2 for e_keep and e_clock because clock signal switches twice in one cycle */
|
||
|
e_keep_1.readOp.dynamic += c3 * g_tp.peri_global.Vdd * g_tp.peri_global.Vdd ;
|
||
|
e_keep_0.readOp.dynamic += c2 * g_tp.peri_global.Vdd * g_tp.peri_global.Vdd ;
|
||
|
e_clock.readOp.dynamic += clock_cap* g_tp.peri_global.Vdd * g_tp.peri_global.Vdd;;
|
||
|
|
||
|
/* static power */
|
||
|
e_switch.readOp.leakage += (cmos_Isub_leakage(WdecNANDn, WdecNANDp, 2, nand)*5//5 NAND2 and 1 NAND3 in a DFF
|
||
|
+ cmos_Isub_leakage(WdecNANDn, WdecNANDn, 3, nand))*g_tp.peri_global.Vdd;
|
||
|
e_switch.readOp.gate_leakage += (cmos_Ig_leakage(WdecNANDn, WdecNANDp, 2, nand)*5//5 NAND2 and 1 NAND3 in a DFF
|
||
|
+ cmos_Ig_leakage(WdecNANDn, WdecNANDn, 3, nand))*g_tp.peri_global.Vdd;
|
||
|
//printf("leakage =%E\n",cmos_Ileak(1, is_dram) );
|
||
|
}
|
||
|
|
||
|
Pipeline::Pipeline(
|
||
|
const InputParameter *configure_interface,
|
||
|
const CoreDynParam & dyn_p_,
|
||
|
enum Device_ty device_ty_,
|
||
|
bool _is_core_pipeline,
|
||
|
bool _is_default)
|
||
|
: l_ip(*configure_interface),
|
||
|
coredynp(dyn_p_),
|
||
|
device_ty(device_ty_),
|
||
|
is_core_pipeline(_is_core_pipeline),
|
||
|
is_default(_is_default),
|
||
|
num_piperegs(0.0)
|
||
|
|
||
|
{
|
||
|
local_result = init_interface(&l_ip);
|
||
|
if (!coredynp.Embedded)
|
||
|
process_ind = true;
|
||
|
else
|
||
|
process_ind = false;
|
||
|
WNANDn = (process_ind)? 25 * l_ip.F_sz_um : g_tp.min_w_nmos_ ;//this was 20 micron for the 0.8 micron process
|
||
|
WNANDp = (process_ind)? 37.5 * l_ip.F_sz_um : g_tp.min_w_nmos_*pmos_to_nmos_sz_ratio();//this was 30 micron for the 0.8 micron process
|
||
|
load_per_pipeline_stage = 2*gate_C(WNANDn + WNANDp, 0, false);
|
||
|
compute();
|
||
|
|
||
|
}
|
||
|
|
||
|
void Pipeline::compute()
|
||
|
{
|
||
|
compute_stage_vector();
|
||
|
DFFCell pipe_reg(false, WNANDn,WNANDp, load_per_pipeline_stage, &l_ip);
|
||
|
pipe_reg.compute_DFF_cell();
|
||
|
|
||
|
double clock_power_pipereg = num_piperegs * pipe_reg.e_clock.readOp.dynamic;
|
||
|
//******************pipeline power: currently, we average all the possibilities of the states of DFFs in the pipeline. A better way to do it is to consider
|
||
|
//the harming distance of two consecutive signals, However McPAT does not have plan to do this in near future as it focuses on worst case power.
|
||
|
double pipe_reg_power = num_piperegs * (pipe_reg.e_switch.readOp.dynamic+pipe_reg.e_keep_0.readOp.dynamic+pipe_reg.e_keep_1.readOp.dynamic)/3+clock_power_pipereg;
|
||
|
double pipe_reg_leakage = num_piperegs * pipe_reg.e_switch.readOp.leakage;
|
||
|
double pipe_reg_gate_leakage = num_piperegs * pipe_reg.e_switch.readOp.gate_leakage;
|
||
|
power.readOp.dynamic +=pipe_reg_power;
|
||
|
power.readOp.leakage +=pipe_reg_leakage;
|
||
|
power.readOp.gate_leakage +=pipe_reg_gate_leakage;
|
||
|
area.set_area(num_piperegs * pipe_reg.area.get_area());
|
||
|
|
||
|
double long_channel_device_reduction = longer_channel_device_reduction(device_ty, coredynp.core_ty);
|
||
|
power.readOp.longer_channel_leakage = power.readOp.leakage*long_channel_device_reduction;
|
||
|
|
||
|
|
||
|
double sckRation = g_tp.sckt_co_eff;
|
||
|
power.readOp.dynamic *= sckRation;
|
||
|
power.writeOp.dynamic *= sckRation;
|
||
|
power.searchOp.dynamic *= sckRation;
|
||
|
double macro_layout_overhead = g_tp.macro_layout_overhead;
|
||
|
if (!coredynp.Embedded)
|
||
|
area.set_area(area.get_area()*macro_layout_overhead);
|
||
|
}
|
||
|
|
||
|
void Pipeline::compute_stage_vector()
|
||
|
{
|
||
|
double num_stages, tot_stage_vector, per_stage_vector;
|
||
|
int opcode_length = coredynp.x86? coredynp.micro_opcode_length:coredynp.opcode_length;
|
||
|
//Hthread = thread_clock_gated? 1:num_thread;
|
||
|
|
||
|
if (!is_core_pipeline)
|
||
|
{
|
||
|
num_piperegs=l_ip.pipeline_stages*l_ip.per_stage_vector;//The number of pipeline stages are calculated based on the achievable throughput and required throughput
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (coredynp.core_ty==Inorder)
|
||
|
{
|
||
|
/* assume 6 pipe stages and try to estimate bits per pipe stage */
|
||
|
/* pipe stage 0/IF */
|
||
|
num_piperegs += coredynp.pc_width*2*coredynp.num_hthreads;
|
||
|
/* pipe stage IF/ID */
|
||
|
num_piperegs += coredynp.fetchW*(coredynp.instruction_length + coredynp.pc_width)*coredynp.num_hthreads;
|
||
|
/* pipe stage IF/ThreadSEL */
|
||
|
if (coredynp.multithreaded) num_piperegs += coredynp.num_hthreads*coredynp.perThreadState; //8 bit thread states
|
||
|
/* pipe stage ID/EXE */
|
||
|
num_piperegs += coredynp.decodeW*(coredynp.instruction_length + coredynp.pc_width + pow(2.0,opcode_length)+ 2*coredynp.int_data_width)*coredynp.num_hthreads;
|
||
|
/* pipe stage EXE/MEM */
|
||
|
num_piperegs += coredynp.issueW*(3 * coredynp.arch_ireg_width + pow(2.0,opcode_length) + 8*2*coredynp.int_data_width/*+2*powers (2,reg_length)*/);
|
||
|
/* pipe stage MEM/WB the 2^opcode_length means the total decoded signal for the opcode*/
|
||
|
num_piperegs += coredynp.issueW*(2*coredynp.int_data_width + pow(2.0,opcode_length) + 8*2*coredynp.int_data_width/*+2*powers (2,reg_length)*/);
|
||
|
// /* pipe stage 5/6 */
|
||
|
// num_piperegs += issueWidth*(data_width + powers (2,opcode_length)/*+2*powers (2,reg_length)*/);
|
||
|
// /* pipe stage 6/7 */
|
||
|
// num_piperegs += issueWidth*(data_width + powers (2,opcode_length)/*+2*powers (2,reg_length)*/);
|
||
|
// /* pipe stage 7/8 */
|
||
|
// num_piperegs += issueWidth*(data_width + powers (2,opcode_length)/**2*powers (2,reg_length)*/);
|
||
|
// /* assume 50% extra in control signals (rule of thumb) */
|
||
|
num_stages=6;
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* assume 12 stage pipe stages and try to estimate bits per pipe stage */
|
||
|
/*OOO: Fetch, decode, rename, IssueQ, dispatch, regread, EXE, MEM, WB, CM */
|
||
|
|
||
|
/* pipe stage 0/1F*/
|
||
|
num_piperegs += coredynp.pc_width*2*coredynp.num_hthreads ;//PC and Next PC
|
||
|
/* pipe stage IF/ID */
|
||
|
num_piperegs += coredynp.fetchW*(coredynp.instruction_length + coredynp.pc_width)*coredynp.num_hthreads;//PC is used to feed branch predictor in ID
|
||
|
/* pipe stage 1D/Renaming*/
|
||
|
num_piperegs += coredynp.decodeW*(coredynp.instruction_length + coredynp.pc_width)*coredynp.num_hthreads;//PC is for branch exe in later stage.
|
||
|
/* pipe stage Renaming/wire_drive */
|
||
|
num_piperegs += coredynp.decodeW*(coredynp.instruction_length + coredynp.pc_width);
|
||
|
/* pipe stage Renaming/IssueQ */
|
||
|
num_piperegs += coredynp.issueW*(coredynp.instruction_length + coredynp.pc_width + 3*coredynp.phy_ireg_width)*coredynp.num_hthreads;//3*coredynp.phy_ireg_width means 2 sources and 1 dest
|
||
|
/* pipe stage IssueQ/Dispatch */
|
||
|
num_piperegs += coredynp.issueW*(coredynp.instruction_length + 3 * coredynp.phy_ireg_width);
|
||
|
/* pipe stage Dispatch/EXE */
|
||
|
|
||
|
num_piperegs += coredynp.issueW*(3 * coredynp.phy_ireg_width + coredynp.pc_width + pow(2.0,opcode_length)/*+2*powers (2,reg_length)*/);
|
||
|
/* 2^opcode_length means the total decoded signal for the opcode*/
|
||
|
num_piperegs += coredynp.issueW*(2*coredynp.int_data_width + pow(2.0,opcode_length)/*+2*powers (2,reg_length)*/);
|
||
|
/*2 source operands in EXE; Assume 2EXE stages* since we do not really distinguish OP*/
|
||
|
num_piperegs += coredynp.issueW*(2*coredynp.int_data_width + pow(2.0,opcode_length)/*+2*powers (2,reg_length)*/);
|
||
|
/* pipe stage EXE/MEM, data need to be read/write, address*/
|
||
|
num_piperegs += coredynp.issueW*(coredynp.int_data_width + coredynp.v_address_width + pow(2.0,opcode_length)/*+2*powers (2,reg_length)*/);//memory Opcode still need to be passed
|
||
|
/* pipe stage MEM/WB; result data, writeback regs */
|
||
|
num_piperegs += coredynp.issueW*(coredynp.int_data_width + coredynp.phy_ireg_width /* powers (2,opcode_length) + (2,opcode_length)+2*powers (2,reg_length)*/);
|
||
|
/* pipe stage WB/CM ; result data, regs need to be updated, address for resolve memory ops in ROB's top*/
|
||
|
num_piperegs += coredynp.commitW*(coredynp.int_data_width + coredynp.v_address_width + coredynp.phy_ireg_width/*+ powers (2,opcode_length)*2*powers (2,reg_length)*/)*coredynp.num_hthreads;
|
||
|
// if (multithreaded)
|
||
|
// {
|
||
|
//
|
||
|
// }
|
||
|
num_stages=12;
|
||
|
|
||
|
}
|
||
|
|
||
|
/* assume 50% extra in control registers and interrupt registers (rule of thumb) */
|
||
|
num_piperegs = num_piperegs * 1.5;
|
||
|
tot_stage_vector=num_piperegs;
|
||
|
per_stage_vector=tot_stage_vector/num_stages;
|
||
|
|
||
|
if (coredynp.core_ty==Inorder)
|
||
|
{
|
||
|
if (coredynp.pipeline_stages>6)
|
||
|
num_piperegs= per_stage_vector*coredynp.pipeline_stages;
|
||
|
}
|
||
|
else//OOO
|
||
|
{
|
||
|
if (coredynp.pipeline_stages>12)
|
||
|
num_piperegs= per_stage_vector*coredynp.pipeline_stages;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
FunctionalUnit::FunctionalUnit(ParseXML *XML_interface, int ithCore_, InputParameter* interface_ip_,const CoreDynParam & dyn_p_, enum FU_type fu_type_)
|
||
|
:XML(XML_interface),
|
||
|
ithCore(ithCore_),
|
||
|
interface_ip(*interface_ip_),
|
||
|
coredynp(dyn_p_),
|
||
|
fu_type(fu_type_)
|
||
|
{
|
||
|
double area_t;//, leakage, gate_leakage;
|
||
|
double pmos_to_nmos_sizing_r = pmos_to_nmos_sz_ratio();
|
||
|
clockRate = coredynp.clockRate;
|
||
|
executionTime = coredynp.executionTime;
|
||
|
|
||
|
//XML_interface=_XML_interface;
|
||
|
uca_org_t result2;
|
||
|
result2 = init_interface(&interface_ip);
|
||
|
if (XML->sys.Embedded)
|
||
|
{
|
||
|
if (fu_type == FPU)
|
||
|
{
|
||
|
num_fu=coredynp.num_fpus;
|
||
|
//area_t = 8.47*1e6*g_tp.scaling_factor.logic_scaling_co_eff;//this is um^2
|
||
|
area_t = 4.47*1e6*(g_ip->F_sz_nm*g_ip->F_sz_nm/90.0/90.0);//this is um^2 The base number
|
||
|
//4.47 contains both VFP and NEON processing unit, VFP is about 40% and NEON is about 60%
|
||
|
if (g_ip->F_sz_nm>90)
|
||
|
area_t = 4.47*1e6*g_tp.scaling_factor.logic_scaling_co_eff;//this is um^2
|
||
|
leakage = area_t *(g_tp.scaling_factor.core_tx_density)*cmos_Isub_leakage(5*g_tp.min_w_nmos_, 5*g_tp.min_w_nmos_*pmos_to_nmos_sizing_r, 1, inv)*g_tp.peri_global.Vdd/2;//unit W
|
||
|
gate_leakage = area_t *(g_tp.scaling_factor.core_tx_density)*cmos_Ig_leakage(5*g_tp.min_w_nmos_, 5*g_tp.min_w_nmos_*pmos_to_nmos_sizing_r, 1, inv)*g_tp.peri_global.Vdd/2;//unit W
|
||
|
//energy = 0.3529/10*1e-9;//this is the energy(nJ) for a FP instruction in FPU usually it can have up to 20 cycles.
|
||
|
// base_energy = coredynp.core_ty==Inorder? 0: 89e-3*3; //W The base energy of ALU average numbers from Intel 4G and 773Mhz (Wattch)
|
||
|
// base_energy *=(g_tp.peri_global.Vdd*g_tp.peri_global.Vdd/1.2/1.2);
|
||
|
base_energy = 0;
|
||
|
per_access_energy = 1.15/1e9/4/1.3/1.3*g_tp.peri_global.Vdd*g_tp.peri_global.Vdd*(g_ip->F_sz_nm/90.0);//g_tp.peri_global.Vdd*g_tp.peri_global.Vdd/1.2/1.2);//0.00649*1e-9; //This is per Hz energy(nJ)
|
||
|
//FPU power from Sandia's processor sizing tech report
|
||
|
FU_height=(18667*num_fu)*interface_ip.F_sz_um;//FPU from Sun's data
|
||
|
}
|
||
|
else if (fu_type == ALU)
|
||
|
{
|
||
|
num_fu=coredynp.num_alus;
|
||
|
area_t = 280*260*g_tp.scaling_factor.logic_scaling_co_eff;//this is um^2 ALU + MUl
|
||
|
leakage = area_t *(g_tp.scaling_factor.core_tx_density)*cmos_Isub_leakage(20*g_tp.min_w_nmos_, 20*g_tp.min_w_nmos_*pmos_to_nmos_sizing_r, 1, inv)*g_tp.peri_global.Vdd/2;//unit W
|
||
|
gate_leakage = area_t*(g_tp.scaling_factor.core_tx_density)*cmos_Ig_leakage(20*g_tp.min_w_nmos_, 20*g_tp.min_w_nmos_*pmos_to_nmos_sizing_r, 1, inv)*g_tp.peri_global.Vdd/2;
|
||
|
// base_energy = coredynp.core_ty==Inorder? 0:89e-3; //W The base energy of ALU average numbers from Intel 4G and 773Mhz (Wattch)
|
||
|
// base_energy *=(g_tp.peri_global.Vdd*g_tp.peri_global.Vdd/1.2/1.2);
|
||
|
base_energy = 0;
|
||
|
per_access_energy = 1.15/3/1e9/4/1.3/1.3*g_tp.peri_global.Vdd*g_tp.peri_global.Vdd*(g_ip->F_sz_nm/90.0);//(g_tp.peri_global.Vdd*g_tp.peri_global.Vdd/1.2/1.2);//0.00649*1e-9; //This is per cycle energy(nJ)
|
||
|
FU_height=(6222*num_fu)*interface_ip.F_sz_um;//integer ALU
|
||
|
|
||
|
}
|
||
|
else if (fu_type == MUL)
|
||
|
{
|
||
|
num_fu=coredynp.num_muls;
|
||
|
area_t = 280*260*3*g_tp.scaling_factor.logic_scaling_co_eff;//this is um^2 ALU + MUl
|
||
|
leakage = area_t *(g_tp.scaling_factor.core_tx_density)*cmos_Isub_leakage(20*g_tp.min_w_nmos_, 20*g_tp.min_w_nmos_*pmos_to_nmos_sizing_r, 1, inv)*g_tp.peri_global.Vdd/2;//unit W
|
||
|
gate_leakage = area_t*(g_tp.scaling_factor.core_tx_density)*cmos_Ig_leakage(20*g_tp.min_w_nmos_, 20*g_tp.min_w_nmos_*pmos_to_nmos_sizing_r, 1, inv)*g_tp.peri_global.Vdd/2;
|
||
|
// base_energy = coredynp.core_ty==Inorder? 0:89e-3*2; //W The base energy of ALU average numbers from Intel 4G and 773Mhz (Wattch)
|
||
|
// base_energy *=(g_tp.peri_global.Vdd*g_tp.peri_global.Vdd/1.2/1.2);
|
||
|
base_energy = 0;
|
||
|
per_access_energy = 1.15*2/3/1e9/4/1.3/1.3*g_tp.peri_global.Vdd*g_tp.peri_global.Vdd*(g_ip->F_sz_nm/90.0);//(g_tp.peri_global.Vdd*g_tp.peri_global.Vdd/1.2/1.2);//0.00649*1e-9; //This is per cycle energy(nJ), coefficient based on Wattch
|
||
|
FU_height=(9334*num_fu )*interface_ip.F_sz_um;//divider/mul from Sun's data
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
cout<<"Unknown Functional Unit Type"<<endl;
|
||
|
exit(0);
|
||
|
}
|
||
|
per_access_energy *=0.5;//According to ARM data embedded processor has much lower per acc energy
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (fu_type == FPU)
|
||
|
{
|
||
|
num_fu=coredynp.num_fpus;
|
||
|
//area_t = 8.47*1e6*g_tp.scaling_factor.logic_scaling_co_eff;//this is um^2
|
||
|
area_t = 8.47*1e6*(g_ip->F_sz_nm*g_ip->F_sz_nm/90.0/90.0);//this is um^2
|
||
|
if (g_ip->F_sz_nm>90)
|
||
|
area_t = 8.47*1e6*g_tp.scaling_factor.logic_scaling_co_eff;//this is um^2
|
||
|
leakage = area_t *(g_tp.scaling_factor.core_tx_density)*cmos_Isub_leakage(5*g_tp.min_w_nmos_, 5*g_tp.min_w_nmos_*pmos_to_nmos_sizing_r, 1, inv)*g_tp.peri_global.Vdd/2;//unit W
|
||
|
gate_leakage = area_t *(g_tp.scaling_factor.core_tx_density)*cmos_Ig_leakage(5*g_tp.min_w_nmos_, 5*g_tp.min_w_nmos_*pmos_to_nmos_sizing_r, 1, inv)*g_tp.peri_global.Vdd/2;//unit W
|
||
|
//energy = 0.3529/10*1e-9;//this is the energy(nJ) for a FP instruction in FPU usually it can have up to 20 cycles.
|
||
|
base_energy = coredynp.core_ty==Inorder? 0: 89e-3*3; //W The base energy of ALU average numbers from Intel 4G and 773Mhz (Wattch)
|
||
|
base_energy *=(g_tp.peri_global.Vdd*g_tp.peri_global.Vdd/1.2/1.2);
|
||
|
per_access_energy = 1.15*3/1e9/4/1.3/1.3*g_tp.peri_global.Vdd*g_tp.peri_global.Vdd*(g_ip->F_sz_nm/90.0);//g_tp.peri_global.Vdd*g_tp.peri_global.Vdd/1.2/1.2);//0.00649*1e-9; //This is per op energy(nJ)
|
||
|
FU_height=(38667*num_fu)*interface_ip.F_sz_um;//FPU from Sun's data
|
||
|
}
|
||
|
else if (fu_type == ALU)
|
||
|
{
|
||
|
num_fu=coredynp.num_alus;
|
||
|
area_t = 280*260*2*g_tp.scaling_factor.logic_scaling_co_eff;//this is um^2 ALU + MUl
|
||
|
leakage = area_t *(g_tp.scaling_factor.core_tx_density)*cmos_Isub_leakage(20*g_tp.min_w_nmos_, 20*g_tp.min_w_nmos_*pmos_to_nmos_sizing_r, 1, inv)*g_tp.peri_global.Vdd/2;//unit W
|
||
|
gate_leakage = area_t*(g_tp.scaling_factor.core_tx_density)*cmos_Ig_leakage(20*g_tp.min_w_nmos_, 20*g_tp.min_w_nmos_*pmos_to_nmos_sizing_r, 1, inv)*g_tp.peri_global.Vdd/2;
|
||
|
base_energy = coredynp.core_ty==Inorder? 0:89e-3; //W The base energy of ALU average numbers from Intel 4G and 773Mhz (Wattch)
|
||
|
base_energy *=(g_tp.peri_global.Vdd*g_tp.peri_global.Vdd/1.2/1.2);
|
||
|
per_access_energy = 1.15/1e9/4/1.3/1.3*g_tp.peri_global.Vdd*g_tp.peri_global.Vdd*(g_ip->F_sz_nm/90.0);//(g_tp.peri_global.Vdd*g_tp.peri_global.Vdd/1.2/1.2);//0.00649*1e-9; //This is per cycle energy(nJ)
|
||
|
FU_height=(6222*num_fu)*interface_ip.F_sz_um;//integer ALU
|
||
|
|
||
|
}
|
||
|
else if (fu_type == MUL)
|
||
|
{
|
||
|
num_fu=coredynp.num_muls;
|
||
|
area_t = 280*260*2*3*g_tp.scaling_factor.logic_scaling_co_eff;//this is um^2 ALU + MUl
|
||
|
leakage = area_t *(g_tp.scaling_factor.core_tx_density)*cmos_Isub_leakage(20*g_tp.min_w_nmos_, 20*g_tp.min_w_nmos_*pmos_to_nmos_sizing_r, 1, inv)*g_tp.peri_global.Vdd/2;//unit W
|
||
|
gate_leakage = area_t*(g_tp.scaling_factor.core_tx_density)*cmos_Ig_leakage(20*g_tp.min_w_nmos_, 20*g_tp.min_w_nmos_*pmos_to_nmos_sizing_r, 1, inv)*g_tp.peri_global.Vdd/2;
|
||
|
base_energy = coredynp.core_ty==Inorder? 0:89e-3*2; //W The base energy of ALU average numbers from Intel 4G and 773Mhz (Wattch)
|
||
|
base_energy *=(g_tp.peri_global.Vdd*g_tp.peri_global.Vdd/1.2/1.2);
|
||
|
per_access_energy = 1.15*2/1e9/4/1.3/1.3*g_tp.peri_global.Vdd*g_tp.peri_global.Vdd*(g_ip->F_sz_nm/90.0);//(g_tp.peri_global.Vdd*g_tp.peri_global.Vdd/1.2/1.2);//0.00649*1e-9; //This is per cycle energy(nJ), coefficient based on Wattch
|
||
|
FU_height=(9334*num_fu )*interface_ip.F_sz_um;//divider/mul from Sun's data
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
cout<<"Unknown Functional Unit Type"<<endl;
|
||
|
exit(0);
|
||
|
}
|
||
|
}
|
||
|
//IEXEU, simple ALU and FPU
|
||
|
// double C_ALU, C_EXEU, C_FPU; //Lum Equivalent capacitance of IEXEU and FPU. Based on Intel and Sun 90nm process fabracation.
|
||
|
//
|
||
|
// C_ALU = 0.025e-9;//F
|
||
|
// C_EXEU = 0.05e-9; //F
|
||
|
// C_FPU = 0.35e-9;//F
|
||
|
area.set_area(area_t*num_fu);
|
||
|
leakage *= num_fu;
|
||
|
gate_leakage *=num_fu;
|
||
|
double macro_layout_overhead = g_tp.macro_layout_overhead;
|
||
|
// if (!XML->sys.Embedded)
|
||
|
area.set_area(area.get_area()*macro_layout_overhead);
|
||
|
}
|
||
|
|
||
|
void FunctionalUnit::computeEnergy(bool is_tdp)
|
||
|
{
|
||
|
double pppm_t[4] = {1,1,1,1};
|
||
|
double FU_duty_cycle;
|
||
|
if (is_tdp)
|
||
|
{
|
||
|
|
||
|
|
||
|
set_pppm(pppm_t, 2, 2, 2, 2);//2 means two source operands needs to be passed for each int instruction.
|
||
|
if (fu_type == FPU)
|
||
|
{
|
||
|
stats_t.readAc.access = num_fu;
|
||
|
tdp_stats = stats_t;
|
||
|
FU_duty_cycle = coredynp.FPU_duty_cycle;
|
||
|
}
|
||
|
else if (fu_type == ALU)
|
||
|
{
|
||
|
stats_t.readAc.access = 1*num_fu;
|
||
|
tdp_stats = stats_t;
|
||
|
FU_duty_cycle = coredynp.ALU_duty_cycle;
|
||
|
}
|
||
|
else if (fu_type == MUL)
|
||
|
{
|
||
|
stats_t.readAc.access = num_fu;
|
||
|
tdp_stats = stats_t;
|
||
|
FU_duty_cycle = coredynp.MUL_duty_cycle;
|
||
|
}
|
||
|
|
||
|
//power.readOp.dynamic = base_energy/clockRate + energy*stats_t.readAc.access;
|
||
|
power.readOp.dynamic = per_access_energy*stats_t.readAc.access + base_energy/clockRate;
|
||
|
double sckRation = g_tp.sckt_co_eff;
|
||
|
power.readOp.dynamic *= sckRation*FU_duty_cycle;
|
||
|
power.writeOp.dynamic *= sckRation;
|
||
|
power.searchOp.dynamic *= sckRation;
|
||
|
|
||
|
power.readOp.leakage = leakage;
|
||
|
power.readOp.gate_leakage = gate_leakage;
|
||
|
double long_channel_device_reduction = longer_channel_device_reduction(Core_device, coredynp.core_ty);
|
||
|
power.readOp.longer_channel_leakage = power.readOp.leakage*long_channel_device_reduction;
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (fu_type == FPU)
|
||
|
{
|
||
|
stats_t.readAc.access = XML->sys.core[ithCore].fpu_accesses;
|
||
|
rtp_stats = stats_t;
|
||
|
}
|
||
|
else if (fu_type == ALU)
|
||
|
{
|
||
|
stats_t.readAc.access = XML->sys.core[ithCore].ialu_accesses;
|
||
|
rtp_stats = stats_t;
|
||
|
}
|
||
|
else if (fu_type == MUL)
|
||
|
{
|
||
|
stats_t.readAc.access = XML->sys.core[ithCore].mul_accesses;
|
||
|
rtp_stats = stats_t;
|
||
|
}
|
||
|
|
||
|
//rt_power.readOp.dynamic = base_energy*executionTime + energy*stats_t.readAc.access;
|
||
|
rt_power.readOp.dynamic = per_access_energy*stats_t.readAc.access + base_energy*executionTime;
|
||
|
double sckRation = g_tp.sckt_co_eff;
|
||
|
rt_power.readOp.dynamic *= sckRation;
|
||
|
rt_power.writeOp.dynamic *= sckRation;
|
||
|
rt_power.searchOp.dynamic *= sckRation;
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
void FunctionalUnit::displayEnergy(uint32_t indent,int plevel,bool is_tdp)
|
||
|
{
|
||
|
string indent_str(indent, ' ');
|
||
|
string indent_str_next(indent+2, ' ');
|
||
|
bool long_channel = XML->sys.longer_channel_device;
|
||
|
|
||
|
// cout << indent_str_next << "Results Broadcast Bus Area = " << bypass->area.get_area() *1e-6 << " mm^2" << endl;
|
||
|
if (is_tdp)
|
||
|
{
|
||
|
if (fu_type == FPU)
|
||
|
{
|
||
|
cout << indent_str << "Floating Point Units (FPUs) (Count: "<< coredynp.num_fpus <<" ):" << endl;
|
||
|
cout << indent_str_next << "Area = " << area.get_area()*1e-6 << " mm^2" << endl;
|
||
|
cout << indent_str_next << "Peak Dynamic = " << power.readOp.dynamic*clockRate << " W" << endl;
|
||
|
// cout << indent_str_next << "Subthreshold Leakage = " << power.readOp.leakage << " W" << endl;
|
||
|
cout << indent_str_next<< "Subthreshold Leakage = "
|
||
|
<< (long_channel? power.readOp.longer_channel_leakage:power.readOp.leakage) <<" W" << endl;
|
||
|
cout << indent_str_next << "Gate Leakage = " << power.readOp.gate_leakage << " W" << endl;
|
||
|
cout << indent_str_next << "Runtime Dynamic = " << rt_power.readOp.dynamic/executionTime << " W" << endl;
|
||
|
cout <<endl;
|
||
|
}
|
||
|
else if (fu_type == ALU)
|
||
|
{
|
||
|
cout << indent_str << "Integer ALUs (Count: "<< coredynp.num_alus <<" ):" << endl;
|
||
|
cout << indent_str_next << "Area = " << area.get_area()*1e-6 << " mm^2" << endl;
|
||
|
cout << indent_str_next << "Peak Dynamic = " << power.readOp.dynamic*clockRate << " W" << endl;
|
||
|
// cout << indent_str_next << "Subthreshold Leakage = " << power.readOp.leakage << " W" << endl;
|
||
|
cout << indent_str_next<< "Subthreshold Leakage = "
|
||
|
<< (long_channel? power.readOp.longer_channel_leakage:power.readOp.leakage) <<" W" << endl;
|
||
|
cout << indent_str_next << "Gate Leakage = " << power.readOp.gate_leakage << " W" << endl;
|
||
|
cout << indent_str_next << "Runtime Dynamic = " << rt_power.readOp.dynamic/executionTime << " W" << endl;
|
||
|
cout <<endl;
|
||
|
}
|
||
|
else if (fu_type == MUL)
|
||
|
{
|
||
|
cout << indent_str << "Complex ALUs (Mul/Div) (Count: "<< coredynp.num_muls <<" ):" << endl;
|
||
|
cout << indent_str_next << "Area = " << area.get_area()*1e-6 << " mm^2" << endl;
|
||
|
cout << indent_str_next << "Peak Dynamic = " << power.readOp.dynamic*clockRate << " W" << endl;
|
||
|
// cout << indent_str_next << "Subthreshold Leakage = " << power.readOp.leakage << " W" << endl;
|
||
|
cout << indent_str_next<< "Subthreshold Leakage = "
|
||
|
<< (long_channel? power.readOp.longer_channel_leakage:power.readOp.leakage) <<" W" << endl;
|
||
|
cout << indent_str_next << "Gate Leakage = " << power.readOp.gate_leakage << " W" << endl;
|
||
|
cout << indent_str_next << "Runtime Dynamic = " << rt_power.readOp.dynamic/executionTime << " W" << endl;
|
||
|
cout <<endl;
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
void FunctionalUnit::leakage_feedback(double temperature)
|
||
|
{
|
||
|
// Update the temperature and initialize the global interfaces.
|
||
|
interface_ip.temp = (unsigned int)round(temperature/10.0)*10;
|
||
|
|
||
|
uca_org_t init_result = init_interface(&interface_ip); // init_result is dummy
|
||
|
|
||
|
// This is part of FunctionalUnit()
|
||
|
double area_t, leakage, gate_leakage;
|
||
|
double pmos_to_nmos_sizing_r = pmos_to_nmos_sz_ratio();
|
||
|
|
||
|
if (fu_type == FPU)
|
||
|
{
|
||
|
area_t = 4.47*1e6*(g_ip->F_sz_nm*g_ip->F_sz_nm/90.0/90.0);//this is um^2 The base number
|
||
|
if (g_ip->F_sz_nm>90)
|
||
|
area_t = 4.47*1e6*g_tp.scaling_factor.logic_scaling_co_eff;//this is um^2
|
||
|
leakage = area_t *(g_tp.scaling_factor.core_tx_density)*cmos_Isub_leakage(5*g_tp.min_w_nmos_, 5*g_tp.min_w_nmos_*pmos_to_nmos_sizing_r, 1, inv)*g_tp.peri_global.Vdd/2;//unit W
|
||
|
gate_leakage = area_t *(g_tp.scaling_factor.core_tx_density)*cmos_Ig_leakage(5*g_tp.min_w_nmos_, 5*g_tp.min_w_nmos_*pmos_to_nmos_sizing_r, 1, inv)*g_tp.peri_global.Vdd/2;//unit W
|
||
|
}
|
||
|
else if (fu_type == ALU)
|
||
|
{
|
||
|
area_t = 280*260*2*num_fu*g_tp.scaling_factor.logic_scaling_co_eff;//this is um^2 ALU + MUl
|
||
|
leakage = area_t *(g_tp.scaling_factor.core_tx_density)*cmos_Isub_leakage(20*g_tp.min_w_nmos_, 20*g_tp.min_w_nmos_*pmos_to_nmos_sizing_r, 1, inv)*g_tp.peri_global.Vdd/2;//unit W
|
||
|
gate_leakage = area_t*(g_tp.scaling_factor.core_tx_density)*cmos_Ig_leakage(20*g_tp.min_w_nmos_, 20*g_tp.min_w_nmos_*pmos_to_nmos_sizing_r, 1, inv)*g_tp.peri_global.Vdd/2;
|
||
|
}
|
||
|
else if (fu_type == MUL)
|
||
|
{
|
||
|
area_t = 280*260*2*3*num_fu*g_tp.scaling_factor.logic_scaling_co_eff;//this is um^2 ALU + MUl
|
||
|
leakage = area_t *(g_tp.scaling_factor.core_tx_density)*cmos_Isub_leakage(20*g_tp.min_w_nmos_, 20*g_tp.min_w_nmos_*pmos_to_nmos_sizing_r, 1, inv)*g_tp.peri_global.Vdd/2;//unit W
|
||
|
gate_leakage = area_t*(g_tp.scaling_factor.core_tx_density)*cmos_Ig_leakage(20*g_tp.min_w_nmos_, 20*g_tp.min_w_nmos_*pmos_to_nmos_sizing_r, 1, inv)*g_tp.peri_global.Vdd/2;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
cout<<"Unknown Functional Unit Type"<<endl;
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
power.readOp.leakage = leakage*num_fu;
|
||
|
power.readOp.gate_leakage = gate_leakage*num_fu;
|
||
|
power.readOp.longer_channel_leakage = longer_channel_device_reduction(Core_device, coredynp.core_ty);
|
||
|
}
|
||
|
|
||
|
UndiffCore::UndiffCore(ParseXML* XML_interface, int ithCore_, InputParameter* interface_ip_, const CoreDynParam & dyn_p_, bool exist_, bool embedded_)
|
||
|
:XML(XML_interface),
|
||
|
ithCore(ithCore_),
|
||
|
interface_ip(*interface_ip_),
|
||
|
coredynp(dyn_p_),
|
||
|
core_ty(coredynp.core_ty),
|
||
|
embedded(XML->sys.Embedded),
|
||
|
pipeline_stage(coredynp.pipeline_stages),
|
||
|
num_hthreads(coredynp.num_hthreads),
|
||
|
issue_width(coredynp.issueW),
|
||
|
exist(exist_)
|
||
|
// is_default(_is_default)
|
||
|
{
|
||
|
if (!exist) return;
|
||
|
double undifferentiated_core=0;
|
||
|
double core_tx_density=0;
|
||
|
double pmos_to_nmos_sizing_r = pmos_to_nmos_sz_ratio();
|
||
|
double undifferentiated_core_coe;
|
||
|
//XML_interface=_XML_interface;
|
||
|
uca_org_t result2;
|
||
|
result2 = init_interface(&interface_ip);
|
||
|
|
||
|
//Compute undifferentiated core area at 90nm.
|
||
|
if (embedded==false)
|
||
|
{
|
||
|
//Based on the results of polynomial/log curve fitting based on undifferentiated core of Niagara, Niagara2, Merom, Penyrn, Prescott, Opteron die measurements
|
||
|
if (core_ty==OOO)
|
||
|
{
|
||
|
//undifferentiated_core = (0.0764*pipeline_stage*pipeline_stage -2.3685*pipeline_stage + 10.405);//OOO
|
||
|
undifferentiated_core = (3.57*log(pipeline_stage)-1.2643)>0?(3.57*log(pipeline_stage)-1.2643):0;
|
||
|
}
|
||
|
else if (core_ty==Inorder)
|
||
|
{
|
||
|
//undifferentiated_core = (0.1238*pipeline_stage + 7.2572)*0.9;//inorder
|
||
|
undifferentiated_core = (-2.19*log(pipeline_stage)+6.55)>0?(-2.19*log(pipeline_stage)+6.55):0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
cout<<"invalid core type"<<endl;
|
||
|
exit(0);
|
||
|
}
|
||
|
undifferentiated_core *= (1+ logtwo(num_hthreads)* 0.0716);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//Based on the results in paper "parametrized processor models" Sandia Labs
|
||
|
if (XML->sys.opt_clockrate)
|
||
|
undifferentiated_core_coe = 0.05;
|
||
|
else
|
||
|
undifferentiated_core_coe = 0;
|
||
|
undifferentiated_core = (0.4109* pipeline_stage - 0.776)*undifferentiated_core_coe;
|
||
|
undifferentiated_core *= (1+ logtwo(num_hthreads)* 0.0426);
|
||
|
}
|
||
|
|
||
|
undifferentiated_core *= g_tp.scaling_factor.logic_scaling_co_eff*1e6;//change from mm^2 to um^2
|
||
|
core_tx_density = g_tp.scaling_factor.core_tx_density;
|
||
|
//undifferentiated_core = 3*1e6;
|
||
|
//undifferentiated_core *= g_tp.scaling_factor.logic_scaling_co_eff;//(g_ip->F_sz_um*g_ip->F_sz_um/0.09/0.09)*;
|
||
|
power.readOp.leakage = undifferentiated_core*(core_tx_density)*cmos_Isub_leakage(5*g_tp.min_w_nmos_, 5*g_tp.min_w_nmos_*pmos_to_nmos_sizing_r, 1, inv)*g_tp.peri_global.Vdd;//unit W
|
||
|
power.readOp.gate_leakage = undifferentiated_core*(core_tx_density)*cmos_Ig_leakage(5*g_tp.min_w_nmos_, 5*g_tp.min_w_nmos_*pmos_to_nmos_sizing_r, 1, inv)*g_tp.peri_global.Vdd;
|
||
|
|
||
|
double long_channel_device_reduction = longer_channel_device_reduction(Core_device, coredynp.core_ty);
|
||
|
power.readOp.longer_channel_leakage = power.readOp.leakage*long_channel_device_reduction;
|
||
|
area.set_area(undifferentiated_core);
|
||
|
|
||
|
scktRatio = g_tp.sckt_co_eff;
|
||
|
power.readOp.dynamic *= scktRatio;
|
||
|
power.writeOp.dynamic *= scktRatio;
|
||
|
power.searchOp.dynamic *= scktRatio;
|
||
|
macro_PR_overhead = g_tp.macro_layout_overhead;
|
||
|
area.set_area(area.get_area()*macro_PR_overhead);
|
||
|
|
||
|
|
||
|
|
||
|
// double vt=g_tp.peri_global.Vth;
|
||
|
// double velocity_index=1.1;
|
||
|
// double c_in=gate_C(g_tp.min_w_nmos_, g_tp.min_w_nmos_*pmos_to_nmos_sizing_r , 0.0, false);
|
||
|
// double c_out= drain_C_(g_tp.min_w_nmos_, NCH, 2, 1, g_tp.cell_h_def, false) + drain_C_(g_tp.min_w_nmos_*pmos_to_nmos_sizing_r, PCH, 1, 1, g_tp.cell_h_def, false) + c_in;
|
||
|
// double w_nmos=g_tp.min_w_nmos_;
|
||
|
// double w_pmos=g_tp.min_w_nmos_*pmos_to_nmos_sizing_r;
|
||
|
// double i_on_n=1.0;
|
||
|
// double i_on_p=1.0;
|
||
|
// double i_on_n_in=1.0;
|
||
|
// double i_on_p_in=1;
|
||
|
// double vdd=g_tp.peri_global.Vdd;
|
||
|
|
||
|
// power.readOp.sc=shortcircuit_simple(vt, velocity_index, c_in, c_out, w_nmos,w_pmos, i_on_n, i_on_p,i_on_n_in, i_on_p_in, vdd);
|
||
|
// power.readOp.dynamic=c_out*vdd*vdd/2;
|
||
|
|
||
|
// cout<<power.readOp.dynamic << "dynamic" <<endl;
|
||
|
// cout<<power.readOp.sc << "sc" << endl;
|
||
|
|
||
|
// power.readOp.sc=shortcircuit(vt, velocity_index, c_in, c_out, w_nmos,w_pmos, i_on_n, i_on_p,i_on_n_in, i_on_p_in, vdd);
|
||
|
// power.readOp.dynamic=c_out*vdd*vdd/2;
|
||
|
//
|
||
|
// cout<<power.readOp.dynamic << "dynamic" <<endl;
|
||
|
// cout<<power.readOp.sc << "sc" << endl;
|
||
|
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
void UndiffCore::displayEnergy(uint32_t indent,int plevel,bool is_tdp)
|
||
|
{
|
||
|
string indent_str(indent, ' ');
|
||
|
string indent_str_next(indent+2, ' ');
|
||
|
bool long_channel = XML->sys.longer_channel_device;
|
||
|
|
||
|
if (is_tdp)
|
||
|
{
|
||
|
cout << indent_str << "UndiffCore:" << endl;
|
||
|
cout << indent_str_next << "Area = " << area.get_area()*1e-6<< " mm^2" << endl;
|
||
|
cout << indent_str_next << "Peak Dynamic = " << power.readOp.dynamic*clockRate << " W" << endl;
|
||
|
//cout << indent_str_next << "Subthreshold Leakage = " << power.readOp.leakage <<" W" << endl;
|
||
|
cout << indent_str_next<< "Subthreshold Leakage = "
|
||
|
<< (long_channel? power.readOp.longer_channel_leakage:power.readOp.leakage) <<" W" << endl;
|
||
|
cout << indent_str_next << "Gate Leakage = " << power.readOp.gate_leakage << " W" << endl;
|
||
|
//cout << indent_str_next << "Runtime Dynamic = " << rt_power.readOp.dynamic/executionTime << " W" << endl;
|
||
|
cout <<endl;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
cout << indent_str << "UndiffCore:" << endl;
|
||
|
cout << indent_str_next << "Area = " << area.get_area()*1e-6<< " mm^2" << endl;
|
||
|
cout << indent_str_next << "Peak Dynamic = " << power.readOp.dynamic*clockRate << " W" << endl;
|
||
|
cout << indent_str_next << "Subthreshold Leakage = " << power.readOp.leakage <<" W" << endl;
|
||
|
cout << indent_str_next << "Gate Leakage = " << power.readOp.gate_leakage << " W" << endl;
|
||
|
//cout << indent_str_next << "Runtime Dynamic = " << rt_power.readOp.dynamic/executionTime << " W" << endl;
|
||
|
cout <<endl;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
inst_decoder::inst_decoder(
|
||
|
bool _is_default,
|
||
|
const InputParameter *configure_interface,
|
||
|
int opcode_length_,
|
||
|
int num_decoders_,
|
||
|
bool x86_,
|
||
|
enum Device_ty device_ty_,
|
||
|
enum Core_type core_ty_)
|
||
|
:is_default(_is_default),
|
||
|
opcode_length(opcode_length_),
|
||
|
num_decoders(num_decoders_),
|
||
|
x86(x86_),
|
||
|
device_ty(device_ty_),
|
||
|
core_ty(core_ty_)
|
||
|
{
|
||
|
/*
|
||
|
* Instruction decoder is different from n to 2^n decoders
|
||
|
* that are commonly used in row decoders in memory arrays.
|
||
|
* The RISC instruction decoder is typically a very simple device.
|
||
|
* We can decode an instruction by simply
|
||
|
* separating the machine word into small parts using wire slices
|
||
|
* The RISC instruction decoder can be approximate by the n to 2^n decoders,
|
||
|
* although this approximation usually underestimate power since each decoded
|
||
|
* instruction normally has more than 1 active signal.
|
||
|
*
|
||
|
* However, decoding a CISC instruction word is much more difficult
|
||
|
* than the RISC case. A CISC decoder is typically set up as a state machine.
|
||
|
* The machine reads the opcode field to determine
|
||
|
* what type of instruction it is,
|
||
|
* and where the other data values are.
|
||
|
* The instruction word is read in piece by piece,
|
||
|
* and decisions are made at each stage as to
|
||
|
* how the remainder of the instruction word will be read.
|
||
|
* (sequencer and ROM are usually needed)
|
||
|
* An x86 decoder can be even more complex since
|
||
|
* it involve both decoding instructions into u-ops and
|
||
|
* merge u-ops when doing micro-ops fusion.
|
||
|
*/
|
||
|
bool is_dram=false;
|
||
|
double pmos_to_nmos_sizing_r;
|
||
|
double load_nmos_width, load_pmos_width;
|
||
|
double C_driver_load, R_wire_load;
|
||
|
Area cell;
|
||
|
|
||
|
l_ip=*configure_interface;
|
||
|
local_result = init_interface(&l_ip);
|
||
|
cell.h =g_tp.cell_h_def;
|
||
|
cell.w =g_tp.cell_h_def;
|
||
|
|
||
|
num_decoder_segments = (int)ceil(opcode_length/18.0);
|
||
|
if (opcode_length > 18) opcode_length = 18;
|
||
|
num_decoded_signals= (int)pow(2.0,opcode_length);
|
||
|
pmos_to_nmos_sizing_r = pmos_to_nmos_sz_ratio();
|
||
|
load_nmos_width=g_tp.max_w_nmos_ /2;
|
||
|
load_pmos_width= g_tp.max_w_nmos_ * pmos_to_nmos_sizing_r;
|
||
|
C_driver_load = 1024*gate_C(load_nmos_width + load_pmos_width, 0, is_dram); //TODO: this number 1024 needs to be revisited
|
||
|
R_wire_load = 3000*l_ip.F_sz_um * g_tp.wire_outside_mat.R_per_um;
|
||
|
|
||
|
final_dec = new Decoder(
|
||
|
num_decoded_signals,
|
||
|
false,
|
||
|
C_driver_load,
|
||
|
R_wire_load,
|
||
|
false/*is_fa*/,
|
||
|
false/*is_dram*/,
|
||
|
false/*wl_tr*/, //to use peri device
|
||
|
cell);
|
||
|
|
||
|
PredecBlk * predec_blk1 = new PredecBlk(
|
||
|
num_decoded_signals,
|
||
|
final_dec,
|
||
|
0,//Assuming predec and dec are back to back
|
||
|
0,
|
||
|
1,//Each Predec only drives one final dec
|
||
|
false/*is_dram*/,
|
||
|
true);
|
||
|
PredecBlk * predec_blk2 = new PredecBlk(
|
||
|
num_decoded_signals,
|
||
|
final_dec,
|
||
|
0,//Assuming predec and dec are back to back
|
||
|
0,
|
||
|
1,//Each Predec only drives one final dec
|
||
|
false/*is_dram*/,
|
||
|
false);
|
||
|
|
||
|
PredecBlkDrv * predec_blk_drv1 = new PredecBlkDrv(0, predec_blk1, false);
|
||
|
PredecBlkDrv * predec_blk_drv2 = new PredecBlkDrv(0, predec_blk2, false);
|
||
|
|
||
|
pre_dec = new Predec(predec_blk_drv1, predec_blk_drv2);
|
||
|
|
||
|
double area_decoder = final_dec->area.get_area() * num_decoded_signals * num_decoder_segments*num_decoders;
|
||
|
//double w_decoder = area_decoder / area.get_h();
|
||
|
double area_pre_dec = (predec_blk_drv1->area.get_area() +
|
||
|
predec_blk_drv2->area.get_area() +
|
||
|
predec_blk1->area.get_area() +
|
||
|
predec_blk2->area.get_area())*
|
||
|
num_decoder_segments*num_decoders;
|
||
|
area.set_area(area.get_area()+ area_decoder + area_pre_dec);
|
||
|
double macro_layout_overhead = g_tp.macro_layout_overhead;
|
||
|
double chip_PR_overhead = g_tp.chip_layout_overhead;
|
||
|
area.set_area(area.get_area()*macro_layout_overhead*chip_PR_overhead);
|
||
|
|
||
|
inst_decoder_delay_power();
|
||
|
|
||
|
double sckRation = g_tp.sckt_co_eff;
|
||
|
power.readOp.dynamic *= sckRation;
|
||
|
power.writeOp.dynamic *= sckRation;
|
||
|
power.searchOp.dynamic *= sckRation;
|
||
|
|
||
|
double long_channel_device_reduction = longer_channel_device_reduction(device_ty,core_ty);
|
||
|
power.readOp.longer_channel_leakage = power.readOp.leakage*long_channel_device_reduction;
|
||
|
|
||
|
}
|
||
|
|
||
|
void inst_decoder::inst_decoder_delay_power()
|
||
|
{
|
||
|
|
||
|
double dec_outrisetime;
|
||
|
double inrisetime=0, outrisetime;
|
||
|
double pppm_t[4] = {1,1,1,1};
|
||
|
double squencer_passes = x86?2:1;
|
||
|
|
||
|
outrisetime = pre_dec->compute_delays(inrisetime);
|
||
|
dec_outrisetime = final_dec->compute_delays(outrisetime);
|
||
|
set_pppm(pppm_t, squencer_passes*num_decoder_segments, num_decoder_segments, squencer_passes*num_decoder_segments, num_decoder_segments);
|
||
|
power = power + pre_dec->power*pppm_t;
|
||
|
set_pppm(pppm_t, squencer_passes*num_decoder_segments, num_decoder_segments*num_decoded_signals,
|
||
|
num_decoder_segments*num_decoded_signals, squencer_passes*num_decoder_segments);
|
||
|
power = power + final_dec->power*pppm_t;
|
||
|
}
|
||
|
void inst_decoder::leakage_feedback(double temperature)
|
||
|
{
|
||
|
l_ip.temp = (unsigned int)round(temperature/10.0)*10;
|
||
|
uca_org_t init_result = init_interface(&l_ip); // init_result is dummy
|
||
|
|
||
|
final_dec->leakage_feedback(temperature);
|
||
|
pre_dec->leakage_feedback(temperature);
|
||
|
|
||
|
double pppm_t[4] = {1,1,1,1};
|
||
|
double squencer_passes = x86?2:1;
|
||
|
|
||
|
set_pppm(pppm_t, squencer_passes*num_decoder_segments, num_decoder_segments, squencer_passes*num_decoder_segments, num_decoder_segments);
|
||
|
power = pre_dec->power*pppm_t;
|
||
|
|
||
|
set_pppm(pppm_t, squencer_passes*num_decoder_segments, num_decoder_segments*num_decoded_signals,num_decoder_segments*num_decoded_signals, squencer_passes*num_decoder_segments);
|
||
|
power = power + final_dec->power*pppm_t;
|
||
|
|
||
|
double sckRation = g_tp.sckt_co_eff;
|
||
|
|
||
|
power.readOp.dynamic *= sckRation;
|
||
|
power.writeOp.dynamic *= sckRation;
|
||
|
power.searchOp.dynamic *= sckRation;
|
||
|
|
||
|
double long_channel_device_reduction = longer_channel_device_reduction(device_ty,core_ty);
|
||
|
power.readOp.longer_channel_leakage = power.readOp.leakage*long_channel_device_reduction;
|
||
|
}
|
||
|
|
||
|
inst_decoder::~inst_decoder()
|
||
|
{
|
||
|
local_result.cleanup();
|
||
|
|
||
|
delete final_dec;
|
||
|
|
||
|
delete pre_dec->blk1;
|
||
|
delete pre_dec->blk2;
|
||
|
delete pre_dec->drv1;
|
||
|
delete pre_dec->drv2;
|
||
|
delete pre_dec;
|
||
|
}
|