242 lines
9.1 KiB
C++
242 lines
9.1 KiB
C++
/*****************************************************************************
|
|
* CACTI 7.0
|
|
* SOFTWARE LICENSE AGREEMENT
|
|
* Copyright 2015 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 "TSV.h"
|
|
|
|
TSV::TSV(enum TSV_type tsv_type,
|
|
/*TechnologyParameter::*/DeviceType *dt)://TSV driver's device type set to be peri_global
|
|
deviceType(dt), tsv_type(tsv_type)
|
|
{
|
|
num_gates = 1;
|
|
num_gates_min = 1;//Is there a minimum number of stages?
|
|
min_w_pmos = deviceType -> n_to_p_eff_curr_drv_ratio * g_tp.min_w_nmos_;
|
|
|
|
switch (tsv_type)
|
|
{
|
|
case Fine:
|
|
cap = g_tp.tsv_parasitic_capacitance_fine;
|
|
res = g_tp.tsv_parasitic_resistance_fine;
|
|
min_area = g_tp.tsv_minimum_area_fine;
|
|
break;
|
|
case Coarse:
|
|
cap = g_tp.tsv_parasitic_capacitance_coarse;
|
|
res = g_tp.tsv_parasitic_resistance_coarse;
|
|
min_area = g_tp.tsv_minimum_area_coarse;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
for (int i = 0; i < MAX_NUMBER_GATES_STAGE; i++)
|
|
{
|
|
w_TSV_n[i] = 0;
|
|
w_TSV_p[i] = 0;
|
|
}
|
|
|
|
double first_buf_stg_coef = 5; // To tune the total buffer delay.
|
|
w_TSV_n[0] = g_tp.min_w_nmos_*first_buf_stg_coef;
|
|
w_TSV_p[0] = min_w_pmos *first_buf_stg_coef;
|
|
|
|
is_dram = 0;
|
|
is_wl_tr = 0;
|
|
|
|
//What does the function assert() mean? Should I put the function here?
|
|
compute_buffer_stage();
|
|
compute_area();
|
|
compute_delay();
|
|
}
|
|
|
|
TSV::~TSV()
|
|
{
|
|
}
|
|
|
|
void TSV::compute_buffer_stage()
|
|
{
|
|
double p_to_n_sz_ratio = deviceType->n_to_p_eff_curr_drv_ratio;
|
|
|
|
//BEOL parasitics in Katti's E modeling and charac. of TSV. Needs further detailed values.
|
|
//double res_beol = 0.1;//inaccurate
|
|
//double cap_beol = 1e-15;
|
|
|
|
//C_load_TSV = cap_beol + cap + cap_beol + gate_C(g_tp.min_w_nmos_ + min_w_pmos, 0);
|
|
C_load_TSV = cap + gate_C(g_tp.min_w_nmos_ + min_w_pmos, 0); //+ 57.5e-15;
|
|
if(g_ip->print_detail_debug)
|
|
{
|
|
cout << " The input cap of 1st buffer: " << gate_C(w_TSV_n[0] + w_TSV_p[0], 0) * 1e15 << " fF";
|
|
}
|
|
double F = C_load_TSV / gate_C(w_TSV_n[0] + w_TSV_p[0], 0);
|
|
if(g_ip->print_detail_debug)
|
|
{
|
|
cout<<"\nF is "<<F<<" \n";
|
|
}
|
|
//Obtain buffer chain stages using logic effort function. Does stage number have to be even?
|
|
num_gates = logical_effort(
|
|
num_gates_min,
|
|
1,
|
|
F,
|
|
w_TSV_n,
|
|
w_TSV_p,
|
|
C_load_TSV,
|
|
p_to_n_sz_ratio,
|
|
is_dram,
|
|
is_wl_tr,
|
|
g_tp.max_w_nmos_/*Correct? Decoder uses max_w_nmos_dec*/);
|
|
}
|
|
|
|
void TSV::compute_area()
|
|
{
|
|
//Obtain the driver chain area and leakage power for TSV
|
|
double Vdd = deviceType->Vdd;
|
|
double cumulative_area = 0;
|
|
double cumulative_curr = 0; // cumulative leakage current
|
|
double cumulative_curr_Ig = 0; // cumulative leakage current
|
|
Buffer_area.h = g_tp.cell_h_def;//cell_h_def is the assigned height for memory cell (5um), is it correct to use it here?
|
|
|
|
//logic_effort() didn't give the size of w_n[0] and w_p[0], which is min size inverter
|
|
//w_TSV_n[0] = g_tp.min_w_nmos_;
|
|
//w_TSV_p[0] = min_w_pmos;
|
|
|
|
int i;
|
|
for (i = 0; i < num_gates; i++)
|
|
{
|
|
cumulative_area += compute_gate_area(INV, 1, w_TSV_p[i], w_TSV_n[i], Buffer_area.h);
|
|
if(g_ip->print_detail_debug)
|
|
{
|
|
cout << "\n\tArea up to the " << i+1 << " stages is: " << cumulative_area << " um2";
|
|
}
|
|
cumulative_curr += cmos_Isub_leakage(w_TSV_n[i], w_TSV_p[i], 1, inv, is_dram);
|
|
cumulative_curr_Ig += cmos_Ig_leakage(w_TSV_n[i], w_TSV_p[i], 1, inv, is_dram);// The operator += is mistakenly put as = in decoder.cc
|
|
}
|
|
power.readOp.leakage = cumulative_curr * Vdd;
|
|
power.readOp.gate_leakage = cumulative_curr_Ig * Vdd;
|
|
|
|
Buffer_area.set_area(cumulative_area);
|
|
Buffer_area.w = (cumulative_area / Buffer_area.h);
|
|
|
|
TSV_metal_area.set_area(min_area * 3.1416/16);
|
|
|
|
if( Buffer_area.get_area() < min_area - TSV_metal_area.get_area() )
|
|
area.set_area(min_area);
|
|
else
|
|
area.set_area(Buffer_area.get_area() + TSV_metal_area.get_area());
|
|
|
|
}
|
|
|
|
void TSV::compute_delay()
|
|
{
|
|
//Buffer chain delay and Dynamic Power
|
|
double rd, tf, this_delay, c_load, c_intrinsic, inrisetime = 0/*The initial time*/;
|
|
//is_dram, is_wl_tr are declared to be false in the constructor
|
|
rd = tr_R_on(w_TSV_n[0], NCH, 1, is_dram, false, is_wl_tr);
|
|
c_load = gate_C(w_TSV_n[1] + w_TSV_p[1], 0.0, is_dram, false, is_wl_tr);
|
|
c_intrinsic = drain_C_(w_TSV_p[0], PCH, 1, 1, area.h, is_dram, false, is_wl_tr) +
|
|
drain_C_(w_TSV_n[0], NCH, 1, 1, area.h, is_dram, false, is_wl_tr);
|
|
tf = rd * (c_intrinsic + c_load);
|
|
//Refer to horowitz function definition
|
|
this_delay = horowitz(inrisetime, tf, 0.5, 0.5, RISE);
|
|
delay += this_delay;
|
|
inrisetime = this_delay / (1.0 - 0.5);
|
|
|
|
double Vdd = deviceType -> Vdd;
|
|
power.readOp.dynamic += (c_load + c_intrinsic) * Vdd * Vdd;
|
|
|
|
int i;
|
|
for (i = 1; i < num_gates - 1; ++i)
|
|
{
|
|
rd = tr_R_on(w_TSV_n[i], NCH, 1, is_dram, false, is_wl_tr);
|
|
c_load = gate_C(w_TSV_p[i+1] + w_TSV_n[i+1], 0.0, is_dram, false, is_wl_tr);
|
|
c_intrinsic = drain_C_(w_TSV_p[i], PCH, 1, 1, area.h, is_dram, false, is_wl_tr) +
|
|
drain_C_(w_TSV_n[i], NCH, 1, 1, area.h, is_dram, false, is_wl_tr);
|
|
tf = rd * (c_intrinsic + c_load);
|
|
this_delay = horowitz(inrisetime, tf, 0.5, 0.5, RISE);
|
|
delay += this_delay;
|
|
inrisetime = this_delay / (1.0 - 0.5);
|
|
power.readOp.dynamic += (c_load + c_intrinsic) * Vdd * Vdd;
|
|
}
|
|
|
|
// add delay of final inverter that drives the TSV
|
|
i = num_gates - 1;
|
|
c_load = C_load_TSV;
|
|
rd = tr_R_on(w_TSV_n[i], NCH, 1, is_dram, false, is_wl_tr);
|
|
c_intrinsic = drain_C_(w_TSV_p[i], PCH, 1, 1, area.h, is_dram, false, is_wl_tr) +
|
|
drain_C_(w_TSV_n[i], NCH, 1, 1, area.h, is_dram, false, is_wl_tr);
|
|
//The delay method for the last stage of buffer chain in Decoder.cc
|
|
|
|
//double res_beol = 0.1;//inaccurate
|
|
//double R_TSV_out = res_beol + res + res_beol;
|
|
double R_TSV_out = res;
|
|
tf = rd * (c_intrinsic + c_load) + R_TSV_out * c_load / 2;
|
|
this_delay = horowitz(inrisetime, tf, 0.5, 0.5, RISE);
|
|
delay += this_delay;
|
|
|
|
power.readOp.dynamic += (c_load + c_intrinsic) * Vdd * Vdd; //Dynamic power done
|
|
|
|
//Is the delay actually delay/(1.0-0.5)??
|
|
//ret_val = this_delay / (1.0 - 0.5);
|
|
//return ret_val;//Originally for decoder.cc to get outrise time
|
|
|
|
|
|
/* This part is to obtain delay in the TSV path, refer to Katti's paper.
|
|
* It can be used alternatively as the step to get the final-stage delay
|
|
double C_ext = c_intrinsic;
|
|
R_dr = rd;
|
|
double C_int = gate_C(g_tp.min_w_nmos_ + min_w_pmos, 0.0, is_dram, false, is_wl_tr);
|
|
delay_TSV_path = 0.693 * (R_dr * C_ext + (R_dr + res_beol) * cap_beol + (R_dr + res_beol + 0.5 * res) * cap
|
|
+ (R_dr + res_beol + res + res_beol) * (cap_beol + C_int);
|
|
delay += delay_TSV_path;
|
|
*/
|
|
}
|
|
|
|
void TSV::print_TSV()
|
|
{
|
|
|
|
cout << "\nTSV Properties:\n\n";
|
|
cout << " Delay Optimal - "<<
|
|
" \n\tTSV Cap: " << cap * 1e15 << " fF" <<
|
|
" \n\tTSV Res: " << res * 1e3 << " mOhm"<<
|
|
" \n\tNumber of Buffer Chain stages - " << num_gates <<
|
|
" \n\tDelay - " << delay * 1e9 << " (ns) "
|
|
" \n\tPowerD - " << power.readOp.dynamic * 1e9<< " (nJ)"
|
|
" \n\tPowerL - " << power.readOp.leakage * 1e3<< " (mW)"
|
|
" \n\tPowerLgate - " << power.readOp.gate_leakage * 1e3<< " (mW)\n" <<
|
|
" \n\tBuffer Area: " << Buffer_area.get_area() << " um2" <<
|
|
" \n\tBuffer Height: " << Buffer_area.h << " um" <<
|
|
" \n\tBuffer Width: " << Buffer_area.w << " um" <<
|
|
" \n\tTSV metal area: " << TSV_metal_area.get_area() << " um2" <<
|
|
" \n\tTSV minimum occupied area: " <<min_area << " um2"<<
|
|
" \n\tTotal area: " << area.get_area() << " um2";
|
|
cout <<endl;
|
|
cout <<endl;
|
|
|
|
}
|
|
|
|
|
|
|