bool do_tests(int repeat, int max_n, int trials) { boost::mt19937 gen; boost::uniform_int<> idist(1, max_n); int errors = 0; for(int i = 0; i < repeat; ++i) { if(!do_test(idist(gen), trials)) { ++errors; } } if(errors != 0) { std::cout << "*** " << errors << " errors detected ***" << std::endl; } return errors == 0; }
/** * This test is similar to "testProcessFlipFlopAtMaxSpeed". * This time the the processes will have random timing , thus we might * discover dead locks and the like. */ void portTest::testRandomTiming() { mt19937 rng(0); // the Mersenne Twister random generator uniform_int_distribution<uint32_t> idist(0, 25); bernoulli_distribution bdist(0.5); for (int i = 0; i < 10; i++) { doTestRandomTiming(// bdist(rng), //bool isOutput, idist(rng), // int initializeDuration, idist(rng), // int registerDuration, idist(rng), // int startDuration, idist(rng), // int execJavaProcessDuration, idist(rng), // int execNativeProcessDuration, idist(rng), // int stopDuration, idist(rng), // int uninitializeDuration, idist(rng)); // int unregisterDuration) } }
std::pair<int, int> simulacion(int bloques, int bloque_size, int vias, int accesos, int pagina_size) { int paginas_disco, paginas_mem, fallos_pagina, fallos_cache, bits_offset, div_virt, div_fisica; std::cout << "Numero de bloques: " << bloques << std::endl; std::cout << "Tamano de bloque: " << bloque_size << std::endl; std::cout << "Numero de vias: " << vias << std::endl; std::cout << "Numero de accesos: " << accesos << std::endl; std::cout << "Tamanio de pagina: " << pagina_size << std::endl; std::cout << "Inicializando..."; std::random_device rseed; // Para numeros aleatorios std::mt19937 rgen(rseed()); // mersenne_twister std::uniform_int_distribution<int> idist(0, DIR_VIRUTALES - 1); // [0,4095] std::uniform_int_distribution<int> odist(0, 1); // [0,1] std::uniform_int_distribution<int> ddist(0, 255); // [0,255] std::uniform_int_distribution<int> nueva_dist(256, 511); // [0,255] /* ins_virtuales[*][x], x: 0 - direccion, 1 - lectura/escritura, 2 - dato */ std::vector<std::vector<int> > ins_virtuales (accesos, std::vector<int> (3,0)); std::vector<int> memoria (POS_MEMORIA); std::vector<int> disco (POS_DISCO); t_tabla tabla; /* Creamos la cache */ Cache mem_cache (vias, bloques, bloque_size); /* Inicializacion */ paginas_disco = POS_DISCO / pagina_size; paginas_mem = POS_MEMORIA / pagina_size; std::uniform_int_distribution<int> mdist(0, paginas_mem-1); // [0,paginas_memoria] fallos_pagina = 0; fallos_cache = 0; bits_offset = bits_para(pagina_size); div_virt = potencia(bits_offset);// para posterior division div_fisica = potencia(bits_para(bloque_size));// para posterior division std::cout << " Inicializacion terminada!" << std::endl; std::cout << "Paginas Memoria: " << paginas_mem << std::endl; std::cout << "Paginas Disco: " << paginas_disco << std::endl; std::cout << "Generando instrucciones..." << std::endl; /* Generar instrucciones virtuales */ for (int i = 0; i < accesos; ++i) { ins_virtuales[i][0] = idist(rgen); ins_virtuales[i][1] = odist(rgen); ins_virtuales[i][2] = nueva_dist(rgen); } std::cout << " Terminado!" << std::endl; std::cout << "Generando tabla de traduccion..." << std::endl; /* Generamos la tabla de traduccion */ int contador; for (contador = 0; contador < accesos; ++contador) { int tmp = ins_virtuales[contador][0]/div_virt; if(tabla.size() > paginas_mem) break; if(tabla.count(tmp) == 0) { tabla[tmp].push_back(odist(rgen)); /* 1 - memoria principal */ tabla[tmp].push_back(0); /* 1 - dato en disco mem llena */ tabla[tmp].push_back(contador); /* dir fisica */ } } for (; contador < accesos; ++contador) { int tmp = ins_virtuales[contador][0]/div_virt; if(tabla.size() >= (paginas_mem + paginas_disco)) break; if(tabla.count(tmp) == 0) { tabla[tmp].push_back(0); /* 1 - memoria principal */ tabla[tmp].push_back(1); /* 1 - dato en disco mem llena */ tabla[tmp].push_back(contador); /* dir disco */ } } std::cout << " Terminado!" << std::endl; std::cout << " Tamaño tabla: " << tabla.size() << std::endl; /* leemos la memoria y el disco */ std::ifstream inputmem; std::ifstream inputdisc; std::string outmem; std::string outdisc; int valor_io; int contador_io = 0; std::cout << "Leyendo memoria..." << std::endl; inputmem.open("memoria.txt", std::ifstream::in); while(inputmem >> valor_io) { memoria[contador_io] = valor_io; contador_io++; } inputmem.close(); std::cout << " Terminado!" << std::endl; if (contador_io == 0) { std::cout << "Memoria vacia, abortando!" << std::endl; return std::make_pair(0,0); } std::cout << "Leyendo disco..." << std::endl; inputdisc.open("disco.txt", std::ifstream::in); contador_io = 0; while(inputdisc >> valor_io) { disco[contador_io] = valor_io; contador_io++; } inputdisc.close(); std::cout << " Terminado!" << std::endl; if (contador_io == 0) { std::cout << "Disco vacio, abortando!" << std::endl; return std::make_pair(0,0); } std::cout << "Procesando instrucciones..." << std::endl; /* Iteramos en cada instruccion */ int dir_fisica, tmp, tmp2; std::vector<int> movimiento (bloque_size,0); std::vector<int> respuesta_cache; for (int i = 0; i < accesos; ++i) { /* Traducimos direccion virtual a fisica */ dir_fisica = ins_virtuales[i][0]/div_virt; /* No esta en memoria principal? */ if(tabla[dir_fisica][0] == 0) { //std::cout << "Fallo Pagina!" << std::endl; tabla[dir_fisica][0] = 1; fallos_pagina++; // nuevo fallo de pagina tmp2 = tabla[dir_fisica][2]; // direccion disco /* no esta asigana? */ if(tabla[dir_fisica][1] == 1) { tabla[dir_fisica][1] = 0; tmp = mdist(rgen); // nueva asignacion. tabla[dir_fisica][2] = tmp; /* Movemos de disco a memoria */ } else tmp = tmp2; // Si esta asignada disco - memoria concuerdan. tmp = tmp * div_virt; tmp2 = tmp2 * div_virt; for(int j = 0; j < pagina_size; ++j) { memoria[tmp + j] = disco[tmp2 + j]; } } /* El dato ya esta en memoria principal */ /* Extraemos direccion fisica */ dir_fisica = tabla[dir_fisica][2] * div_virt; /* Agregamos el offset */ dir_fisica = dir_fisica + (ins_virtuales[i][0] % div_virt); /* Cargamos los datos que hay en la memoria por si hay un miss en cache */ tmp = dir_fisica - (dir_fisica % div_fisica); // quitamos el offset de un bloque. for (int j = 0; j < bloque_size; ++j) { movimiento[j] = memoria[tmp + j]; } /* Lectura o escritura */ if (ins_virtuales[i][1] == 0) { //std::cout << "Read" << std::endl; respuesta_cache = mem_cache.read_cache(dir_fisica, movimiento); } else { //::cout << "Write" << std::endl; respuesta_cache = mem_cache.write_cache(dir_fisica, movimiento, ins_virtuales[i][2]); } /* Analimamos la respuesta de la cache */ /* no fue un hit? */ if(respuesta_cache[0] != 1) fallos_cache++; /* hay que escribir en memoria, por write-back? */ if (respuesta_cache[1] == 1) { //std::cout << "write-back" << std::endl; tmp = respuesta_cache[2]; // donde, escribir tmp = tmp - (tmp % div_fisica); // quitamos el offset del bloque. for (int j = 0; j < bloque_size; ++j) { memoria[tmp + j] = respuesta_cache[3+j]; } } } std::cout << " Terminado!" << std::endl; std::cout << "Reescribiendo memoria..." << std::endl; /* Excribimos en los archivos */ std::ofstream ofm ("memoria.txt", std::ofstream::out); for (int i = 0; i < POS_MEMORIA; ++i) { ofm << memoria[i] << "\n"; } ofm.close(); std::cout << "Terminado!" << std::endl; std::cout << "Reescribiendo disco..." << std::endl; std::ofstream ofd ("disco.txt", std::ofstream::out); for (int i = 0; i < POS_DISCO; ++i) { ofd << disco[i] << "\n"; } ofd.close(); std::cout << "Terminado!" << std::endl; std::cout << fallos_pagina << " " << fallos_cache << std::endl; return std::make_pair(fallos_pagina, fallos_cache); }
Graph * geo_hier(long seed, int nlevels, /* number of levels (=size of following array) */ int edgemeth, /* method of attaching edges */ int aux, /* auxiliary parameter for edge method (threshold) */ geo_parms *pp) /* array of parameter structures, one per level */ { Graph *newG, *tG, *GG, *srcG, *dstG; long *numv; /* array of sizes of lower-level graphs */ geo_parms *curparms, workparms[MAXLEVEL]; register i,k,indx; long dst; int temp,total,lowsize,otherend,blen,level; long maxP[MAXLEVEL], maxDiam[MAXLEVEL], wt[MAXLEVEL]; Vertex *np,*vp,*up,*base; Arc *ap; char vnamestr[MAXNAMELEN]; if (seed) /* convention: zero seed means don't use */ gb_init_rand(seed); if (nlevels < 1 || nlevels > MAXLEVEL) { gb_trouble_code = bad_specs+HIER_TRBL; return NULL; } /* 1 <= nlevels <= MAXLEVEL */ /* copy the parameters so we can modify them, and caller doesn't * see the changes. */ for (level=0; level<nlevels; level++) bcopy((char *)&pp[level],&workparms[level],sizeof(geo_parms)); level = 0; gb_trouble_code = 0; tG = NULL; do { gb_recycle(tG); tG = geo(0L,workparms); } while (tG != NULL && !isconnected(tG)); if (tG==NULL) return tG; maxDiam[0] = fdiam(tG); maxP[0] = maxDiam[0]; wt[0] = 1; for (i=1; i<nlevels; i++) maxDiam[i] = -1; curparms = workparms; while (++level < nlevels) { long tdiam; curparms++; /* parameters for graphs @ next level */ /* spread out the numbers of nodes per graph at this level */ numv = (long *) calloc(tG->n,sizeof(long)); lowsize = curparms->n; randomize(numv,tG->n,curparms->n,3*tG->n); /* create a subordinate graph for each vertex in the "top" graph, * and add it into the new graph as a whole. * We construct the subgraphs all at once to ensure that each * has a unique address. */ for (i=0,vp=tG->vertices; i<tG->n; i++,vp++) { curparms->n = numv[i]; do { newG = geo(0L,curparms); if (newG==NULL) return NULL; } while (!isconnected(newG)); vp->sub = newG; tdiam = fdiam(newG); if (tdiam>maxDiam[level]) maxDiam[level] = tdiam; } /* do some calculations before "flattening" the top Graph */ total = 0; for (i=0; i<tG->n; i++) { /* translate node numbers */ temp = numv[i]; numv[i]= total; total += temp; } if (total != tG->n*lowsize) { fprintf(stderr,"bad size of new graph!\n"); fprintf(stderr,"total %d tG->n %ld lowsize %d\n",total,tG->n,lowsize); gb_trouble_code = impossible+HIER_TRBL; return NULL; } /* now create what will become the "new" top-level graph */ newG = gb_new_graph(total); if (newG==NULL) { gb_trouble_code += HIER_TRBL; return NULL; } /* resolution of the new graph */ newG->Gscale = tG->Gscale * curparms->scale; /* compute edge weights for this level */ wt[level] = maxP[level-1] + 1; maxP[level] = (maxDiam[level]*wt[level]) + (maxDiam[level-1]*maxP[level-1]); for (i=0,vp=tG->vertices; i<tG->n; i++,vp++) { strcpy(vnamestr,vp->name); /* base name for all "offspring" */ blen = strlen(vnamestr); vnamestr[blen] = '.'; GG = tG->vertices[i].sub; base = newG->vertices + numv[i]; /* start of this node's */ for (k=0,np=base,up=GG->vertices; k<GG->n; k++,np++,up++) { /* add the node's edges */ for (ap=up->arcs; ap; ap=ap->next) { otherend = ap->tip - GG->vertices; if (k < otherend) gb_new_edge(np,base+otherend,ap->len); } /* now set the new node's position */ np->xpos = tG->vertices[i].xpos * curparms->scale + up->xpos; np->ypos = tG->vertices[i].ypos * curparms->scale + up->ypos; /* give the "new" node a name by catenating top & bot names */ strcpy(vnamestr+blen+1,up->name); np->name = gb_save_string(vnamestr); } /* loop over GG's vertices */ } /* loop over top-level vertices */ /* * Now we have to transfer the top-level edges to new graph. * This is done by one of three methods: * 0: choose a random node in each subgraph * 1: attach to the smallest-degree non-leaf node in each * 2: attach to smallest-degree node * 3: attach to first node with degree less than aux */ for (i=0; i<tG->n; i++) { Vertex *srcp, *dstp; Graph *srcG, *dstG; srcG = tG->vertices[i].sub; if (srcG == NULL) { /* paranoia */ gb_trouble_code = impossible+HIER_TRBL+1; return NULL; } for (ap=tG->vertices[i].arcs; ap; ap=ap->next) { dst = ap->tip - tG->vertices; if (i > dst) /* consider each edge only ONCE */ continue; dstG = ap->tip->sub; if (dstG == NULL) { /* paranoia */ gb_trouble_code = impossible+HIER_TRBL+1; return NULL; } /* choose endpoints of the top-level edge */ switch (edgemeth) { case 0: /* choose random node in each */ srcp = srcG->vertices + gb_next_rand()%srcG->n; dstp = dstG->vertices + gb_next_rand()%dstG->n; break; case 1: /* find nonleaf node of least degree in each */ /* This causes problems with graph size < 3 */ if (srcG->n > 2) srcp = find_small_deg(srcG,NOLEAF); else srcp = find_small_deg(srcG,LEAFOK); if (dstG->n > 2) dstp = find_small_deg(dstG,NOLEAF); else dstp = find_small_deg(dstG,LEAFOK); break; case 2: /* find node of smallest degree */ srcp = find_small_deg(srcG,LEAFOK); dstp = find_small_deg(dstG,LEAFOK); break; case 3: /* first node w/degree < aux */ srcp = find_thresh_deg(srcG,aux); dstp = find_thresh_deg(dstG,aux); default: gb_trouble_code = bad_specs+HIER_TRBL; return NULL; } /* switch on edgemeth */ /* pointer arithmetic: isn't it fun? printf("Copying edge from %d to %d\n", numv[i]+(srcp - srcG->vertices), numv[dst] + (dstp - dstG->vertices)); */ if (srcp==NULL || dstp==NULL) { gb_trouble_code = impossible + HIER_TRBL+2; return NULL; } srcp = newG->vertices + numv[i] + (srcp - srcG->vertices); dstp = newG->vertices + numv[dst] + (dstp - dstG->vertices); gb_new_edge(srcp,dstp,idist(srcp,dstp)); } /* for each arc */ } /* for each vertex of top graph */ /* now make the "new" graph the "top" graph and recycle others */ for (i=0,vp=tG->vertices; i<tG->n; i++,vp++) gb_recycle(vp->sub); gb_recycle(tG); tG = newG; free(numv); } /* while more levels */ /* Finally, go back and add the policy weights, * based upon the computed max diameters * and Max Path lengths. */ for (i=0; i<tG->n; i++) for (ap=tG->vertices[i].arcs; ap; ap=ap->next) { dst = ap->tip - tG->vertices; if (i > dst) /* consider each edge only ONCE */ continue; assert(i != dst); /* no self loops */ /* i < dst: it is safe to refer to ap's mate by ap+1. */ level = edge_level(&tG->vertices[i],&tG->vertices[dst],nlevels); ap->policywt = (ap+1)->policywt = wt[level]; } /* construct the utility and id strings for the new graph. * Space constraints will restrict us to keeping about 4 levels' * worth of info. */ { char buf[ID_FIELD_SIZE+1]; register char *cp; int len, nextlen, left; strcpy(tG->util_types,GEO_UTIL); /* same for all geo graphs, */ /* defined in geo.h */ cp = tG->id; sprintf(cp,"geo_hier(%ld,%d,%d,%d,[",seed,nlevels,edgemeth,aux); len = strlen(cp); left = ID_FIELD_SIZE - len; cp += len; for (i=0; (i < nlevels) && (left > 0); i++) { nextlen = printparms(buf,&pp[i]); strncpy(cp,buf,left); left -= nextlen; cp += nextlen; } if (left > 0) { sprintf(buf,"])"); nextlen = strlen(buf); strncpy(cp,buf,left); } } return tG; } /* geo_hier() */