int main(int argc, char **argv) { u_int n_port, n_row, flit_width; double bitline_len, wordline_len, xb_in_len, xb_out_len; double Atotal = 0; n_port = atoi(argv[1]); n_row = PARM(in_buf_set); flit_width = PARM(flit_width); /* 1 read port and 1 write port */ bitline_len = n_row * (RegCellHeight + 2 * WordlineSpacing); wordline_len = flit_width * (RegCellWidth + 2 * 2 * BitlineSpacing); /* input buffer area */ Atotal += n_port * (bitline_len * wordline_len); /* only have a crossbar if more than one port */ if (n_port > 1) { xb_in_len = n_port * flit_width * CrsbarCellWidth; xb_out_len = n_port * flit_width * CrsbarCellHeight; /* crossbar area */ Atotal += xb_in_len * xb_out_len; } printf("%g", Atotal); exit(0); }
/* Layout concerns drive any restrictions you might add here */ int SIM_organizational_parameters_valid(int rows, int cols, int Ndwl, int Ndbl, int Nspd, int Ntwl, int Ntbl, int Ntspd) { /* don't want more than 8 subarrays for each of data/tag */ if (Ndwl*Ndbl>PARM(MAXSUBARRAYS)) return(0); if (Ntwl*Ntbl>PARM(MAXSUBARRAYS)) return(0); /* add more constraints here as necessary */ return(1); }
/* Sel inverter delay (part of the output driver) see section 6.8 */ double SIM_selb_delay_tag_path(double inrisetime, double *outrisetime) { double Ceq,Tst1,tf; Ceq = SIM_draincap(Woutdrvseln,NCH,1)+SIM_draincap(Woutdrvselp,PCH,1)+ SIM_gatecap(Woutdrvnandn+Woutdrvnandp,10.0); tf = Ceq*SIM_transreson(Woutdrvseln,NCH,1); Tst1 = SIM_horowitz(inrisetime,tf,PARM(VTHOUTDRINV),PARM(VTHOUTDRNAND),RISE); *outrisetime = Tst1/(1.0-PARM(VTHOUTDRNAND)); return(Tst1); }
void getOptBuffering(int *k , double *h , double Length) { if (PARM(buffering_scheme) == MIN_DELAY) { if (PARM(shielding)) { double r = computeResistance(Length); double c_g = 2*computeGroundCapacitance(Length); double c_c = 2*computeCouplingCapacitance(Length); *k = (int) sqrt(((0.4*r*c_g)+(0.57*r*c_c))/ (0.7*BufferDriveResistance*BufferInputCapacitance)); //k is the number of buffers to be inserted *h = sqrt(((0.7*BufferDriveResistance*c_g)+ (1.4*1.5*BufferDriveResistance*c_c))/(0.7*r*BufferInputCapacitance)); //the size of the buffers to be inserted } else { double r = computeResistance(Length); double c_g = 2*computeGroundCapacitance(Length); double c_c = 2*computeCouplingCapacitance(Length); *k = (int) sqrt(((0.4*r*c_g)+(1.51*r*c_c))/ (0.7*BufferDriveResistance*BufferInputCapacitance)); *h = sqrt(((0.7*BufferDriveResistance*c_g)+ (1.4*2.2*BufferDriveResistance*c_c))/(0.7*r*BufferInputCapacitance)); } } else if (PARM(buffering_scheme)== STAGGERED) { double r = computeResistance(Length); double c_g = 2*computeGroundCapacitance(Length); double c_c = 2*computeCouplingCapacitance(Length); *k = (int) sqrt(((0.4*r*c_g)+(0.57*r*c_c))/ (0.7*BufferDriveResistance*BufferInputCapacitance)); *h = sqrt(((0.7*BufferDriveResistance*c_g)+ (1.4*1.5*BufferDriveResistance*c_c))/(0.7*r*BufferInputCapacitance)); } else { fprintf(stderr, "ERROR, Specified buffering scheme is not supported.\n"); exit(1); } }
/* Tag array wordline delay (see section 6.3 of tech report) */ double SIM_wordline_tag_delay(int C, int A, int Ntspd, int Ntwl, double inrisetime, double *outrisetime) { double tf,m,a,b,c; double Cline,Rline,Ceq,nextinputtime; int tagbits; double Tworddrivedel,Twordchargedel; /* number of tag bits */ tagbits = PARM(ADDRESS_BITS)+2-(int)logtwo((double)C)+(int)logtwo((double)A); /* first stage */ Ceq = SIM_draincap(Wdecinvn,NCH,1) + SIM_draincap(Wdecinvp,PCH,1) + SIM_gatecap(Wdecinvn+Wdecinvp,20.0); tf = SIM_transreson(Wdecinvn,NCH,1)*Ceq; Tworddrivedel = SIM_horowitz(inrisetime,tf,PARM(VSINV),PARM(VSINV),RISE); nextinputtime = Tworddrivedel/(1.0-PARM(VSINV)); /* second stage */ Cline = (SIM_gatecappass(Wmemcella,(BitWidth-2*Wmemcella)/2.0)+ SIM_gatecappass(Wmemcella,(BitWidth-2*Wmemcella)/2.0)+ Cwordmetal)*tagbits*A*Ntspd/Ntwl+ SIM_draincap(Wdecinvn,NCH,1) + SIM_draincap(Wdecinvp,PCH,1); Rline = Rwordmetal*tagbits*A*Ntspd/(2*Ntwl); tf = (SIM_transreson(Wdecinvp,PCH,1)+Rline)*Cline; Twordchargedel = SIM_horowitz(nextinputtime,tf,PARM(VSINV),PARM(VSINV),FALL); *outrisetime = Twordchargedel/PARM(VSINV); return(Tworddrivedel+Twordchargedel); }
// Computes the coupling capacitance considering cross-talk // The parameter "Length" has units of "m" double computeCouplingCapacitance(double Length) { double c_c; int widthSpacingConfig = PARM(width_spacing); if (widthSpacingConfig == SWIDTH_SSPACE) { double A = 1.14*(WireMetalThickness/WireMinSpacing) * exp(-4*WireMinSpacing/(WireMinSpacing + 8.01*WireDielectricThickness)); double B = 2.37*pow((WireMinWidth/(WireMinWidth + 0.31*WireMinSpacing)), 0.28); double C1 = pow((WireDielectricThickness/(WireDielectricThickness + 8.96*WireMinSpacing)), 0.76) * exp(-2*WireMinSpacing/(WireMinSpacing + 6*WireDielectricThickness)); c_c = WireDielectricConstant*8.85e-12*(A + (B*C1))*Length; } else if (widthSpacingConfig == SWIDTH_DSPACE) { double minSpacingNew = 2*WireMinSpacing + WireMinWidth; double A = 1.14*(WireMetalThickness/minSpacingNew) * exp(-4*minSpacingNew/(minSpacingNew + 8.01*WireDielectricThickness)); double B = 2.37*pow((WireMinWidth/(WireMinWidth + 0.31*minSpacingNew)), 0.28); double C1 = pow((WireDielectricThickness/(WireDielectricThickness + 8.96*minSpacingNew)), 0.76) * exp(-2*minSpacingNew/(minSpacingNew + 6*WireDielectricThickness)); c_c = WireDielectricConstant*8.85e-12*(A + (B*C1))*Length; } else if (widthSpacingConfig == DWIDTH_SSPACE) { double minWidthNew = 2*WireMinWidth; double A = 1.14*(WireMetalThickness/WireMinSpacing) * exp(-4*WireMinSpacing/(WireMinSpacing + 8.01*WireDielectricThickness)); double B = 2.37*pow((2*minWidthNew/(2*minWidthNew + 0.31*WireMinSpacing)), 0.28); double C1 = pow((WireDielectricThickness/(WireDielectricThickness + 8.96*WireMinSpacing)), 0.76) * exp(-2*WireMinSpacing/(WireMinSpacing + 6*WireDielectricThickness)); c_c = WireDielectricConstant*8.85e-12*(A + (B*C1))*Length; } else if (widthSpacingConfig == DWIDTH_DSPACE) { double minWidthNew = 2*WireMinWidth; double minSpacingNew = 2*WireMinSpacing; double A = 1.14*(WireMetalThickness/minSpacingNew) * exp(-4*minSpacingNew/(minSpacingNew + 8.01*WireDielectricThickness)); double B = 2.37*pow((minWidthNew/(minWidthNew + 0.31*minSpacingNew)), 0.28); double C1 = pow((WireDielectricThickness/(WireDielectricThickness + 8.96*minSpacingNew)), 0.76) * exp(-2*minSpacingNew/(minSpacingNew + 6*WireDielectricThickness)); c_c = WireDielectricConstant*8.85e-12*(A + (B*C1))*Length; } else { fprintf(stderr, "ERROR, Specified width spacing configuration is not supported.\n"); exit(1); } return c_c; // Coupling capacitance is in "F" }
static double SIM_resultbus_cap(void) { double Cline, reg_height; /* compute size of result bus tags */ reg_height = PARM(RUU_size) * (RegCellHeight + WordlineSpacing * 3 * PARM(ruu_issue_width)); /* assume num alu's = ialu */ /* FIXME: generate a more detailed result bus network model */ /* WHS: 3200 should go to PARM */ /* WHS: use minimal pitch for buses */ Cline = CCmetal * (reg_height + 0.5 * PARM(res_ialu) * 3200 * LSCALE); /* or use result bus length measured from 21264 die photo */ // Cline = CCmetal * 3.3 * 1000; return Cline; }
/* record write data bitline and memory cell activity */ inline int FUNC(SIM_buf_power_data_write, SIM_power_array_info_t *info, SIM_power_array_t *arr, char *data_line, char *old_data, char *new_data) { /* drive the wordline */ SIM_power_array_dec(info, arr, NULL, 0, SIM_ARRAY_WRITE); /* write data */ SIM_power_array_data_write(info, arr, NULL, PARM(flit_width) / 8, data_line, old_data, new_data); return 0; }
/* Valid driver (see section 6.9 of tech report) Note that this will only be called for a direct mapped cache */ double SIM_valid_driver_delay(int C, int A, int Ntbl, int Ntspd, double inputtime) { double Ceq,Tst1,tf; Ceq = SIM_draincap(Wmuxdrv12n,NCH,1)+SIM_draincap(Wmuxdrv12p,PCH,1)+Cout; tf = Ceq*SIM_transreson(Wmuxdrv12p,PCH,1); Tst1 = SIM_horowitz(inputtime,tf,PARM(VTHMUXDRV1),0.5,FALL); return(Tst1); }
// COMPUTE WIRE CAPACITANCE using PTM models // The parameter "Length" has units of "m" double computeGroundCapacitance(double Length) { double c_g; int widthSpacingConfig = PARM(width_spacing); if (widthSpacingConfig == SWIDTH_SSPACE) { double A = (WireMinWidth/WireDielectricThickness); double B = 2.04*pow((WireMinSpacing/(WireMinSpacing + 0.54*WireDielectricThickness)), 1.77); double C1 = pow((WireMetalThickness/(WireMetalThickness + 4.53*WireDielectricThickness)), 0.07); c_g = WireDielectricConstant*8.85e-12*(A+(B*C1))*Length; // c_g is in "F" } else if (widthSpacingConfig == SWIDTH_DSPACE) { double minSpacingNew = 2*WireMinSpacing + WireMinWidth; double A = (WireMinWidth/WireDielectricThickness); double B = 2.04*pow((minSpacingNew/(minSpacingNew + 0.54*WireDielectricThickness)), 1.77); double C1 = pow((WireMetalThickness/(WireMetalThickness + 4.53*WireDielectricThickness)), 0.07); c_g = WireDielectricConstant*8.85e-12*(A+(B*C1))*Length; // c_g is in "F" } else if (widthSpacingConfig == DWIDTH_SSPACE) { double minWidthNew = 2*WireMinWidth; double A = (minWidthNew/WireDielectricThickness); double B = 2.04*pow((WireMinSpacing/(WireMinSpacing + 0.54*WireDielectricThickness)), 1.77); double C1 = pow((WireMetalThickness/(WireMetalThickness + 4.53*WireDielectricThickness)), 0.07); c_g = WireDielectricConstant*8.85e-12*(A+(B*C1))*Length; // c_g is in "F" } else if (widthSpacingConfig == DWIDTH_DSPACE) { double minWidthNew = 2*WireMinWidth; double minSpacingNew = 2*WireMinSpacing; double A = (minWidthNew/WireDielectricThickness); double B = 2.04*pow((minSpacingNew/(minSpacingNew+ 0.54*WireDielectricThickness)), 1.77); double C1 = pow((WireMetalThickness/(WireMetalThickness + 4.53*WireDielectricThickness)), 0.07); c_g = WireDielectricConstant*8.85e-12*(A+(B*C1))*Length; // c_g is in "F" } else { fprintf(stderr, "ERROR, Specified width spacing configuration is not supported.\n"); exit( 1 ); } return c_g; // Ground capacitance is in "F" }
int main(int argc, char **argv) { double link_len; u_int data_width; double Pdynamic, Pleakage, Ptotal; double freq; double load; double link_area; #if ( PARM(TECH_POINT) <= 90 ) if (argc < 3) { fprintf(stderr, "orion_link: [length] [load]\n"); exit(1); } /* read arguments */ /* link length is also the core size*/ link_len = atof(argv[1]); //unit micro-meter link_len = link_len * 1e-6; //unit meter load = atof(argv[2]); freq = PARM(Freq); data_width = PARM(flit_width); Pdynamic = 0.5 * load * LinkDynamicEnergyPerBitPerMeter(link_len, Vdd) * freq * link_len * (double)data_width; Pleakage = LinkLeakagePowerPerMeter(link_len, Vdd) * link_len * data_width; Ptotal = (Pdynamic + Pleakage) * PARM(in_port); link_area = LinkArea(link_len, data_width) * PARM(in_port); fprintf(stdout, "Link power is %g\n", Ptotal); fprintf(stdout, "Link area is %g\n", link_area); #else fprintf(stderr, "Link power and area are only supported for 90nm, 65nm, 45nm and 32nm\n"); #endif return 0; }
/* Data output delay (data side) -- see section 6.8 This is the time through the NAND/NOR gate and the final inverter assuming sel is already present */ double SIM_dataoutput_delay(int C, int B, int A, int Ndbl, int Nspd, int Ndwl, double inrisetime, double *outrisetime) { double Ceq,Rwire,Rline; double aspectRatio; /* as height over width */ double ramBlocks; /* number of RAM blocks */ double tf; double nordel,outdel,nextinputtime; double hstack,vstack; /* calculate some layout info */ aspectRatio = (2.0*C)/(8.0*B*B*A*A*Ndbl*Ndbl*Nspd*Nspd); hstack = (aspectRatio > 1.0) ? aspectRatio : 1.0/aspectRatio; ramBlocks = Ndwl*Ndbl; hstack = hstack * sqrt(ramBlocks/ hstack); vstack = ramBlocks/ hstack; /* Delay of NOR gate */ Ceq = 2*SIM_draincap(Woutdrvnorn,NCH,1)+SIM_draincap(Woutdrvnorp,PCH,2)+ SIM_gatecap(Woutdrivern,10.0); tf = Ceq*SIM_transreson(Woutdrvnorp,PCH,2); nordel = SIM_horowitz(inrisetime,tf,PARM(VTHOUTDRNOR),PARM(VTHOUTDRIVE),FALL); nextinputtime = nordel/(PARM(VTHOUTDRIVE)); /* Delay of final output driver */ Ceq = (SIM_draincap(Woutdrivern,NCH,1)+SIM_draincap(Woutdriverp,PCH,1))* ((8*B*A)/PARM(BITOUT)) + Cwordmetal*(8*B*A*Nspd* (vstack)) + Cout; Rwire = Rwordmetal*(8*B*A*Nspd* (vstack))/2; tf = Ceq*(SIM_transreson(Woutdriverp,PCH,1)+Rwire); outdel = SIM_horowitz(nextinputtime,tf,PARM(VTHOUTDRIVE),0.5,RISE); *outrisetime = outdel/0.5; return(outdel+nordel); }
/* * width - um * nchannel - whether n or p-channel (boolean) * stack - number of transistors in series that are on * * return drain cap in Farads */ double SIM_draincap(double width, int nchannel, int stack) { double Cdiffside,Cdiffarea,Coverlap,cap; double overlapCap; double swAreaUnderGate; double area_peri; double diffArea; double diffPeri; double l = 0.4 * LSCALE; diffArea = l * width; diffPeri = 2 * l + 2 * width; #if defined(Pdelta_w) if(nchannel == 0) { overlapCap = (width - 2 * Pdelta_w) * PCov; swAreaUnderGate = (width - 2 * Pdelta_w) * PCjswA; area_peri = ((diffArea * PCja) + (diffPeri * PCjsw)); return(stack*(area_peri + overlapCap + swAreaUnderGate)); } else { overlapCap = (width - 2 * Ndelta_w) * NCov; swAreaUnderGate = (width - 2 * Ndelta_w) * NCjswA; area_peri = ((diffArea * NCja * LSCALE) + (diffPeri * NCjsw * LSCALE)); return(stack*(area_peri + overlapCap + swAreaUnderGate)); } #endif Cdiffside = (nchannel) ? PARM(Cndiffside) : PARM(Cpdiffside); Cdiffarea = (nchannel) ? PARM(Cndiffarea) : PARM(Cpdiffarea); //Coverlap = (nchannel) ? (PARM(Cndiffovlp)+PARM(Cnoxideovlp)) : // (PARM(Cpdiffovlp)+PARM(Cpoxideovlp)); Coverlap = (nchannel) ? PARM(Cnoverlap) : PARM(Cpoverlap); /* calculate directly-connected (non-stacked) capacitance */ /* then add in capacitance due to stacking */ if (width >= 10) { cap = 3.0*Leff*width/2.0*Cdiffarea + 6.0*Leff*Cdiffside + width*Coverlap; cap += (double)(stack-1)*(Leff*width*Cdiffarea + 4.0*Leff*Cdiffside + 2.0*width*Coverlap); } else { cap = 3.0*Leff*width*Cdiffarea + (6.0*Leff+width)*Cdiffside + width*Coverlap; cap += (double)(stack-1)*(Leff*width*Cdiffarea + 2.0*Leff*Cdiffside + 2.0*width*Coverlap); } return(cap * SCALE_T); }
/* Data array wordline delay (see section 6.2 of tech report) */ double SIM_wordline_delay(int B, int A, int Ndwl, int Nspd, double inrisetime, double *outrisetime) { double Rpdrive,nextrisetime; double desiredrisetime,psize,nsize; double tf,nextinputtime,Ceq,Req,Rline,Cline; int cols; double Tworddrivedel,Twordchargedel; cols = 8*B*A*Nspd/Ndwl; /* Choose a transistor size that makes sense */ /* Use a first-order approx */ desiredrisetime = krise*log((double)(cols))/2.0; Cline = (SIM_gatecappass(Wmemcella,0.0)+ SIM_gatecappass(Wmemcella,0.0)+ Cwordmetal)*cols; Rpdrive = desiredrisetime/(Cline*log(PARM(VSINV))*-1.0); psize = SIM_restowidth(Rpdrive,PCH); if (psize > Wworddrivemax) { psize = Wworddrivemax; } /* Now that we have a reasonable psize, do the rest as before */ /* If we keep the ratio the same as the tag wordline driver, the threshold voltage will be close to VSINV */ nsize = psize * Wdecinvn/Wdecinvp; Ceq = SIM_draincap(Wdecinvn,NCH,1) + SIM_draincap(Wdecinvp,PCH,1) + SIM_gatecap(nsize+psize,20.0); tf = SIM_transreson(Wdecinvn,NCH,1)*Ceq; Tworddrivedel = SIM_horowitz(inrisetime,tf,PARM(VSINV),PARM(VSINV),RISE); nextinputtime = Tworddrivedel/(1.0-PARM(VSINV)); Cline = (SIM_gatecappass(Wmemcella,(BitWidth-2*Wmemcella)/2.0)+ SIM_gatecappass(Wmemcella,(BitWidth-2*Wmemcella)/2.0)+ Cwordmetal)*cols+ SIM_draincap(nsize,NCH,1) + SIM_draincap(psize,PCH,1); Rline = Rwordmetal*cols/2; tf = (SIM_transreson(psize,PCH,1)+Rline)*Cline; Twordchargedel = SIM_horowitz(nextinputtime,tf,PARM(VSINV),PARM(VSINV),FALL); *outrisetime = Twordchargedel/PARM(VSINV); return(Tworddrivedel+Twordchargedel); }
/* * width - gate width in um (length is Leff) * wirelength - poly wire length going to gate in lambda * return gate capacitance in Farads */ double SIM_gatecap(double width,double wirelength) { double overlapCap; double gateCap; double l = 0.1525; #if defined(Pdelta_w) overlapCap = (width - 2*Pdelta_w) * PCov; gateCap = ((width - 2*Pdelta_w) * (l * LSCALE - 2*Pdelta_l) * PCg) + 2.0 * overlapCap; return gateCap; #endif return(width*Leff*PARM(Cgate)+wirelength*Cpolywire*Leff * SCALE_T); /* return(width*Leff*PARM(Cgate)); */ /* return(width*CgateLeff+wirelength*Cpolywire*Leff);*/ }
// The following function computes the wire resistance considering // width-spacing combination and a width-dependent resistivity model double computeResistance(double Length) { double r, rho; int widthSpacingConfig = PARM(width_spacing); if (widthSpacingConfig == SWIDTH_SSPACE) { // rho is in "ohm.m" rho = 2.202e-8 + (1.030e-15 / (WireMinWidth - 2*WireBarrierThickness)); r = ((rho * Length) / ((WireMinWidth - 2*WireBarrierThickness) * (WireMetalThickness - WireBarrierThickness))); // r is in "ohm" } else if (widthSpacingConfig == SWIDTH_DSPACE) { // rho is in "ohm.m" rho = 2.202e-8 + (1.030e-15 / (WireMinWidth - 2*WireBarrierThickness)); r = ((rho * Length) / ((WireMinWidth - 2*WireBarrierThickness) * (WireMetalThickness - WireBarrierThickness))); // r is in "ohm" } else if (widthSpacingConfig == DWIDTH_SSPACE) { // rho is in "ohm.m" rho = 2.202e-8 + (1.030e-15 / (2*WireMinWidth - 2*WireBarrierThickness)); r = ((rho * Length) / ((2*WireMinWidth - 2*WireBarrierThickness) * (WireMetalThickness - WireBarrierThickness))); // r is in "ohm" } else if (widthSpacingConfig == DWIDTH_DSPACE) { // rho is in "ohm.m" rho = 2.202e-8 + (1.030e-15 / (2*WireMinWidth - 2*WireBarrierThickness)); r = ((rho * Length) / ((2*WireMinWidth - 2*WireBarrierThickness) * (WireMetalThickness - WireBarrierThickness))); // r is in "ohm" } else { //fprintf(stderr, "ERROR, Specified width spacing configuration is not supported.\n"); exit( 1 ); } return r; }
int main(int argc, char **argv) { int max_flag = AVG_ENERGY, plot_flag = 0; u_int print_depth = 0; double load = 1; char *name, opt; /* parse options */ while ((opt = getopt(argc, argv, "+pmd:l:")) != -1) { switch (opt) { case 'p': plot_flag = 1; break; case 'm': max_flag = MAX_ENERGY; break; case 'd': print_depth = atoi(optarg); break; case 'l': load = atof(optarg); break; } } if (optind >= argc) { fprintf(stderr, "orion_router_power: [-pm] [-d print_depth] [-l load] <router_name>\n"); return 1; } else { name = argv[optind]; } SIM_router_init(&GLOB(router_info), &GLOB(router_power), NULL); SIM_router_stat_energy(&GLOB(router_info), &GLOB(router_power), print_depth, name, max_flag, load, plot_flag, PARM(Freq)); return 0; }
/* * time unit: 1 cycle * e_fin: average # of flits received by one input port during unit time * (at most 0.5 for InfiniBand router) * e_buf_wrt: average # of input buffer writes of all ports during unit time * e_buf_wrt = e_fin * n_buf_in * e_buf_rd: average # of input buffer reads of all ports during unit time * e_buf_rd = e_buf_wrt * (splitted into different input ports in program) * e_cbuf_fin: average # of flits passing through the switch during unit time * e_cbuf_fin = e_fin * n_total_in * e_cbuf_wrt: average # of central buffer writes during unit time * e_cbuf_wrt = e_cbuf_fin / (pipe_depth * pipe_width) * e_cbuf_rd: average # of central buffer reads during unit time * e_cbuf_rd = e_cbuf_wrt * e_arb: average # of arbitrations per arbiter during unit time * assume e_arb = 1 * * NOTES: (1) negative print_depth means infinite print depth * * FIXME: (1) hack: SIM_array_stat_energy cannot be used for shared buffer, * we use it now anyway */ double SIM_router_stat_energy(SIM_router_info_t *info, SIM_router_power_t *router, int print_depth, char *path, int max_avg, double e_fin, int plot_flag, double freq) { double Eavg = 0, Eatomic, Estruct, Estatic = 0; double Pbuf = 0, Pxbar = 0, Pvc_arbiter = 0, Psw_arbiter = 0, Pclock = 0, Ptotal = 0; double Pbuf_static = 0, Pxbar_static = 0, Pvc_arbiter_static = 0, Psw_arbiter_static = 0, Pclock_static = 0; double Pbuf_dyn = 0, Pxbar_dyn = 0, Pvc_arbiter_dyn = 0, Psw_arbiter_dyn = 0, Pclock_dyn = 0; double e_in_buf_rw, e_cache_in_buf_rw, e_mc_in_buf_rw, e_io_in_buf_rw; double e_cbuf_fin, e_cbuf_rw, e_out_buf_rw; int next_depth; u_int path_len, n_regs; int vc_allocator_enabled = 1; /* expected value computation */ e_in_buf_rw = e_fin * info->n_in; e_cache_in_buf_rw = e_fin * info->n_cache_in; e_mc_in_buf_rw = e_fin * info->n_mc_in; e_io_in_buf_rw = e_fin * info->n_io_in; e_cbuf_fin = e_fin * info->n_total_in; e_out_buf_rw = e_cbuf_fin / info->n_total_out * info->n_out; e_cbuf_rw = e_cbuf_fin * info->flit_width / info->central_buf_info.blk_bits; next_depth = NEXT_DEPTH(print_depth); path_len = SIM_strlen(path); /* input buffers */ if (info->in_buf) { Eavg += SIM_array_stat_energy(&info->in_buf_info, &router->in_buf, e_in_buf_rw, e_in_buf_rw, next_depth, SIM_strcat(path, "input buffer"), max_avg); SIM_res_path(path, path_len); } if (info->cache_in_buf) { Eavg += SIM_array_stat_energy(&info->cache_in_buf_info, &router->cache_in_buf, e_cache_in_buf_rw, e_cache_in_buf_rw, next_depth, SIM_strcat(path, "cache input buffer"), max_avg); SIM_res_path(path, path_len); } if (info->mc_in_buf) { Eavg += SIM_array_stat_energy(&info->mc_in_buf_info, &router->mc_in_buf, e_mc_in_buf_rw, e_mc_in_buf_rw, next_depth, SIM_strcat(path, "memory controller input buffer"), max_avg); SIM_res_path(path, path_len); } if (info->io_in_buf) { Eavg += SIM_array_stat_energy(&info->io_in_buf_info, &router->io_in_buf, e_io_in_buf_rw, e_io_in_buf_rw, next_depth, SIM_strcat(path, "I/O input buffer"), max_avg); SIM_res_path(path, path_len); } /* output buffers */ if (info->out_buf) { /* local output ports don't use router buffers */ Eavg += SIM_array_stat_energy(&info->out_buf_info, &router->out_buf, e_out_buf_rw, e_out_buf_rw, next_depth, SIM_strcat(path, "output buffer"), max_avg); SIM_res_path(path, path_len); } /* central buffer */ if (info->central_buf) { Eavg += SIM_array_stat_energy(&info->central_buf_info, &router->central_buf, e_cbuf_rw, e_cbuf_rw, next_depth, SIM_strcat(path, "central buffer"), max_avg); SIM_res_path(path, path_len); Eavg += SIM_crossbar_stat_energy(&router->in_cbuf_crsbar, next_depth, SIM_strcat(path, "central buffer input crossbar"), max_avg, e_cbuf_fin); SIM_res_path(path, path_len); Eavg += SIM_crossbar_stat_energy(&router->out_cbuf_crsbar, next_depth, SIM_strcat(path, "central buffer output crossbar"), max_avg, e_cbuf_fin); SIM_res_path(path, path_len); /* dirty hack, REMEMBER to REMOVE Estruct and Eatomic */ Estruct = 0; n_regs = info->central_buf_info.n_set * (info->central_buf_info.read_ports + info->central_buf_info.write_ports); /* ignore e_switch for now because we overestimate wordline driver cap */ Eatomic = router->cbuf_ff.e_keep_0 * (info->pipe_depth - 1) * (n_regs - 2 * (e_cbuf_rw + e_cbuf_rw)); SIM_print_stat_energy(SIM_strcat(path, "central buffer pipeline registers/keep 0"), Eatomic, NEXT_DEPTH(next_depth)); SIM_res_path(path, path_len); Estruct += Eatomic; Eatomic = router->cbuf_ff.e_clock * (info->pipe_depth - 1) * n_regs; SIM_print_stat_energy(SIM_strcat(path, "central buffer pipeline registers/clock"), Eatomic, NEXT_DEPTH(next_depth)); SIM_res_path(path, path_len); Estruct += Eatomic; SIM_print_stat_energy(SIM_strcat(path, "central buffer pipeline registers"), Estruct, next_depth); SIM_res_path(path, path_len); Eavg += Estruct; } Pbuf_dyn = Eavg * freq; Pbuf_static = router->I_buf_static * Vdd * SCALE_S; Pbuf = Pbuf_dyn + Pbuf_static; /* main crossbar */ if (info->crossbar_model) { Eavg += SIM_crossbar_stat_energy(&router->crossbar, next_depth, SIM_strcat(path, "crossbar"), max_avg, e_cbuf_fin); SIM_res_path(path, path_len); } Pxbar_dyn = (Eavg * freq - Pbuf_dyn); Pxbar_static = router->I_crossbar_static * Vdd * SCALE_S; Pxbar = Pxbar_dyn + Pxbar_static; /* switch allocation (arbiter energy only) */ /* input (local) arbiter for switch allocation*/ if (info->sw_in_arb_model) { /* assume # of active input arbiters is (info->in_n_switch * info->n_in * e_fin) * assume (info->n_v_channel*info->n_v_class)/2 vcs are making request at each arbiter */ Eavg += SIM_arbiter_stat_energy(&router->sw_in_arb, &info->sw_in_arb_queue_info, (info->n_v_channel*info->n_v_class)/2, next_depth, SIM_strcat(path, "switch allocator input arbiter"), max_avg) * info->in_n_switch * info->n_in * e_fin; SIM_res_path(path, path_len); if (info->n_cache_in) { Eavg += SIM_arbiter_stat_energy(&router->cache_in_arb, &info->cache_in_arb_queue_info, e_fin / info->cache_n_switch, next_depth, SIM_strcat(path, "cache input arbiter"), max_avg) * info->cache_n_switch * info->n_cache_in; SIM_res_path(path, path_len); } if (info->n_mc_in) { Eavg += SIM_arbiter_stat_energy(&router->mc_in_arb, &info->mc_in_arb_queue_info, e_fin / info->mc_n_switch, next_depth, SIM_strcat(path, "memory controller input arbiter"), max_avg) * info->mc_n_switch * info->n_mc_in; SIM_res_path(path, path_len); } if (info->n_io_in) { Eavg += SIM_arbiter_stat_energy(&router->io_in_arb, &info->io_in_arb_queue_info, e_fin / info->io_n_switch, next_depth, SIM_strcat(path, "I/O input arbiter"), max_avg) * info->io_n_switch * info->n_io_in; SIM_res_path(path, path_len); } } /* output (global) arbiter for switch allocation*/ if (info->sw_out_arb_model) { /* assume # of active output arbiters is (info->n_switch_out * (e_cbuf_fin/info->n_switch_out)) * assume (info->n_in)/2 request at each output arbiter */ Eavg += SIM_arbiter_stat_energy(&router->sw_out_arb, &info->sw_out_arb_queue_info, info->n_in / 2, next_depth, SIM_strcat(path, "switch allocator output arbiter"), max_avg) * info->n_switch_out * (e_cbuf_fin / info->n_switch_out); SIM_res_path(path, path_len); } if(info->sw_out_arb_model || info->sw_out_arb_model){ Psw_arbiter_dyn = Eavg * freq - Pbuf_dyn - Pxbar_dyn; Psw_arbiter_static = router->I_sw_arbiter_static * Vdd * SCALE_S; Psw_arbiter = Psw_arbiter_dyn + Psw_arbiter_static; } /* virtual channel allocation (arbiter energy only) */ /* HACKs: * - assume 1 header flit in every 5 flits for now, hence * 0.2 */ if(info->vc_allocator_type == ONE_STAGE_ARB && info->vc_out_arb_model ){ /* one stage arbitration (vc allocation)*/ /* # of active arbiters */ double nActiveArbs = e_fin * info->n_in * 0.2 / 2; //flit_rate * n_in * 0.2 / 2 /* assume for each active arbiter, there is 2 requests on average (should use expected value from simulation) */ Eavg += SIM_arbiter_stat_energy(&router->vc_out_arb, &info->vc_out_arb_queue_info, 1, next_depth, SIM_strcat(path, "vc allocation arbiter"), max_avg) * nActiveArbs; SIM_res_path(path, path_len); } else if(info->vc_allocator_type == TWO_STAGE_ARB && info->vc_in_arb_model && info->vc_out_arb_model){ /* first stage arbitration (vc allocation)*/ if (info->vc_in_arb_model) { // # of active stage-1 arbiters (# of new header flits) double nActiveArbs = e_fin * info->n_in * 0.2; /* assume an active arbiter has n_v_channel/2 requests on average (should use expected value from simulation) */ Eavg += SIM_arbiter_stat_energy(&router->vc_in_arb, &info->vc_in_arb_queue_info, info->n_v_channel/2, next_depth, SIM_strcat(path, "vc allocation arbiter (stage 1)"), max_avg) * nActiveArbs; SIM_res_path(path, path_len); } /* second stage arbitration (vc allocation)*/ if (info->vc_out_arb_model) { /* # of active stage-2 arbiters */ double nActiveArbs = e_fin * info->n_in * 0.2 / 2; //flit_rate * n_in * 0.2 / 2 /* assume for each active arbiter, there is 2 requests on average (should use expected value from simulation) */ Eavg += SIM_arbiter_stat_energy(&router->vc_out_arb, &info->vc_out_arb_queue_info, 2, next_depth, SIM_strcat(path, "vc allocation arbiter (stage 2)"), max_avg) * nActiveArbs; SIM_res_path(path, path_len); } } else if(info->vc_allocator_type == VC_SELECT && info->n_v_channel > 1 && info->n_in > 1){ double n_read = e_fin * info->n_in * 0.2; double n_write = e_fin * info->n_in * 0.2; Eavg += SIM_array_stat_energy(&info->vc_select_buf_info, &router->vc_select_buf, n_read , n_write, next_depth, SIM_strcat(path, "vc selection"), max_avg); SIM_res_path(path, path_len); } else{ vc_allocator_enabled = 0; //set to 0 means no vc allocator is used } if(info->n_v_channel > 1 && vc_allocator_enabled){ Pvc_arbiter_dyn = Eavg * freq - Pbuf_dyn - Pxbar_dyn - Psw_arbiter_dyn; Pvc_arbiter_static = router->I_vc_arbiter_static * Vdd * SCALE_S; Pvc_arbiter = Pvc_arbiter_dyn + Pvc_arbiter_static; } /*router clock power (supported for 90nm and below) */ if(PARM(TECH_POINT) <=90){ Eavg += SIM_total_clockEnergy(info, router); Pclock_dyn = Eavg * freq - Pbuf_dyn - Pxbar_dyn - Pvc_arbiter_dyn - Psw_arbiter_dyn; Pclock_static = router->I_clock_static * Vdd * SCALE_S; Pclock = Pclock_dyn + Pclock_static; } /* static power */ Estatic = router->I_static * Vdd * Period * SCALE_S; SIM_print_stat_energy(SIM_strcat(path, "static energy"), Estatic, next_depth); SIM_res_path(path, path_len); Eavg += Estatic; Ptotal = Eavg * freq; SIM_print_stat_energy(path, Eavg, print_depth); if (plot_flag) fprintf(stdout, "Buffer:%g\tCrossbar:%g\tVC_allocator:%g\tSW_allocator:%g\tClock:%g\tTotal:%g\n", Pbuf, Pxbar, Pvc_arbiter, Psw_arbiter, Pclock, Ptotal); return Eavg; }
int SIM_crossbar_init(SIM_power_crossbar_t *crsbar, int model, u_int n_in, u_int n_out, u_int in_seg, u_int out_seg, u_int data_width, u_int degree, int connect_type, int trans_type, double in_len, double out_len, double *req_len) { double in_length, out_length, ctr_length, Nsize, in_wire_cap, I_static; if ((crsbar->model = model) && model < CROSSBAR_MAX_MODEL) { crsbar->n_in = n_in; crsbar->n_out = n_out; crsbar->in_seg = 0; crsbar->out_seg = 0; crsbar->data_width = data_width; crsbar->degree = degree; crsbar->connect_type = connect_type; crsbar->trans_type = trans_type; /* redundant field */ crsbar->mask = HAMM_MASK(data_width); crsbar->n_chg_in = crsbar->n_chg_int = crsbar->n_chg_out = crsbar->n_chg_ctr = 0; switch (model) { case MATRIX_CROSSBAR: crsbar->in_seg = in_seg; crsbar->out_seg = out_seg; /* FIXME: need accurate spacing */ in_length = n_out * data_width * CrsbarCellWidth; out_length = n_in * data_width * CrsbarCellHeight; if (in_length < in_len) in_length = in_len; if (out_length < out_len) out_length = out_len; ctr_length = in_length / 2; if (req_len) *req_len = in_length; in_wire_cap = in_length * CC3metal; crsbar->e_chg_out = SIM_crossbar_out_cap(out_length, n_in, out_seg, connect_type, trans_type, &Nsize) * EnergyFactor; crsbar->e_chg_in = SIM_crossbar_in_cap(in_wire_cap, n_out, in_seg, connect_type, trans_type, &Nsize) * EnergyFactor; /* FIXME: wire length estimation, really reset? */ /* control signal should reset after transmission is done, so no 1/2 */ crsbar->e_chg_ctr = SIM_crossbar_ctr_cap(ctr_length, data_width, 0, 0, 0, connect_type, trans_type) * EnergyFactor; crsbar->e_chg_int = 0; /* static power */ I_static = 0; /* tri-state buffers */ I_static += ((Woutdrvnandp * (NAND2_TAB[0] + NAND2_TAB[1] + NAND2_TAB[2]) + Woutdrvnandn * NAND2_TAB[3]) / 4 + (Woutdrvnorp * NOR2_TAB[0] + Woutdrvnorn * (NOR2_TAB[1] + NOR2_TAB[2] + NOR2_TAB[3])) / 4 + Woutdrivern * NMOS_TAB[0] + Woutdriverp * PMOS_TAB[0]) * n_in * n_out * data_width; /* input driver */ I_static += (Wdecinvn * NMOS_TAB[0] + Wdecinvp * PMOS_TAB[0]) * n_in * data_width; /* output driver */ I_static += (Woutdrivern * NMOS_TAB[0] + Woutdriverp * PMOS_TAB[0]) * n_out * data_width; /* control signal inverter */ I_static += (Wdecinvn * NMOS_TAB[0] + Wdecinvp * PMOS_TAB[0]) * n_in * n_out; crsbar->I_static = I_static / PARM(TECH_POINT) * 100; break; case MULTREE_CROSSBAR: /* input wire horizontal segment length */ in_length = n_in * data_width * CrsbarCellWidth * (n_out / 2); in_wire_cap = in_length * CCmetal; /* input wire vertical segment length */ in_length = n_in * data_width * (5 * Lamda) * (n_out / 2); in_wire_cap += in_length * CC3metal; ctr_length = n_in * data_width * CrsbarCellWidth * (n_out / 2) / 2; crsbar->e_chg_out = SIM_crossbar_out_cap(0, degree, 0, connect_type, trans_type, NULL) * EnergyFactor; crsbar->e_chg_in = SIM_crossbar_in_cap(in_wire_cap, n_out, 0, connect_type, trans_type, NULL) * EnergyFactor; crsbar->e_chg_int = SIM_crossbar_int_cap(degree, connect_type, trans_type) * EnergyFactor; /* redundant field */ crsbar->depth = (u_int)ceil(log(n_in) / log(degree)); /* control signal should reset after transmission is done, so no 1/2 */ if (crsbar->depth == 1) /* only one level of control signal */ crsbar->e_chg_ctr = SIM_crossbar_ctr_cap(ctr_length, data_width, 0, 0, degree, connect_type, trans_type) * EnergyFactor; else { /* first level and last level control signals */ crsbar->e_chg_ctr = SIM_crossbar_ctr_cap(ctr_length, data_width, 0, 1, degree, connect_type, trans_type) * EnergyFactor + SIM_crossbar_ctr_cap(0, data_width, 1, 0, degree, connect_type, trans_type) * EnergyFactor; /* intermediate control signals */ if (crsbar->depth > 2) crsbar->e_chg_ctr += (crsbar->depth - 2) * SIM_crossbar_ctr_cap(0, data_width, 1, 1, degree, connect_type, trans_type) * EnergyFactor; } /* static power */ I_static = 0; /* input driver */ I_static += (Wdecinvn * NMOS_TAB[0] + Wdecinvp * PMOS_TAB[0]) * n_in * data_width; /* output driver */ I_static += (Woutdrivern * NMOS_TAB[0] + Woutdriverp * PMOS_TAB[0]) * n_out * data_width; /* mux */ I_static += (WdecNORp * NOR2_TAB[0] + WdecNORn * (NOR2_TAB[1] + NOR2_TAB[2] + NOR2_TAB[3])) / 4 * (2 * n_in - 1) * n_out * data_width; /* control signal inverter */ I_static += (Wdecinvn * NMOS_TAB[0] + Wdecinvp * PMOS_TAB[0]) * n_in * n_out; crsbar->I_static = I_static / PARM(TECH_POINT) * 100; break; case CUT_THRU_CROSSBAR: /* only support 4x4 now */ in_length = 2 * data_width * MAX(CrsbarCellWidth, CrsbarCellHeight); ctr_length = in_length / 2; crsbar->e_chg_in = SIM_crossbar_io_cap(in_length) * EnergyFactor; crsbar->e_chg_out = 0; /* control signal should reset after transmission is done, so no 1/2 */ crsbar->e_chg_ctr = SIM_crossbar_ctr_cap(ctr_length, data_width, 0, 0, 0, TRISTATE_GATE, 0) * EnergyFactor; crsbar->e_chg_int = 0; break; default: /* some error handler */ break; } return 0; } else return -1; }
int FUNC(SIM_reg_power_init, SIM_power_array_info_t *info, SIM_power_array_t *arr, SIM_reg_port_state_t *read_port, SIM_reg_port_state_t *write_port) { /* ==================== set parameters ==================== */ /* general parameters */ info->share_rw = 0; info->read_ports = PARM(read_port); info->write_ports = PARM(write_port); info->n_set = PARM(n_regs); info->blk_bits = PARM(reg_width); info->assoc = 1; info->data_width = PARM(reg_width); info->data_end = PARM(data_end); /* sub-array partition parameters */ info->data_ndwl = PARM( ndwl ); info->data_ndbl = PARM( ndbl ); info->data_nspd = PARM( nspd ); info->data_n_share_amp = 1; /* model parameters */ info->row_dec_model = PARM( row_dec_model ); info->row_dec_pre_model = PARM( row_dec_pre_model ); info->data_wordline_model = PARM( wordline_model ); info->data_bitline_model = PARM( bitline_model ); info->data_bitline_pre_model = PARM( bitline_pre_model ); info->data_mem_model = PARM( mem_model ); #if (PARM(data_end) == 2) info->data_amp_model = PARM(amp_model); #else info->data_amp_model = SIM_NO_MODEL; #endif /* PARM(data_end) == 2 */ info->outdrv_model = PARM( outdrv_model ); info->data_colsel_pre_model = SIM_NO_MODEL; info->col_dec_model = SIM_NO_MODEL; info->col_dec_pre_model = SIM_NO_MODEL; info->mux_model = SIM_NO_MODEL; /* no tag array */ info->tag_wordline_model = SIM_NO_MODEL; info->tag_bitline_model = SIM_NO_MODEL; info->tag_bitline_pre_model = SIM_NO_MODEL; info->tag_mem_model = SIM_NO_MODEL; info->tag_attach_mem_model = SIM_NO_MODEL; info->tag_amp_model = SIM_NO_MODEL; info->tag_colsel_pre_model = SIM_NO_MODEL; info->comp_model = SIM_NO_MODEL; info->comp_pre_model = SIM_NO_MODEL; /* ==================== set flags ==================== */ info->write_policy = 0; /* no dirty bit */ /* ==================== compute redundant fields ==================== */ info->n_item = info->blk_bits / info->data_width; info->eff_data_cols = info->blk_bits * info->assoc * info->data_nspd; /* ==================== call back functions ==================== */ info->get_entry_valid_bit = NULL; info->get_entry_dirty_bit = NULL; info->get_entry_tag = NULL; info->get_set_tag = NULL; info->get_set_use_bit = NULL; /* initialize state variables */ if (read_port) SIM_reg_port_state_init(info, read_port, info->read_ports); if (write_port) SIM_reg_port_state_init(info, write_port, info->write_ports); return SIM_array_power_init( info, arr ); }
* (2) no column decoder */ #include "SIM_port.h" #if ( PARM( POWER_STATS )) #include <stdio.h> #include <math.h> #include "SIM_reg_power.h" /* global variables */ GLOBDEF( SIM_power_array_t, reg_power ); GLOBDEF( SIM_power_array_info_t, reg_info ); GLOBDEF( SIM_reg_port_state_t, reg_read_port )[PARM(read_port)]; GLOBDEF( SIM_reg_port_state_t, reg_write_port )[PARM(write_port)]; static int SIM_reg_port_state_init(SIM_power_array_info_t *info, SIM_reg_port_state_t *port, u_int n_port); int FUNC(SIM_reg_power_init, SIM_power_array_info_t *info, SIM_power_array_t *arr, SIM_reg_port_state_t *read_port, SIM_reg_port_state_t *write_port) { /* ==================== set parameters ==================== */ /* general parameters */ info->share_rw = 0; info->read_ports = PARM(read_port); info->write_ports = PARM(write_port); info->n_set = PARM(n_regs); info->blk_bits = PARM(reg_width);
int main(int argc, char **argv) { int max_flag = AVG_ENERGY, plot_flag = 0; u_int print_depth = 0; double load = 1; char *name, opt; /* parse options */ while ((opt = getopt(argc, argv, "+pmd:l:")) != -1) { switch (opt) { case 'p': plot_flag = 1; break; case 'm': max_flag = MAX_ENERGY; break; case 'd': print_depth = atoi(optarg); break; case 'l': load = atof(optarg); break; } } if (optind >= argc) { fprintf(stderr, "test_router: [-pm] [-d print_depth] [-l load] <router_name>\n"); exit(1); } else { name = argv[optind]; } FUNC(SIM_router_power_init, &GLOB(router_info), &GLOB(router_power)); SIM_router_stat_energy(&GLOB(router_info), &GLOB(router_power), print_depth, name, max_flag, load, plot_flag, PARM(Freq)); //load = SIM_reg_stat_energy(&GLOB(router_info).in_buf_info, &GLOB(router_power).in_buf, 0, 1, 0, NULL, 0); //printf("%g\n", load); exit(0); }
/*setup_windows{{{*/ void setup_windows(int flags) { obj_param_t tmp_parm; globl_drop_depth =25; globl_flags = DROP_SHADOW; init_gui(WIDTH, HEIGHT, flags); SET_COLOR(globl_fg, 0 ,0 ,0); SET_COLOR(globl_bg, 224 ,224 ,204); SET_COLOR(globl_move_color, 0x1f,0x8f,0x1f); SET_COLOR(hscroll_color, 0 ,0x7f,0xff); SET_COLOR(sprite_color, 0xff,0x7f,0); SET_COLOR(window_color, 0 ,0 ,0xff); SET_COLOR(scroll_b_color, 0xff,0 ,0xff); SET_COLOR(scroll_a_color, 0xff,0 ,0); change_message_grp = new_group(40,40, 202, 77, globl_flags, globl_drop_depth); simple_window(change_message_grp, 200, 75); PARM(50, 45,100,20, &globl_fg, &globl_bg, SHOW_FOCUS | QUIT_BUTTON, proc_button_box); tmp_parm.dp1 = (void *)"Okay"; new_obj(change_message_grp, &tmp_parm); PARM(12,16,172,20,&globl_fg, &globl_bg, MAX_CHARS|SHOW_FOCUS, proc_edit_line); tmp_parm.d3 = 80; text_edit_object = new_obj(change_message_grp, &tmp_parm); select_grp = new_group(0,0,WIDTH, HEIGHT,0,0); PARM(305,126,320,240,&globl_fg,&globl_bg,0,select_special); select_special_object = new_obj(select_grp, &tmp_parm); PARM(0,0, 304, 126, 0,0, 0, select_quit_on_click); tmp_parm.user_flags = 0; new_obj(select_grp, &tmp_parm); PARM(0,126,304,240, 0,0, 0, select_quit_on_click); tmp_parm.user_flags = HORIZONTAL; new_obj(select_grp, &tmp_parm); PARM(0, 366, 305, 112, 0,0, 0, select_quit_on_click); tmp_parm.user_flags = 0; new_obj(select_grp, &tmp_parm); PARM(305, 0, 320, 126, 0,0, 0, select_quit_on_click); new_obj(select_grp, &tmp_parm); PARM(305, 366, 320, 114, 0,0, 0, select_quit_on_click); tmp_parm.user_flags = VERTICAL; new_obj(select_grp, &tmp_parm); PARM(625, 0, 15, 480, 0,0,0, select_quit_on_click); tmp_parm.user_flags = 0; new_obj(select_grp, &tmp_parm); main_grp = new_group(0,0, WIDTH, HEIGHT, 0, 0); PARM(0,0,WIDTH,HEIGHT,&globl_fg,&globl_bg,DROP_ACCUM|LOAD_XPM_FROM_ARRAY,proc_bitmap); tmp_parm.dp1 = back_xpm; background_object = new_obj(main_grp, &tmp_parm); PARM(82,22,0,0,&globl_fg,&globl_bg, TOGGLE|CALL_BUTTON|SHOW_FOCUS|LOAD_XPM_FROM_ARRAY,proc_icon_button); tmp_parm.callback = undo_button; tmp_parm.d1 = FALSE; tmp_parm.d2 = 1; tmp_parm.dp1 = undo_xpm; new_obj(main_grp, &tmp_parm); /* tools */ PARM(124, 22, 0, 0, &globl_fg, &globl_bg, CALL_BUTTON|SHOW_FOCUS|LOAD_XPM_FROM_ARRAY, proc_icon_button); tmp_parm.callback = tool_change; tmp_parm.d1 = FALSE; tmp_parm.d2 = 2; tmp_parm.dp1 = select_xpm; select_object = new_obj(main_grp, &tmp_parm); PARM(82, 53, 0, 0, &globl_fg, &globl_bg, CALL_BUTTON|SHOW_FOCUS|LOAD_XPM_FROM_ARRAY, proc_icon_button); tmp_parm.callback = tool_change; tmp_parm.d1 = FALSE; tmp_parm.d2 = 2; tmp_parm.dp1 = pal_hi_low_xpm; pal_hi_low_object = new_obj(main_grp, &tmp_parm); PARM(124, 53, 0, 0, &globl_fg, &globl_bg, CALL_BUTTON|SHOW_FOCUS|LOAD_XPM_FROM_ARRAY,proc_icon_button); tmp_parm.callback = tool_change; tmp_parm.d1 = FALSE; tmp_parm.d2 = 2; tmp_parm.dp1 = flip_xpm; flip_object = new_obj(main_grp, &tmp_parm); PARM(82,88,0,0,&globl_fg,&globl_bg, CALL_BUTTON|SHOW_FOCUS|LOAD_XPM_FROM_ARRAY,proc_icon_button); tmp_parm.callback = tool_change; tmp_parm.d1 = TRUE; tmp_parm.d2 = 2; tmp_parm.dp1 = line_xpm; line_object = new_obj(main_grp, &tmp_parm); last_tool = line_object; PARM(124,88,0,0,&globl_fg,&globl_bg, CALL_BUTTON|SHOW_FOCUS|LOAD_XPM_FROM_ARRAY,proc_icon_button); tmp_parm.callback = tool_change; tmp_parm.d1 = FALSE; tmp_parm.d2 = 2; tmp_parm.dp1 = put_pat_xpm; put_pat_object = new_obj(main_grp, &tmp_parm); PARM(82,123,0,0,&globl_fg,&globl_bg, CALL_BUTTON|SHOW_FOCUS|LOAD_XPM_FROM_ARRAY,proc_icon_button); tmp_parm.callback = tool_change; tmp_parm.d1 = FALSE; tmp_parm.d2 = 2; tmp_parm.dp1 = fill_xpm; fill_object = new_obj(main_grp, &tmp_parm); PARM(124,123,0,0,&globl_fg,&globl_bg, CALL_BUTTON|SHOW_FOCUS|LOAD_XPM_FROM_ARRAY,proc_icon_button); tmp_parm.callback = tool_change; tmp_parm.d1 = FALSE; tmp_parm.d2 = 2; tmp_parm.dp1 = clear_to_color_xpm; clear_to_color_object = new_obj(main_grp, &tmp_parm); PARM(82,158,0,0,&globl_fg,&globl_bg, CALL_BUTTON|SHOW_FOCUS|LOAD_XPM_FROM_ARRAY,proc_icon_button); tmp_parm.callback = tool_change; tmp_parm.d1 = FALSE; tmp_parm.d2 = 2; tmp_parm.dp1 = pic_xpm; pic_object = new_obj(main_grp, &tmp_parm); PARM(124,158,0,0,&globl_fg,&globl_bg, CALL_BUTTON|SHOW_FOCUS|LOAD_XPM_FROM_ARRAY,proc_icon_button); tmp_parm.callback = tool_change; tmp_parm.d1 = FALSE; tmp_parm.d2 = 2; tmp_parm.dp1 = pic_pat_xpm; pic_pat_object = new_obj(main_grp, &tmp_parm); /* not tools */ #ifndef WINDOWS PARM(580,450,50,17,&globl_fg,&globl_bg,SHOW_FOCUS|CALL_BUTTON|DROP_SHADOW,proc_button_box); tmp_parm.dp1 = (void *)"F/W"; tmp_parm.callback = fw_bottom; new_obj(main_grp, &tmp_parm); #endif PARM(580,1,50,17,&globl_fg,&globl_bg,SHOW_FOCUS|CALL_BUTTON|DROP_SHADOW,proc_button_box); tmp_parm.dp1 = (void *)"Quit"; tmp_parm.callback = really_quit; new_obj(main_grp, &tmp_parm); PARM(500,1,50,17,&globl_fg,&globl_bg,SHOW_FOCUS|CALL_BUTTON|DROP_SHADOW,proc_button_box); tmp_parm.dp1 = (void *)"About"; tmp_parm.callback = about; new_obj(main_grp, &tmp_parm); PARM(20,1, 50,17,&globl_fg,&globl_bg,SHOW_FOCUS|CALL_BUTTON|DROP_SHADOW,proc_button_box); tmp_parm.dp1 = (void *)"Load"; tmp_parm.user_flags = LOAD; tmp_parm.callback=load_save_top; new_obj(main_grp, &tmp_parm); load_grp = new_menu(20,5, load_menu, &globl_fg, &globl_bg); PARM(75,1, 50,17,&globl_fg,&globl_bg,SHOW_FOCUS|CALL_BUTTON|DROP_SHADOW,proc_button_box); tmp_parm.dp1 = (void *)"Save"; tmp_parm.user_flags = SAVE; tmp_parm.callback=load_save_top; new_obj(main_grp, &tmp_parm); save_grp = new_menu(75,5, save_menu, &globl_fg, &globl_bg); high_low_grp = new_menu(124,88, high_low_menu, &globl_fg, &sprite_color); hor_ver_grp = new_menu(124,88,horizontal_vertical_menu, &globl_fg, &sprite_color); pal_hi_low_grp = new_menu(124,88, pal_hi_low_menu, &globl_fg, &sprite_color); copy_move_grp = new_menu(124,88,copy_move_menu, &globl_fg, &sprite_color); PARM(380,1,90,17,&globl_fg,&globl_bg,SHOW_FOCUS|CALL_BUTTON|DROP_SHADOW,proc_button_box); tmp_parm.dp1 = (void *)"Background"; tmp_parm.callback = change_background; new_obj(main_grp, &tmp_parm); PARM(425,81,0,0,&globl_fg,&globl_bg, CALL_BUTTON|SHOW_FOCUS|LOAD_XPM_FROM_ARRAY,proc_icon_button); tmp_parm.callback = preview_zoom_change; tmp_parm.d1 = FALSE; tmp_parm .d2 = 4; tmp_parm.dp1 = zoom_out_xpm; preview_zoom_out = new_obj(main_grp,&tmp_parm); PARM(461,81,0,0,&globl_fg,&globl_bg, CALL_BUTTON|SHOW_FOCUS|LOAD_XPM_FROM_ARRAY,proc_icon_button); tmp_parm.callback = preview_zoom_change; tmp_parm.d1 = FALSE; tmp_parm.d2 = 5; tmp_parm.dp1 = zoom_in_xpm; preview_zoom_in = new_obj(main_grp,&tmp_parm); PARM(499,83, 31,27, &globl_fg,&globl_bg,CALL_BUTTON,proc_button_box); tmp_parm.callback = change_bg_color; tmp_parm.dp1 = (char *)" "; bg_color_box = new_obj(main_grp, &tmp_parm); UPDATE_BG_COLOR; PARM(305,114,320,11,&globl_move_color, &globl_bg,SHOW_FOCUS|CALL_BUTTON,proc_scroll_bar); tmp_parm.d2 = 256; tmp_parm.d1 = 0; tmp_parm.callback = preview_scroll_change; preview_scroll_bar = new_obj(main_grp, &tmp_parm); PARM(292,126,11,240,&globl_move_color,&globl_bg,SHOW_FOCUS|CALL_BUTTON,proc_scroll_bar); tmp_parm.d2 = 0; tmp_parm.d1 = 0; preview_y_scroll = new_obj(main_grp,&tmp_parm); PARM(305,367,320,11,&globl_move_color,&globl_bg,SHOW_FOCUS|CALL_BUTTON,proc_scroll_bar); tmp_parm.d2 = 0; tmp_parm.d1 = 0; preview_x_scroll = new_obj(main_grp,&tmp_parm); tmp_parm.callback = preview_size_change; PARM(293,82,0,0,&globl_fg, &globl_bg, SHOW_FOCUS|CALL_BUTTON, proc_radio_button); tmp_parm.d1 = TRUE; tmp_parm.d2 = 1; tmp_parm.dp1 = (void *)"NTSC"; preview_ntsc = new_obj(main_grp, &tmp_parm); PARM(293,96,0,0,&globl_fg, &globl_bg, SHOW_FOCUS|CALL_BUTTON, proc_radio_button); tmp_parm.d1 = FALSE; tmp_parm.d2 = 1; tmp_parm.dp1 = (void *)"PAL"; preview_pal = new_obj(main_grp, &tmp_parm); PARM(348,82,0,0,&globl_fg, &globl_bg, SHOW_FOCUS|CALL_BUTTON, proc_radio_button); tmp_parm.d1 = TRUE; tmp_parm.d2 = 2; tmp_parm.dp1 = (void *)"40 cell"; preview_40c = new_obj(main_grp, &tmp_parm); PARM(348,96,0,0,&globl_fg, &globl_bg, SHOW_FOCUS|CALL_BUTTON, proc_radio_button); tmp_parm.d1 = FALSE; tmp_parm.d2 = 2; tmp_parm.dp1 = (void *)"32 cell"; preview_32c = new_obj(main_grp, &tmp_parm); PARM(190,297,11,176,&globl_move_color,&globl_bg,CALL_BUTTON|SHOW_FOCUS,proc_scroll_bar); tmp_parm.d2 = 0xf6; tmp_parm.d1 = 0; tmp_parm.callback = pattern_select_bot; pattern_select_scroll_bar = new_obj(main_grp, &tmp_parm); PARM(10,301,179,0xa*16,&globl_fg,&globl_bg,0,proc_pattern_select); pattern_select_object = new_obj(main_grp, &tmp_parm); PARM(10,22,70,260,&globl_fg,&globl_bg,0,proc_palette_change_object); palette_change_object = new_obj(main_grp, &tmp_parm); /* Pattern edit */ PARM(88,200,67,83,&globl_fg,&globl_bg,0,proc_pattern_edit); pattern_edit_object = new_obj(main_grp, &tmp_parm); PARM(305,126,320,240,&globl_fg,&globl_bg,0,proc_preview_object); preview_object = new_obj(main_grp,&tmp_parm); PARM(540,88,65,17,&globl_fg,&globl_bg,SHOW_FOCUS|CALL_BUTTON,proc_button_box); tmp_parm.dp1 = (void *)"overlay"; tmp_parm.callback = load_ovr_window; preview_overlay = new_obj(main_grp, &tmp_parm); /* View and edit what? */ tmp_parm.callback = edit_change; PARM(254,96,0,0,&globl_fg,&globl_bg, SHOW_FOCUS|CALL_BUTTON|LOAD_XPM_FROM_ARRAY, proc_icon_button); tmp_parm.d1 = TRUE; tmp_parm.d2 = 3; tmp_parm.user_flags = EDIT_SCROLL_A; tmp_parm.dp1 = scroll_a_edit_xpm; new_obj(main_grp, &tmp_parm); currently_editing = EDIT_SCROLL_A; PARM(254,120,0,0,&globl_fg,&globl_bg, SHOW_FOCUS|CALL_BUTTON|LOAD_XPM_FROM_ARRAY, proc_icon_button); tmp_parm.d1 = FALSE; tmp_parm.d2 = 3; tmp_parm.user_flags = EDIT_SCROLL_B; tmp_parm.dp1 = scroll_b_edit_xpm; new_obj(main_grp, &tmp_parm); PARM(254,144,0,0,&globl_fg,&globl_bg, SHOW_FOCUS|CALL_BUTTON|LOAD_XPM_FROM_ARRAY, proc_icon_button); tmp_parm.d1 = FALSE; tmp_parm.d2 = 3; tmp_parm.user_flags = EDIT_SPRITE; tmp_parm.dp1 = sprite_edit_xpm; new_obj(main_grp, &tmp_parm); tmp_parm.callback = edit_change; PARM(230,96,0,0,&globl_fg,&globl_bg, SHOW_FOCUS|CALL_BUTTON|LOAD_XPM_FROM_ARRAY|SINGLE_RADIO, proc_icon_button); tmp_parm.d1 = TRUE; tmp_parm.d2 = 4; tmp_parm.user_flags = VIEW_SCROLL_B; tmp_parm.dp1 = scroll_b_xpm; new_obj(main_grp, &tmp_parm); PARM(230,120,0,0,&globl_fg,&globl_bg, SHOW_FOCUS|CALL_BUTTON|LOAD_XPM_FROM_ARRAY|SINGLE_RADIO, proc_icon_button); tmp_parm.d1 = TRUE; tmp_parm.d2 = 4; tmp_parm.user_flags = VIEW_SCROLL_A; tmp_parm.dp1 = scroll_a_xpm; new_obj(main_grp, &tmp_parm); PARM(230,120+24,0,0,&globl_fg,&globl_bg, SHOW_FOCUS|CALL_BUTTON|LOAD_XPM_FROM_ARRAY|SINGLE_RADIO, proc_icon_button); tmp_parm.d1 = TRUE; tmp_parm.d2 = 4; tmp_parm.user_flags = VIEW_SCROLL_B_HIGH; tmp_parm.dp1 = scroll_b_high_xpm; new_obj(main_grp, &tmp_parm); PARM(230,120+24+24,0,0,&globl_fg,&globl_bg, SHOW_FOCUS|CALL_BUTTON|LOAD_XPM_FROM_ARRAY|SINGLE_RADIO, proc_icon_button); tmp_parm.d1 = TRUE; tmp_parm.d2 = 4; tmp_parm.user_flags = VIEW_SCROLL_A_HIGH; tmp_parm.dp1 = scroll_a_high_xpm; new_obj(main_grp, &tmp_parm); PARM(353,25,31,31, &hscroll_color, &globl_bg, 0, proc_scroll_size); new_obj(main_grp, &tmp_parm); PARM(415,25,41,41, &globl_fg, &globl_bg, 0, proc_sprite_size); new_obj(main_grp, &tmp_parm); PARM(369, 64,0,0,&globl_fg, &globl_bg, 0, proc_ctext); tmp_parm.dp1 = (void *)malloc( 8 ); snprintf(tmp_parm.dp1, 8, "64x64"); scroll_width = 1; scroll_height = 1; scroll_size2 =new_obj(main_grp, &tmp_parm); sprite_width = 0; sprite_height = 0; PARM(410, 393,41,51, &globl_fg, &globl_bg, CALL_BUTTON|MODULAR|HEX|INACTIVE, proc_knob); tmp_parm.d1 = 40; tmp_parm.d2 = 0x400; tmp_parm.user_flags = KNOB; tmp_parm.callback = knob_tick; knob = new_obj(main_grp, &tmp_parm); PARM(244,410, 23,24,&globl_fg, &globl_bg, LOAD_XPM_FROM_ARRAY|SHOW_FOCUS|CALL_BUTTON|SINGLE_RADIO,proc_icon_button); tmp_parm.dp1 = small_knob_xpm; tmp_parm.d1 = FALSE; tmp_parm.d2 = 200; tmp_parm.callback = knob_select; knob_icon = new_obj(main_grp,&tmp_parm); PARM(315, 422, 0,0, &globl_fg, &globl_bg, 0, proc_ctext); tmp_parm.dp1 = (void *)malloc(64); snprintf( tmp_parm.dp1, 64, ":<"); knob_text = new_obj(main_grp,&tmp_parm); PARM(272, 256, 11, 82, &globl_fg, &globl_bg, 0, proc_scroll_bar_special) tmp_parm.d1 = 2; tmp_parm.d2 = 2; tmp_parm.user_flags = HORIZONTAL; horizontal_scroll_bar = new_obj(main_grp, &tmp_parm); PARM(493,385, 82,11, &globl_fg, &globl_bg, 0, proc_scroll_bar_special); tmp_parm.d1 = 0; tmp_parm.d2 = 1; tmp_parm.user_flags = VERTICAL; vertical_scroll_bar = new_obj(main_grp, &tmp_parm); PARM(462, 401, 0,0, &globl_fg, &globl_bg, SHOW_FOCUS|CALL_BUTTON|LOAD_XPM_FROM_ARRAY, proc_icon_button); tmp_parm.d1 = TRUE; tmp_parm.d2 = 5; tmp_parm.dp1 = (void *)scroll_a_edit_xpm; tmp_parm.callback = knob_tick; tmp_parm.user_flags = SELECT_A; select_a_object = new_obj(main_grp, &tmp_parm); PARM(462, 423, 0,0, &globl_fg, &globl_bg, SHOW_FOCUS|CALL_BUTTON|LOAD_XPM_FROM_ARRAY, proc_icon_button); tmp_parm.d1 = FALSE; tmp_parm.d2 = 5; tmp_parm.dp1 = (void *)scroll_b_edit_xpm; tmp_parm.callback = knob_tick; tmp_parm.user_flags = SELECT_B; new_obj(main_grp, &tmp_parm); tmp_parm.proc = load_default_mega; select_b_object = new_obj(main_grp, &tmp_parm); PARM(172, 177, 0,0, &globl_fg, &globl_bg, SHOW_FOCUS|SINGLE_RADIO|LOAD_XPM_FROM_ARRAY, proc_icon_button); // tmp_parm.callback = stop_bot; tmp_parm.dp1 = (void *)clob_xpm; tmp_parm.d1 = FALSE; tmp_parm.d2 = 401; clob_object = new_obj(main_grp, &tmp_parm); PARM(172, 202, 0,0, &globl_fg, &globl_bg, CALL_BUTTON|SHOW_FOCUS|SINGLE_RADIO|LOAD_XPM_FROM_ARRAY, proc_icon_button); tmp_parm.callback = stop_bot; tmp_parm.dp1 = (void *)stop_xpm; tmp_parm.d1 = FALSE; tmp_parm.d2 = 401; stop_object = new_obj(main_grp, &tmp_parm); PARM(172, 227, 0,0, &globl_fg, &globl_bg, CALL_BUTTON|SHOW_FOCUS|SINGLE_RADIO|LOAD_XPM_FROM_ARRAY, proc_icon_button); tmp_parm.callback = go_bot; tmp_parm.dp1 = (void *)clear_xpm; tmp_parm.d1 = FALSE; tmp_parm.d2 = 401; new_obj(main_grp, &tmp_parm); PARM(172, 252, 0,0, &globl_fg, &globl_bg, CALL_BUTTON|SHOW_FOCUS|SINGLE_RADIO|LOAD_XPM_FROM_ARRAY, proc_icon_button); tmp_parm.callback = new_bot; tmp_parm.dp1 = (void *)new_xpm; tmp_parm.d1 = FALSE; tmp_parm.d2 = 401; new_obj(main_grp, &tmp_parm); PARM(490, 400, 140, 45, &globl_fg, &globl_bg, DROP_SHADOW, proc_info); info_object = new_obj(main_grp, &tmp_parm); /* SHADOW BOX */ PARM(170, 175, 25, 100, &globl_fg, &globl_bg, DROP_SHADOW, proc_shadow_box); new_obj(main_grp, &tmp_parm); PARM(460, 400, 25, 45, &globl_fg, &globl_bg, DROP_SHADOW, proc_shadow_box); new_obj(main_grp, &tmp_parm); PARM(270, 254, 14, 86, &globl_fg, &globl_bg, DROP_SHADOW, proc_shadow_box); new_obj(main_grp, &tmp_parm); PARM(491,383, 86, 14, &globl_fg, &globl_bg, DROP_SHADOW, proc_shadow_box); new_obj(main_grp, &tmp_parm); PARM(240, 407, 150, 30, &globl_fg, &globl_bg, DROP_SHADOW, proc_shadow_box); knob_message_box = new_obj(main_grp, &tmp_parm); PARM(405, 400, 50, 45, &globl_fg, &globl_bg, DROP_SHADOW, proc_shadow_box); new_obj(main_grp, &tmp_parm); PARM(340, 21, 58, 50, &globl_fg,&globl_bg, DROP_SHADOW, proc_shadow_box); scroll_size1 = new_obj(main_grp, &tmp_parm); PARM(340+67, 21, 58, 50, &globl_fg,&globl_bg, DROP_SHADOW, proc_shadow_box); sprite_size1 = new_obj(main_grp, &tmp_parm); PARM(340+67+67+((58/4)-6), 20+((50/4)-6)-1, 20, 20, &globl_fg, &globl_bg, CALL_BUTTON|SHOW_FOCUS|SINGLE_RADIO|LOAD_XPM_FROM_ARRAY,proc_icon_button); tmp_parm.callback = sprite_overlay; tmp_parm.dp1 = (void *)minus_xpm; tmp_parm.d1 = FALSE; tmp_parm.d2 = 401; minus_object = new_obj(main_grp, &tmp_parm); PARM(340+67+67+((58/4)-6), 20+((50/2)+2)-1, 20, 20, &globl_fg, &globl_bg, CALL_BUTTON|SHOW_FOCUS|SINGLE_RADIO|LOAD_XPM_FROM_ARRAY,proc_icon_button); tmp_parm.dp1 = (void *)plus_xpm; tmp_parm.d1 = FALSE; tmp_parm.d2 = 401; plus_object = new_obj(main_grp, &tmp_parm); PARM(340+67+67+((58/4)+15), 20+((50/4)-6)-1, 20, 20, &globl_fg, &globl_bg, CALL_BUTTON|SHOW_FOCUS|SINGLE_RADIO|LOAD_XPM_FROM_ARRAY,proc_icon_button); tmp_parm.dp1 = (void *)a_xpm; tmp_parm.d1 = FALSE; tmp_parm.d2 = 401; a_object = new_obj(main_grp, &tmp_parm); PARM(340+67+67+((58/4)+15), 20+((50/2)+2)-1, 20, 20, &globl_fg, &globl_bg, CALL_BUTTON|SHOW_FOCUS|SINGLE_RADIO|LOAD_XPM_FROM_ARRAY,proc_icon_button); tmp_parm.dp1 = (void *)b_xpm; tmp_parm.d1 = FALSE; tmp_parm.d2 = 401; b_object = new_obj(main_grp, &tmp_parm); PARM(340+67+67,21,58,50, &globl_fg, &globl_bg, DROP_SHADOW, proc_shadow_box); new_obj(main_grp,&tmp_parm); PARM(228, 94, 50, 148-24-24, &globl_fg,&globl_bg, DROP_SHADOW, proc_shadow_box); new_obj(main_grp, &tmp_parm); PARM(8,19,152,266,&globl_fg,&globl_bg,DROP_SHADOW,proc_shadow_box); new_obj(main_grp, &tmp_parm); PARM(8,295,198,179,&globl_fg,&globl_bg,DROP_SHADOW,proc_shadow_box); new_obj(main_grp, &tmp_parm); PARM(288,80,340,300,&globl_fg,&globl_bg,DROP_SHADOW,proc_shadow_box); preview_box_object = new_obj(main_grp, &tmp_parm); red.r = 0x7f; red.g = 0; red.b = 0; green.r = 0; green.g = 0x7f; green.b = 0; blue.r = 0; blue.g = 0; blue.b = 0x7f; PARM(168,22,100,11,&red,&globl_bg,SHOW_FOCUS|CALL_BUTTON,proc_scroll_bar); tmp_parm.d2 = 7; tmp_parm.d1 = current_vdp->palette[current_palette][current_palette_index].r / (0xff/7); tmp_parm.callback = color_change_bot; rgb_red_object = new_obj(main_grp, &tmp_parm); tmp_parm.d1 = current_vdp->palette[current_palette][current_palette_index].g / (0xff/7); tmp_parm.y+=18; tmp_parm.fg = &green; rgb_green_object = new_obj(main_grp, &tmp_parm); tmp_parm.d1 = current_vdp->palette[current_palette][current_palette_index].b / (0xff/7); tmp_parm.y+=18; tmp_parm.fg = &blue; rgb_blue_object = new_obj(main_grp, &tmp_parm); PARM(301,38,24,8,¤t_color_text_color,&globl_bg,0,proc_ctext); tmp_parm.dp1 = (void *)malloc(4); current_color_text_object = new_obj(main_grp,&tmp_parm); PARM(301,52,24,8, ¤t_color_text_color, &globl_bg, 0,proc_ctext); tmp_parm.dp1 = (void *)malloc(4); current_color_text2_object = new_obj(main_grp, &tmp_parm); update_color_text(); PARM(276,30,50,30,&globl_fg,¤t_vdp->palette[0][0],0,proc_shadow_box); current_color_object = new_obj(main_grp, &tmp_parm); PARM(165,19,170,55,&globl_fg,&globl_bg,DROP_SHADOW,proc_shadow_box); rgb_box_object = new_obj(main_grp, &tmp_parm); overlay_sel = setup_overlay_window(400,300, LOAD, "an image", load_ovr_callback); background_sel = setup_overlay_window(400,300, LOAD, "an image", load_background_callback); pointers = new_group(200, 300, 151,151,globl_flags,globl_drop_depth); simple_window(pointers, 150, 150); PARM( 25, 100, 100, 30, &globl_fg, &globl_bg, QUIT_BUTTON|SHOW_FOCUS, proc_button_box); tmp_parm.dp1 = (char *)"OK"; new_obj(pointers, &tmp_parm); PARM(30, 20, 0,0, &hscroll_color, &globl_bg, SHOW_FOCUS|SINGLE_RADIO, proc_radio_button); tmp_parm.d1 = FALSE; tmp_parm.d2 = 50; tmp_parm.dp1 = (char *)"hscroll"; hscroll_radio = new_obj(pointers, &tmp_parm); PARM(30, 31, 0,0, &sprite_color, &globl_bg, SHOW_FOCUS|SINGLE_RADIO, proc_radio_button); tmp_parm.d1 = FALSE; tmp_parm.d2 = 50; tmp_parm.dp1 = (char *)"sprite"; sprite_radio = new_obj(pointers, &tmp_parm); PARM(30, 42, 0,0, &scroll_a_color, &globl_bg, SHOW_FOCUS|SINGLE_RADIO, proc_radio_button); tmp_parm.d1 = FALSE; tmp_parm.d2 = 50; tmp_parm.dp1 = (char *)"scroll_a"; scroll_a_radio = new_obj(pointers, &tmp_parm); PARM(30, 53, 0,0, &scroll_b_color, &globl_bg, SHOW_FOCUS|SINGLE_RADIO, proc_radio_button); tmp_parm.d1 = FALSE; tmp_parm.d2 = 50; tmp_parm.dp1 = (char *)"scroll_b"; scroll_b_radio = new_obj(pointers, &tmp_parm); PARM(30, 64, 0,0, &window_color, &globl_bg, SHOW_FOCUS|SINGLE_RADIO, proc_radio_button); tmp_parm.d1 = FALSE; tmp_parm.d2 = 50; tmp_parm.dp1 = (char *)"window"; window_radio = new_obj(pointers, &tmp_parm); load_sel = setup_overlay_window(400,300, LOAD, "123456", load_save_bottom); save_sel = setup_overlay_window(400,300, SAVE, "123456", load_save_bottom); }
/* Comparator Delay (see section 6.6) */ double SIM_compare_time(int C, int A, int Ntbl, int Ntspd, double inputtime, double *outputtime) { double Req,Ceq,tf,st1del,st2del,st3del,nextinputtime,m; double c1,c2,r1,r2,tstep,a,b,c; double Tcomparatorni; int cols,tagbits; /* First Inverter */ Ceq = SIM_gatecap(Wcompinvn2+Wcompinvp2,10.0) + SIM_draincap(Wcompinvp1,PCH,1) + SIM_draincap(Wcompinvn1,NCH,1); Req = SIM_transreson(Wcompinvp1,PCH,1); tf = Req*Ceq; st1del = SIM_horowitz(inputtime,tf,PARM(VTHCOMPINV),PARM(VTHCOMPINV),FALL); nextinputtime = st1del/PARM(VTHCOMPINV); /* Second Inverter */ Ceq = SIM_gatecap(Wcompinvn3+Wcompinvp3,10.0) + SIM_draincap(Wcompinvp2,PCH,1) + SIM_draincap(Wcompinvn2,NCH,1); Req = SIM_transreson(Wcompinvn2,NCH,1); tf = Req*Ceq; st2del = SIM_horowitz(inputtime,tf,PARM(VTHCOMPINV),PARM(VTHCOMPINV),RISE); nextinputtime = st1del/(1.0-PARM(VTHCOMPINV)); /* Third Inverter */ Ceq = SIM_gatecap(Wevalinvn+Wevalinvp,10.0) + SIM_draincap(Wcompinvp3,PCH,1) + SIM_draincap(Wcompinvn3,NCH,1); Req = SIM_transreson(Wcompinvp3,PCH,1); tf = Req*Ceq; st3del = SIM_horowitz(nextinputtime,tf,PARM(VTHCOMPINV),PARM(VTHEVALINV),FALL); nextinputtime = st1del/(PARM(VTHEVALINV)); /* Final Inverter (virtual ground driver) discharging compare part */ tagbits = PARM(ADDRESS_BITS) - (int)logtwo((double)C) + (int)logtwo((double)A); cols = tagbits*Ntbl*Ntspd; r1 = SIM_transreson(Wcompn,NCH,2); r2 = SIM_transresswitch(Wevalinvn,NCH,1); c2 = (tagbits)*(SIM_draincap(Wcompn,NCH,1)+SIM_draincap(Wcompn,NCH,2))+ SIM_draincap(Wevalinvp,PCH,1) + SIM_draincap(Wevalinvn,NCH,1); c1 = (tagbits)*(SIM_draincap(Wcompn,NCH,1)+SIM_draincap(Wcompn,NCH,2)) +SIM_draincap(Wcompp,PCH,1) + SIM_gatecap(Wmuxdrv12n+Wmuxdrv12p,20.0) + cols*Cwordmetal; /* time to go to threshold of mux driver */ tstep = (r2*c2+(r1+r2)*c1)*log(1.0/PARM(VTHMUXDRV1)); /* take into account non-zero input rise time */ m = Vdd/nextinputtime; if ((tstep) <= (0.5*(Vdd-Vt)/m)) { a = m; b = 2*((Vdd*PARM(VTHEVALINV))-Vt); c = -2*(tstep)*(Vdd-Vt)+1/m*((Vdd*PARM(VTHEVALINV))-Vt)*((Vdd*PARM(VTHEVALINV))-Vt); Tcomparatorni = (-b+sqrt(b*b-4*a*c))/(2*a); } else { Tcomparatorni = (tstep) + (Vdd+Vt)/(2*m) - (Vdd*PARM(VTHEVALINV))/m; } *outputtime = Tcomparatorni/(1.0-PARM(VTHMUXDRV1)); return(Tcomparatorni+st1del+st2del+st3del); }
static int SIM_buf_set_para(SIM_power_array_info_t *info, int share_buf, u_int n_read_port, u_int n_write_port, u_int n_entry, u_int line_width, int outdrv) { /* ==================== set parameters ==================== */ /* general parameters */ info->share_rw = 0; info->read_ports = n_read_port; info->write_ports = n_write_port; info->n_set = n_entry; info->blk_bits = line_width; info->assoc = 1; info->data_width = line_width; info->data_end = PARM(data_end); /* no sub-array partition */ info->data_ndwl = 1; info->data_ndbl = 1; info->data_nspd = 1; info->data_n_share_amp = 1; /* model parameters */ if (share_buf) { info->row_dec_model = PARM(row_dec_model); info->row_dec_pre_model = PARM(row_dec_pre_model); } else { info->row_dec_model = SIM_NO_MODEL; info->row_dec_pre_model = SIM_NO_MODEL; } info->data_wordline_model = PARM( wordline_model ); info->data_bitline_model = PARM( bitline_model ); info->data_bitline_pre_model = PARM( bitline_pre_model ); info->data_mem_model = PARM( mem_model ); #if (PARM(data_end) == 2) info->data_amp_model = PARM(amp_model); #else info->data_amp_model = SIM_NO_MODEL; #endif /* PARM(data_end) == 2 */ if (outdrv) info->outdrv_model = PARM(outdrv_model); else info->outdrv_model = SIM_NO_MODEL; info->data_colsel_pre_model = SIM_NO_MODEL; info->col_dec_model = SIM_NO_MODEL; info->col_dec_pre_model = SIM_NO_MODEL; info->mux_model = SIM_NO_MODEL; /* FIXME: not true for shared buffer */ /* no tag array */ info->tag_wordline_model = SIM_NO_MODEL; info->tag_bitline_model = SIM_NO_MODEL; info->tag_bitline_pre_model = SIM_NO_MODEL; info->tag_mem_model = SIM_NO_MODEL; info->tag_attach_mem_model = SIM_NO_MODEL; info->tag_amp_model = SIM_NO_MODEL; info->tag_colsel_pre_model = SIM_NO_MODEL; info->comp_model = SIM_NO_MODEL; info->comp_pre_model = SIM_NO_MODEL; /* ==================== set flags ==================== */ info->write_policy = 0; /* no dirty bit */ /* ==================== compute redundant fields ==================== */ info->n_item = info->blk_bits / info->data_width; info->eff_data_cols = info->blk_bits * info->assoc * info->data_nspd; /* ==================== call back functions ==================== */ info->get_entry_valid_bit = NULL; info->get_entry_dirty_bit = NULL; info->get_entry_tag = NULL; info->get_set_tag = NULL; info->get_set_use_bit = NULL; /* initialize state variables */ //if (read_port) SIM_buf_port_state_init(info, read_port, info->read_ports); //if (write_port) SIM_buf_port_state_init(info, write_port, info->write_ports); return 0; }
int FUNC(SIM_router_power_init, SIM_power_router_info_t *info, SIM_power_router_t *router) { u_int line_width; int share_buf, outdrv; /* PHASE 1: set parameters */ /* general parameters */ info->n_in = PARM(in_port); info->n_cache_in = PARM(cache_in_port); info->n_mc_in = PARM(mc_in_port); info->n_io_in = PARM(io_in_port); info->n_total_in = PARM(in_port) + PARM(cache_in_port) + PARM(mc_in_port) + PARM(io_in_port); info->n_out = PARM(out_port); info->n_cache_out = PARM(cache_out_port); info->n_mc_out = PARM(mc_out_port); info->n_io_out = PARM(io_out_port); info->n_total_out = PARM(out_port) + PARM(cache_out_port) + PARM(mc_out_port) + PARM(io_out_port); info->flit_width = PARM(flit_width); /* virtual channel parameters */ info->n_v_channel = MAX(PARM(v_channel), 1); info->n_v_class = MAX(info->n_v_channel, PARM(v_class)); info->cache_class = MAX(PARM(cache_class), 1); info->mc_class = MAX(PARM(mc_class), 1); info->io_class = MAX(PARM(io_class), 1); /* shared buffer implies buffer has tags, so no virtual class -> no sharing */ /* separate buffer & shared switch implies buffer has tri-state output driver, so no v class -> no sharing */ if (info->n_v_class > 1) { info->in_share_buf = PARM(in_share_buf); info->out_share_buf = PARM(out_share_buf); info->in_share_switch = PARM(in_share_switch); info->out_share_switch = PARM(out_share_switch); } else { info->in_share_buf = 0; info->out_share_buf = 0; info->in_share_switch = 0; info->out_share_switch = 0; } /* crossbar */ info->crossbar_model = PARM(crossbar_model); info->degree = PARM(crsbar_degree); info->connect_type = PARM(connect_type); info->trans_type = PARM(trans_type); info->crossbar_in_len = PARM(crossbar_in_len); info->crossbar_out_len = PARM(crossbar_out_len); /* input buffer */ info->in_buf = PARM(in_buf); #if (PARM(in_buf)) outdrv = !info->in_share_buf && info->in_share_switch; SIM_buf_set_para(&info->in_buf_info, info->in_share_buf, PARM(in_buf_rport), 1, PARM(in_buf_set), PARM(flit_width), outdrv); #endif /* PARM(in_buf) */ #if (PARM(cache_in_port)) info->cache_in_buf = PARM(cache_in_buf); #if (PARM(cache_in_buf)) #if (PARM(cache_class) > 1) share_buf = info->in_share_buf; outdrv = !share_buf && info->in_share_switch; #else outdrv = share_buf = 0; #endif /* PARM(cache_class) > 1 */ SIM_buf_set_para(&info->cache_in_buf_info, share_buf, PARM(cache_in_buf_rport), 1, PARM(cache_in_buf_set), PARM(flit_width), outdrv); #endif /* PARM(cache_in_buf) */ #else info->cache_in_buf = 0; #endif /* PARM(cache_in_port) */ #if (PARM(mc_in_port)) info->mc_in_buf = PARM(mc_in_buf); #if (PARM(mc_in_buf)) #if (PARM(mc_class) > 1) share_buf = info->in_share_buf; outdrv = !share_buf && info->in_share_switch; #else outdrv = share_buf = 0; #endif /* PARM(mc_class) > 1 */ SIM_buf_set_para(&info->mc_in_buf_info, share_buf, PARM(mc_in_buf_rport), 1, PARM(mc_in_buf_set), PARM(flit_width), outdrv); #endif /* PARM(mc_in_buf) */ #else info->mc_in_buf = 0; #endif /* PARM(mc_in_port) */ #if (PARM(io_in_port)) info->io_in_buf = PARM(io_in_buf); #if (PARM(io_in_buf)) #if (PARM(io_class) > 1) share_buf = info->in_share_buf; outdrv = !share_buf && info->in_share_switch; #else outdrv = share_buf = 0; #endif /* PARM(io_class) > 1 */ SIM_buf_set_para(&info->io_in_buf_info, share_buf, PARM(io_in_buf_rport), 1, PARM(io_in_buf_set), PARM(flit_width), outdrv); #endif /* PARM(io_in_buf) */ #else info->io_in_buf = 0; #endif /* PARM(io_in_port) */ /* output buffer */ info->out_buf = PARM(out_buf); #if (PARM(out_buf)) /* output buffer has no tri-state buffer anyway */ SIM_buf_set_para(&info->out_buf_info, info->out_share_buf, 1, PARM(out_buf_wport), PARM(out_buf_set), PARM(flit_width), 0); #endif /* PARM(out_buf) */ /* central buffer */ info->central_buf = PARM(central_buf); #if (PARM(central_buf)) info->pipe_depth = PARM(pipe_depth); /* central buffer is always shared */ SIM_buf_set_para(&info->central_buf_info, 1, PARM(cbuf_rport), PARM(cbuf_wport), PARM(cbuf_set), PARM(cbuf_width) * PARM(flit_width), 0); /* dirty hack */ info->cbuf_ff_model = NEG_DFF; #endif /* PARM(central_buf) */ /* input port arbiter */ if (info->n_v_class > 1) { if (info->in_arb_model = PARM(in_arb_model)) { if (PARM(in_arb_model) == QUEUE_ARBITER) { SIM_buf_set_para(&info->in_arb_queue_info, 0, 1, 1, info->n_v_class, SIM_power_logtwo(info->n_v_class), 0); if (info->cache_class > 1) SIM_buf_set_para(&info->cache_in_arb_queue_info, 0, 1, 1, info->cache_class, SIM_power_logtwo(info->cache_class), 0); if (info->mc_class > 1) SIM_buf_set_para(&info->mc_in_arb_queue_info, 0, 1, 1, info->mc_class, SIM_power_logtwo(info->mc_class), 0); if (info->io_class > 1) SIM_buf_set_para(&info->io_in_arb_queue_info, 0, 1, 1, info->io_class, SIM_power_logtwo(info->io_class), 0); info->in_arb_ff_model = SIM_NO_MODEL; } else info->in_arb_ff_model = PARM(in_arb_ff_model); } else info->in_arb_ff_model = SIM_NO_MODEL; } else { info->in_arb_model = SIM_NO_MODEL; info->in_arb_ff_model = SIM_NO_MODEL; } /* output port arbiter */ #if ((PARM(in_port) + PARM(cache_in_port) + PARM(mc_in_port) + PARM(io_in_port)) > 2) if (info->out_arb_model = PARM(out_arb_model)) { if (PARM(out_arb_model) == QUEUE_ARBITER) { line_width = SIM_power_logtwo(info->n_total_in - 1); SIM_buf_set_para(&info->out_arb_queue_info, 0, 1, 1, info->n_total_in - 1, line_width, 0); info->out_arb_ff_model = SIM_NO_MODEL; } else info->out_arb_ff_model = PARM(out_arb_ff_model); } else info->out_arb_ff_model = SIM_NO_MODEL; #else info->out_arb_model = SIM_NO_MODEL; info->out_arb_ff_model = SIM_NO_MODEL; #endif /* (PARM(in_port) + PARM(cache_in_port) + PARM(mc_in_port) + PARM(io_in_port)) > 2 */ /* redundant fields */ if (info->in_buf) { if (info->in_share_buf) info->in_n_switch = info->in_buf_info.read_ports; else if (info->in_share_switch) info->in_n_switch = 1; else info->in_n_switch = info->n_v_class; } else info->in_n_switch = 1; if (info->cache_in_buf) { if (info->in_share_buf) info->cache_n_switch = info->cache_in_buf_info.read_ports; else if (info->in_share_switch) info->cache_n_switch = 1; else info->cache_n_switch = info->cache_class; } else info->cache_n_switch = 1; if (info->mc_in_buf) { if (info->in_share_buf) info->mc_n_switch = info->mc_in_buf_info.read_ports; else if (info->in_share_switch) info->mc_n_switch = 1; else info->mc_n_switch = info->mc_class; } else info->mc_n_switch = 1; if (info->io_in_buf) { if (info->in_share_buf) info->io_n_switch = info->io_in_buf_info.read_ports; else if (info->in_share_switch) info->io_n_switch = 1; else info->io_n_switch = info->io_class; } else info->io_n_switch = 1; info->n_switch_in = info->n_in * info->in_n_switch + info->n_cache_in * info->cache_n_switch + info->n_mc_in * info->mc_n_switch + info->n_io_in * info->io_n_switch; /* no buffering for local output ports */ info->n_switch_out = info->n_cache_out + info->n_mc_out + info->n_io_out; if (info->out_buf) { if (info->out_share_buf) info->n_switch_out += info->n_out * info->out_buf_info.write_ports; else if (info->out_share_switch) info->n_switch_out += info->n_out; else info->n_switch_out += info->n_out * info->n_v_class; } else info->n_switch_out += info->n_out; /* PHASE 2: initialization */ SIM_router_power_init(info, router); return 0; }
int SIM_router_init(SIM_router_info_t *info, SIM_router_power_t *router_power, SIM_router_area_t *router_area) { u_int line_width; int share_buf, outdrv; /* PHASE 1: set parameters */ /* general parameters */ info->n_in = PARM(in_port); info->n_cache_in = PARM(cache_in_port);//0 in our case info->n_mc_in = PARM(mc_in_port);//0 in our case info->n_io_in = PARM(io_in_port);//0 in our case info->n_total_in = PARM(in_port) + PARM(cache_in_port) + PARM(mc_in_port) + PARM(io_in_port);//equal to in_port info->n_out = PARM(out_port); info->n_cache_out = PARM(cache_out_port);//0 here info->n_mc_out = PARM(mc_out_port);//0 here info->n_io_out = PARM(io_out_port);//0 here info->n_total_out = PARM(out_port) + PARM(cache_out_port) + PARM(mc_out_port) + PARM(io_out_port);//equal to out_port info->flit_width = FLITSIZE*8;//FLITSIZE is defined in defaults.h and can be specified in nirgam.config in bytes /* virtual channel parameters */ info->n_v_channel = MAX(PARM(v_channel), 1); info->n_v_class = MAX(PARM(v_class), 1); info->cache_class = MAX(PARM(cache_class), 1);//0 here info->mc_class = MAX(PARM(mc_class), 1); //0 here info->io_class = MAX(PARM(io_class), 1);//0 here /* shared buffer implies buffer has tags */ /* separate buffer & shared switch implies buffer has tri-state output driver*/ if (info->n_v_class * info->n_v_channel > 1) //no sharing in our case { info->in_share_buf = PARM(in_share_buf); info->out_share_buf = PARM(out_share_buf); info->in_share_switch = PARM(in_share_switch); info->out_share_switch = PARM(out_share_switch); } else { info->in_share_buf = 0; info->out_share_buf = 0; info->in_share_switch = 0; info->out_share_switch = 0; } /* crossbar */ info->crossbar_model = PARM(crossbar_model); info->degree = PARM(crsbar_degree); info->connect_type = PARM(connect_type); info->trans_type = PARM(trans_type); info->xb_in_seg = PARM(xb_in_seg); info->xb_out_seg = PARM(xb_out_seg); info->crossbar_in_len = PARM(crossbar_in_len); info->crossbar_out_len = PARM(crossbar_out_len); /* HACK HACK HACK */ info->exp_xb_model = PARM(exp_xb_model); info->exp_in_seg = PARM(exp_in_seg); info->exp_out_seg = PARM(exp_out_seg); /* input buffer */ info->in_buf = PARM(in_buf);//have i/p buffer or not, we have info->in_buffer_model = PARM(in_buffer_type);//can be SRAM or REGISTER if (info->in_buf) { outdrv = !info->in_share_buf && info->in_share_switch;//outdrv ?? //NUM_BUFS is buffer depth, the 2nd parameter specifies whether buffer is fifo or not(1 means it is fifo) //parameters: router address, isfifo, no. of read ports, no. of write ports, buffer depth, data width in bits, outdrv, buffer model(SRAM or REGISTER) SIM_array_init(&info->in_buf_info, 1, PARM(in_buf_rport), 1, NUM_BUFS, FLITSIZE*8, outdrv, info->in_buffer_model); //this function in SIM_array_l.cpp } //no need for nirgam config. if (PARM(cache_in_port)) { info->cache_in_buf = PARM(cache_in_buf); if (info->cache_in_buf) { if (PARM(cache_class) > 1) { share_buf = info->in_share_buf; outdrv = !share_buf && info->in_share_switch; } else { outdrv = share_buf = 0; } SIM_array_init(&info->cache_in_buf_info, 1, PARM(cache_in_buf_rport), 1, PARM(cache_in_buf_set), FLITSIZE*8, outdrv, SRAM); } } //no need for nirgam config. if (PARM(mc_in_port)) { info->mc_in_buf = PARM(mc_in_buf); if (info->mc_in_buf) { if (PARM(mc_class) > 1) { share_buf = info->in_share_buf; outdrv = !share_buf && info->in_share_switch; } else { outdrv = share_buf = 0; } SIM_array_init(&info->mc_in_buf_info, 1, PARM(mc_in_buf_rport), 1, PARM(mc_in_buf_set),FLITSIZE*8, outdrv, SRAM); } } //not needed if (PARM(io_in_port)) { info->io_in_buf = PARM(io_in_buf); if (info->io_in_buf) { if (PARM(io_class) > 1) { share_buf = info->in_share_buf; outdrv = !share_buf && info->in_share_switch; } else { outdrv = share_buf = 0; } SIM_array_init(&info->io_in_buf_info, 1, PARM(io_in_buf_rport), 1, PARM(io_in_buf_set), FLITSIZE*8, outdrv, SRAM); } } /* output buffer */ info->out_buf = PARM(out_buf); info->out_buffer_model = PARM(out_buffer_type); if (info->out_buf) { /* output buffer has no tri-state buffer anyway */ SIM_array_init(&info->out_buf_info, 1, 1, PARM(out_buf_wport), PARM(out_buf_set), FLITSIZE*8, 0, info->out_buffer_model); } //not needed /* central buffer */ info->central_buf = PARM(central_buf); if (info->central_buf) { info->pipe_depth = PARM(pipe_depth); /* central buffer is no FIFO */ SIM_array_init(&info->central_buf_info, 0, PARM(cbuf_rport), PARM(cbuf_wport), PARM(cbuf_set), PARM(cbuf_width) * FLITSIZE*8, 0, SRAM); /* dirty hack */ info->cbuf_ff_model = NEG_DFF; } /* switch allocator input port arbiter */ if (info->n_v_class * info->n_v_channel > 1) { if (info->sw_in_arb_model = PARM(sw_in_arb_model)) { if (PARM(sw_in_arb_model) == QUEUE_ARBITER) { SIM_array_init(&info->sw_in_arb_queue_info, 1, 1, 1, info->n_v_class*info->n_v_channel, SIM_logtwo(info->n_v_class*info->n_v_channel), 0, REGISTER); if (info->cache_class > 1) SIM_array_init(&info->cache_in_arb_queue_info, 1, 1, 1, info->cache_class, SIM_logtwo(info->cache_class), 0, REGISTER); if (info->mc_class > 1) SIM_array_init(&info->mc_in_arb_queue_info, 1, 1, 1, info->mc_class, SIM_logtwo(info->mc_class), 0, REGISTER); if (info->io_class > 1) SIM_array_init(&info->io_in_arb_queue_info, 1, 1, 1, info->io_class, SIM_logtwo(info->io_class), 0, REGISTER); info->sw_in_arb_ff_model = SIM_NO_MODEL; } else info->sw_in_arb_ff_model = PARM(sw_in_arb_ff_model); } else info->sw_in_arb_ff_model = SIM_NO_MODEL; } else { info->sw_in_arb_model = SIM_NO_MODEL; info->sw_in_arb_ff_model = SIM_NO_MODEL; } /* switch allocator output port arbiter */ if (info->n_total_in > 2) { info->sw_out_arb_model = PARM(sw_out_arb_model); if (info->sw_out_arb_model) { if (info->sw_out_arb_model == QUEUE_ARBITER) { line_width = SIM_logtwo(info->n_total_in - 1); SIM_array_init(&info->sw_out_arb_queue_info, 1, 1, 1, info->n_total_in - 1, line_width, 0, REGISTER); info->sw_out_arb_ff_model = SIM_NO_MODEL; } else { info->sw_out_arb_ff_model = PARM(sw_out_arb_ff_model); } } else { info->sw_out_arb_ff_model = SIM_NO_MODEL; } } else { info->sw_out_arb_model = SIM_NO_MODEL; info->sw_out_arb_ff_model = SIM_NO_MODEL; } /* virtual channel allocator type */ if (info->n_v_channel > 1) { info->vc_allocator_type = PARM(vc_allocator_type); } else info->vc_allocator_type = SIM_NO_MODEL; /* virtual channel allocator input port arbiter */ if ( info->n_v_channel > 1 && info->n_in > 1) { if (info->vc_in_arb_model = PARM(vc_in_arb_model)) { if (PARM(vc_in_arb_model) == QUEUE_ARBITER) { SIM_array_init(&info->vc_in_arb_queue_info, 1, 1, 1, info->n_v_channel, SIM_logtwo(info->n_v_channel), 0, REGISTER); info->vc_in_arb_ff_model = SIM_NO_MODEL; } else { info->vc_in_arb_ff_model = PARM(vc_in_arb_ff_model); } } else { info->vc_in_arb_ff_model = SIM_NO_MODEL; } } else { info->vc_in_arb_model = SIM_NO_MODEL; info->vc_in_arb_ff_model = SIM_NO_MODEL; } /* virtual channel allocator output port arbiter */ if (info->n_in > 1 && info->n_v_channel > 1) { info->vc_out_arb_model = PARM(vc_out_arb_model); if (info->vc_out_arb_model) { if (info->vc_out_arb_model == QUEUE_ARBITER) { line_width = SIM_logtwo((info->n_total_in - 1)*info->n_v_channel); SIM_array_init(&info->vc_out_arb_queue_info, 1, 1, 1, (info->n_total_in -1) * info->n_v_channel, line_width, 0, REGISTER); info->vc_out_arb_ff_model = SIM_NO_MODEL; } else { info->vc_out_arb_ff_model = PARM(vc_out_arb_ff_model); } } else { info->vc_out_arb_ff_model = SIM_NO_MODEL; } } else { info->vc_out_arb_model = SIM_NO_MODEL; info->vc_out_arb_ff_model = SIM_NO_MODEL; } /*virtual channel allocation vc selection model */ // for NIRGAM //total number of entries = Number of Vcs //total cell width =log2(num_vcs) bit //in nirgam, we have assumed a list of available VCs(no. of Vcs) . info->vc_select_buf_type = PARM(vc_select_buf_type); if (info->vc_allocator_type == VC_SELECT && info->n_v_channel > 1 && info->n_in > 1) { info->vc_select_buf_type = PARM(vc_select_buf_type); SIM_array_init(&info->vc_select_buf_info, 1, 1, 1, info->n_v_channel, SIM_logtwo(info->n_v_channel), 0, info->vc_select_buf_type); } else { info->vc_select_buf_type = SIM_NO_MODEL; } /* redundant fields */ if (info->in_buf) { if (info->in_share_buf) info->in_n_switch = info->in_buf_info.read_ports; else if (info->in_share_switch) info->in_n_switch = 1; else info->in_n_switch = info->n_v_class * info->n_v_channel; } else info->in_n_switch = 1; if (info->cache_in_buf) { if (info->in_share_buf) info->cache_n_switch = info->cache_in_buf_info.read_ports; else if (info->in_share_switch) info->cache_n_switch = 1; else info->cache_n_switch = info->cache_class; } else info->cache_n_switch = 1; if (info->mc_in_buf) { if (info->in_share_buf) info->mc_n_switch = info->mc_in_buf_info.read_ports; else if (info->in_share_switch) info->mc_n_switch = 1; else info->mc_n_switch = info->mc_class; } else info->mc_n_switch = 1; if (info->io_in_buf) { if (info->in_share_buf) info->io_n_switch = info->io_in_buf_info.read_ports; else if (info->in_share_switch) info->io_n_switch = 1; else info->io_n_switch = info->io_class; } else info->io_n_switch = 1; info->n_switch_in = info->n_in * info->in_n_switch + info->n_cache_in * info->cache_n_switch + info->n_mc_in * info->mc_n_switch + info->n_io_in * info->io_n_switch; /* no buffering for local output ports */ info->n_switch_out = info->n_cache_out + info->n_mc_out + info->n_io_out; if (info->out_buf) { if (info->out_share_buf) info->n_switch_out += info->n_out * info->out_buf_info.write_ports; else if (info->out_share_switch) info->n_switch_out += info->n_out; else info->n_switch_out += info->n_out * info->n_v_class * info->n_v_channel; } else info->n_switch_out += info->n_out; /* clock related parameters */ info->pipelined = PARM(pipelined); info->H_tree_clock = PARM(H_tree_clock); info->router_diagonal = PARM(router_diagonal); if (info->pipelined || info->H_tree_clock) { info->clock_enabled = 1; } /* PHASE 2: initialization */ if (router_power) { SIM_router_power_init(info, router_power); } if (router_area) { SIM_router_area_init(info, router_area); } return 0; }
/* Decoder delay in the tag array (see section 6.1 of tech report) */ double SIM_decoder_tag_delay(int C, int B, int A, int Ndwl, int Ndbl, int Nspd, int Ntwl, int Ntbl, int Ntspd, double *Tdecdrive, double *Tdecoder1, double *Tdecoder2, double *outrisetime) { double Ceq,Req,Rwire,rows,tf,nextinputtime,vth = 0,tstep,m,a,b,c; int numstack; /* Calculate rise time. Consider two inverters */ Ceq = SIM_draincap(Wdecdrivep,PCH,1)+SIM_draincap(Wdecdriven,NCH,1) + SIM_gatecap(Wdecdrivep+Wdecdriven,0.0); tf = Ceq*SIM_transreson(Wdecdriven,NCH,1); nextinputtime = SIM_horowitz(0.0,tf,PARM(VTHINV100x60),PARM(VTHINV100x60),FALL)/ (PARM(VTHINV100x60)); Ceq = SIM_draincap(Wdecdrivep,PCH,1)+SIM_draincap(Wdecdriven,NCH,1) + SIM_gatecap(Wdecdrivep+Wdecdriven,0.0); tf = Ceq*SIM_transreson(Wdecdriven,NCH,1); nextinputtime = SIM_horowitz(nextinputtime,tf,PARM(VTHINV100x60),PARM(VTHINV100x60), RISE)/ (1.0-PARM(VTHINV100x60)); /* First stage: driving the decoders */ rows = C/(8*B*A*Ntbl*Ntspd); Ceq = SIM_draincap(Wdecdrivep,PCH,1)+SIM_draincap(Wdecdriven,NCH,1) + 4*SIM_gatecap(Wdec3to8n+Wdec3to8p,10.0)*(Ntwl*Ntbl)+ Cwordmetal*0.25*8*B*A*Ntbl*Ntspd; Rwire = Rwordmetal*0.125*8*B*A*Ntbl*Ntspd; tf = (Rwire + SIM_transreson(Wdecdrivep,PCH,1))*Ceq; *Tdecdrive = SIM_horowitz(nextinputtime,tf,PARM(VTHINV100x60),PARM(VTHNAND60x90), FALL); nextinputtime = *Tdecdrive/PARM(VTHNAND60x90); /* second stage: driving a bunch of nor gates with a nand */ numstack = (int)(ceil((1.0/3.0)*logtwo( (double)((double)C/(double)(B*A*Ntbl*Ntspd))))); if (numstack==0) numstack = 1; if (numstack>5) numstack = 5; Ceq = 3*SIM_draincap(Wdec3to8p,PCH,1) +SIM_draincap(Wdec3to8n,NCH,3) + SIM_gatecap(WdecNORn+WdecNORp,((numstack*40)+20.0))*rows + Cbitmetal*rows*8; Rwire = Rbitmetal*rows*8/2; tf = Ceq*(Rwire+SIM_transreson(Wdec3to8n,NCH,3)); /* we only want to charge the output to the threshold of the nor gate. But the threshold depends on the number of inputs to the nor. */ switch(numstack) { case 1: vth = PARM(VTHNOR12x4x1); break; case 2: vth = PARM(VTHNOR12x4x2); break; case 3: vth = PARM(VTHNOR12x4x3); break; case 4: vth = PARM(VTHNOR12x4x4); break; case 5: vth = PARM(VTHNOR12x4x4); break; case 6: vth = PARM(VTHNOR12x4x4); break; default: printf("error:numstack=%d\n",numstack); } *Tdecoder1 = SIM_horowitz(nextinputtime,tf,PARM(VTHNAND60x90),vth,RISE); nextinputtime = *Tdecoder1/(1.0-vth); /* Final stage: driving an inverter with the nor */ Req = SIM_transreson(WdecNORp,PCH,numstack); Ceq = (SIM_gatecap(Wdecinvn+Wdecinvp,20.0)+ numstack*SIM_draincap(WdecNORn,NCH,1)+ SIM_draincap(WdecNORp,PCH,numstack)); tf = Req*Ceq; *Tdecoder2 = SIM_horowitz(nextinputtime,tf,vth,PARM(VSINV),FALL); *outrisetime = *Tdecoder2/(PARM(VSINV)); return(*Tdecdrive+*Tdecoder1+*Tdecoder2); }
void SIM_calculate_time(time_result_type *result, time_parameter_type *parameters) { int Ndwl,Ndbl,Nspd,Ntwl,Ntbl,Ntspd,rows,columns,tag_driver_size1,tag_driver_size2; double access_time; double before_mux,after_mux; double decoder_data_driver,decoder_data_3to8,decoder_data_inv; double decoder_data,decoder_tag,wordline_data,wordline_tag; double decoder_tag_driver,decoder_tag_3to8,decoder_tag_inv; double bitline_data,bitline_tag,sense_amp_data,sense_amp_tag; double compare_tag,mux_driver,data_output,selb = 0; double time_till_compare,time_till_select,driver_cap,valid_driver; double cycle_time, precharge_del; double outrisetime,inrisetime; rows = parameters->number_of_sets; columns = 8*parameters->block_size*parameters->associativity; /* go through possible Ndbl,Ndwl and find the smallest */ /* Because of area considerations, I don't think it makes sense to break either dimension up larger than MAXN */ result->cycle_time = BIGNUM; result->access_time = BIGNUM; for (Nspd=1;Nspd<=PARM(MAXSPD);Nspd=Nspd*2) { for (Ndwl=1;Ndwl<=PARM(MAXN);Ndwl=Ndwl*2) { for (Ndbl=1;Ndbl<=PARM(MAXN);Ndbl=Ndbl*2) { for (Ntspd=1;Ntspd<=PARM(MAXSPD);Ntspd=Ntspd*2) { for (Ntwl=1;Ntwl<=1;Ntwl=Ntwl*2) { for (Ntbl=1;Ntbl<=PARM(MAXN);Ntbl=Ntbl*2) { if (SIM_organizational_parameters_valid (rows,columns,Ndwl,Ndbl,Nspd,Ntwl,Ntbl,Ntspd)) { /* Calculate data side of cache */ decoder_data = SIM_decoder_delay(parameters->cache_size,parameters->block_size, parameters->associativity,Ndwl,Ndbl,Nspd,Ntwl,Ntbl,Ntspd, &decoder_data_driver,&decoder_data_3to8, &decoder_data_inv,&outrisetime); inrisetime = outrisetime; wordline_data = SIM_wordline_delay(parameters->block_size, parameters->associativity,Ndwl,Nspd, inrisetime,&outrisetime); inrisetime = outrisetime; bitline_data = SIM_bitline_delay(parameters->cache_size,parameters->associativity, parameters->block_size,Ndwl,Ndbl,Nspd, inrisetime,&outrisetime); inrisetime = outrisetime; sense_amp_data = SIM_sense_amp_delay(inrisetime,&outrisetime); inrisetime = outrisetime; data_output = SIM_dataoutput_delay(parameters->cache_size,parameters->block_size, parameters->associativity,Ndbl,Nspd,Ndwl, inrisetime,&outrisetime); inrisetime = outrisetime; /* if the associativity is 1, the data output can come right after the sense amp. Otherwise, it has to wait until the data access has been done. */ if (parameters->associativity==1) { before_mux = decoder_data + wordline_data + bitline_data + sense_amp_data + data_output; after_mux = 0; } else { before_mux = decoder_data + wordline_data + bitline_data + sense_amp_data; after_mux = data_output; } /* * Now worry about the tag side. */ decoder_tag = SIM_decoder_tag_delay(parameters->cache_size, parameters->block_size,parameters->associativity, Ndwl,Ndbl,Nspd,Ntwl,Ntbl,Ntspd, &decoder_tag_driver,&decoder_tag_3to8, &decoder_tag_inv,&outrisetime); inrisetime = outrisetime; wordline_tag = SIM_wordline_tag_delay(parameters->cache_size, parameters->associativity,Ntspd,Ntwl, inrisetime,&outrisetime); inrisetime = outrisetime; bitline_tag = SIM_bitline_tag_delay(parameters->cache_size,parameters->associativity, parameters->block_size,Ntwl,Ntbl,Ntspd, inrisetime,&outrisetime); inrisetime = outrisetime; sense_amp_tag = SIM_sense_amp_tag_delay(inrisetime,&outrisetime); inrisetime = outrisetime; compare_tag = SIM_compare_time(parameters->cache_size,parameters->associativity, Ntbl,Ntspd, inrisetime,&outrisetime); inrisetime = outrisetime; if (parameters->associativity == 1) { mux_driver = 0; valid_driver = SIM_valid_driver_delay(parameters->cache_size, parameters->associativity,Ntbl,Ntspd,inrisetime); time_till_compare = decoder_tag + wordline_tag + bitline_tag + sense_amp_tag; time_till_select = time_till_compare+ compare_tag + valid_driver; /* * From the above info, calculate the total access time */ access_time = MAX(before_mux+after_mux,time_till_select); } else { mux_driver = SIM_mux_driver_delay(parameters->cache_size,parameters->block_size, parameters->associativity,Ndbl,Nspd,Ndwl,Ntbl,Ntspd, inrisetime,&outrisetime); selb = SIM_selb_delay_tag_path(inrisetime,&outrisetime); valid_driver = 0; time_till_compare = decoder_tag + wordline_tag + bitline_tag + sense_amp_tag; time_till_select = time_till_compare+ compare_tag + mux_driver + selb; access_time = MAX(before_mux,time_till_select) +after_mux; } /* * Calcuate the cycle time */ precharge_del = SIM_precharge_delay(wordline_data); cycle_time = access_time + precharge_del; /* * The parameters are for a 0.8um process. A quick way to * scale the results to another process is to divide all * the results by FUDGEFACTOR. Normally, FUDGEFACTOR is 1. */ if (result->cycle_time+1e-11*(result->best_Ndwl+result->best_Ndbl+result->best_Nspd+result->best_Ntwl+result->best_Ntbl+result->best_Ntspd) > cycle_time/PARM(FUDGEFACTOR)+1e-11*(Ndwl+Ndbl+Nspd+Ntwl+Ntbl+Ntspd)) { result->cycle_time = cycle_time/PARM(FUDGEFACTOR); result->access_time = access_time/PARM(FUDGEFACTOR); result->best_Ndwl = Ndwl; result->best_Ndbl = Ndbl; result->best_Nspd = Nspd; result->best_Ntwl = Ntwl; result->best_Ntbl = Ntbl; result->best_Ntspd = Ntspd; result->decoder_delay_data = decoder_data/PARM(FUDGEFACTOR); result->decoder_delay_tag = decoder_tag/PARM(FUDGEFACTOR); result->dec_tag_driver = decoder_tag_driver/PARM(FUDGEFACTOR); result->dec_tag_3to8 = decoder_tag_3to8/PARM(FUDGEFACTOR); result->dec_tag_inv = decoder_tag_inv/PARM(FUDGEFACTOR); result->dec_data_driver = decoder_data_driver/PARM(FUDGEFACTOR); result->dec_data_3to8 = decoder_data_3to8/PARM(FUDGEFACTOR); result->dec_data_inv = decoder_data_inv/PARM(FUDGEFACTOR); result->wordline_delay_data = wordline_data/PARM(FUDGEFACTOR); result->wordline_delay_tag = wordline_tag/PARM(FUDGEFACTOR); result->bitline_delay_data = bitline_data/PARM(FUDGEFACTOR); result->bitline_delay_tag = bitline_tag/PARM(FUDGEFACTOR); result->sense_amp_delay_data = sense_amp_data/PARM(FUDGEFACTOR); result->sense_amp_delay_tag = sense_amp_tag/PARM(FUDGEFACTOR); result->compare_part_delay = compare_tag/PARM(FUDGEFACTOR); result->drive_mux_delay = mux_driver/PARM(FUDGEFACTOR); result->selb_delay = selb/PARM(FUDGEFACTOR); result->drive_valid_delay = valid_driver/PARM(FUDGEFACTOR); result->data_output_delay = data_output/PARM(FUDGEFACTOR); result->precharge_delay = precharge_del/PARM(FUDGEFACTOR); } } } } } } } } }
/* Delay of the multiplexor Driver (see section 6.7) */ double SIM_mux_driver_delay(int C, int B, int A, int Ndbl, int Nspd, int Ndwl, int Ntbl, int Ntspd, double inputtime, double *outputtime) { double Ceq,Req,tf,nextinputtime; double Tst1,Tst2,Tst3; /* first driver stage - Inverte "match" to produce "matchb" */ /* the critical path is the DESELECTED case, so consider what happens when the address bit is true, but match goes low */ Ceq = SIM_gatecap(WmuxdrvNORn+WmuxdrvNORp,15.0)*(8*B/PARM(BITOUT)) + SIM_draincap(Wmuxdrv12n,NCH,1) + SIM_draincap(Wmuxdrv12p,PCH,1); Req = SIM_transreson(Wmuxdrv12p,PCH,1); tf = Ceq*Req; Tst1 = SIM_horowitz(inputtime,tf,PARM(VTHMUXDRV1),PARM(VTHMUXDRV2),FALL); nextinputtime = Tst1/PARM(VTHMUXDRV2); /* second driver stage - NOR "matchb" with address bits to produce sel */ Ceq = SIM_gatecap(Wmuxdrv3n+Wmuxdrv3p,15.0) + 2*SIM_draincap(WmuxdrvNORn,NCH,1) + SIM_draincap(WmuxdrvNORp,PCH,2); Req = SIM_transreson(WmuxdrvNORn,NCH,1); tf = Ceq*Req; Tst2 = SIM_horowitz(nextinputtime,tf,PARM(VTHMUXDRV2),PARM(VTHMUXDRV3),RISE); nextinputtime = Tst2/(1-PARM(VTHMUXDRV3)); /* third driver stage - invert "select" to produce "select bar" */ Ceq = PARM(BITOUT)*SIM_gatecap(Woutdrvseln+Woutdrvselp+Woutdrvnorn+Woutdrvnorp,20.0)+ SIM_draincap(Wmuxdrv3p,PCH,1) + SIM_draincap(Wmuxdrv3n,NCH,1) + Cwordmetal*8*B*A*Nspd*Ndbl/2.0; Req = (Rwordmetal*8*B*A*Nspd*Ndbl/2)/2 + SIM_transreson(Wmuxdrv3p,PCH,1); tf = Ceq*Req; Tst3 = SIM_horowitz(nextinputtime,tf,PARM(VTHMUXDRV3),PARM(VTHOUTDRINV),FALL); *outputtime = Tst3/(PARM(VTHOUTDRINV)); return(Tst1 + Tst2 + Tst3); }