void Comparator::CalculateLatency(double _rampInput) { if (!initialized) { cout << "[Comparator] Error: Require initialization first!" << endl; } else { rampInput = _rampInput; double resPullDown; double capNode; double tr; /* time constant */ double gm; /* transconductance */ double beta; /* for horowitz calculation */ double temp; readLatency = 0; for (int i = 0; i < COMPARATOR_INV_CHAIN_LEN - 1; i++) { resPullDown = CalculateOnResistance(widthNMOSInv[i], NMOS, inputParameter->temperature, *tech); capNode = capOutput[i] + capInput[i+1]; tr = resPullDown * capNode; gm = CalculateTransconductance(widthNMOSInv[i], NMOS, *tech); beta = 1 / (resPullDown * gm); readLatency += horowitz(tr, beta, rampInput, &temp); rampInput = temp; /* for next stage */ } tr = resBottom * capBottom + (resBottom + resTop) * capTop; readLatency += horowitz(tr, 0, rampInput, &rampOutput); rampInput = _rampInput; writeLatency = readLatency; } }
// nand gate sizing calculation void Htree2::input_nand(double s1, double s2, double l_eff) { Wire w1(wt, l_eff); double pton_size = deviceType->n_to_p_eff_curr_drv_ratio; // input capacitance of a repeater = input capacitance of nand. double nsize = s1*(1 + pton_size)/(2 + pton_size); nsize = (nsize < 1) ? 1 : nsize; double tc = 2*tr_R_on(nsize*min_w_nmos, NCH, 1) * (drain_C_(nsize*min_w_nmos, NCH, 1, 1, g_tp.cell_h_def)*2 + 2 * gate_C(s2*(min_w_nmos + min_w_pmos), 0)); delay+= horowitz (w1.out_rise_time, tc, deviceType->Vth/deviceType->Vdd, deviceType->Vth/deviceType->Vdd, RISE); power.readOp.dynamic += 0.5 * (2*drain_C_(pton_size * nsize*min_w_pmos, PCH, 1, 1, g_tp.cell_h_def) + drain_C_(nsize*min_w_nmos, NCH, 1, 1, g_tp.cell_h_def) + 2*gate_C(s2*(min_w_nmos + min_w_pmos), 0)) * deviceType->Vdd * deviceType->Vdd; power.searchOp.dynamic += 0.5 * (2*drain_C_(pton_size * nsize*min_w_pmos, PCH, 1, 1, g_tp.cell_h_def) + drain_C_(nsize*min_w_nmos, NCH, 1, 1, g_tp.cell_h_def) + 2*gate_C(s2*(min_w_nmos + min_w_pmos), 0)) * deviceType->Vdd * deviceType->Vdd * wire_bw ; power.readOp.leakage += (wire_bw*cmos_Isub_leakage(min_w_nmos*(nsize*2), min_w_pmos * nsize * 2, 2, nand))*deviceType->Vdd; power.readOp.gate_leakage += (wire_bw*cmos_Ig_leakage(min_w_nmos*(nsize*2), min_w_pmos * nsize * 2, 2, nand))*deviceType->Vdd; }
double Wire::signal_rise_time() { /* rise time of inverter 1's output */ double ft; /* fall time of inverter 2's output */ double rt; double timeconst; timeconst = (drain_C_(g_tp.min_w_nmos_, NCH, 1, 1, g_tp.cell_h_def) + drain_C_(min_w_pmos, PCH, 1, 1, g_tp.cell_h_def) + gate_C(min_w_pmos + g_tp.min_w_nmos_, 0)) * tr_R_on(g_tp.min_w_nmos_, NCH, 1); rt = horowitz(0, timeconst, deviceType->Vth / deviceType->Vdd, deviceType->Vth / deviceType->Vdd, RISE) / deviceType->Vth; timeconst = (drain_C_(g_tp.min_w_nmos_, NCH, 1, 1, g_tp.cell_h_def) + drain_C_(min_w_pmos, PCH, 1, 1, g_tp.cell_h_def) + gate_C(min_w_pmos + g_tp.min_w_nmos_, 0)) * tr_R_on(min_w_pmos, PCH, 1); ft = horowitz(rt, timeconst, deviceType->Vth / deviceType->Vdd, deviceType->Vth / deviceType->Vdd, FALL) / (deviceType->Vdd - deviceType->Vth); return ft; //sec }
void TSV::_CalculateLatencyAndPower(double _rampInput, double &_dynamicEnergy, double &_latency) { //Buffer chain delay and Dynamic Power double delay = 0.0; double rd, tf, this_delay, c_load, c_intrinsic; double capInput, capOutput; double rampInput, rampOutput; double beta = 0.5; /* Carried over from CACTI3DD. */ if (num_gates > 0) { rd = CalculateOnResistance(w_TSV_n[0], NMOS, inputParameter->temperature, *tech); CalculateGateCapacitance(INV, 1, w_TSV_n[1], w_TSV_p[1], tech->featureSize * MAX_TRANSISTOR_HEIGHT, *tech, &capInput, &capOutput); c_load = capInput + capOutput; c_intrinsic = CalculateDrainCap(w_TSV_p[0], PMOS, tech->featureSize * MAX_TRANSISTOR_HEIGHT, *tech) + CalculateDrainCap(w_TSV_n[0], NMOS, tech->featureSize * MAX_TRANSISTOR_HEIGHT, *tech); tf = rd * (c_intrinsic + c_load); // NVSIM3D - _rampInput should be subarray's senseAmpMuxLev2 rampOutput rampInput = _rampInput; this_delay = horowitz(tf, beta, rampInput, &rampOutput); delay += this_delay; double Vdd = tech->vdd; _dynamicEnergy = (c_load + c_intrinsic) * Vdd * Vdd; int i; for (i = 1; i < num_gates - 1; ++i) { rd = CalculateOnResistance(w_TSV_n[i], NMOS, inputParameter->temperature, *tech); CalculateGateCapacitance(INV, 1, w_TSV_n[i+1], w_TSV_p[i+1], tech->featureSize * MAX_TRANSISTOR_HEIGHT, *tech, &capInput, &capOutput); c_load = capInput + capOutput; c_intrinsic = CalculateDrainCap(w_TSV_p[i], PMOS, tech->featureSize * MAX_TRANSISTOR_HEIGHT, *tech) + CalculateDrainCap(w_TSV_n[i], NMOS, tech->featureSize * MAX_TRANSISTOR_HEIGHT, *tech); tf = rd * (c_intrinsic + c_load); rampInput = rampOutput; this_delay = horowitz(tf, beta, rampInput, &rampOutput); delay += this_delay; _dynamicEnergy += (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 = CalculateOnResistance(w_TSV_n[i], NMOS, inputParameter->temperature, *tech); c_intrinsic = CalculateDrainCap(w_TSV_p[i], PMOS, tech->featureSize * MAX_TRANSISTOR_HEIGHT, *tech) + CalculateDrainCap(w_TSV_n[i], NMOS, tech->featureSize * MAX_TRANSISTOR_HEIGHT, *tech); double R_TSV_out = res; tf = rd * (c_intrinsic + c_load) + R_TSV_out * c_load / 2; rampInput = rampOutput; this_delay = horowitz(tf, beta, rampInput, &rampOutput); delay += this_delay; _dynamicEnergy += (c_load + c_intrinsic) * Vdd * Vdd; _latency = delay; } else { rampInput = _rampInput; c_load = cap; double R_TSV_out = res; tf = R_TSV_out * c_load / 2; double Vdd = tech->vdd; this_delay = horowitz(tf, beta, rampInput, &rampOutput); delay += this_delay; _dynamicEnergy += (c_load) * Vdd * Vdd; _latency = delay; } }
/* * Calculates the delay, power and area of the transmitter circuit. * * The transmitter delay is the sum of nand gate delay, inverter delay * low swing nmos delay, and the wire delay * (ref: Technical report 6) */ void Wire::low_swing_model() { double len = wire_length; double beta = pmos_to_nmos_sz_ratio(); double inputrise = (in_rise_time == 0) ? signal_rise_time() : in_rise_time; /* Final nmos low swing driver size calculation: * Try to size the driver such that the delay * is less than 8FO4. * If the driver size is greater than * the max allowable size, assume max size for the driver. * In either case, recalculate the delay using * the final driver size assuming slow input with * finite rise time instead of ideal step input * * (ref: Technical report 6) */ double cwire = wire_cap(len); /* load capacitance */ double rwire = wire_res(len); #define RES_ADJ (8.6) // Increase in resistance due to low driving vol. double driver_res = (-8 * g_tp.FO4 / (log(0.5) * cwire)) / RES_ADJ; double nsize = R_to_w(driver_res, NCH); nsize = MIN(nsize, g_tp.max_w_nmos_); nsize = MAX(nsize, g_tp.min_w_nmos_); if (rwire * cwire > 8 * g_tp.FO4) { nsize = g_tp.max_w_nmos_; } // size the inverter appropriately to minimize the transmitter delay // Note - In order to minimize leakage, we are not adding a set of inverters to // bring down delay. Instead, we are sizing the single gate // based on the logical effort. double st_eff = sqrt( (2 + beta / 1 + beta) * gate_C(nsize, 0) / (gate_C(2 * g_tp.min_w_nmos_, 0) + gate_C(2 * min_w_pmos, 0))); double req_cin = ((2 + beta / 1 + beta) * gate_C(nsize, 0)) / st_eff; double inv_size = req_cin / (gate_C(min_w_pmos, 0) + gate_C(g_tp.min_w_nmos_, 0)); inv_size = MAX(inv_size, 1); /* nand gate delay */ double res_eq = (2 * tr_R_on(g_tp.min_w_nmos_, NCH, 1)); double cap_eq = 2 * drain_C_(min_w_pmos, PCH, 1, 1, g_tp.cell_h_def) + drain_C_(2 * g_tp.min_w_nmos_, NCH, 1, 1, g_tp.cell_h_def) + gate_C(inv_size * g_tp.min_w_nmos_, 0) + gate_C(inv_size * min_w_pmos, 0); double timeconst = res_eq * cap_eq; delay = horowitz(inputrise, timeconst, deviceType->Vth / deviceType->Vdd, deviceType->Vth / deviceType->Vdd, RISE); double temp_power = cap_eq * deviceType->Vdd * deviceType->Vdd; inputrise = delay / (deviceType->Vdd - deviceType->Vth); /* for the next stage */ /* Inverter delay: * The load capacitance of this inv depends on * the gate capacitance of the final stage nmos * transistor which in turn depends on nsize */ res_eq = tr_R_on(inv_size * min_w_pmos, PCH, 1); cap_eq = drain_C_(inv_size * min_w_pmos, PCH, 1, 1, g_tp.cell_h_def) + drain_C_(inv_size * g_tp.min_w_nmos_, NCH, 1, 1, g_tp.cell_h_def) + gate_C(nsize, 0); timeconst = res_eq * cap_eq; delay += horowitz(inputrise, timeconst, deviceType->Vth / deviceType->Vdd, deviceType->Vth / deviceType->Vdd, FALL); temp_power += cap_eq * deviceType->Vdd * deviceType->Vdd; transmitter.delay = delay; transmitter.power.readOp.dynamic = temp_power * 2; /* since it is a diff. model*/ transmitter.power.readOp.leakage = 0.5 * deviceType->Vdd * (4 * cmos_Ileak(g_tp.min_w_nmos_, min_w_pmos, g_ip->temp) * NAND2_LEAK_STACK_FACTOR + 4 * cmos_Ileak(g_tp.min_w_nmos_, g_tp.min_w_nmos_, g_ip->temp)); inputrise = delay / deviceType->Vth; /* nmos delay + wire delay */ cap_eq = cwire + drain_C_(nsize, NCH, 1, 1, g_tp.cell_h_def) * 2 + nsense * sense_amp_input_cap(); //+receiver cap /* * NOTE: nmos is used as both pull up and pull down transistor * in the transmitter. This is because for low voltage swing, drive * resistance of nmos is less than pmos * (for a detailed graph ref: On-Chip Wires: Scaling and Efficiency) */ timeconst = (tr_R_on(nsize, NCH, 1) * RES_ADJ) * (cwire + drain_C_(nsize, NCH, 1, 1, g_tp.cell_h_def) * 2) + rwire * cwire / 2 + (tr_R_on(nsize, NCH, 1) * RES_ADJ + rwire) * nsense * sense_amp_input_cap(); /* * since we are pre-equalizing and overdriving the low * swing wires, the net time constant is less * than the actual value */ delay += horowitz(inputrise, timeconst, deviceType->Vth / deviceType->Vdd, .25, 0); #define VOL_SWING .1 temp_power += cap_eq * VOL_SWING * .400; /* .4v is the over drive voltage */ temp_power *= 2; /* differential wire */ l_wire.delay = delay - transmitter.delay; l_wire.power.readOp.dynamic = temp_power - transmitter.power.readOp.dynamic; l_wire.power.readOp.leakage = 0.5 * deviceType->Vdd * (4 * simplified_nmos_leakage(nsize, g_ip->temp)); //double rt = horowitz(inputrise, timeconst, deviceType->Vth/deviceType->Vdd, // deviceType->Vth/deviceType->Vdd, RISE)/deviceType->Vth; delay += g_tp.sense_delay; sense_amp.delay = g_tp.sense_delay; out_rise_time = g_tp.sense_delay / (deviceType->Vth); sense_amp.power.readOp.dynamic = g_tp.sense_dy_power; sense_amp.power.readOp.leakage = 0; //FIXME power.readOp.dynamic = temp_power + sense_amp.power.readOp.dynamic; power.readOp.leakage = transmitter.power.readOp.leakage + l_wire.power.readOp.leakage + sense_amp.power.readOp.leakage; }
// tristate buffer model consisting of not, nand, nor, and driver transistors void Htree2::output_buffer(double s1, double s2, double l_eff) { Wire w1(wt, l_eff); double pton_size = deviceType->n_to_p_eff_curr_drv_ratio; // input capacitance of repeater = input capacitance of nand + nor. double size = s1*(1 + pton_size)/(2 + pton_size + 1 + 2*pton_size); double s_eff = //stage eff of a repeater in a wire (gate_C(s2*(min_w_nmos + min_w_pmos), 0) + w1.wire_cap(l_eff*1e-6))/ gate_C(s2*(min_w_nmos + min_w_pmos), 0); double tr_size = gate_C(s1*(min_w_nmos + min_w_pmos), 0) * 1/2/(s_eff*gate_C(min_w_pmos, 0)); size = (size < 1) ? 1 : size; double res_nor = 2*tr_R_on(size*min_w_pmos, PCH, 1); double res_ptrans = tr_R_on(tr_size*min_w_nmos, NCH, 1); double cap_nand_out = drain_C_(size*min_w_nmos, NCH, 1, 1, g_tp.cell_h_def) + drain_C_(size*min_w_pmos, PCH, 1, 1, g_tp.cell_h_def)*2 + gate_C(tr_size*min_w_pmos, 0); double cap_ptrans_out = 2 *(drain_C_(tr_size*min_w_pmos, PCH, 1, 1, g_tp.cell_h_def) + drain_C_(tr_size*min_w_nmos, NCH, 1, 1, g_tp.cell_h_def)) + gate_C(s1*(min_w_nmos + min_w_pmos), 0); double tc = res_nor * cap_nand_out + (res_nor + res_ptrans) * cap_ptrans_out; delay += horowitz (w1.out_rise_time, tc, deviceType->Vth/deviceType->Vdd, deviceType->Vth/deviceType->Vdd, RISE); //nand power.readOp.dynamic += 0.5 * (2*drain_C_(size*min_w_pmos, PCH, 1, 1, g_tp.cell_h_def) + drain_C_(size*min_w_nmos, NCH, 1, 1, g_tp.cell_h_def) + gate_C(tr_size*(min_w_pmos), 0)) * deviceType->Vdd * deviceType->Vdd; power.searchOp.dynamic += 0.5 * (2*drain_C_(size*min_w_pmos, PCH, 1, 1, g_tp.cell_h_def) + drain_C_(size*min_w_nmos, NCH, 1, 1, g_tp.cell_h_def) + gate_C(tr_size*(min_w_pmos), 0)) * deviceType->Vdd * deviceType->Vdd*init_wire_bw; //not power.readOp.dynamic += 0.5 * (drain_C_(size*min_w_pmos, PCH, 1, 1, g_tp.cell_h_def) +drain_C_(size*min_w_nmos, NCH, 1, 1, g_tp.cell_h_def) +gate_C(size*(min_w_nmos + min_w_pmos), 0)) * deviceType->Vdd * deviceType->Vdd; power.searchOp.dynamic += 0.5 * (drain_C_(size*min_w_pmos, PCH, 1, 1, g_tp.cell_h_def) +drain_C_(size*min_w_nmos, NCH, 1, 1, g_tp.cell_h_def) +gate_C(size*(min_w_nmos + min_w_pmos), 0)) * deviceType->Vdd * deviceType->Vdd*init_wire_bw; //nor power.readOp.dynamic += 0.5 * (drain_C_(size*min_w_pmos, PCH, 1, 1, g_tp.cell_h_def) + 2*drain_C_(size*min_w_nmos, NCH, 1, 1, g_tp.cell_h_def) +gate_C(tr_size*(min_w_nmos + min_w_pmos), 0)) * deviceType->Vdd * deviceType->Vdd; power.searchOp.dynamic += 0.5 * (drain_C_(size*min_w_pmos, PCH, 1, 1, g_tp.cell_h_def) + 2*drain_C_(size*min_w_nmos, NCH, 1, 1, g_tp.cell_h_def) +gate_C(tr_size*(min_w_nmos + min_w_pmos), 0)) * deviceType->Vdd * deviceType->Vdd*init_wire_bw; //output transistor power.readOp.dynamic += 0.5 * ((drain_C_(tr_size*min_w_pmos, PCH, 1, 1, g_tp.cell_h_def) +drain_C_(tr_size*min_w_nmos, NCH, 1, 1, g_tp.cell_h_def))*2 + gate_C(s1*(min_w_nmos + min_w_pmos), 0)) * deviceType->Vdd * deviceType->Vdd; power.searchOp.dynamic += 0.5 * ((drain_C_(tr_size*min_w_pmos, PCH, 1, 1, g_tp.cell_h_def) +drain_C_(tr_size*min_w_nmos, NCH, 1, 1, g_tp.cell_h_def))*2 + gate_C(s1*(min_w_nmos + min_w_pmos), 0)) * deviceType->Vdd * deviceType->Vdd*init_wire_bw; if(uca_tree) { power.readOp.leakage += cmos_Isub_leakage(min_w_nmos*tr_size*2, min_w_pmos*tr_size*2, 1, inv)*deviceType->Vdd*wire_bw;/*inverter + output tr*/ power.readOp.leakage += cmos_Isub_leakage(min_w_nmos*size*3, min_w_pmos*size*3, 2, nand)*deviceType->Vdd*wire_bw;//nand power.readOp.leakage += cmos_Isub_leakage(min_w_nmos*size*3, min_w_pmos*size*3, 2, nor)*deviceType->Vdd*wire_bw;//nor power.readOp.gate_leakage += cmos_Ig_leakage(min_w_nmos*tr_size*2, min_w_pmos*tr_size*2, 1, inv)*deviceType->Vdd*wire_bw;/*inverter + output tr*/ power.readOp.gate_leakage += cmos_Ig_leakage(min_w_nmos*size*3, min_w_pmos*size*3, 2, nand)*deviceType->Vdd*wire_bw;//nand power.readOp.gate_leakage += cmos_Ig_leakage(min_w_nmos*size*3, min_w_pmos*size*3, 2, nor)*deviceType->Vdd*wire_bw;//nor //power.readOp.gate_leakage *=; } else { power.readOp.leakage += cmos_Isub_leakage(min_w_nmos*tr_size*2, min_w_pmos*tr_size*2, 1, inv)*deviceType->Vdd*wire_bw;/*inverter + output tr*/ power.readOp.leakage += cmos_Isub_leakage(min_w_nmos*size*3, min_w_pmos*size*3, 2, nand)*deviceType->Vdd*wire_bw;//nand power.readOp.leakage += cmos_Isub_leakage(min_w_nmos*size*3, min_w_pmos*size*3, 2, nor)*deviceType->Vdd*wire_bw;//nor power.readOp.gate_leakage += cmos_Ig_leakage(min_w_nmos*tr_size*2, min_w_pmos*tr_size*2, 1, inv)*deviceType->Vdd*wire_bw;/*inverter + output tr*/ power.readOp.gate_leakage += cmos_Ig_leakage(min_w_nmos*size*3, min_w_pmos*size*3, 2, nand)*deviceType->Vdd*wire_bw;//nand power.readOp.gate_leakage += cmos_Ig_leakage(min_w_nmos*size*3, min_w_pmos*size*3, 2, nor)*deviceType->Vdd*wire_bw;//nor //power.readOp.gate_leakage *=deviceType->Vdd*wire_bw; } }