void TSV::Initialize(TSV_type tsv_type, bool buffered) { int num_gates_min = 1; double min_w_pmos = tech->pnSizeRatio * MIN_NMOS_SIZE * tech->featureSize; num_gates = 1; cap = tech->capTSV[tsv_type]; res = tech->resTSV[tsv_type]; min_area = tech->areaTSV[tsv_type] * 1e-12; if (!buffered) { num_gates = 0; } else { double first_buf_stg_coef = 5; // To tune the total buffer delay. w_TSV_n[0] = MIN_NMOS_SIZE * first_buf_stg_coef * tech->featureSize; w_TSV_p[0] = w_TSV_n[0] * tech->pnSizeRatio; //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 + CalculateGateCap(MIN_NMOS_SIZE * tech->featureSize + min_w_pmos, *tech); //+ 57.5e-15; #ifdef NVSIM3DDEBUG cout << " The input cap of 1st buffer: " << CalculateGateCap(w_TSV_n[0] + w_TSV_p[0], *tech) * 1e15 << " fF"; #endif F = C_load_TSV / CalculateGateCap(w_TSV_n[0] + w_TSV_p[0], *tech); #ifdef NVSIM3DDEBUG cout<<"\nF is "<<F<<" \n"; #endif //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, tech->pnSizeRatio, MAX_NMOS_SIZE * tech->featureSize, *tech ); } initialized = true; if (num_gates > MAX_NUMBER_GATES_STAGE) { invalid = true; } }
void CalculateGateCapacitance( int gateType, int numInput, double widthNMOS, double widthPMOS, double heightTransistorRegion, Technology tech, double *capInput, double *capOutput) { /* TO-DO: most parts of this function is the same of CalculateGateArea, * perhaps they will be combined in future */ double ratio = widthPMOS / (widthPMOS + widthNMOS); double maxWidthPMOS = 0, maxWidthNMOS = 0; double unitWidthDrainP = 0, unitWidthDrainN = 0; double widthDrainP = 0, widthDrainN = 0; double heightDrainP = 0, heightDrainN = 0; int numFoldedPMOS = 1, numFoldedNMOS = 1; if (ratio == 0) { /* no PMOS */ maxWidthPMOS = 0; maxWidthNMOS = heightTransistorRegion; } else if (ratio == 1) { /* no NMOS */ maxWidthPMOS = heightTransistorRegion; maxWidthNMOS = 0; } else { maxWidthPMOS = ratio * (heightTransistorRegion - MIN_GAP_BET_P_AND_N_DIFFS * tech.featureSize); maxWidthNMOS = maxWidthPMOS / ratio * (1 - ratio); } if (widthPMOS > 0) { if (widthPMOS < maxWidthPMOS) { /* No folding */ unitWidthDrainP = 0; heightDrainP = widthPMOS; } else { /* Folding */ if (maxWidthPMOS < 3 * tech.featureSize) { cout << "Error: Unable to do PMOS folding because PMOS size limitation is less than 3F!" <<endl; exit(-1); } numFoldedPMOS = (int)(ceil(widthPMOS / (maxWidthPMOS - 3 * tech.featureSize))); /* 3F for folding overhead */ unitWidthDrainP = (numFoldedPMOS-1) * tech.featureSize * MIN_GAP_BET_POLY; heightDrainP = maxWidthPMOS; } } else { unitWidthDrainP = 0; heightDrainP = 0; } if (widthNMOS > 0) { if (widthNMOS < maxWidthNMOS) { /* No folding */ unitWidthDrainN = 0; heightDrainN = widthNMOS; } else { /* Folding */ if (maxWidthNMOS < 3 * tech.featureSize) { cout << "Error: Unable to do NMOS folding because NMOS size limitation is less than 3F!" <<endl; exit(-1); } numFoldedNMOS = (int)(ceil(widthNMOS / (maxWidthNMOS - 3 * tech.featureSize))); /* 3F for folding overhead */ unitWidthDrainN = (numFoldedNMOS-1) * tech.featureSize * MIN_GAP_BET_POLY; heightDrainN = maxWidthNMOS; } } else { unitWidthDrainN = 0; heightDrainN = 0; } switch (gateType) { case INV: if (widthPMOS > 0) widthDrainP = tech.featureSize * (CONTACT_SIZE + MIN_GAP_BET_CONTACT_POLY * 2) + unitWidthDrainP; if (widthNMOS > 0) widthDrainN = tech.featureSize * (CONTACT_SIZE + MIN_GAP_BET_CONTACT_POLY * 2) + unitWidthDrainN; break; case NOR: /* PMOS is in series, worst case capacitance is below */ if (widthPMOS > 0) widthDrainP = tech.featureSize * (CONTACT_SIZE + MIN_GAP_BET_CONTACT_POLY * 2) + unitWidthDrainP * numInput + (numInput - 1) * tech.featureSize * MIN_GAP_BET_POLY; /* NMOS is parallel, capacitance is multiplied as below */ if (widthNMOS > 0) widthDrainN = (tech.featureSize * (CONTACT_SIZE + MIN_GAP_BET_CONTACT_POLY * 2) + unitWidthDrainN) * numInput; break; case NAND: /* NMOS is in series, worst case capacitance is below */ if (widthNMOS > 0) widthDrainN = tech.featureSize * (CONTACT_SIZE + MIN_GAP_BET_CONTACT_POLY * 2) + unitWidthDrainN * numInput + (numInput - 1) * tech.featureSize * MIN_GAP_BET_POLY; /* PMOS is parallel, capacitance is multiplied as below */ if (widthPMOS > 0) widthDrainP = (tech.featureSize * (CONTACT_SIZE + MIN_GAP_BET_CONTACT_POLY * 2) + unitWidthDrainP) * numInput; break; default: widthDrainN = widthDrainP = 0; } /* Junction capacitance */ double capDrainBottomN = widthDrainN * heightDrainN * tech.capJunction; double capDrainBottomP = widthDrainP * heightDrainP * tech.capJunction; /* Sidewall capacitance */ double capDrainSidewallN, capDrainSidewallP; if (numFoldedNMOS % 2 == 0) capDrainSidewallN = 2 * widthDrainN * tech.capSidewall; else capDrainSidewallN = (2 * widthDrainN + heightDrainN) * tech.capSidewall; if (numFoldedPMOS % 2 == 0) capDrainSidewallP = 2 * widthDrainP * tech.capSidewall; else capDrainSidewallP = (2* widthDrainP + heightDrainP) * tech.capSidewall; /* Drain to channel capacitance */ double capDrainToChannelN = numFoldedNMOS * heightDrainN * tech.capDrainToChannel; double capDrainToChannelP = numFoldedPMOS * heightDrainP * tech.capDrainToChannel; if (capOutput) *(capOutput) = capDrainBottomN + capDrainBottomP + capDrainSidewallN + capDrainSidewallP + capDrainToChannelN + capDrainToChannelP; if (capInput) *(capInput) = CalculateGateCap(widthNMOS, tech) + CalculateGateCap(widthPMOS, tech); }