/***************************************************************************** * 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 #include #include #include "parameter.h" #include "area.h" #include "basic_circuit.h" #include using namespace std; InputParameter * g_ip; TechnologyParameter g_tp; // ali bool is_equal(double first, double second) { if((first == 0) && (second ==0)) { return true; } if((second==0) || (second!=second)) return true; if((first!=first) || (second!=second)) // both are NaNs { return true; } if(first==0) { if(fabs(first-second)<(second*0.000001)) return true; } else { if(fabs(first-second)<(first*0.000001)) return true; } return false; } /** void DeviceType::display(uint32_t indent) const { string indent_str(indent, ' '); cout << indent_str << "C_g_ideal = " << setw(12) << C_g_ideal << " F/um" << endl; cout << indent_str << "C_fringe = " << setw(12) << C_fringe << " F/um" << endl; cout << indent_str << "C_overlap = " << setw(12) << C_overlap << " F/um" << endl; cout << indent_str << "C_junc = " << setw(12) << C_junc << " F/um^2" << endl; cout << indent_str << "C_junc_sw = " << setw(12) << C_junc_sidewall << " F/um^2" << endl; cout << indent_str << "l_phy = " << setw(12) << l_phy << " um" << endl; cout << indent_str << "l_elec = " << setw(12) << l_elec << " um" << endl; cout << indent_str << "R_nch_on = " << setw(12) << R_nch_on << " ohm-um" << endl; cout << indent_str << "R_pch_on = " << setw(12) << R_pch_on << " ohm-um" << endl; cout << indent_str << "Vdd = " << setw(12) << Vdd << " V" << endl; cout << indent_str << "Vth = " << setw(12) << Vth << " V" << endl; cout << indent_str << "I_on_n = " << setw(12) << I_on_n << " A/um" << endl; cout << indent_str << "I_on_p = " << setw(12) << I_on_p << " A/um" << endl; cout << indent_str << "I_off_n = " << setw(12) << I_off_n << " A/um" << endl; cout << indent_str << "I_off_p = " << setw(12) << I_off_p << " A/um" << endl; cout << indent_str << "C_ox = " << setw(12) << C_ox << " F/um^2" << endl; cout << indent_str << "t_ox = " << setw(12) << t_ox << " um" << endl; cout << indent_str << "n_to_p_eff_curr_drv_ratio = " << n_to_p_eff_curr_drv_ratio << endl; } **/ bool DeviceType::isEqual(const DeviceType & dev) { if( !is_equal(C_g_ideal,dev.C_g_ideal)) {display(0); cout << "\n\n\n"; dev.display(0); assert(false);} if( !is_equal(C_fringe,dev.C_fringe)) {display(0); cout << "\n\n\n"; dev.display(0);assert(false);} if( !is_equal(C_overlap , dev.C_overlap)) {display(0); cout << "\n\n\n"; dev.display(0);assert(false);} if( !is_equal(C_junc , dev.C_junc)) {display(0); cout << "\n\n\n"; dev.display(0);assert(false);} if( !is_equal(C_junc_sidewall , dev.C_junc_sidewall)) {display(0); cout << "\n\n\n"; dev.display(0);assert(false);} if( !is_equal(l_phy , dev.l_phy)) {display(0); cout << "\n\n\n"; dev.display(0);assert(false);} if( !is_equal(l_elec , dev.l_elec)) {display(0); cout << "\n\n\n"; dev.display(0);assert(false);} if( !is_equal(R_nch_on , dev.R_nch_on)) {display(0); cout << "\n\n\n"; dev.display(0);assert(false);} if( !is_equal(R_pch_on , dev.R_pch_on)) {display(0); cout << "\n\n\n"; dev.display(0);assert(false);} if( !is_equal(Vdd , dev.Vdd)) {display(0); cout << "\n\n\n"; dev.display(0);assert(false);} if( !is_equal(Vth , dev.Vth)) {display(0); cout << "\n\n\n"; dev.display(0);assert(false);} //// if( !is_equal(Vcc_min , dev.Vcc_min)) {display(0); cout << "\n\n\n"; dev.display(0);assert(false);} if( !is_equal(I_on_n , dev.I_on_n)) {display(0); cout << "\n\n\n"; dev.display(0);assert(false);} if( !is_equal(I_on_p , dev.I_on_p)) {display(0); cout << "\n\n\n"; dev.display(0);assert(false);} if( !is_equal(I_off_n , dev.I_off_n)) {display(0); cout << "\n\n\n"; dev.display(0);assert(false);} if( !is_equal(I_off_p , dev.I_off_p)) {display(0); cout << "\n\n\n"; dev.display(0);assert(false);} if( !is_equal(I_g_on_n , dev.I_g_on_n)) {display(0); cout << "\n\n\n"; dev.display(0);assert(false);} if( !is_equal(I_g_on_p , dev.I_g_on_p)) {display(0); cout << "\n\n\n"; dev.display(0);assert(false);} if( !is_equal(C_ox , dev.C_ox)) {display(0); cout << "\n\n\n"; dev.display(0);assert(false);} if( !is_equal(t_ox , dev.t_ox)) {display(0); cout << "\n\n\n"; dev.display(0);assert(false);} if( !is_equal(n_to_p_eff_curr_drv_ratio , dev.n_to_p_eff_curr_drv_ratio)) {display(0); cout << "\n\n\n"; dev.display(0);assert(false);} if( !is_equal(long_channel_leakage_reduction , dev.long_channel_leakage_reduction)) {display(0);cout << "\n\n\n"; dev.display(0); assert(false);} if( !is_equal(Mobility_n , dev.Mobility_n)) {display(0); cout << "\n\n\n"; dev.display(0);assert(false);} // auxilary parameters ///if( !is_equal(Vdsat , dev.Vdsat)) {display(0); cout << "\n\n\n"; dev.display(0); assert(false);} ///if( !is_equal(gmp_to_gmn_multiplier , dev.gmp_to_gmn_multiplier)) {display(0); cout << "\n\n\n"; dev.display(0); assert(false);} return true; } double scan_single_input_double(char* line, const char* name, const char* unit_name, bool print) { double temp; char unit[300]; memset(unit,0,300); sscanf(&line[strlen(name)], "%*[ \t]%s%*[ \t]%lf",unit,&temp); if(print) cout << name << ": " << temp << " " << unit << endl; return temp; } double scan_five_input_double(char* line, const char* name, const char* unit_name, int flavor, bool print) { double temp[5]; char unit[300]; memset(unit,0,300); sscanf(&line[strlen(name)], "%*[ \t]%s%*[ \t]%lf%*[ \t]%lf%*[ \t]%lf%*[ \t]%lf%*[ \t]%lf" ,unit,&(temp[0]),&(temp[1]),&(temp[2]),&(temp[3]), &(temp[4]) ); if (print) cout << name << "[" << flavor <<"]: " << temp[flavor] << " " << unit<< endl; return temp[flavor]; } void scan_five_input_double_temperature(char* line, const char* name, const char* unit_name, int flavor, unsigned int temperature, bool print, double & result) { double temp[5]; unsigned int thermal_temp; char unit[300]; memset(unit,0,300); sscanf(&line[strlen(name)], "%*[ \t]%s%*[ \t]%u%*[ \t]%lf%*[ \t]%lf%*[ \t]%lf%*[ \t]%lf%*[ \t]%lf" ,unit,&thermal_temp,&(temp[0]),&(temp[1]),&(temp[2]),&(temp[3]), &(temp[4]) ); if(thermal_temp==(temperature-300)) { if (print) cout << name << ": " << temp[flavor] << " "<< unit << endl; result = temp[flavor]; } } void DeviceType::assign(const string & in_file, int tech_flavor, unsigned int temperature) { FILE *fp = fopen(in_file.c_str(), "r"); char line[5000]; //char temp_var[5000]; //double temp[5]; //unsigned int thermal_temp; double nmos_effective_resistance_multiplier; if(!fp) { cout << in_file << " is missing!\n"; exit(-1); } while(fscanf(fp, "%[^\n]\n", line) != EOF) { if (!strncmp("-C_g_ideal", line, strlen("-C_g_ideal"))) { C_g_ideal=scan_five_input_double(line,"-C_g_ideal","F/um",tech_flavor,g_ip->print_detail_debug); continue; } if (!strncmp("-C_fringe", line, strlen("-C_fringe"))) { C_fringe=scan_five_input_double(line,"-C_fringe","F/um",tech_flavor,g_ip->print_detail_debug); continue; } if (!strncmp("-C_junc_sw", line, strlen("-C_junc_sw"))) { C_junc_sidewall =scan_five_input_double(line,"-C_junc_sw","F/um",tech_flavor,g_ip->print_detail_debug); continue; } if (!strncmp("-C_junc", line, strlen("-C_junc"))) { C_junc=scan_five_input_double(line,"-C_junc","F/um",tech_flavor,g_ip->print_detail_debug); continue; } if (!strncmp("-l_phy", line, strlen("-l_phy"))) { l_phy=scan_five_input_double(line,"-l_phy","F/um",tech_flavor,g_ip->print_detail_debug); continue; } if (!strncmp("-l_elec", line, strlen("-l_elec"))) { l_elec=scan_five_input_double(line,"-l_elec","F/um",tech_flavor,g_ip->print_detail_debug); continue; } if (!strncmp("-nmos_effective_resistance_multiplier", line, strlen("-nmos_effective_resistance_multiplier"))) { nmos_effective_resistance_multiplier=scan_five_input_double(line,"-nmos_effective_resistance_multiplier","F/um",tech_flavor,g_ip->print_detail_debug); continue; } if (!strncmp("-Vdd", line, strlen("-Vdd"))) { Vdd=scan_five_input_double(line,"-Vdd","F/um",tech_flavor,g_ip->print_detail_debug); continue; } if (!strncmp("-Vth", line, strlen("-Vth"))) { Vth=scan_five_input_double(line,"-Vth","F/um",tech_flavor,g_ip->print_detail_debug); continue; } if (!strncmp("-Vdsat", line, strlen("-Vdsat"))) { Vdsat=scan_five_input_double(line,"-Vdsat","V",tech_flavor,g_ip->print_detail_debug); continue; } if (!strncmp("-I_on_n", line, strlen("-I_on_n"))) { I_on_n=scan_five_input_double(line,"-I_on_n","F/um",tech_flavor,g_ip->print_detail_debug); continue; } if (!strncmp("-I_on_p", line, strlen("-I_on_p"))) { I_on_p = scan_five_input_double(line,"-I_on_p","F/um",tech_flavor,g_ip->print_detail_debug); continue; } if (!strncmp("-I_off_n", line, strlen("-I_off_n"))) { scan_five_input_double_temperature(line,"-I_off_n","F/um",tech_flavor,temperature,g_ip->print_detail_debug,I_off_n); continue; } if (!strncmp("-I_g_on_n", line, strlen("-I_g_on_n"))) { scan_five_input_double_temperature(line,"-I_g_on_n","F/um",tech_flavor,temperature,g_ip->print_detail_debug,I_g_on_n); continue; } if (!strncmp("-C_ox", line, strlen("-C_ox"))) { C_ox=scan_five_input_double(line,"-C_ox","F/um",tech_flavor,g_ip->print_detail_debug); continue; } if (!strncmp("-t_ox", line, strlen("-t_ox"))) { t_ox=scan_five_input_double(line,"-t_ox","F/um",tech_flavor,g_ip->print_detail_debug); continue; } if (!strncmp("-n2p_drv_rt", line, strlen("-n2p_drv_rt"))) { n_to_p_eff_curr_drv_ratio=scan_five_input_double(line,"-n2p_drv_rt","F/um",tech_flavor,g_ip->print_detail_debug); continue; } if (!strncmp("-lch_lk_rdc", line, strlen("-lch_lk_rdc"))) { long_channel_leakage_reduction=scan_five_input_double(line,"-lch_lk_rdc","F/um",tech_flavor,g_ip->print_detail_debug); continue; } if (!strncmp("-Mobility_n", line, strlen("-Mobility_n"))) { Mobility_n=scan_five_input_double(line,"-Mobility_n","F/um",tech_flavor,g_ip->print_detail_debug); continue; } if (!strncmp("-gmp_to_gmn_multiplier", line, strlen("-gmp_to_gmn_multiplier"))) { gmp_to_gmn_multiplier=scan_five_input_double(line,"-gmp_to_gmn_multiplier","F/um",tech_flavor,g_ip->print_detail_debug); continue; } if (!strncmp("-n_to_p_eff_curr_drv_ratio", line, strlen("-n_to_p_eff_curr_drv_ratio"))) { n_to_p_eff_curr_drv_ratio=scan_five_input_double(line,"-n_to_p_eff_curr_drv_ratio","F/um",tech_flavor,g_ip->print_detail_debug); continue; } } C_overlap = 0.2*C_g_ideal; if(tech_flavor>=3) R_nch_on = nmos_effective_resistance_multiplier * g_tp.vpp / I_on_n;//ohm-micron else R_nch_on = nmos_effective_resistance_multiplier * Vdd / I_on_n;//ohm-micron R_pch_on = n_to_p_eff_curr_drv_ratio * R_nch_on;//ohm-micron I_off_p = I_off_n; I_g_on_p = I_g_on_n; if(g_ip->print_detail_debug) { ///cout << nmos_effective_resistance_multiplier << " -- " << Vdd << " -- " << I_on_n << " -- " << n_to_p_eff_curr_drv_ratio << endl; cout << "C_overlap: " << C_overlap << " F/um" << endl; cout << "R_nch_on: " << R_nch_on << " ohm-micron" << endl; cout << "R_pch_on: " << R_pch_on << " ohm-micron" << endl; } fclose(fp); } void DeviceType::interpolate(double alpha, const DeviceType& dev1, const DeviceType& dev2) { C_g_ideal = alpha*dev1.C_g_ideal+(1-alpha)*dev2.C_g_ideal; C_fringe = alpha*dev1.C_fringe+(1-alpha)*dev2.C_fringe; C_overlap = alpha*dev1.C_overlap+(1-alpha)*dev2.C_overlap; C_junc = alpha*dev1.C_junc+(1-alpha)*dev2.C_junc; l_phy = alpha*dev1.l_phy+(1-alpha)*dev2.l_phy; l_elec = alpha*dev1.l_elec+(1-alpha)*dev2.l_elec; R_nch_on = alpha*dev1.R_nch_on+(1-alpha)*dev2.R_nch_on; R_pch_on = alpha*dev1.R_pch_on+(1-alpha)*dev2.R_pch_on; Vdd = alpha*dev1.Vdd+(1-alpha)*dev2.Vdd; Vth = alpha*dev1.Vth+(1-alpha)*dev2.Vth; Vcc_min = alpha*dev1.Vcc_min+(1-alpha)*dev2.Vcc_min; I_on_n = alpha*dev1.I_on_n+(1-alpha)*dev2.I_on_n; I_on_p = alpha*dev1.I_on_p+(1-alpha)*dev2.I_on_p; I_off_n = alpha*dev1.I_off_n+(1-alpha)*dev2.I_off_n; I_off_p = alpha*dev1.I_off_p+(1-alpha)*dev2.I_off_p; I_g_on_n = alpha*dev1.I_g_on_n+(1-alpha)*dev2.I_g_on_n; I_g_on_p = alpha*dev1.I_g_on_p+(1-alpha)*dev2.I_g_on_p; C_ox = alpha*dev1.C_ox+(1-alpha)*dev2.C_ox; t_ox = alpha*dev1.t_ox+(1-alpha)*dev2.t_ox; n_to_p_eff_curr_drv_ratio = alpha*dev1.n_to_p_eff_curr_drv_ratio+(1-alpha)*dev2.n_to_p_eff_curr_drv_ratio; long_channel_leakage_reduction = alpha*dev1.long_channel_leakage_reduction+(1-alpha)*dev2.long_channel_leakage_reduction; Mobility_n = alpha*dev1.Mobility_n+(1-alpha)*dev2.Mobility_n; Vdsat = alpha*dev1.Vdsat + (1-alpha)*dev2.Vdsat; gmp_to_gmn_multiplier = alpha*dev1.gmp_to_gmn_multiplier + (1-alpha)*dev2.gmp_to_gmn_multiplier; n_to_p_eff_curr_drv_ratio = alpha*dev1.n_to_p_eff_curr_drv_ratio + (1-alpha)*dev2.n_to_p_eff_curr_drv_ratio; C_junc_sidewall = dev1.C_junc_sidewall; } double scan_input_double_inter_type(char* line, const char * name, const char * unit_name, int proj_type, int tech_flavor, bool print) { assert(proj_typeprint_detail_debug; while(fscanf(fp, "%[^\n]\n", line) != EOF) { if (!strncmp("-wire_pitch", line, strlen("-wire_pitch"))) { pitch =scan_input_double_inter_type(line,"-wire_pitch","um",g_ip->ic_proj_type,tech_flavor,print); continue; } if (!strncmp("-barrier_thickness", line, strlen("-barrier_thickness"))) { barrier_thickness =scan_input_double_inter_type(line,"-barrier_thickness","ohm",g_ip->ic_proj_type,tech_flavor,print); continue; } if (!strncmp("-dishing_thickness", line, strlen("-dishing_thickness"))) { dishing_thickness =scan_input_double_inter_type(line,"-dishing_thickness","um",g_ip->ic_proj_type,tech_flavor,print); continue; } if (!strncmp("-alpha_scatter", line, strlen("-alpha_scatter"))) { alpha_scatter =scan_input_double_inter_type(line,"-alpha_scatter","um",g_ip->ic_proj_type,tech_flavor,print); continue; } if (!strncmp("-aspect_ratio", line, strlen("-aspect_ratio"))) { aspect_ratio =scan_input_double_inter_type(line,"-aspect_ratio","um",g_ip->ic_proj_type,tech_flavor,print); continue; } if (!strncmp("-miller_value", line, strlen("-miller_value"))) { miller_value =scan_input_double_inter_type(line,"-miller_value","um",g_ip->ic_proj_type,tech_flavor,print); continue; } if (!strncmp("-horiz_dielectric_constant", line, strlen("-horiz_dielectric_constant"))) { horiz_dielectric_constant =scan_input_double_inter_type(line,"-horiz_dielectric_constant","um",g_ip->ic_proj_type,tech_flavor,print); continue; } if (!strncmp("-vert_dielectric_constant", line, strlen("-vert_dielectric_constant"))) { vert_dielectric_constant =scan_input_double_inter_type(line,"-vert_dielectric_constant","um",g_ip->ic_proj_type,tech_flavor,print); continue; } if (!strncmp("-ild_thickness", line, strlen("-ild_thickness"))) { ild_thickness =scan_input_double_inter_type(line,"-ild_thickness","um",g_ip->ic_proj_type,tech_flavor,print); continue; } if (!strncmp("-fringe_cap", line, strlen("-fringe_cap"))) { fringe_cap =scan_input_double_inter_type(line,"-fringe_cap","um",g_ip->ic_proj_type,tech_flavor,print); continue; } if (!strncmp("-wire_r_per_micron", line, strlen("-wire_r_per_micron"))) { R_per_um =scan_input_double_inter_type(line,"-wire_r_per_micron","um",g_ip->ic_proj_type,tech_flavor,print); continue; } if (!strncmp("-wire_c_per_micron", line, strlen("-wire_c_per_micron"))) { C_per_um =scan_input_double_inter_type(line,"-wire_c_per_micron","um",g_ip->ic_proj_type,tech_flavor,print); continue; } if (!strncmp("-resistivity", line, strlen("-resistivity"))) { resistivity =scan_input_double_inter_type(line,"-resistivity","um",g_ip->ic_proj_type,tech_flavor,print); continue; } } pitch *= g_ip->F_sz_um; wire_width = pitch/ 2; //micron wire_thickness = aspect_ratio * wire_width;//micron wire_spacing = pitch - wire_width;//micron if((projection_type!=1) || (tech_flavor!=3)) { R_per_um = wire_resistance(resistivity, wire_width, wire_thickness, barrier_thickness, dishing_thickness, alpha_scatter);//ohm/micron if(print) cout << R_per_um << " = wire_resistance(" << resistivity << "," << wire_width << "," << wire_thickness << "," << barrier_thickness << "," << dishing_thickness << "," << alpha_scatter << ")\n"; C_per_um = wire_capacitance(wire_width, wire_thickness, wire_spacing, ild_thickness, miller_value, horiz_dielectric_constant, vert_dielectric_constant, fringe_cap);//F/micron. if(print) cout << C_per_um << " = wire_capacitance(" << wire_width << "," << wire_thickness << "," << wire_spacing << "," << ild_thickness << "," << miller_value << "," << horiz_dielectric_constant << "," << vert_dielectric_constant << "," << fringe_cap << ")\n"; } fclose(fp); } bool InterconnectType::isEqual(const InterconnectType & inter) { if( !is_equal(pitch , inter.pitch)) {display(0); assert(false);} if( !is_equal(R_per_um , inter.R_per_um)) {display(0); assert(false);} if( !is_equal(C_per_um , inter.C_per_um)) {display(0); assert(false);} if( !is_equal(horiz_dielectric_constant , inter.horiz_dielectric_constant)) {display(0); assert(false);} if( !is_equal(vert_dielectric_constant , inter.vert_dielectric_constant)) {display(0); assert(false);} if( !is_equal(aspect_ratio , inter.aspect_ratio)) {display(0); assert(false);} if( !is_equal(miller_value , inter.miller_value)) {display(0); assert(false);} if( !is_equal(ild_thickness , inter.ild_thickness)) {display(0); assert(false);} //auxilary parameters ///if( !is_equal(wire_width , inter.wire_width)) {display(0); assert(false);} ///if( !is_equal(wire_thickness , inter.wire_thickness)) {display(0); assert(false);} ///if( !is_equal(wire_spacing , inter.wire_spacing)) {display(0); assert(false);} ///if( !is_equal(barrier_thickness , inter.barrier_thickness)) {display(0); assert(false);} ///if( !is_equal(dishing_thickness , inter.dishing_thickness)) {display(0); assert(false);} ///if( !is_equal(alpha_scatter , inter.alpha_scatter)) {display(0); assert(false);} ///if( !is_equal(fringe_cap , inter.fringe_cap)) {display(0); assert(false);} return true; } void InterconnectType::interpolate(double alpha, const InterconnectType & inter1, const InterconnectType & inter2) { pitch = alpha*inter1.pitch + (1-alpha)*inter2.pitch; R_per_um = alpha*inter1.R_per_um + (1-alpha)*inter2.R_per_um; C_per_um = alpha*inter1.C_per_um + (1-alpha)*inter2.C_per_um; horiz_dielectric_constant = alpha*inter1.horiz_dielectric_constant + (1-alpha)*inter2.horiz_dielectric_constant; vert_dielectric_constant = alpha*inter1.vert_dielectric_constant + (1-alpha)*inter2.vert_dielectric_constant; aspect_ratio = alpha*inter1.aspect_ratio + (1-alpha)*inter2.aspect_ratio; miller_value = alpha*inter1.miller_value + (1-alpha)*inter2.miller_value; ild_thickness = alpha*inter1.ild_thickness + (1-alpha)*inter2.ild_thickness; } void scan_five_input_double_mem_type(char* line, const char* name, const char* unit_name, int flavor, int cell_type, bool print, double & result) { double temp[5]; int cell_type_temp; char unit[300]; memset(unit,0,300); sscanf(&line[strlen(name)], "%*[ \t]%s%*[ \t]%d%*[ \t]%lf%*[ \t]%lf%*[ \t]%lf%*[ \t]%lf%*[ \t]%lf" ,unit,&cell_type_temp,&(temp[0]),&(temp[1]),&(temp[2]),&(temp[3]), &(temp[4]) ); if(cell_type_temp==cell_type) { if (print) cout << name << ": " << temp[flavor] << " "<< unit << endl; result = temp[flavor]; } } // cell_type --> sram(0),cam(1),dram(2) void MemoryType::assign(const string & in_file, int tech_flavor, int cell_type) { FILE *fp = fopen(in_file.c_str(), "r"); char line[5000]; //char temp_var[5000]; //double temp; //unsigned int thermal_temp; double vdd_cell,vdd; if(!fp) { cout << in_file << " is missing!\n"; exit(-1); } while(fscanf(fp, "%[^\n]\n", line) != EOF) { if (!strncmp("-Vdd", line, strlen("-Vdd"))) { vdd=scan_five_input_double(line,"-Vdd","V",tech_flavor,g_ip->print_detail_debug); continue; } if (!strncmp("-vdd_cell", line, strlen("-vdd_cell"))) { scan_five_input_double_mem_type(line,"-vdd_cell","V",tech_flavor,cell_type, g_ip->print_detail_debug,vdd_cell); continue; } if (!strncmp("-Wmemcella", line, strlen("-Wmemcella"))) { scan_five_input_double_mem_type(line,"-Wmemcella","V",tech_flavor,cell_type, g_ip->print_detail_debug,cell_a_w); continue; } if (!strncmp("-Wmemcellpmos", line, strlen("-Wmemcellpmos"))) { scan_five_input_double_mem_type(line,"-Wmemcellpmos","V",tech_flavor,cell_type, g_ip->print_detail_debug,cell_pmos_w); continue; } if (!strncmp("-Wmemcellnmos", line, strlen("-Wmemcellnmos"))) { scan_five_input_double_mem_type(line,"-Wmemcellnmos","V",tech_flavor,cell_type, g_ip->print_detail_debug,cell_nmos_w); continue; } if (!strncmp("-area_cell", line, strlen("-area_cell"))) { scan_five_input_double_mem_type(line,"-area_cell","V",tech_flavor,cell_type, g_ip->print_detail_debug,area_cell); continue; } if (!strncmp("-asp_ratio_cell", line, strlen("-asp_ratio_cell"))) { scan_five_input_double_mem_type(line,"-asp_ratio_cell","V",tech_flavor,cell_type, g_ip->print_detail_debug,asp_ratio_cell); continue; } } if(cell_type!=2) cell_a_w *= g_ip->F_sz_um; cell_pmos_w *= g_ip->F_sz_um; cell_nmos_w *= g_ip->F_sz_um; if(cell_type!=2) area_cell *= (g_ip->F_sz_um* g_ip->F_sz_um); ///assert(asp_ratio_cell!=0); b_w = sqrt(area_cell / (asp_ratio_cell)); b_h = asp_ratio_cell * b_w; if(cell_type==2) //dram Vbitpre = vdd_cell; else // sram or cam Vbitpre = vdd; Vbitfloating = Vbitpre*0.7; //display(5); } void MemoryType::interpolate(double alpha, const MemoryType& mem1, const MemoryType& mem2) { cell_a_w = alpha * mem1.cell_a_w + (1-alpha) * mem2.cell_a_w; cell_pmos_w = alpha * mem1.cell_pmos_w + (1-alpha) * mem2.cell_pmos_w; cell_nmos_w = alpha * mem1.cell_nmos_w + (1-alpha) * mem2.cell_nmos_w; area_cell = alpha * mem1.area_cell + (1-alpha) * mem2.area_cell; asp_ratio_cell = alpha * mem1.asp_ratio_cell + (1-alpha) * mem2.asp_ratio_cell; Vbitpre = mem2.Vbitpre; Vbitfloating = Vbitpre*0.7; // updating dependant variables after scaling/interpolating ///assert(asp_ratio_cell!=0); b_w = sqrt(area_cell / (asp_ratio_cell)); b_h = asp_ratio_cell * b_w; //display(10); } bool MemoryType::isEqual(const MemoryType & mem) { if( !is_equal(b_w , mem.b_w)) {display(0); cout << "\n\n\n"; mem.display(0); assert(false);} if( !is_equal(b_h , mem.b_h)) {display(0); cout << "\n\n\n"; mem.display(0); assert(false);} if( !is_equal(cell_a_w , mem.cell_a_w)) {display(0); cout << "\n\n\n"; mem.display(0); assert(false);} if( !is_equal(cell_pmos_w , mem.cell_pmos_w)) {display(0); cout << "\n\n\n"; mem.display(0); assert(false);} if( !is_equal(cell_nmos_w , mem.cell_nmos_w)) {display(0); cout << "\n\n\n"; mem.display(0); assert(false);} if( !is_equal(Vbitpre , mem.Vbitpre)) {display(0); cout << "\n\n\n"; mem.display(0); assert(false);} ///if( !is_equal(Vbitfloating , mem.Vbitfloating)) {display(0); cout << "\n\n\n"; mem.display(0); assert(false);} // needed to calculate b_w b_h ///if( !is_equal(area_cell , mem.area_cell)) {display(0); assert(false);} ///if( !is_equal(asp_ratio_cell , mem.asp_ratio_cell)) {display(0); assert(false);} return true; } void ScalingFactor::assign(const string & in_file) { FILE *fp = fopen(in_file.c_str(), "r"); char line[5000]; //char temp_var[5000]; if(!fp) { cout << in_file << " is missing!\n"; exit(-1); } while(fscanf(fp, "%[^\n]\n", line) != EOF) { if (!strncmp("-logic_scaling_co_eff", line, strlen("-logic_scaling_co_eff"))) { logic_scaling_co_eff = scan_single_input_double(line,"-logic_scaling_co_eff","F/um", g_ip->print_detail_debug); continue; } if (!strncmp("-core_tx_density", line, strlen("-core_tx_density"))) { core_tx_density = scan_single_input_double(line,"-core_tx_density","F/um", g_ip->print_detail_debug); continue; } } fclose(fp); } void ScalingFactor::interpolate(double alpha, const ScalingFactor& dev1, const ScalingFactor& dev2) { logic_scaling_co_eff = alpha*dev1.logic_scaling_co_eff + (1-alpha)*dev2.logic_scaling_co_eff; core_tx_density = alpha*dev1.core_tx_density + (1-alpha)*dev2.core_tx_density; } bool ScalingFactor::isEqual(const ScalingFactor & scal) { if( !is_equal(logic_scaling_co_eff,scal.logic_scaling_co_eff)) { display(0); assert(false);} if( !is_equal(core_tx_density,scal.core_tx_density)) { display(0); assert(false);} if( !is_equal(long_channel_leakage_reduction , scal.long_channel_leakage_reduction)) { display(0); assert(false);} return true; } void TechnologyParameter::find_upper_and_lower_tech(double technology, int &tech_lo, string& in_file_lo, int &tech_hi, string& in_file_hi) { if (technology < 181 && technology > 179) { tech_lo = 180; in_file_lo = "tech_params/180nm.dat"; tech_hi = 180; in_file_hi = "tech_params/180nm.dat"; } else if (technology < 91 && technology > 89) { tech_lo = 90; in_file_lo = "tech_params/90nm.dat"; tech_hi = 90; in_file_hi = "tech_params/90nm.dat"; } else if (technology < 66 && technology > 64) { tech_lo = 65; in_file_lo = "tech_params/65nm.dat"; tech_hi = 65; in_file_hi = "tech_params/65nm.dat"; } else if (technology < 46 && technology > 44) { tech_lo = 45; in_file_lo = "tech_params/45nm.dat"; tech_hi = 45; in_file_hi = "tech_params/45nm.dat"; } else if (technology < 33 && technology > 31) { tech_lo = 32; in_file_lo = "tech_params/32nm.dat"; tech_hi = 32; in_file_hi = "tech_params/32nm.dat"; } else if (technology < 23 && technology > 21) { tech_lo = 22; in_file_lo = "tech_params/22nm.dat"; tech_hi = 22; in_file_hi = "tech_params/22nm.dat"; } else if (technology < 180 && technology > 90) { tech_lo = 180; in_file_lo = "tech_params/180nm.dat"; tech_hi = 90; in_file_hi = "tech_params/90nm.dat"; } else if (technology < 90 && technology > 65) { tech_lo = 90; in_file_lo = "tech_params/90nm.dat"; tech_hi = 65; in_file_hi = "tech_params/65nm.dat"; } else if (technology < 65 && technology > 45) { tech_lo = 65; in_file_lo = "tech_params/65nm.dat"; tech_hi = 45; in_file_hi = "tech_params/45nm.dat"; } else if (technology < 45 && technology > 32) { tech_lo = 45; in_file_lo = "tech_params/45nm.dat"; tech_hi = 32; in_file_hi = "tech_params/32nm.dat"; } else if (technology < 32 && technology > 22) { tech_lo = 32; in_file_lo = "tech_params/32nm.dat"; tech_hi = 22; in_file_hi = "tech_params/22nm.dat"; } /** else if (technology < 22 && technology > 16) { tech_lo = 22; in_file_lo = "tech_params/22nm.dat"; tech_hi = 16; in_file_hi = "tech_params/16nm.dat"; } **/ else { cout<<"Invalid technology nodes"<tsv_is_subarray_type; } else { tsv_type = g_ip->tsv_os_bank_type; } fp = fopen(in_file.c_str(), "r"); while(fscanf(fp, "%[^\n]\n", line) != EOF) { if (!strncmp("-tsv_pitch", line, strlen("-tsv_pitch"))) { tsv_pitch = scan_input_double_tsv_type(line,"-tsv_pitch","F/um", g_ip->ic_proj_type, tsv_type, g_ip->print_detail_debug); continue; } if (!strncmp("-tsv_diameter", line, strlen("-tsv_diameter"))) { tsv_diameter = scan_input_double_tsv_type(line,"-tsv_diameter","F/um", g_ip->ic_proj_type, tsv_type, g_ip->print_detail_debug); continue; } if (!strncmp("-tsv_length", line, strlen("-tsv_length"))) { tsv_length = scan_input_double_tsv_type(line,"-tsv_length","F/um", g_ip->ic_proj_type, tsv_type, g_ip->print_detail_debug); continue; } if (!strncmp("-tsv_dielec_thickness", line, strlen("-tsv_dielec_thickness"))) { tsv_dielec_thickness = scan_input_double_tsv_type(line,"-tsv_dielec_thickness","F/um", g_ip->ic_proj_type, tsv_type, g_ip->print_detail_debug); continue; } if (!strncmp("-tsv_contact_resistance", line, strlen("-tsv_contact_resistance"))) { tsv_contact_resistance = scan_input_double_tsv_type(line,"-tsv_contact_resistance","F/um", g_ip->ic_proj_type, tsv_type, g_ip->print_detail_debug); continue; } if (!strncmp("-tsv_depletion_width", line, strlen("-tsv_depletion_width"))) { tsv_depletion_width = scan_input_double_tsv_type(line,"-tsv_depletion_width","F/um", g_ip->ic_proj_type, tsv_type, g_ip->print_detail_debug); continue; } if (!strncmp("-tsv_liner_dielectric_cons", line, strlen("-tsv_liner_dielectric_cons"))) { tsv_liner_dielectric_constant = scan_input_double_tsv_type(line,"-tsv_liner_dielectric_cons","F/um", g_ip->ic_proj_type, tsv_type, g_ip->print_detail_debug); continue; } tsv_length *= g_ip->num_die_3d; if(iter==0) { tsv_parasitic_resistance_fine = tsv_resistance(BULK_CU_RESISTIVITY, tsv_length, tsv_diameter, tsv_contact_resistance); tsv_parasitic_capacitance_fine = tsv_capacitance(tsv_length, tsv_diameter, tsv_pitch, tsv_dielec_thickness, tsv_liner_dielectric_constant, tsv_depletion_width); tsv_minimum_area_fine = tsv_area(tsv_pitch); } else { tsv_parasitic_resistance_coarse = tsv_resistance(BULK_CU_RESISTIVITY, tsv_length, tsv_diameter, tsv_contact_resistance); tsv_parasitic_capacitance_coarse = tsv_capacitance(tsv_length, tsv_diameter, tsv_pitch, tsv_dielec_thickness, tsv_liner_dielectric_constant, tsv_depletion_width); tsv_minimum_area_coarse = tsv_area(tsv_pitch); } } fclose(fp); } } void TechnologyParameter::init(double technology, bool is_tag) { FILE *fp ; reset(); char line[5000]; //char temp_var[5000]; uint32_t ram_cell_tech_type = (is_tag) ? g_ip->tag_arr_ram_cell_tech_type : g_ip->data_arr_ram_cell_tech_type; uint32_t peri_global_tech_type = (is_tag) ? g_ip->tag_arr_peri_global_tech_type : g_ip->data_arr_peri_global_tech_type; int tech_lo, tech_hi; string in_file_lo, in_file_hi; double alpha; // used for technology interpolation technology = technology * 1000.0; // in the unit of nm find_upper_and_lower_tech(technology, tech_lo,in_file_lo,tech_hi,in_file_hi); // excluding some cases. if((tech_lo==22) && (tech_hi==22)) { if (ram_cell_tech_type == 3 ) { cout<<"current version does not support eDRAM technologies at 22nm"<print_detail_debug); continue; } if (!strncmp("-dram_cell_Vdd", line, strlen("-dram_cell_Vdd"))) { dram_cell_Vdd += alpha* scan_five_input_double(line,"-dram_cell_Vdd","F/um", ram_cell_tech_type, g_ip->print_detail_debug); continue; } if (!strncmp("-dram_cell_C", line, strlen("-dram_cell_C"))) { dram_cell_C += alpha* scan_five_input_double(line,"-dram_cell_C","F/um", ram_cell_tech_type, g_ip->print_detail_debug); continue; } if (!strncmp("-dram_cell_I_off_worst_case_len_temp", line, strlen("-dram_cell_I_off_worst_case_len_temp"))) { dram_cell_I_off_worst_case_len_temp += alpha* scan_five_input_double(line,"-dram_cell_I_off_worst_case_len_temp","F/um", ram_cell_tech_type, g_ip->print_detail_debug); continue; } if (!strncmp("-vpp", line, strlen("-vpp"))) { vpp += alpha* scan_five_input_double(line,"-vpp","F/um", ram_cell_tech_type, g_ip->print_detail_debug); continue; } if (!strncmp("-sckt_co_eff", line, strlen("-sckt_co_eff"))) { sckt_co_eff += alpha * scan_single_input_double(line,"-sckt_co_eff","F/um", g_ip->print_detail_debug); continue; } if (!strncmp("-chip_layout_overhead", line, strlen("-chip_layout_overhead"))) { chip_layout_overhead += alpha * scan_single_input_double(line,"-chip_layout_overhead","F/um", g_ip->print_detail_debug); continue; } if (!strncmp("-macro_layout_overhead", line, strlen("-macro_layout_overhead"))) { macro_layout_overhead += alpha * scan_single_input_double(line,"-macro_layout_overhead","F/um", g_ip->print_detail_debug); continue; } } fclose(fp); DeviceType peri_global_lo, peri_global_hi; peri_global_lo.assign(in_file_lo, peri_global_tech_type, g_ip->temp); peri_global_hi.assign(in_file_hi, peri_global_tech_type, g_ip->temp); peri_global.interpolate(alpha,peri_global_lo,peri_global_hi); // in the original code some field of this devide has not been initialized/ // I make them 0 for compatibility. ///peri_global.I_on_p = 0.0; DeviceType sleep_tx_lo, sleep_tx_hi; sleep_tx_lo.assign(in_file_lo, 1, g_ip->temp); sleep_tx_hi.assign(in_file_hi, 1, g_ip->temp); sleep_tx.interpolate(alpha, sleep_tx_lo, sleep_tx_hi); DeviceType sram_cell_lo, sram_cell_hi; sram_cell_lo.assign(in_file_lo, ram_cell_tech_type, g_ip->temp); sram_cell_hi.assign(in_file_hi, ram_cell_tech_type, g_ip->temp); sram_cell.interpolate(alpha, sram_cell_lo, sram_cell_hi); // in the original code some field of this devide has not been initialized/ // I make them 0 for compatibility. //sram_cell.Vdd=0.0; ///sram_cell.I_on_p=0.0; ///sram_cell.C_ox=0.0; DeviceType dram_acc_lo, dram_acc_hi; dram_acc_lo.assign(in_file_lo, (ram_cell_tech_type==comm_dram? ram_cell_tech_type:dram_cell_tech_flavor), g_ip->temp); dram_acc_hi.assign(in_file_hi, (ram_cell_tech_type==comm_dram? ram_cell_tech_type:dram_cell_tech_flavor), g_ip->temp); dram_acc.interpolate(alpha, dram_acc_lo, dram_acc_hi); // dram_acc exceptions //dram_acc.R_nch_on = g_tp.dram_cell_Vdd / g_tp.dram_acc.I_on_n; //dram_acc.R_pch_on = 0; if(tech_lo<=22) { } else if(tech_lo<=32) { if(ram_cell_tech_type == lp_dram) dram_acc.Vth = 0.44129; else dram_acc.Vth = 1.0; } else if(tech_lo<=45) { if(ram_cell_tech_type == lp_dram) dram_acc.Vth = 0.44559; else dram_acc.Vth = 1.0; } else if(tech_lo<=65) { if(ram_cell_tech_type == lp_dram) dram_acc.Vth = 0.43806; else dram_acc.Vth = 1.0; } else if(tech_lo<=90) { if(ram_cell_tech_type == lp_dram) dram_acc.Vth = 0.4545; else dram_acc.Vth = 1.0; } // in the original code some field of this devide has not been initialized/ // I make them 0 for compatibility. dram_acc.Vdd= 0.0; dram_acc.I_on_p = 0.0; dram_acc.I_off_n = 0.0; dram_acc.I_off_p = 0.0; dram_acc.C_ox = 0.0; dram_acc.t_ox = 0.0; dram_acc.n_to_p_eff_curr_drv_ratio = 0.0; DeviceType dram_wl_lo, dram_wl_hi; dram_wl_lo.assign(in_file_lo, (ram_cell_tech_type==comm_dram? ram_cell_tech_type:dram_cell_tech_flavor), g_ip->temp); dram_wl_hi.assign(in_file_hi, (ram_cell_tech_type==comm_dram? ram_cell_tech_type:dram_cell_tech_flavor), g_ip->temp); dram_wl.interpolate(alpha, dram_wl_lo, dram_wl_hi); // in the original code some field of this devide has not been initialized/ // I make them 0 for compatibility. dram_wl.Vdd = 0.0; dram_wl.Vth = 0.0; dram_wl.I_on_p = 0.0; dram_wl.C_ox = 0.0; dram_wl.t_ox = 0.0; // if ram_cell_tech_type is not 3 or 4 ( which means edram and comm-dram) // then reset dram_wl dram_acc if(ram_cell_tech_type <3) { dram_acc.reset(); dram_wl.reset(); } DeviceType cam_cell_lo, cam_cell_hi; cam_cell_lo.assign(in_file_lo, ram_cell_tech_type, g_ip->temp); cam_cell_hi.assign(in_file_hi, ram_cell_tech_type, g_ip->temp); cam_cell.interpolate(alpha, cam_cell_lo, cam_cell_hi); MemoryType dram_lo, dram_hi; dram_lo.assign(in_file_lo, ram_cell_tech_type, 2); // cell_type = dram(2) dram_hi.assign(in_file_hi, ram_cell_tech_type, 2); dram.interpolate(alpha,dram_lo,dram_hi); MemoryType sram_lo, sram_hi; sram_lo.assign(in_file_lo, ram_cell_tech_type, 0); // cell_type = sram(0) sram_hi.assign(in_file_hi, ram_cell_tech_type, 0); sram.interpolate(alpha,sram_lo,sram_hi); // sram cell execptions /*sram_lo.assign(in_file_lo, 0, g_ip->temp); sram.cell_a_w =sram_lo.cell_a_w; sram.b_h = sram_lo.b_h; sram.b_w = sram_lo.b_w; */ MemoryType cam_lo, cam_hi; cam_lo.assign(in_file_lo, ram_cell_tech_type, 1); // cell_type = sram(0) cam_hi.assign(in_file_hi, ram_cell_tech_type, 1); cam.interpolate(alpha,cam_lo,cam_hi); ScalingFactor scaling_factor_lo, scaling_factor_hi; scaling_factor_lo.assign(in_file_lo); scaling_factor_hi.assign(in_file_hi); scaling_factor.interpolate(alpha, scaling_factor_lo,scaling_factor_hi); //vcc_min peri_global.Vcc_min += (alpha * peri_global_lo.Vdd + (1-alpha)*peri_global_hi.Vdd) * 0.35; sleep_tx.Vcc_min += (alpha*sleep_tx_lo.Vdd+(1-alpha)*sleep_tx_hi.Vdd); sram_cell.Vcc_min += (alpha*sram_cell_lo.Vdd +(1-alpha)*sram_cell_hi.Vdd)* 0.65; fp = fopen(in_file_hi.c_str(), "r"); while(fscanf(fp, "%[^\n]\n", line) != EOF) { if (!strncmp("-sense_delay", line, strlen("-sense_delay"))) { sense_delay = scan_single_input_double(line,"-sense_delay","F/um", g_ip->print_detail_debug); continue; } if (!strncmp("-sense_dy_power", line, strlen("-sense_dy_power"))) { sense_dy_power = scan_single_input_double(line,"-sense_dy_power","F/um", g_ip->print_detail_debug); continue; } if (!strncmp("-sckt_co_eff", line, strlen("-sckt_co_eff"))) { sckt_co_eff += (1-alpha)* scan_single_input_double(line,"-sckt_co_eff","F/um", g_ip->print_detail_debug); continue; } if (!strncmp("-chip_layout_overhead", line, strlen("-chip_layout_overhead"))) { chip_layout_overhead += (1-alpha)* scan_single_input_double(line,"-chip_layout_overhead","F/um", g_ip->print_detail_debug); continue; } if (!strncmp("-macro_layout_overhead", line, strlen("-macro_layout_overhead"))) { macro_layout_overhead += (1-alpha)* scan_single_input_double(line,"-macro_layout_overhead","F/um", g_ip->print_detail_debug); continue; } if (!strncmp("-dram_cell_I_on", line, strlen("-dram_cell_I_on"))) { dram_cell_I_on += (1-alpha) * scan_five_input_double(line,"-dram_cell_I_on","F/um", ram_cell_tech_type, g_ip->print_detail_debug); continue; } if (!strncmp("-dram_cell_Vdd", line, strlen("-dram_cell_Vdd"))) { dram_cell_Vdd += (1-alpha) * scan_five_input_double(line,"-dram_cell_Vdd","F/um", ram_cell_tech_type, g_ip->print_detail_debug); continue; } if (!strncmp("-dram_cell_C", line, strlen("-dram_cell_C"))) { dram_cell_C += (1-alpha) * scan_five_input_double(line,"-dram_cell_C","F/um", ram_cell_tech_type, g_ip->print_detail_debug); continue; } if (!strncmp("-dram_cell_I_off_worst_case_len_temp", line, strlen("-dram_cell_I_off_worst_case_len_temp"))) { dram_cell_I_off_worst_case_len_temp += (1-alpha) * scan_five_input_double(line,"-dram_cell_I_off_worst_case_len_temp","F/um", ram_cell_tech_type, g_ip->print_detail_debug); continue; } if (!strncmp("-vpp", line, strlen("-vpp"))) { vpp += (1-alpha)* scan_five_input_double(line,"-vpp","F/um", ram_cell_tech_type, g_ip->print_detail_debug); continue; } } fclose(fp); //Currently we are not modeling the resistance/capacitance of poly anywhere. //Continuous function (or date have been processed) does not need linear interpolation w_comp_inv_p1 = 12.5 * g_ip->F_sz_um;//this was 10 micron for the 0.8 micron process w_comp_inv_n1 = 7.5 * g_ip->F_sz_um;//this was 6 micron for the 0.8 micron process w_comp_inv_p2 = 25 * g_ip->F_sz_um;//this was 20 micron for the 0.8 micron process w_comp_inv_n2 = 15 * g_ip->F_sz_um;//this was 12 micron for the 0.8 micron process w_comp_inv_p3 = 50 * g_ip->F_sz_um;//this was 40 micron for the 0.8 micron process w_comp_inv_n3 = 30 * g_ip->F_sz_um;//this was 24 micron for the 0.8 micron process w_eval_inv_p = 100 * g_ip->F_sz_um;//this was 80 micron for the 0.8 micron process w_eval_inv_n = 50 * g_ip->F_sz_um;//this was 40 micron for the 0.8 micron process w_comp_n = 12.5 * g_ip->F_sz_um;//this was 10 micron for the 0.8 micron process w_comp_p = 37.5 * g_ip->F_sz_um;//this was 30 micron for the 0.8 micron process MIN_GAP_BET_P_AND_N_DIFFS = 5 * g_ip->F_sz_um; MIN_GAP_BET_SAME_TYPE_DIFFS = 1.5 * g_ip->F_sz_um; HPOWERRAIL = 2 * g_ip->F_sz_um; cell_h_def = 50 * g_ip->F_sz_um; w_poly_contact = g_ip->F_sz_um; spacing_poly_to_contact = g_ip->F_sz_um; spacing_poly_to_poly = 1.5 * g_ip->F_sz_um; ram_wl_stitching_overhead_ = 7.5 * g_ip->F_sz_um; min_w_nmos_ = 3 * g_ip->F_sz_um / 2; max_w_nmos_ = 100 * g_ip->F_sz_um; w_iso = 12.5*g_ip->F_sz_um;//was 10 micron for the 0.8 micron process w_sense_n = 3.75*g_ip->F_sz_um; // sense amplifier N-trans; was 3 micron for the 0.8 micron process w_sense_p = 7.5*g_ip->F_sz_um; // sense amplifier P-trans; was 6 micron for the 0.8 micron process w_sense_en = 5*g_ip->F_sz_um; // Sense enable transistor of the sense amplifier; was 4 micron for the 0.8 micron process w_nmos_b_mux = 6 * min_w_nmos_; w_nmos_sa_mux = 6 * min_w_nmos_; w_pmos_bl_precharge = 6 * pmos_to_nmos_sz_ratio() * min_w_nmos_; w_pmos_bl_eq = pmos_to_nmos_sz_ratio() * min_w_nmos_; if (ram_cell_tech_type == comm_dram) { max_w_nmos_dec = 8 * g_ip->F_sz_um; h_dec = 8; // in the unit of memory cell height } else { max_w_nmos_dec = g_tp.max_w_nmos_; h_dec = 4; // in the unit of memory cell height } double gmn_sense_amp_latch = (peri_global.Mobility_n / 2) * peri_global.C_ox * (w_sense_n / peri_global.l_elec) * peri_global.Vdsat; double gmp_sense_amp_latch = peri_global.gmp_to_gmn_multiplier * gmn_sense_amp_latch; gm_sense_amp_latch = gmn_sense_amp_latch + gmp_sense_amp_latch; ///cout << "wire_local " << g_ip->ic_proj_type << " " << ((ram_cell_tech_type == comm_dram)?3:0) << endl; InterconnectType wire_local_lo, wire_local_hi; wire_local_lo.assign(in_file_lo,g_ip->ic_proj_type,(ram_cell_tech_type == comm_dram)?3:0); wire_local_hi.assign(in_file_hi,g_ip->ic_proj_type,(ram_cell_tech_type == comm_dram)?3:0); wire_local.interpolate(alpha,wire_local_lo,wire_local_hi); ///cout << "wire_inside_mat " << g_ip->ic_proj_type << " " << g_ip->wire_is_mat_type << endl; InterconnectType wire_inside_mat_lo, wire_inside_mat_hi; wire_inside_mat_lo.assign(in_file_lo, g_ip->ic_proj_type, g_ip->wire_is_mat_type); wire_inside_mat_hi.assign(in_file_hi, g_ip->ic_proj_type, g_ip->wire_is_mat_type); wire_inside_mat.interpolate(alpha, wire_inside_mat_lo, wire_inside_mat_hi); ///cout << "wire_outside_mat " << g_ip->ic_proj_type << " " << g_ip->wire_os_mat_type << endl; InterconnectType wire_outside_mat_lo, wire_outside_mat_hi; wire_outside_mat_lo.assign(in_file_lo, g_ip->ic_proj_type, g_ip->wire_os_mat_type); wire_outside_mat_hi.assign(in_file_hi, g_ip->ic_proj_type, g_ip->wire_os_mat_type); wire_outside_mat.interpolate(alpha, wire_outside_mat_lo, wire_outside_mat_hi); unit_len_wire_del = wire_inside_mat.R_per_um * wire_inside_mat.C_per_um / 2; // assign value for TSV parameters assign_tsv(in_file_hi); fringe_cap = wire_local_hi.fringe_cap; // fringe_cap is similar for all wire types. double rd = tr_R_on(min_w_nmos_, NCH, 1); double p_to_n_sizing_r = pmos_to_nmos_sz_ratio(); double c_load = gate_C(min_w_nmos_ * (1 + p_to_n_sizing_r), 0.0); double tf = rd * c_load; kinv = horowitz(0, tf, 0.5, 0.5, RISE); double KLOAD = 1; c_load = KLOAD * (drain_C_(min_w_nmos_, NCH, 1, 1, cell_h_def) + drain_C_(min_w_nmos_ * p_to_n_sizing_r, PCH, 1, 1, cell_h_def) + gate_C(min_w_nmos_ * 4 * (1 + p_to_n_sizing_r), 0.0)); tf = rd * c_load; FO4 = horowitz(0, tf, 0.5, 0.5, RISE); } #define PRINT(A,X) cout << A << ": " << X << " , " << tech.X << endl bool TechnologyParameter::isEqual(const TechnologyParameter& tech) { if(!is_equal(ram_wl_stitching_overhead_,tech.ram_wl_stitching_overhead_)) {assert(false);} //fs if(!is_equal(min_w_nmos_,tech.min_w_nmos_)) {assert(false);} //fs if(!is_equal(max_w_nmos_,tech.max_w_nmos_)) {assert(false);} //fs if(!is_equal(max_w_nmos_dec,tech.max_w_nmos_dec)) {assert(false);} //fs+ ram_cell_tech_type if(!is_equal(unit_len_wire_del,tech.unit_len_wire_del)) {assert(false);} //wire_inside_mat if(!is_equal(FO4,tech.FO4)) {assert(false);} //fs if(!is_equal(kinv,tech.kinv)) {assert(false);} //fs if(!is_equal(vpp,tech.vpp )) {assert(false);}//input if(!is_equal(w_sense_en,tech.w_sense_en)) {assert(false);}//fs if(!is_equal(w_sense_n,tech.w_sense_n)) {assert(false);} //fs if(!is_equal(w_sense_p,tech.w_sense_p)) {assert(false);} //fs if(!is_equal(sense_delay,tech.sense_delay)) {PRINT("sense_delay",sense_delay); assert(false);} // input if(!is_equal(sense_dy_power,tech.sense_dy_power)) {assert(false);} //input if(!is_equal(w_iso,tech.w_iso)) {assert(false);} //fs if(!is_equal(w_poly_contact,tech.w_poly_contact)) {assert(false);} //fs if(!is_equal(spacing_poly_to_poly,tech.spacing_poly_to_poly)) {assert(false);} //fs if(!is_equal(spacing_poly_to_contact,tech.spacing_poly_to_contact)) {assert(false);}//fs //CACTI3D auxilary variables ///if(!is_equal(tsv_pitch,tech.tsv_pitch)) {assert(false);} ///if(!is_equal(tsv_diameter,tech.tsv_diameter)) {assert(false);} ///if(!is_equal(tsv_length,tech.tsv_length)) {assert(false);} ///if(!is_equal(tsv_dielec_thickness,tech.tsv_dielec_thickness)) {assert(false);} ///if(!is_equal(tsv_contact_resistance,tech.tsv_contact_resistance)) {assert(false);} ///if(!is_equal(tsv_depletion_width,tech.tsv_depletion_width)) {assert(false);} ///if(!is_equal(tsv_liner_dielectric_constant,tech.tsv_liner_dielectric_constant)) {assert(false);} //CACTI3DD TSV params if(!is_equal(tsv_parasitic_capacitance_fine,tech.tsv_parasitic_capacitance_fine )) {PRINT("tsv_parasitic_capacitance_fine",tsv_parasitic_capacitance_fine); assert(false);} if(!is_equal(tsv_parasitic_resistance_fine,tech.tsv_parasitic_resistance_fine)) {assert(false);} if(!is_equal(tsv_minimum_area_fine,tech.tsv_minimum_area_fine)) {assert(false);} if(!is_equal(tsv_parasitic_capacitance_coarse,tech.tsv_parasitic_capacitance_coarse)) {assert(false);} if(!is_equal(tsv_parasitic_resistance_coarse,tech.tsv_parasitic_resistance_coarse)) {assert(false);} if(!is_equal(tsv_minimum_area_coarse,tech.tsv_minimum_area_coarse)) {assert(false);} //fs if(!is_equal(w_comp_inv_p1,tech.w_comp_inv_p1)) {assert(false);} if(!is_equal(w_comp_inv_p2,tech.w_comp_inv_p2)) {assert(false);} if(!is_equal(w_comp_inv_p3,tech.w_comp_inv_p3)) {assert(false);} if(!is_equal(w_comp_inv_n1,tech.w_comp_inv_n1)) {assert(false);} if(!is_equal(w_comp_inv_n2,tech.w_comp_inv_n2)) {assert(false);} if(!is_equal(w_comp_inv_n3,tech.w_comp_inv_n3)) {assert(false);} if(!is_equal(w_eval_inv_p,tech.w_eval_inv_p)) {assert(false);} if(!is_equal(w_eval_inv_n,tech.w_eval_inv_n)) {assert(false);} if(!is_equal(w_comp_n,tech.w_comp_n)) {assert(false);} if(!is_equal(w_comp_p,tech.w_comp_p)) {assert(false);} if(!is_equal(dram_cell_I_on,tech.dram_cell_I_on)) {assert(false);} //ram_cell_tech_type if(!is_equal(dram_cell_Vdd,tech.dram_cell_Vdd)) {assert(false);} if(!is_equal(dram_cell_I_off_worst_case_len_temp,tech.dram_cell_I_off_worst_case_len_temp)) {assert(false);} if(!is_equal(dram_cell_C,tech.dram_cell_C)) {assert(false);} if(!is_equal(gm_sense_amp_latch,tech.gm_sense_amp_latch)) {assert(false);} // depends on many things if(!is_equal(w_nmos_b_mux,tech.w_nmos_b_mux)) {assert(false);} //fs if(!is_equal(w_nmos_sa_mux,tech.w_nmos_sa_mux)) {assert(false);}//fs if(!is_equal(w_pmos_bl_precharge,tech.w_pmos_bl_precharge)) {PRINT("w_pmos_bl_precharge",w_pmos_bl_precharge);assert(false);}//fs if(!is_equal(w_pmos_bl_eq,tech.w_pmos_bl_eq)) {assert(false);}//fs if(!is_equal(MIN_GAP_BET_P_AND_N_DIFFS,tech.MIN_GAP_BET_P_AND_N_DIFFS)) {assert(false);}//fs if(!is_equal(MIN_GAP_BET_SAME_TYPE_DIFFS,tech.MIN_GAP_BET_SAME_TYPE_DIFFS)) {assert(false);}//fs if(!is_equal(HPOWERRAIL,tech.HPOWERRAIL)) {assert(false);}//fs if(!is_equal(cell_h_def,tech.cell_h_def)) {assert(false);}//fs if(!is_equal(chip_layout_overhead,tech.chip_layout_overhead )) {assert(false);}//input if(!is_equal(macro_layout_overhead,tech.macro_layout_overhead)) {cout <cache_sz / NUMBER_STACKED_DIE_LAYERS; // capacity per stacked die layer if (Ndwl != 1 || //Ndwl is fixed to 1 for CAM Ndcm != 1 || //Ndcm is fixed to 1 for CAM Nspd < 1 || Nspd > 1 || //Nspd is fixed to 1 for CAM Ndsam_lev_1 != 1 || //Ndsam_lev_1 is fixed to one Ndsam_lev_2 != 1 || //Ndsam_lev_2 is fixed to one Ndbl < 2) //FIXME: why should Ndbl be >1 for very small CAMs? { return; } if (g_ip->specific_tag) { tagbits = int(ceil(g_ip->tag_w/8.0)*8); } else { tagbits = int(ceil((ADDRESS_BITS + EXTRA_TAG_BITS)/8.0)*8); } //computation of no. of rows and cols of a subarray tag_num_r_subarray = (int)ceil(capacity_per_die / (g_ip->nbanks*tagbits/8.0 * Ndbl));//TODO: error check input of tagbits and blocksize //TODO: for pure CAM, g_ip->block should be number of entries. tag_num_c_subarray = tagbits; if (tag_num_r_subarray == 0) return; if (tag_num_r_subarray > MAXSUBARRAYROWS) return; if (tag_num_c_subarray < MINSUBARRAYCOLS) return; if (tag_num_c_subarray > MAXSUBARRAYCOLS) return; num_r_subarray = tag_num_r_subarray; //FIXME: what about num_c_subarray? num_subarrays = Ndwl * Ndbl; // calculate cell dimensions cam_cell.h = g_tp.cam.b_h + 2 * wire_local.pitch * (g_ip->num_rw_ports-1 + g_ip->num_rd_ports + g_ip->num_wr_ports) + 2 * wire_local.pitch*(g_ip->num_search_ports-1) + wire_local.pitch * g_ip->num_se_rd_ports; cam_cell.w = g_tp.cam.b_w + 2 * wire_local.pitch * (g_ip->num_rw_ports-1 + g_ip->num_rd_ports + g_ip->num_wr_ports) + 2 * wire_local.pitch*(g_ip->num_search_ports-1) + wire_local.pitch * g_ip->num_se_rd_ports; //FIXME: curious where this is getting used in a CAM cell.h = g_tp.sram.b_h + 2 * wire_local.pitch * (g_ip->num_wr_ports +g_ip->num_rw_ports-1 + g_ip->num_rd_ports) + 2 * wire_local.pitch*(g_ip->num_search_ports-1); cell.w = g_tp.sram.b_w + 2 * wire_local.pitch * (g_ip->num_rw_ports -1 + (g_ip->num_rd_ports - g_ip->num_se_rd_ports) + g_ip->num_wr_ports) + g_tp.wire_local.pitch * g_ip->num_se_rd_ports + 2 * wire_local.pitch*(g_ip->num_search_ports-1); // calculate wire parameters double c_b_metal = cell.h * wire_local.C_per_um; // double C_bl; c_b_metal = cam_cell.h * wire_local.C_per_um;//IBM and SUN design, SRAM array uses dummy cells to fill the blank space due to mismatch on CAM-RAM V_b_sense = (0.05 * g_tp.sram_cell.Vdd > VBITSENSEMIN) ? 0.05 * g_tp.sram_cell.Vdd : VBITSENSEMIN; deg_bl_muxing = 1;//FA fix as 1 // "/ 2.0" below is due to the fact that two adjacent access transistors share drain // contacts in a physical layout double Cbitrow_drain_cap = drain_C_(g_tp.cam.cell_a_w, NCH, 1, 0, cam_cell.w, false, true) / 2.0;//TODO: comment out these two lines // C_bl = num_r_subarray * (Cbitrow_drain_cap + c_b_metal); dram_refresh_period = 0; // do/di: data in/out, for fully associative they are the data width for normal read and write // so/si: search data in/out, for fully associative they are the data width for the search ops // for CAM, si=di, but so = matching address. do = data out = di (for normal read/write) // so/si needs broadcase while do/di do not switch (Ndbl) { case (0): cout << " Invalid Ndbl \n"< num_mats_h_dir) { return; } num_di_b_mat = tagbits; num_si_b_mat = tagbits;//*num_subarrays/num_mats; num_di_b_subbank = num_di_b_mat * num_act_mats_hor_dir;//normal cache or normal r/w for FA num_si_b_subbank = num_si_b_mat; //* num_act_mats_hor_dir_sl; inside the data is broadcast int num_addr_b_row_dec = _log2(num_r_subarray); num_addr_b_row_dec +=_log2(num_subarrays/num_mats); int number_subbanks = num_mats / num_act_mats_hor_dir; number_subbanks_decode = _log2(number_subbanks);//TODO: add log2(num_subarray_per_bank) to FA/CAM num_rw_ports = g_ip->num_rw_ports; num_rd_ports = g_ip->num_rd_ports; num_wr_ports = g_ip->num_wr_ports; num_se_rd_ports = g_ip->num_se_rd_ports; num_search_ports = g_ip->num_search_ports; number_addr_bits_mat = num_addr_b_row_dec + _log2(deg_bl_muxing) + _log2(deg_sa_mux_l1_non_assoc) + _log2(Ndsam_lev_2); num_di_b_bank_per_port = tagbits; num_si_b_bank_per_port = tagbits; num_do_b_bank_per_port = tagbits; num_so_b_bank_per_port = int(ceil(log2(num_r_subarray)) + ceil(log2(num_subarrays))); if ((!is_tag) && (g_ip->data_assoc > 1) && (!g_ip->fast_access)) { number_way_select_signals_mat = g_ip->data_assoc; } // add ECC adjustment to all data signals that traverse on H-trees. if (g_ip->add_ecc_b_ == true) { ECC_adjustment(); } is_valid = true; } void DynamicParameter::init_FA() { const InterconnectType &wire_local = g_tp.wire_local; //Disabling 3D model since a 3D stacked FA is never tested assert(NUMBER_STACKED_DIE_LAYERS == 1); unsigned int capacity_per_die = g_ip->cache_sz; if (Ndwl != 1 || //Ndwl is fixed to 1 for FA Ndcm != 1 || //Ndcm is fixed to 1 for FA Nspd < 1 || Nspd > 1 || //Nspd is fixed to 1 for FA Ndsam_lev_1 != 1 || //Ndsam_lev_1 is fixed to one Ndsam_lev_2 != 1 || //Ndsam_lev_2 is fixed to one Ndbl < 2) { return; } //***********compute row, col of an subarray //either fully-asso or cam if (g_ip->specific_tag) { tagbits = g_ip->tag_w; } else { tagbits = ADDRESS_BITS + EXTRA_TAG_BITS - _log2(g_ip->block_sz); } tagbits = (((tagbits + 3) >> 2) << 2); tag_num_r_subarray = (int)(capacity_per_die / (g_ip->nbanks*g_ip->block_sz * Ndbl)); tag_num_c_subarray = (int)ceil((tagbits * Nspd / Ndwl));// + EPSILON); if (tag_num_r_subarray == 0) return; if (tag_num_r_subarray > MAXSUBARRAYROWS) return; if (tag_num_c_subarray < MINSUBARRAYCOLS) return; if (tag_num_c_subarray > MAXSUBARRAYCOLS) return; data_num_r_subarray = tag_num_r_subarray; data_num_c_subarray = 8 * g_ip->block_sz; if (data_num_r_subarray == 0) return; if (data_num_r_subarray > MAXSUBARRAYROWS) return; if (data_num_c_subarray < MINSUBARRAYCOLS) return; if (data_num_c_subarray > MAXSUBARRAYCOLS) return; num_r_subarray = tag_num_r_subarray; num_subarrays = Ndwl * Ndbl; //****************end of computation of row, col of an subarray // calculate wire parameters cam_cell.h = g_tp.cam.b_h + 2 * wire_local.pitch * (g_ip->num_rw_ports-1 + g_ip->num_rd_ports + g_ip->num_wr_ports) + 2 * wire_local.pitch*(g_ip->num_search_ports-1) + wire_local.pitch * g_ip->num_se_rd_ports; cam_cell.w = g_tp.cam.b_w + 2 * wire_local.pitch * (g_ip->num_rw_ports-1 + g_ip->num_rd_ports + g_ip->num_wr_ports) + 2 * wire_local.pitch*(g_ip->num_search_ports-1) + wire_local.pitch * g_ip->num_se_rd_ports; cell.h = g_tp.sram.b_h + 2 * wire_local.pitch * (g_ip->num_wr_ports +g_ip->num_rw_ports-1 + g_ip->num_rd_ports) + 2 * wire_local.pitch*(g_ip->num_search_ports-1); cell.w = g_tp.sram.b_w + 2 * wire_local.pitch * (g_ip->num_rw_ports -1 + (g_ip->num_rd_ports - g_ip->num_se_rd_ports) + g_ip->num_wr_ports) + g_tp.wire_local.pitch * g_ip->num_se_rd_ports + 2 * wire_local.pitch*(g_ip->num_search_ports-1); double c_b_metal = cell.h * wire_local.C_per_um; // double C_bl; c_b_metal = cam_cell.h * wire_local.C_per_um;//IBM and SUN design, SRAM array uses dummy cells to fill the blank space due to mismatch on CAM-RAM V_b_sense = (0.05 * g_tp.sram_cell.Vdd > VBITSENSEMIN) ? 0.05 * g_tp.sram_cell.Vdd : VBITSENSEMIN; deg_bl_muxing = 1;//FA fix as 1 // "/ 2.0" below is due to the fact that two adjacent access transistors share drain // contacts in a physical layout double Cbitrow_drain_cap = drain_C_(g_tp.cam.cell_a_w, NCH, 1, 0, cam_cell.w, false, true) / 2.0;//TODO: comment out these two lines // C_bl = num_r_subarray * (Cbitrow_drain_cap + c_b_metal); dram_refresh_period = 0; // do/di: data in/out, for fully associative they are the data width for normal read and write // so/si: search data in/out, for fully associative they are the data width for the search ops // for CAM, si=di, but so = matching address. do = data out = di (for normal read/write) // so/si needs broadcase while do/di do not switch (Ndbl) { case (0): cout << " Invalid Ndbl \n"<block_sz;//TODO:internal perfetch should be considered also for fa num_do_b_subbank = num_so_b_subbank + tag_num_c_subarray; deg_sa_mux_l1_non_assoc = 1; deg_senseamp_muxing_non_associativity = deg_sa_mux_l1_non_assoc; num_act_mats_hor_dir = 1; num_act_mats_hor_dir_sl = num_mats_h_dir;//TODO: this is unnecessary, since search op, num_mats is used //compute num_do_mat for tag if (num_act_mats_hor_dir > num_mats_h_dir) { return; } //compute di for mat subbank and bank if (fully_assoc) { num_di_b_mat = num_do_b_mat; //*num_subarrays/num_mats; bits per mat of CAM/FA is as same as cache, //but inside the mat wire tracks need to be reserved for search data bus num_si_b_mat = tagbits; } num_di_b_subbank = num_di_b_mat * num_act_mats_hor_dir;//normal cache or normal r/w for FA num_si_b_subbank = num_si_b_mat; //* num_act_mats_hor_dir_sl; inside the data is broadcast int num_addr_b_row_dec = _log2(num_r_subarray); num_addr_b_row_dec +=_log2(num_subarrays/num_mats); int number_subbanks = num_mats / num_act_mats_hor_dir; number_subbanks_decode = _log2(number_subbanks);//TODO: add log2(num_subarray_per_bank) to FA/CAM num_rw_ports = g_ip->num_rw_ports; num_rd_ports = g_ip->num_rd_ports; num_wr_ports = g_ip->num_wr_ports; num_se_rd_ports = g_ip->num_se_rd_ports; num_search_ports = g_ip->num_search_ports; number_addr_bits_mat = num_addr_b_row_dec + _log2(deg_bl_muxing) + _log2(deg_sa_mux_l1_non_assoc) + _log2(Ndsam_lev_2); num_di_b_bank_per_port = g_ip->out_w + tagbits;//TODO: out_w or block_sz? num_si_b_bank_per_port = tagbits; num_do_b_bank_per_port = g_ip->out_w + tagbits; num_so_b_bank_per_port = g_ip->out_w; if ((!is_tag) && (g_ip->data_assoc > 1) && (!g_ip->fast_access)) { number_way_select_signals_mat = g_ip->data_assoc; } // add ECC adjustment to all data signals that traverse on H-trees. if (g_ip->add_ecc_b_ == true) { ECC_adjustment(); } is_valid = true; } //DynamicParameter::init_Mem() //{ //} // //DynamicParameter::init_3DMem() //{ //} //*** Calculate number of rows and columns in a subarray bool DynamicParameter::calc_subarr_rc(unsigned int capacity_per_die) { // If it's not an FA tag/data array, Ndwl should be at least two and Ndbl should be // at least two because an array is assumed to have at least one mat. A mat // consists of two rows and two columns of subarrays. if (Ndwl < 2 || Ndbl < 2) { return false; } if ((is_dram) && (!is_tag) && (Ndcm > 1)) { return false; // For a DRAM array, each bitline has its own sense-amp } // if data array, let tagbits = 0 if (is_tag) { if (g_ip->specific_tag) { tagbits = g_ip->tag_w; } else { tagbits = ADDRESS_BITS + EXTRA_TAG_BITS - _log2(capacity_per_die) + _log2(g_ip->tag_assoc*2 - 1); } // tagbits = (((tagbits + 3) >> 2) << 2); //FIXME: NAV: Why are we doing this? num_r_subarray = (int)ceil(capacity_per_die / (g_ip->nbanks * g_ip->block_sz * g_ip->tag_assoc * Ndbl * Nspd)); num_c_subarray = (int)ceil((tagbits * g_ip->tag_assoc * Nspd / Ndwl)); } else { num_r_subarray = (int)ceil(capacity_per_die / (g_ip->nbanks * g_ip->block_sz * g_ip->data_assoc * Ndbl * Nspd)); num_c_subarray = (int)ceil((8 * g_ip->block_sz * g_ip->data_assoc * Nspd / Ndwl)); if(g_ip->is_3d_mem) { double capacity_per_die_double = (double)g_ip->cache_sz / g_ip->num_die_3d; //num_c_subarray = 1 << (int)ceil((double)_log2( 8*capacity_per_die / (g_ip->nbanks * Ndbl * Ndwl) )/2 ) ; //num_r_subarray = 1 << (int)ceil((double)_log2( 8*capacity_per_die / (g_ip->nbanks * Ndbl * Ndwl * num_c_subarray) ) ); num_c_subarray = g_ip->page_sz_bits/Ndwl; num_r_subarray = 1 << (int)floor(_log2((double) g_ip->cache_sz / g_ip->num_die_3d / num_c_subarray / g_ip->nbanks / Ndbl / Ndwl * 1024 * 1024 * 1024) +0.5); if (g_ip->print_detail_debug) { cout << "parameter.cc: capacity_per_die_double = " << capacity_per_die_double << " Gbit"<< endl; cout << "parameter.cc: g_ip->nbanks * Ndbl * Ndwl = " << (g_ip->nbanks * Ndbl * Ndwl) << endl; //cout << "parameter.cc: subarray capacity = " << 8*capacity_per_die / (g_ip->nbanks * Ndbl * Ndwl) << endl; //cout << "parameter.cc: total bit add per subarray = " << _log2( 8*capacity_per_die / (g_ip->nbanks * Ndbl * Ndwl) ) << endl; cout << "parameter.cc: num_r_subarray = " << num_r_subarray << endl; cout << "parameter.cc: num_c_subarray = " << num_c_subarray << endl; } } } if (num_r_subarray < MINSUBARRAYROWS) return false; if (num_r_subarray == 0) return false; if (num_r_subarray > MAXSUBARRAYROWS) return false; if (num_c_subarray < MINSUBARRAYCOLS) return false; if (num_c_subarray > MAXSUBARRAYCOLS) return false; num_subarrays = Ndwl * Ndbl; return true; } DynamicParameter::DynamicParameter( bool is_tag_, int pure_ram_, int pure_cam_, double Nspd_, unsigned int Ndwl_, unsigned int Ndbl_, unsigned int Ndcm_, unsigned int Ndsam_lev_1_, unsigned int Ndsam_lev_2_, Wire_type wt, bool is_main_mem_): is_tag(is_tag_), pure_ram(pure_ram_), pure_cam(pure_cam_), tagbits(0), Nspd(Nspd_), Ndwl(Ndwl_), Ndbl(Ndbl_),Ndcm(Ndcm_), Ndsam_lev_1(Ndsam_lev_1_), Ndsam_lev_2(Ndsam_lev_2_),wtype(wt), number_way_select_signals_mat(0), V_b_sense(0), use_inp_params(0), is_main_mem(is_main_mem_), cell(), is_valid(false) { ram_cell_tech_type = (is_tag) ? g_ip->tag_arr_ram_cell_tech_type : g_ip->data_arr_ram_cell_tech_type; is_dram = ((ram_cell_tech_type == lp_dram) || (ram_cell_tech_type == comm_dram)); unsigned int capacity_per_die = g_ip->cache_sz / NUMBER_STACKED_DIE_LAYERS; // capacity per stacked die layer const InterconnectType & wire_local = g_tp.wire_local; fully_assoc = (g_ip->fully_assoc) ? true : false; if (pure_cam) { init_CAM(); return; } if (fully_assoc) { init_FA(); return; } //*** Calculate number of rows and columns in a subarray // Return if their dimensions do not meet the minimum specs if (!calc_subarr_rc(capacity_per_die)) return; //** Calculate cell dimensions if(is_tag) { cell.h = g_tp.sram.b_h + 2 * wire_local.pitch * (g_ip->num_rw_ports - 1 + g_ip->num_rd_ports + g_ip->num_wr_ports); cell.w = g_tp.sram.b_w + 2 * wire_local.pitch * (g_ip->num_rw_ports - 1 + g_ip->num_wr_ports + (g_ip->num_rd_ports - g_ip->num_se_rd_ports)) + wire_local.pitch * g_ip->num_se_rd_ports; } else { if (is_dram) { cell.h = g_tp.dram.b_h; cell.w = g_tp.dram.b_w; } else { cell.h = g_tp.sram.b_h + 2 * wire_local.pitch * (g_ip->num_wr_ports + g_ip->num_rw_ports - 1 + g_ip->num_rd_ports); cell.w = g_tp.sram.b_w + 2 * wire_local.pitch * (g_ip->num_rw_ports - 1 + (g_ip->num_rd_ports - g_ip->num_se_rd_ports) + g_ip->num_wr_ports) + g_tp.wire_local.pitch * g_ip->num_se_rd_ports; } } double c_b_metal = cell.h * wire_local.C_per_um; double C_bl; if (is_dram) { deg_bl_muxing = 1; if (ram_cell_tech_type == comm_dram) { double Cbitrow_drain_cap = drain_C_(g_tp.dram.cell_a_w, NCH, 1, 0, cell.w, true, true) / 2.0; C_bl = num_r_subarray * (Cbitrow_drain_cap + c_b_metal); //C_bl = num_r_subarray * c_b_metal; V_b_sense = (g_tp.dram_cell_Vdd/2) * g_tp.dram_cell_C / (g_tp.dram_cell_C + C_bl); if (V_b_sense < VBITSENSEMIN && !(g_ip->is_3d_mem && g_ip->force_cache_config) ) { return; } dram_refresh_period = 64e-3; } else { double Cbitrow_drain_cap = drain_C_(g_tp.dram.cell_a_w, NCH, 1, 0, cell.w, true, true) / 2.0; C_bl = num_r_subarray * (Cbitrow_drain_cap + c_b_metal); V_b_sense = (g_tp.dram_cell_Vdd/2) * g_tp.dram_cell_C /(g_tp.dram_cell_C + C_bl); if (V_b_sense < VBITSENSEMIN) { return; //Sense amp input signal is smaller that minimum allowable sense amp input signal } V_b_sense = VBITSENSEMIN; // in any case, we fix sense amp input signal to a constant value //v_storage_worst = g_tp.dram_cell_Vdd / 2 - VBITSENSEMIN * (g_tp.dram_cell_C + C_bl) / g_tp.dram_cell_C; //dram_refresh_period = 1.1 * g_tp.dram_cell_C * v_storage_worst / g_tp.dram_cell_I_off_worst_case_len_temp; dram_refresh_period = 0.9 * g_tp.dram_cell_C * VDD_STORAGE_LOSS_FRACTION_WORST * g_tp.dram_cell_Vdd / g_tp.dram_cell_I_off_worst_case_len_temp; } } else { //SRAM V_b_sense = (0.05 * g_tp.sram_cell.Vdd > VBITSENSEMIN) ? 0.05 * g_tp.sram_cell.Vdd : VBITSENSEMIN; deg_bl_muxing = Ndcm; // "/ 2.0" below is due to the fact that two adjacent access transistors share drain // contacts in a physical layout double Cbitrow_drain_cap = drain_C_(g_tp.sram.cell_a_w, NCH, 1, 0, cell.w, false, true) / 2.0; C_bl = num_r_subarray * (Cbitrow_drain_cap + c_b_metal); dram_refresh_period = 0; } // do/di: data in/out, for fully associative they are the data width for normal read and write // so/si: search data in/out, for fully associative they are the data width for the search ops // for CAM, si=di, but so = matching address. do = data out = di (for normal read/write) // so/si needs broadcase while do/di do not num_mats_h_dir = MAX(Ndwl / 2, 1); num_mats_v_dir = MAX(Ndbl / 2, 1); num_mats = num_mats_h_dir * num_mats_v_dir; num_do_b_mat = MAX((num_subarrays/num_mats) * num_c_subarray / (deg_bl_muxing * Ndsam_lev_1 * Ndsam_lev_2), 1); if (!(fully_assoc|| pure_cam) && (num_do_b_mat < (num_subarrays/num_mats))) { return; } int deg_sa_mux_l1_non_assoc; //TODO:the i/o for subbank is not necessary and should be removed. if (!is_tag) { if (is_main_mem == true) { num_do_b_subbank = g_ip->int_prefetch_w * g_ip->out_w; //CACTI3DD DRAM page size if(g_ip->is_3d_mem) num_do_b_subbank = g_ip->page_sz_bits; deg_sa_mux_l1_non_assoc = Ndsam_lev_1; } else { if (g_ip->fast_access == true) { num_do_b_subbank = g_ip->out_w * g_ip->data_assoc; deg_sa_mux_l1_non_assoc = Ndsam_lev_1; } else { num_do_b_subbank = g_ip->out_w; deg_sa_mux_l1_non_assoc = Ndsam_lev_1 / g_ip->data_assoc; if (deg_sa_mux_l1_non_assoc < 1) { return; } } } } else { num_do_b_subbank = tagbits * g_ip->tag_assoc; if (num_do_b_mat < tagbits) { return; } deg_sa_mux_l1_non_assoc = Ndsam_lev_1; //num_do_b_mat = g_ip->tag_assoc / num_mats_h_dir; } deg_senseamp_muxing_non_associativity = deg_sa_mux_l1_non_assoc; num_act_mats_hor_dir = num_do_b_subbank / num_do_b_mat; if (g_ip->is_3d_mem && num_act_mats_hor_dir == 0) num_act_mats_hor_dir = 1; if (num_act_mats_hor_dir == 0) { return; } //compute num_do_mat for tag if (is_tag) { if (!(fully_assoc || pure_cam)) { num_do_b_mat = g_ip->tag_assoc / num_act_mats_hor_dir; num_do_b_subbank = num_act_mats_hor_dir * num_do_b_mat; } } if ((g_ip->is_cache == false && is_main_mem == true) || (PAGE_MODE == 1 && is_dram)) { if (num_act_mats_hor_dir * num_do_b_mat * Ndsam_lev_1 * Ndsam_lev_2 != (int)g_ip->page_sz_bits) { return; } } // if (is_tag == false && g_ip->is_cache == true && !fully_assoc && !pure_cam && //TODO: TODO burst transfer should also apply to RAM arrays if (is_tag == false && g_ip->is_main_mem == true && num_act_mats_hor_dir*num_do_b_mat*Ndsam_lev_1*Ndsam_lev_2 < ((int) g_ip->out_w * (int) g_ip->burst_len * (int) g_ip->data_assoc)) { return; } if (num_act_mats_hor_dir > num_mats_h_dir) { return; } //compute di for mat subbank and bank if(!is_tag) { if(g_ip->fast_access == true) { num_di_b_mat = num_do_b_mat / g_ip->data_assoc; } else { num_di_b_mat = num_do_b_mat; } } else { num_di_b_mat = tagbits; } num_di_b_subbank = num_di_b_mat * num_act_mats_hor_dir;//normal cache or normal r/w for FA num_si_b_subbank = num_si_b_mat; //* num_act_mats_hor_dir_sl; inside the data is broadcast int num_addr_b_row_dec = _log2(num_r_subarray); if ((fully_assoc ||pure_cam)) num_addr_b_row_dec +=_log2(num_subarrays/num_mats); int number_subbanks = num_mats / num_act_mats_hor_dir; number_subbanks_decode = _log2(number_subbanks);//TODO: add log2(num_subarray_per_bank) to FA/CAM num_rw_ports = g_ip->num_rw_ports; num_rd_ports = g_ip->num_rd_ports; num_wr_ports = g_ip->num_wr_ports; num_se_rd_ports = g_ip->num_se_rd_ports; num_search_ports = g_ip->num_search_ports; if (is_dram && is_main_mem) { number_addr_bits_mat = MAX((unsigned int) num_addr_b_row_dec, _log2(deg_bl_muxing) + _log2(deg_sa_mux_l1_non_assoc) + _log2(Ndsam_lev_2)); if (g_ip->print_detail_debug) { cout << "parameter.cc: number_addr_bits_mat = " << num_addr_b_row_dec << endl; cout << "parameter.cc: num_addr_b_row_dec = " << num_addr_b_row_dec << endl; cout << "parameter.cc: num_addr_b_mux_sel = " << _log2(deg_bl_muxing) + _log2(deg_sa_mux_l1_non_assoc) + _log2(Ndsam_lev_2) << endl; } } else { number_addr_bits_mat = num_addr_b_row_dec + _log2(deg_bl_muxing) + _log2(deg_sa_mux_l1_non_assoc) + _log2(Ndsam_lev_2); } if (is_tag) { num_di_b_bank_per_port = tagbits; num_do_b_bank_per_port = g_ip->data_assoc; } else { num_di_b_bank_per_port = g_ip->out_w + g_ip->data_assoc; num_do_b_bank_per_port = g_ip->out_w; } if ((!is_tag) && (g_ip->data_assoc > 1) && (!g_ip->fast_access)) { number_way_select_signals_mat = g_ip->data_assoc; } // add ECC adjustment to all data signals that traverse on H-trees. if (g_ip->add_ecc_b_ == true) ECC_adjustment(); is_valid = true; } void DynamicParameter::ECC_adjustment() { num_do_b_mat += (int) (ceil(num_do_b_mat / num_bits_per_ecc_b_)); num_di_b_mat += (int) (ceil(num_di_b_mat / num_bits_per_ecc_b_)); num_di_b_subbank += (int) (ceil(num_di_b_subbank / num_bits_per_ecc_b_)); num_do_b_subbank += (int) (ceil(num_do_b_subbank / num_bits_per_ecc_b_)); num_di_b_bank_per_port += (int) (ceil(num_di_b_bank_per_port / num_bits_per_ecc_b_)); num_do_b_bank_per_port += (int) (ceil(num_do_b_bank_per_port / num_bits_per_ecc_b_)); num_so_b_mat += (int) (ceil(num_so_b_mat / num_bits_per_ecc_b_)); num_si_b_mat += (int) (ceil(num_si_b_mat / num_bits_per_ecc_b_)); num_si_b_subbank += (int) (ceil(num_si_b_subbank / num_bits_per_ecc_b_)); num_so_b_subbank += (int) (ceil(num_so_b_subbank / num_bits_per_ecc_b_)); num_si_b_bank_per_port += (int) (ceil(num_si_b_bank_per_port / num_bits_per_ecc_b_)); num_so_b_bank_per_port += (int) (ceil(num_so_b_bank_per_port / num_bits_per_ecc_b_)); } //DynamicParameter::DynamicParameter( // bool is_tag_, // int pure_ram_, // int pure_cam_, // double Nspd_, // unsigned int Ndwl_, // unsigned int Ndbl_, // unsigned int Ndcm_, // unsigned int Ndsam_lev_1_, // unsigned int Ndsam_lev_2_, // Wire_type wt, // bool is_main_mem_): // is_tag(is_tag_), pure_ram(pure_ram_), pure_cam(pure_cam_), tagbits(0), Nspd(Nspd_), Ndwl(Ndwl_), Ndbl(Ndbl_),Ndcm(Ndcm_), // Ndsam_lev_1(Ndsam_lev_1_), Ndsam_lev_2(Ndsam_lev_2_),wtype(wt), // number_way_select_signals_mat(0), V_b_sense(0), use_inp_params(0), // is_main_mem(is_main_mem_), cell(), is_valid(false) // ram_cell_tech_type = (is_tag) ? g_ip->tag_arr_ram_cell_tech_type : g_ip->data_arr_ram_cell_tech_type; // is_dram = ((ram_cell_tech_type == lp_dram) || (ram_cell_tech_type == comm_dram)); // // unsigned int capacity_per_die = g_ip->cache_sz / NUMBER_STACKED_DIE_LAYERS; // capacity per stacked die layer // const /*TechnologyParameter::*/InterconnectType & wire_local = g_tp.wire_local; // fully_assoc = (g_ip->fully_assoc) ? true : false; // // if (fully_assoc || pure_cam) // { // fully-assocative cache -- ref: CACTi 2.0 report // if (Ndwl != 1 || //Ndwl is fixed to 1 for FA // Ndcm != 1 || //Ndcm is fixed to 1 for FA // Nspd < 1 || Nspd > 1 || //Nspd is fixed to 1 for FA // Ndsam_lev_1 != 1 || //Ndsam_lev_1 is fixed to one // Ndsam_lev_2 != 1 || //Ndsam_lev_2 is fixed to one // Ndbl < 2) // { // return; // } // } // // if ((is_dram) && (!is_tag) && (Ndcm > 1)) // { // return; // For a DRAM array, each bitline has its own sense-amp // } // // // If it's not an FA tag/data array, Ndwl should be at least two and Ndbl should be // // at least two because an array is assumed to have at least one mat. And a mat // // is formed out of two horizontal subarrays and two vertical subarrays // if (fully_assoc == false && (Ndwl < 1 || Ndbl < 1)) // { // return; // } // // //***********compute row, col of an subarray // if (!(fully_assoc || pure_cam))//Not fully_asso nor cam // { // // if data array, let tagbits = 0 // if (is_tag) // { // if (g_ip->specific_tag) // { // tagbits = g_ip->tag_w; // } // else // { // tagbits = ADDRESS_BITS + EXTRA_TAG_BITS - _log2(capacity_per_die) + // _log2(g_ip->tag_assoc*2 - 1) - _log2(g_ip->nbanks); // // } // tagbits = (((tagbits + 3) >> 2) << 2); // // num_r_subarray = (int)ceil(capacity_per_die / (g_ip->nbanks * // g_ip->block_sz * g_ip->tag_assoc * Ndbl * Nspd));// + EPSILON); // num_c_subarray = (int)ceil((tagbits * g_ip->tag_assoc * Nspd / Ndwl));// + EPSILON); // //burst_length = 1; // } // else // { // num_r_subarray = (int)ceil(capacity_per_die / (g_ip->nbanks * // g_ip->block_sz * g_ip->data_assoc * Ndbl * Nspd));// + EPSILON); // num_c_subarray = (int)ceil((8 * g_ip->block_sz * g_ip->data_assoc * Nspd / Ndwl));// + EPSILON); + EPSILON); // // burst_length = g_ip->block_sz * 8 / g_ip->out_w; // if(g_ip->is_3d_mem) // { // double capacity_per_die_double = (double)g_ip->cache_sz / g_ip->num_die_3d; // //num_c_subarray = 1 << (int)ceil((double)_log2( 8*capacity_per_die / (g_ip->nbanks * Ndbl * Ndwl) )/2 ) ; // //num_r_subarray = 1 << (int)ceil((double)_log2( 8*capacity_per_die / (g_ip->nbanks * Ndbl * Ndwl * num_c_subarray) ) ); // num_c_subarray = g_ip->page_sz_bits/Ndwl; // num_r_subarray = 1 << (int)floor(_log2((double) g_ip->cache_sz / g_ip->num_die_3d // / num_c_subarray / g_ip->nbanks / Ndbl / Ndwl * 1024 * 1024 * 1024) +0.5); // if (g_ip->print_detail_debug) // { // cout << "parameter.cc: capacity_per_die_double = " << capacity_per_die_double << " Gbit"<< endl; // cout << "parameter.cc: g_ip->nbanks * Ndbl * Ndwl = " << (g_ip->nbanks * Ndbl * Ndwl) << endl; // //cout << "parameter.cc: subarray capacity = " << 8*capacity_per_die / (g_ip->nbanks * Ndbl * Ndwl) << endl; // //cout << "parameter.cc: total bit add per subarray = " << _log2( 8*capacity_per_die / (g_ip->nbanks * Ndbl * Ndwl) ) << endl; // cout << "parameter.cc: num_r_subarray = " << num_r_subarray << endl; // cout << "parameter.cc: num_c_subarray = " << num_c_subarray << endl; // } // // } // } // // if (num_r_subarray < MINSUBARRAYROWS) return; // if (num_r_subarray == 0) return; // if (num_r_subarray > MAXSUBARRAYROWS) return; // if (num_c_subarray < MINSUBARRAYCOLS) return; // if (num_c_subarray > MAXSUBARRAYCOLS) return; // // } // // else // {//either fully-asso or cam // if (pure_cam) // { // if (g_ip->specific_tag) // { // tagbits = int(ceil(g_ip->tag_w/8.0)*8); // } // else // { // tagbits = int(ceil((ADDRESS_BITS + EXTRA_TAG_BITS)/8.0)*8); //// cout<<"Pure CAM needs tag width to be specified"<> 2) << 2); // // tag_num_r_subarray = (int)ceil(capacity_per_die / (g_ip->nbanks*tagbits/8.0 * Ndbl));//TODO: error check input of tagbits and blocksize //TODO: for pure CAM, g_ip->block should be number of entries. // //tag_num_c_subarray = (int)(tagbits + EPSILON); // tag_num_c_subarray = tagbits; // if (tag_num_r_subarray == 0) return; // if (tag_num_r_subarray > MAXSUBARRAYROWS) return; // if (tag_num_c_subarray < MINSUBARRAYCOLS) return; // if (tag_num_c_subarray > MAXSUBARRAYCOLS) return; // num_r_subarray = tag_num_r_subarray; // } // else //fully associative // { // if (g_ip->specific_tag) // { // tagbits = g_ip->tag_w; // } // else // { // tagbits = ADDRESS_BITS + EXTRA_TAG_BITS - _log2(g_ip->block_sz);//TODO: should be the page_offset=log2(page size), but this info is not avail with CACTI, for McPAT this is no problem. // } // tagbits = (((tagbits + 3) >> 2) << 2); // // tag_num_r_subarray = (int)(capacity_per_die / (g_ip->nbanks*g_ip->block_sz * Ndbl)); // tag_num_c_subarray = (int)ceil((tagbits * Nspd / Ndwl));// + EPSILON); // if (tag_num_r_subarray == 0) return; // if (tag_num_r_subarray > MAXSUBARRAYROWS) return; // if (tag_num_c_subarray < MINSUBARRAYCOLS) return; // if (tag_num_c_subarray > MAXSUBARRAYCOLS) return; // // data_num_r_subarray = tag_num_r_subarray; // data_num_c_subarray = 8 * g_ip->block_sz; // if (data_num_r_subarray == 0) return; // if (data_num_r_subarray > MAXSUBARRAYROWS) return; // if (data_num_c_subarray < MINSUBARRAYCOLS) return; // if (data_num_c_subarray > MAXSUBARRAYCOLS) return; // num_r_subarray = tag_num_r_subarray; // } // } // // num_subarrays = Ndwl * Ndbl; // //****************end of computation of row, col of an subarray // // // calculate wire parameters // if (fully_assoc || pure_cam) // { // cam_cell.h = g_tp.cam.b_h + 2 * wire_local.pitch * (g_ip->num_rw_ports-1 + g_ip->num_rd_ports + g_ip->num_wr_ports) // + 2 * wire_local.pitch*(g_ip->num_search_ports-1) + wire_local.pitch * g_ip->num_se_rd_ports; // cam_cell.w = g_tp.cam.b_w + 2 * wire_local.pitch * (g_ip->num_rw_ports-1 + g_ip->num_rd_ports + g_ip->num_wr_ports) // + 2 * wire_local.pitch*(g_ip->num_search_ports-1) + wire_local.pitch * g_ip->num_se_rd_ports; // // cell.h = g_tp.sram.b_h + 2 * wire_local.pitch * (g_ip->num_wr_ports +g_ip->num_rw_ports-1 + g_ip->num_rd_ports) // + 2 * wire_local.pitch*(g_ip->num_search_ports-1); // cell.w = g_tp.sram.b_w + 2 * wire_local.pitch * (g_ip->num_rw_ports -1 + (g_ip->num_rd_ports - g_ip->num_se_rd_ports) // + g_ip->num_wr_ports) + g_tp.wire_local.pitch * g_ip->num_se_rd_ports + 2 * wire_local.pitch*(g_ip->num_search_ports-1); // } // else // { // if(is_tag) // { // cell.h = g_tp.sram.b_h + 2 * wire_local.pitch * (g_ip->num_rw_ports - 1 + g_ip->num_rd_ports + // g_ip->num_wr_ports); // cell.w = g_tp.sram.b_w + 2 * wire_local.pitch * (g_ip->num_rw_ports - 1 + g_ip->num_wr_ports + // (g_ip->num_rd_ports - g_ip->num_se_rd_ports)) + // wire_local.pitch * g_ip->num_se_rd_ports; // } // else // { // if (is_dram) // { // cell.h = g_tp.dram.b_h; // cell.w = g_tp.dram.b_w; // } // else // { // cell.h = g_tp.sram.b_h + 2 * wire_local.pitch * (g_ip->num_wr_ports + // g_ip->num_rw_ports - 1 + g_ip->num_rd_ports); // cell.w = g_tp.sram.b_w + 2 * wire_local.pitch * (g_ip->num_rw_ports - 1 + // (g_ip->num_rd_ports - g_ip->num_se_rd_ports) + // g_ip->num_wr_ports) + g_tp.wire_local.pitch * g_ip->num_se_rd_ports; // } // } // } // // double c_b_metal = cell.h * wire_local.C_per_um; // double C_bl; // // if (!(fully_assoc || pure_cam)) // { // if (is_dram) // { // deg_bl_muxing = 1; // if (ram_cell_tech_type == comm_dram) // { // double Cbitrow_drain_cap = drain_C_(g_tp.dram.cell_a_w, NCH, 1, 0, cell.w, true, true) / 2.0; // C_bl = num_r_subarray * (Cbitrow_drain_cap + c_b_metal); // //C_bl = num_r_subarray * c_b_metal; // V_b_sense = (g_tp.dram_cell_Vdd/2) * g_tp.dram_cell_C / (g_tp.dram_cell_C + C_bl); // if (V_b_sense < VBITSENSEMIN && !(g_ip->is_3d_mem && g_ip->force_cache_config) ) // { // return; // } // // /* // C_bl = num_r_subarray * c_b_metal; // V_b_sense = (g_tp.dram_cell_Vdd/2) * g_tp.dram_cell_C / (g_tp.dram_cell_C + C_bl); // if (V_b_sense < VBITSENSEMIN) // { // return; // } // V_b_sense = VBITSENSEMIN; // in any case, we fix sense amp input signal to a constant value // */ // dram_refresh_period = 64e-3; // // } // else // { // double Cbitrow_drain_cap = drain_C_(g_tp.dram.cell_a_w, NCH, 1, 0, cell.w, true, true) / 2.0; // C_bl = num_r_subarray * (Cbitrow_drain_cap + c_b_metal); // V_b_sense = (g_tp.dram_cell_Vdd/2) * g_tp.dram_cell_C /(g_tp.dram_cell_C + C_bl); // // if (V_b_sense < VBITSENSEMIN) // { // return; //Sense amp input signal is smaller that minimum allowable sense amp input signal // } // V_b_sense = VBITSENSEMIN; // in any case, we fix sense amp input signal to a constant value // //v_storage_worst = g_tp.dram_cell_Vdd / 2 - VBITSENSEMIN * (g_tp.dram_cell_C + C_bl) / g_tp.dram_cell_C; // //dram_refresh_period = 1.1 * g_tp.dram_cell_C * v_storage_worst / g_tp.dram_cell_I_off_worst_case_len_temp; // dram_refresh_period = 0.9 * g_tp.dram_cell_C * VDD_STORAGE_LOSS_FRACTION_WORST * g_tp.dram_cell_Vdd / g_tp.dram_cell_I_off_worst_case_len_temp; // } // } // else // { //SRAM // V_b_sense = (0.05 * g_tp.sram_cell.Vdd > VBITSENSEMIN) ? 0.05 * g_tp.sram_cell.Vdd : VBITSENSEMIN; // deg_bl_muxing = Ndcm; // // "/ 2.0" below is due to the fact that two adjacent access transistors share drain // // contacts in a physical layout // double Cbitrow_drain_cap = drain_C_(g_tp.sram.cell_a_w, NCH, 1, 0, cell.w, false, true) / 2.0; // C_bl = num_r_subarray * (Cbitrow_drain_cap + c_b_metal); // dram_refresh_period = 0; // } // } // else // { // c_b_metal = cam_cell.h * wire_local.C_per_um;//IBM and SUN design, SRAM array uses dummy cells to fill the blank space due to mismatch on CAM-RAM // V_b_sense = (0.05 * g_tp.sram_cell.Vdd > VBITSENSEMIN) ? 0.05 * g_tp.sram_cell.Vdd : VBITSENSEMIN; // deg_bl_muxing = 1;//FA fix as 1 // // "/ 2.0" below is due to the fact that two adjacent access transistors share drain // // contacts in a physical layout // double Cbitrow_drain_cap = drain_C_(g_tp.cam.cell_a_w, NCH, 1, 0, cam_cell.w, false, true) / 2.0;//TODO: comment out these two lines // C_bl = num_r_subarray * (Cbitrow_drain_cap + c_b_metal); // dram_refresh_period = 0; // } // // // // do/di: data in/out, for fully associative they are the data width for normal read and write // // so/si: search data in/out, for fully associative they are the data width for the search ops // // for CAM, si=di, but so = matching address. do = data out = di (for normal read/write) // // so/si needs broadcase while do/di do not // // if (fully_assoc || pure_cam) // { // switch (Ndbl) { // case (0): // cout << " Invalid Ndbl \n"<int_prefetch_w * g_ip->out_w; // //CACTI3DD DRAM page size // if(g_ip->is_3d_mem) // num_do_b_subbank = g_ip->page_sz_bits; // deg_sa_mux_l1_non_assoc = Ndsam_lev_1; // } // else // { // if (g_ip->fast_access == true) // { // num_do_b_subbank = g_ip->out_w * g_ip->data_assoc; // deg_sa_mux_l1_non_assoc = Ndsam_lev_1; // } // else // { // // num_do_b_subbank = g_ip->out_w; // deg_sa_mux_l1_non_assoc = Ndsam_lev_1 / g_ip->data_assoc; // if (deg_sa_mux_l1_non_assoc < 1) // { // return; // } // // } // } // } // else // { // num_do_b_subbank = tagbits * g_ip->tag_assoc; // if (num_do_b_mat < tagbits) // { // return; // } // deg_sa_mux_l1_non_assoc = Ndsam_lev_1; // //num_do_b_mat = g_ip->tag_assoc / num_mats_h_dir; // } // } // else // { // if (fully_assoc) // { // num_so_b_subbank = 8 * g_ip->block_sz;//TODO:internal perfetch should be considered also for fa // num_do_b_subbank = num_so_b_subbank + tag_num_c_subarray; // } // else // { // num_so_b_subbank = int(ceil(log2(num_r_subarray)) + ceil(log2(num_subarrays)));//the address contains the matched data // num_do_b_subbank = tag_num_c_subarray; // } // // deg_sa_mux_l1_non_assoc = 1; // } // // deg_senseamp_muxing_non_associativity = deg_sa_mux_l1_non_assoc; // // if (fully_assoc || pure_cam) // { // num_act_mats_hor_dir = 1; // num_act_mats_hor_dir_sl = num_mats_h_dir;//TODO: this is unnecessary, since search op, num_mats is used // } // else // { // num_act_mats_hor_dir = num_do_b_subbank / num_do_b_mat; // if (g_ip->is_3d_mem && num_act_mats_hor_dir == 0) // num_act_mats_hor_dir = 1; // if (num_act_mats_hor_dir == 0) // { // return; // } // } // // //compute num_do_mat for tag // if (is_tag) // { // if (!(fully_assoc || pure_cam)) // { // num_do_b_mat = g_ip->tag_assoc / num_act_mats_hor_dir; // num_do_b_subbank = num_act_mats_hor_dir * num_do_b_mat; // } // } // // if ((g_ip->is_cache == false && is_main_mem == true) || (PAGE_MODE == 1 && is_dram)) // { // if (num_act_mats_hor_dir * num_do_b_mat * Ndsam_lev_1 * Ndsam_lev_2 != (int)g_ip->page_sz_bits) // { // return; // } // } // //// if (is_tag == false && g_ip->is_cache == true && !fully_assoc && !pure_cam && //TODO: TODO burst transfer should also apply to RAM arrays // if (is_tag == false && g_ip->is_main_mem == true && // num_act_mats_hor_dir*num_do_b_mat*Ndsam_lev_1*Ndsam_lev_2 < ((int) g_ip->out_w * (int) g_ip->burst_len * (int) g_ip->data_assoc)) // { // return; // } // // if (num_act_mats_hor_dir > num_mats_h_dir) // { // return; // } // // // //compute di for mat subbank and bank // if (!(fully_assoc ||pure_cam)) // { // if(!is_tag) // { // if(g_ip->fast_access == true) // { // num_di_b_mat = num_do_b_mat / g_ip->data_assoc; // } // else // { // num_di_b_mat = num_do_b_mat; // } // } // else // { // num_di_b_mat = tagbits; // } // } // else // { // if (fully_assoc) // { // num_di_b_mat = num_do_b_mat; // //*num_subarrays/num_mats; bits per mat of CAM/FA is as same as cache, // //but inside the mat wire tracks need to be reserved for search data bus // num_si_b_mat = tagbits; // } // else // { // num_di_b_mat = tagbits; // num_si_b_mat = tagbits;//*num_subarrays/num_mats; // } // // } // // num_di_b_subbank = num_di_b_mat * num_act_mats_hor_dir;//normal cache or normal r/w for FA // num_si_b_subbank = num_si_b_mat; //* num_act_mats_hor_dir_sl; inside the data is broadcast // // int num_addr_b_row_dec = _log2(num_r_subarray); // if ((fully_assoc ||pure_cam)) // num_addr_b_row_dec +=_log2(num_subarrays/num_mats); // int number_subbanks = num_mats / num_act_mats_hor_dir; // number_subbanks_decode = _log2(number_subbanks);//TODO: add log2(num_subarray_per_bank) to FA/CAM // // num_rw_ports = g_ip->num_rw_ports; // num_rd_ports = g_ip->num_rd_ports; // num_wr_ports = g_ip->num_wr_ports; // num_se_rd_ports = g_ip->num_se_rd_ports; // num_search_ports = g_ip->num_search_ports; // // if (is_dram && is_main_mem) // { // number_addr_bits_mat = MAX((unsigned int) num_addr_b_row_dec, // _log2(deg_bl_muxing) + _log2(deg_sa_mux_l1_non_assoc) + _log2(Ndsam_lev_2)); // if (g_ip->print_detail_debug) // { // cout << "parameter.cc: number_addr_bits_mat = " << num_addr_b_row_dec << endl; // cout << "parameter.cc: num_addr_b_row_dec = " << num_addr_b_row_dec << endl; // cout << "parameter.cc: num_addr_b_mux_sel = " << _log2(deg_bl_muxing) + _log2(deg_sa_mux_l1_non_assoc) + _log2(Ndsam_lev_2) << endl; // } // } // else // { // number_addr_bits_mat = num_addr_b_row_dec + _log2(deg_bl_muxing) + // _log2(deg_sa_mux_l1_non_assoc) + _log2(Ndsam_lev_2); // } // // if (!(fully_assoc ||pure_cam)) // { // if (is_tag) // { // num_di_b_bank_per_port = tagbits; // num_do_b_bank_per_port = g_ip->data_assoc; // } // else // { // num_di_b_bank_per_port = g_ip->out_w + g_ip->data_assoc; // num_do_b_bank_per_port = g_ip->out_w; // } // } // else // { // if (fully_assoc) // { // num_di_b_bank_per_port = g_ip->out_w + tagbits;//TODO: out_w or block_sz? // num_si_b_bank_per_port = tagbits; // num_do_b_bank_per_port = g_ip->out_w + tagbits; // num_so_b_bank_per_port = g_ip->out_w; // } // else // { // num_di_b_bank_per_port = tagbits; // num_si_b_bank_per_port = tagbits; // num_do_b_bank_per_port = tagbits; // num_so_b_bank_per_port = int(ceil(log2(num_r_subarray)) + ceil(log2(num_subarrays))); // } // } // // if ((!is_tag) && (g_ip->data_assoc > 1) && (!g_ip->fast_access)) // { // number_way_select_signals_mat = g_ip->data_assoc; // } // // // add ECC adjustment to all data signals that traverse on H-trees. // if (g_ip->add_ecc_b_ == true) // { // num_do_b_mat += (int) (ceil(num_do_b_mat / num_bits_per_ecc_b_)); // num_di_b_mat += (int) (ceil(num_di_b_mat / num_bits_per_ecc_b_)); // num_di_b_subbank += (int) (ceil(num_di_b_subbank / num_bits_per_ecc_b_)); // num_do_b_subbank += (int) (ceil(num_do_b_subbank / num_bits_per_ecc_b_)); // num_di_b_bank_per_port += (int) (ceil(num_di_b_bank_per_port / num_bits_per_ecc_b_)); // num_do_b_bank_per_port += (int) (ceil(num_do_b_bank_per_port / num_bits_per_ecc_b_)); // // num_so_b_mat += (int) (ceil(num_so_b_mat / num_bits_per_ecc_b_)); // num_si_b_mat += (int) (ceil(num_si_b_mat / num_bits_per_ecc_b_)); // num_si_b_subbank += (int) (ceil(num_si_b_subbank / num_bits_per_ecc_b_)); // num_so_b_subbank += (int) (ceil(num_so_b_subbank / num_bits_per_ecc_b_)); // num_si_b_bank_per_port += (int) (ceil(num_si_b_bank_per_port / num_bits_per_ecc_b_)); // num_so_b_bank_per_port += (int) (ceil(num_so_b_bank_per_port / num_bits_per_ecc_b_)); // } // // is_valid = true; //}