📄 time.c.svn-base
字号:
rows = (C/(B*Ndbl));
if(!force_tag) {
//tagbits = ADDRESS_BITS + EXTRA_TAG_BITS-(int)logtwo((double)B);
tagbits = ADDRESS_BITS + EXTRA_TAG_BITS-(int)(logtwo((double)B) + EPSILON);
}
else {
tagbits = force_tag_size;
}
cols = (CHUNKSIZE*B)+tagbits;
}
/* calculate some layout info */
if(Ndwl*Ndbl==1) {
l_outdrv_v= 0;
l_outdrv_h= cols;
Coutdrvtreesegments[0] = GlobalCwordmetal*cols;
Routdrvtreesegments[0] = 0.5*GlobalRwordmetal*cols;
Cline = gatecap(Wsenseextdrv1n+Wsenseextdrv1p,10.0 / FUDGEFACTOR)+GlobalCwordmetal*cols;
Cload = Cline / gatecap(1.0,0.0);
current_ndriveW = Cload*SizingRatio/3;
current_pdriveW = 2*Cload*SizingRatio/3;
nr_outdrvtreesegments = 0;
}
else if(Ndwl*Ndbl==2) {
l_outdrv_v= 0;
l_outdrv_h= 2*cols;
Coutdrvtreesegments[0] = GlobalCwordmetal*2*cols;
Routdrvtreesegments[0] = 0.5*GlobalRwordmetal*2*cols;
Cline = gatecap(Wsenseextdrv1n+Wsenseextdrv1p,10.0/ FUDGEFACTOR)+GlobalCwordmetal*2*cols;
Cload = Cline / gatecap(1.0,0.0);
current_ndriveW = Cload*SizingRatio/3;
current_pdriveW = 2*Cload*SizingRatio/3;
nr_outdrvtreesegments = 0;
}
else if(Ndwl*Ndbl>2) {
nr_subarrays_left = Ndwl* Ndbl;
nr_subarrays_left /= 2;
/*dt: assuming the sense amps are in the middle of each subarray */
horizontal_step = cols/2;
vertical_step = rows/2;
l_outdrv_h = horizontal_step;
Coutdrvtreesegments[0] = GlobalCwordmetal*horizontal_step;
Routdrvtreesegments[0] = 0.5*GlobalRwordmetal*horizontal_step;
nr_outdrvtreesegments = 1;
horizontal_step *= 2;
v_or_h = 1; // next step is vertical
while(nr_subarrays_left > 1) {
nr_outdrvtreesegments++;
if(v_or_h) {
l_outdrv_v += vertical_step;
Coutdrvtreesegments[nr_outdrvtreesegments-1] = GlobalCbitmetal*vertical_step;
Routdrvtreesegments[nr_outdrvtreesegments-1] = 0.5*GlobalRbitmetal*vertical_step;
v_or_h = 0;
vertical_step *= 2;
nr_subarrays_left /= 2;
}
else {
l_outdrv_h += horizontal_step;
Coutdrvtreesegments[nr_outdrvtreesegments-1] = GlobalCwordmetal*horizontal_step;
Routdrvtreesegments[nr_outdrvtreesegments-1] = 0.5*GlobalRwordmetal*horizontal_step;
v_or_h = 1;
horizontal_step *= 2;
nr_subarrays_left /= 2;
}
}
/*dt: Now that we have all the H-tree segments for the output tree,
we can walk it in reverse and calc the gate widths*/
previous_ndriveW = Wsenseextdrv1n;
previous_pdriveW = Wsenseextdrv1p;
for(i = nr_outdrvtreesegments-1;i>0;i--) {
Cline = gatecap(previous_ndriveW+previous_pdriveW,0)+Coutdrvtreesegments[i];
Cload = Cline / gatecap(1.0,0.0);
current_ndriveW = Cload*SizingRatio/3;
current_pdriveW = 2*Cload*SizingRatio/3;
WoutdrvtreeN[i] = current_ndriveW;
previous_ndriveW = current_ndriveW;
previous_pdriveW = current_pdriveW;
}
}
if(nr_outdrvtreesegments >= 20) {
printf("Too many segments in the output H-tree. Overflowing the preallocated array!");
exit(1);
}
// typical width of gate considered for the estimating val of draincap.
Cload = gatecap(previous_ndriveW+previous_pdriveW,0) + Coutdrvtreesegments[0] +
(draincap(5.0/ FUDGEFACTOR,NCH,1)+draincap(5.0/ FUDGEFACTOR,PCH,1))*A*muxover;
Woutdrivern = (Cload/gatecap(1.0,0.0))*SizingRatio/3;
Woutdriverp = (Cload/gatecap(1.0,0.0))*SizingRatio*2/3;
// eff load for nor gate = gatecap(drv_p);
// factor of 2 is needed to account for series nmos transistors in nor2
Woutdrvnorp = 2*Woutdriverp*SizingRatio*2/3;
Woutdrvnorn = Woutdriverp*SizingRatio/3;
// factor of 2 is needed to account for series nmos transistors in nand2
Woutdrvnandp = Woutdrivern*SizingRatio*2/3;
Woutdrvnandn = 2*Woutdrivern*SizingRatio/3;
Woutdrvselp = (Woutdrvnandp + Woutdrvnandn) * SizingRatio*2/3;
Woutdrvseln = (Woutdrvnandp + Woutdrvnandn) * SizingRatio/3;
}
void compute_tag_device_widths(int C,int B,int A,int Ntspd,int Ntwl,int Ntbl,double NSubbanks)
{
int rows,cols, tagbits, numstack,l_predec_nor_v,l_predec_nor_h;
double Cline, Cload, Rpdrive,desiredrisetime;
double effWtdecNORn,effWtdecNORp,effWtdec3to8n,effWtdec3to8p, wire_res, wire_cap;
int horizontal_edge = 0;
int nr_subarrays_left = 0, v_or_h = 0;
int horizontal_step = 0, vertical_step = 0;
int h_inv_predecode = 0, v_inv_predecode = 0;
double previous_ndriveW = 0, previous_pdriveW = 0, current_ndriveW = 0, current_pdriveW = 0;
rows = C/(CHUNKSIZE*B*A*Ntbl*Ntspd);
if(!force_tag) {
//v4.1: Fixing double->int type conversion problems. EPSILON is added below to make sure
//the final int value is the correct one
//tagbits = ADDRESS_BITS + EXTRA_TAG_BITS-(int)logtwo((double)C)+(int)logtwo((double)A)-(int)(logtwo(NSubbanks));
tagbits = (int) (ADDRESS_BITS + EXTRA_TAG_BITS-(int)logtwo((double)C)+(int)logtwo((double)A)-(int)(logtwo(NSubbanks)) + EPSILON);
}
else {
tagbits = force_tag_size;
}
cols = tagbits * A * Ntspd/Ntwl;
// capacitive load on the wordline - C_int + C_memCellLoad * NCells
Cline = (gatecappass(Wmemcella,(BitWidth-2*Wmemcella)/2.0)+
gatecappass(Wmemcella,(BitWidth-2*Wmemcella)/2.0)+ TagCwordmetal)*cols;
/*dt: changing the calculations for the tag wordline to be the same as for the data wordline*/
/* Use a first-order approx */
desiredrisetime = krise*log((double)(cols))/2.0;
Rpdrive = desiredrisetime/(Cline*log(VSINV)*-1.0);
WtwlDrvp = restowidth(Rpdrive,PCH);
if (WtwlDrvp > Wworddrivemax) {
WtwlDrvp = Wworddrivemax;
}
WtwlDrvn = WtwlDrvp/2;
Wtdecinvn = (WtwlDrvn + WtwlDrvp)*SizingRatio*1/3;
Wtdecinvp = (WtwlDrvn + WtwlDrvp)*SizingRatio*2/3;
// determine widths of nand, nor gates in the tag decoder
// width of NOR driving decInv -
// effective width (NORp + NORn = Cout/SizingRatio( FANOUT))
// Cout = Wdecinvn + Wdecinvp; SizingRatio = 3;
// nsize = effWidth/3; psize = 2*effWidth/3;
numstack =
(int)ceil((1.0/3.0)*logtwo( (double)((double)C/(double)(B*A*Ntbl*Ntspd))));
if (numstack==0) numstack = 1;
if (numstack>5) numstack = 5;
effWtdecNORn = (Wtdecinvn + Wtdecinvp)*SizingRatio/3;
effWtdecNORp = 2*(Wtdecinvn + Wtdecinvp)*SizingRatio/3;
WtdecNORn = effWtdecNORn;
WtdecNORp = effWtdecNORp * numstack;
/*dt: The *8 is there because above we mysteriously divide the capacity in BYTES by the number of BITS per wordline */
l_predec_nor_v = rows*8;
/*dt: If we follow the original drawings from the TR's, then there is almost no horizontal wires, only the poly for contacting
the nor gates. The poly part we don't model right now */
l_predec_nor_h = 0;
// find width of the nand gates in the 3-8 decoders
Cline = gatecap(WtdecNORn+WtdecNORp,((numstack*40)/ FUDGEFACTOR + 20.0 / FUDGEFACTOR))*rows/8 +
GlobalCbitmetal*(l_predec_nor_v) + GlobalCwordmetal*(l_predec_nor_h);
Cload = Cline / gatecap(1.0,0.0);
effWtdec3to8n = Cload*SizingRatio/3;
effWtdec3to8p = 2*Cload*SizingRatio/3;
Wtdec3to8n = effWtdec3to8n * 3; // nand3 gate
Wtdec3to8p = effWtdec3to8p;
horizontal_edge = cols*Ntwl;
previous_ndriveW = Wtdec3to8n;
previous_pdriveW = Wtdec3to8p;
if(Ntwl*Ntbl==1 ) {
wire_cap = GlobalCwordmetal*horizontal_edge;
wire_res = 0.5*GlobalRwordmetal*horizontal_edge;
Ctdectreesegments[0] = GlobalCwordmetal*horizontal_edge;
Rtdectreesegments[0] = 0.5*GlobalRwordmetal*horizontal_edge;
Cline = 4*gatecap(previous_ndriveW+previous_pdriveW,10.0 / FUDGEFACTOR)+GlobalCwordmetal*horizontal_edge;
Cload = Cline / gatecap(1.0,0.0);
current_ndriveW = Cload*SizingRatio/3;
current_pdriveW = 2*Cload*SizingRatio/3;
nr_tdectreesegments = 0;
}
else if(Ntwl*Ntbl==2 || Ntwl*Ntbl==4) {
wire_cap = GlobalCwordmetal*0.5*horizontal_edge;
wire_res = 0.5*GlobalRwordmetal*0.5*horizontal_edge;
Ctdectreesegments[0] = GlobalCwordmetal*horizontal_edge;
Rtdectreesegments[0] = 0.5*GlobalRwordmetal*horizontal_edge;
Cline = 4*gatecap(previous_ndriveW+previous_pdriveW,10.0 / FUDGEFACTOR)+GlobalCwordmetal*horizontal_edge;
Cload = Cline / gatecap(1.0,0.0);
current_ndriveW = Cload*SizingRatio/3;
current_pdriveW = 2*Cload*SizingRatio/3;
nr_tdectreesegments = 0;
}
else {
nr_subarrays_left = Ntwl*Ntbl;
nr_subarrays_left /= 4;
horizontal_step = cols;
vertical_step = C/(B*A*Ntbl*Ntspd);
h_inv_predecode = horizontal_step;
Ctdectreesegments[0] = GlobalCwordmetal*horizontal_step;
Rtdectreesegments[0] = 0.5*GlobalRwordmetal*horizontal_step;
Cline = 4*gatecap(previous_ndriveW+previous_pdriveW,10.0 / FUDGEFACTOR)+GlobalCwordmetal*horizontal_step;
Cload = Cline / gatecap(1.0,0.0);
current_ndriveW = Cload*SizingRatio/3;
current_pdriveW = 2*Cload*SizingRatio/3;
WtdecdrivetreeN[0] = current_ndriveW;
nr_tdectreesegments = 1;
horizontal_step *= 2;
v_or_h = 1; // next step is vertical
while(nr_subarrays_left > 1) {
previous_ndriveW = current_ndriveW;
previous_pdriveW = current_pdriveW;
nr_tdectreesegments++;
if(v_or_h) {
v_inv_predecode += vertical_step;
Ctdectreesegments[nr_tdectreesegments-1] = GlobalCbitmetal*vertical_step;
Rtdectreesegments[nr_tdectreesegments-1] = 0.5*GlobalRbitmetal*vertical_step;
Cline = gatecap(previous_ndriveW+previous_pdriveW,0)+GlobalCbitmetal*vertical_step;
v_or_h = 0;
vertical_step *= 2;
nr_subarrays_left /= 2;
}
else {
h_inv_predecode += horizontal_step;
Ctdectreesegments[nr_tdectreesegments-1] = GlobalCwordmetal*horizontal_step;
Rtdectreesegments[nr_tdectreesegments-1] = 0.5*GlobalRwordmetal*horizontal_step;
Cline = gatecap(previous_ndriveW+previous_pdriveW,0)+GlobalCwordmetal*horizontal_step;
v_or_h = 1;
horizontal_step *= 2;
nr_subarrays_left /= 2;
}
Cload = Cline / gatecap(1.0,0.0);
current_ndriveW = Cload*SizingRatio/3;
current_pdriveW = 2*Cload*SizingRatio/3;
WtdecdrivetreeN[nr_tdectreesegments-1] = current_ndriveW;
}
if(nr_tdectreesegments >= 10) {
printf("Too many segments in the tag decoder H-tree. Overflowing the preallocated array!");
exit(1);
}
wire_cap = GlobalCbitmetal*v_inv_predecode + GlobalCwordmetal*h_inv_predecode;
wire_res = 0.5*(GlobalRbitmetal*v_inv_predecode + GlobalRwordmetal*h_inv_predecode);
}
Cline = 4*gatecap(Wtdec3to8n+Wtdec3to8p,10.0 / FUDGEFACTOR) + wire_cap;
Cload = Cline / gatecap(1.0,0.0);
Wtdecdriven_second = current_ndriveW;
Wtdecdrivep_second = current_pdriveW;
// Size of second driver
Wtdecdriven_first = (Wtdecdriven_second + Wtdecdrivep_second)*SizingRatio/3;
Wtdecdrivep_first = 2*(Wtdecdriven_second + Wtdecdrivep_second)*SizingRatio/3;
}
double cmos_ileakage(double nWidth, double pWidth,
double nVthresh_dual, double nVthreshold, double pVthresh_dual, double pVthreshold) {
double leakage = 0.0;
static int valid_cache = 0;
static double cached_nmos_thresh = 0;
static double cached_pmos_thresh = 0;
static double norm_nmos_leakage = 0;
static double norm_pmos_leakage = 0;
if(have_leakage_params) {
if (dualVt == TRUE) {
if((cached_nmos_thresh == nVthresh_dual) && (cached_pmos_thresh == pVthresh_dual) && valid_cache) {
leakage = nWidth*norm_nmos_leakage + pWidth*norm_pmos_leakage;
}
else {
leakage = simplified_cmos_leakage(nWidth*inv_Leff,pWidth*inv_Leff,nVthresh_dual,pVthresh_dual,&norm_nmos_leakage,&norm_pmos_leakage);
cached_nmos_thresh = nVthresh_dual;
cached_pmos_thresh = pVthresh_dual;
norm_nmos_leakage = inv_Leff*norm_nmos_leakage;
norm_pmos_leakage = inv_Leff*norm_pmos_leakage;
valid_cache = 1;
}
}
else {
if((cached_nmos_thresh == nVthreshold) && (cached_pmos_thresh == pVthreshold) && valid_cache) {
leakage = nWidth*norm_nmos_leakage + pWidth*norm_pmos_leakage;
}
else {
leakage = simplified_cmos_leakage(nWidth*inv_Leff,pWidth*inv_Leff,nVthreshold,pVthreshold,&norm_nmos_leakage,&norm_pmos_leakage);
cached_nmos_thresh = nVthreshold;
cached_pmos_thresh = pVthreshold;
norm_nmos_leakage = inv_Leff*norm_nmos_leakage;
norm_pmos_leakage = inv_Leff*norm_pmos_leakage;
valid_cache = 1;
}
}
}
else {
leakage = 0;
}
return leakage;
}
void reset_powerDef(powerDef *power) {
power->readOp.dynamic = 0.0;
power->readOp.leakage = 0.0;
power->writeOp.dynamic = 0.0;
power->writeOp.leakage = 0.0;
}
void mult_powerDef(powerDef *power, int val) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -