forked from HewlettPackard/cacti
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathTSV.cc
242 lines (208 loc) · 9.06 KB
/
TSV.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
/*****************************************************************************
* 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;
}