double Arbiter::arb_req() { double temp = ((R - 1) * (2 * gate_C(NTn1, 0) + gate_C(PTn1, 0)) + 2 * gate_C(NTn2, 0) + gate_C(PTn2, 0) + gate_C(NTi, 0) + gate_C(PTi, 0) + drain_C_(NTi, 0, 1, 1, g_tp.cell_h_def) + drain_C_(PTi, 1, 1, 1, g_tp.cell_h_def)); return temp; }
// 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 Arbiter::crossbar_ctrline() { double temp = (Cw3(o_len * 1e-6 /* m */) + flit_size * transmission_buf_ctrcap() + drain_C_(NTi, 0, 1, 1, g_tp.cell_h_def) + drain_C_(PTi, 1, 1, 1, g_tp.cell_h_def) + gate_C(NTi, 0) + gate_C(PTi, 0)); return temp; }
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 Wire::delay_optimal_wire() { double len = wire_length; //double min_wire_width = wire_width; //m double beta = pmos_to_nmos_sz_ratio(); double switching = 0; // switching energy double short_ckt = 0; // short-circuit energy double tc = 0; // time constant // input cap of min sized driver double input_cap = gate_C(g_tp.min_w_nmos_ + min_w_pmos, 0); // output parasitic capacitance of // the min. sized driver double out_cap = drain_C_(min_w_pmos, PCH, 1, 1, g_tp.cell_h_def) + drain_C_(g_tp.min_w_nmos_, NCH, 1, 1, g_tp.cell_h_def); // drive resistance double out_res = (tr_R_on(g_tp.min_w_nmos_, NCH, 1) + tr_R_on(min_w_pmos, PCH, 1)) / 2; double wr = wire_res(len); //ohm // wire cap /m double wc = wire_cap(len); // size the repeater such that the delay of the wire is minimum double repeater_scaling = sqrt(out_res * wc / (wr * input_cap)); // len will cancel // calc the optimum spacing between the repeaters (m) repeater_spacing = sqrt(2 * out_res * (out_cap + input_cap) / ((wr / len) * (wc / len))); repeater_size = repeater_scaling; switching = (repeater_scaling * (input_cap + out_cap) + repeater_spacing * (wc / len)) * deviceType->Vdd * deviceType->Vdd; tc = out_res * (input_cap + out_cap) + out_res * wc / len * repeater_spacing / repeater_scaling + wr / len * repeater_spacing * input_cap * repeater_scaling + 0.5 * (wr / len) * (wc / len) * repeater_spacing * repeater_spacing; delay = 0.693 * tc * len / repeater_spacing; #define Ishort_ckt 65e-6 /* across all tech Ref:Banerjee et al. {IEEE TED} */ short_ckt = deviceType->Vdd * g_tp.min_w_nmos_ * Ishort_ckt * 1.0986 * repeater_scaling * tc; area.set_area((len / repeater_spacing) * compute_gate_area(INV, 1, min_w_pmos * repeater_scaling, g_tp.min_w_nmos_ * repeater_scaling, g_tp.cell_h_def)); power.readOp.dynamic = ((len / repeater_spacing) * (switching + short_ckt)); power.readOp.leakage = ((len / repeater_spacing) * (1 + beta) / 2 * deviceType->Vdd * deviceType->I_off_n * g_tp.min_w_nmos_ * repeater_scaling); }
powerDef Wire::wire_model(double space, double size, double* delay) { powerDef ptemp; double len = 1; //double min_wire_width = wire_width; //m double beta = pmos_to_nmos_sz_ratio(); // switching energy double switching = 0; // short-circuit energy double short_ckt = 0; // time constant double tc = 0; // input cap of min sized driver double input_cap = gate_C(g_tp.min_w_nmos_ + min_w_pmos, 0); // output parasitic capacitance of // the min. sized driver double out_cap = drain_C_(min_w_pmos, PCH, 1, 1, g_tp.cell_h_def) + drain_C_(g_tp.min_w_nmos_, NCH, 1, 1, g_tp.cell_h_def); // drive resistance double out_res = (tr_R_on(g_tp.min_w_nmos_, NCH, 1) + tr_R_on(min_w_pmos, PCH, 1)) / 2; double wr = wire_res(len); //ohm // wire cap /m double wc = wire_cap(len); repeater_spacing = space; repeater_size = size; switching = (repeater_size * (input_cap + out_cap) + repeater_spacing * (wc / len)) * deviceType->Vdd * deviceType->Vdd; tc = out_res * (input_cap + out_cap) + out_res * wc / len * repeater_spacing / repeater_size + wr / len * repeater_spacing * out_cap * repeater_size + 0.5 * (wr / len) * (wc / len) * repeater_spacing * repeater_spacing; *delay = 0.693 * tc * len / repeater_spacing; #define Ishort_ckt 65e-6 /* across all tech Ref:Banerjee et al. {IEEE TED} */ short_ckt = deviceType->Vdd * g_tp.min_w_nmos_ * Ishort_ckt * 1.0986 * repeater_size * tc; ptemp.readOp.dynamic = ((len / repeater_spacing) * (switching + short_ckt)); ptemp.readOp.leakage = ((len / repeater_spacing) * (1 + beta) / 2 * deviceType->Vdd * deviceType->I_off_n * g_tp.min_w_nmos_ * repeater_size); return ptemp; }
/*Function to calculate the gate capacitance*/ double Router::gate_cap(double w) { return (double) gate_C (w*1e6 /*u*/, 0); }
double Arbiter::arb_int() { double temp = (drain_C_(NTn1, 0, 1, 1, g_tp.cell_h_def) * 2 + drain_C_(PTn1, 1, 1, 1, g_tp.cell_h_def) + 2 * gate_C(NTn2, 0) + gate_C(PTn2, 0)); return temp; }
double Arbiter::arb_pri() { double temp = 2 * (2 * gate_C(NTn1, 0) + gate_C(PTn1, 0)); /* switching capacitance of flip-flop is ignored */ return temp; }
double Arbiter::transmission_buf_ctrcap() { double temp = gate_C(NTtr, 0) + gate_C(PTtr, 0); return temp; }
double Wire::sense_amp_input_cap() { return drain_C_(g_tp.w_iso, PCH, 1, 1, g_tp.cell_h_def) + gate_C(g_tp.w_sense_en + g_tp.w_sense_n, 0) + drain_C_(g_tp.w_sense_n, NCH, 1, 1, g_tp.cell_h_def) + drain_C_(g_tp.w_sense_p, PCH, 1, 1, g_tp.cell_h_def); }
/* * 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; } }