static void cache_miss(struct cache *cache, enum access_type type, struct set *set, struct decoded_address *access_addr) { cache->miss_count[type]++; struct cache_entry *e = entry_to_evict(set); if ((e->flags & VALID) && (e->flags & DIRTY)) { // write the contents of the evicted address to the // next level cache struct decoded_address evict_addr; evict_addr.tag = e->tag; evict_addr.index = access_addr->index; evict_addr.offset = 0; cache->writeback_count++; cache_access(cache->next, WRITE_ACCESS, encode_address(&evict_addr, cache)); } cache_access(cache->next, READ_ACCESS, encode_address(access_addr, cache)); e->tag = access_addr->tag; e->age = 0; e->flags = VALID; if (type == WRITE_ACCESS) e->flags |= DIRTY; }
/* system call memory access function */ enum md_fault_type dcache_access_fn(struct mem_t *mem, /* memory space to access */ enum mem_cmd cmd, /* memory access cmd, Read or Write */ md_addr_t addr, /* data address to access */ void *p, /* data input/output buffer */ int nbytes) /* number of bytes to access */ { if (dtlb) cache_access(dtlb, cmd, addr, NULL, nbytes, 0, NULL, NULL, 0); if (cache_dl1) cache_access(cache_dl1, cmd, addr, NULL, nbytes, 0, NULL, NULL, 0); return mem_access(mem, cmd, addr, p, nbytes); }
int main_(int argc, char *argv[]) { int cache_params[CACHE_COUNT * 3]; parse_args(argc, argv, cache_params); struct cache caches[CACHE_COUNT]; int j = 0; for (int i = 0; i < CACHE_COUNT; ++i) { int level = i + 1; int c = cache_params[j++]; int b = cache_params[j++]; int s = cache_params[j++]; cache_init(&caches[i], &caches[i+1], level, c, b, s); } caches[CACHE_COUNT - 1].next = NULL; void *addr; char rw; while (!feof(stdin)) { fscanf(stdin, "%c %p\n", &rw, &addr); cache_access(caches, rw2access_type(rw), addr); } print_results(caches); for (int i = 0; i < CACHE_COUNT; ++i) { cache_destroy(&caches[i]); } return 0; }
uns64 memsys_access_modeA(Memsys *sys, Addr lineaddr, Access_Type type, uns core_id){ Flag needs_dcache_access=FALSE; Flag is_write=FALSE; if(type == ACCESS_TYPE_IFETCH){ // no icache in this mode } if(type == ACCESS_TYPE_LOAD){ needs_dcache_access=TRUE; is_write=FALSE; } if(type == ACCESS_TYPE_STORE){ needs_dcache_access=TRUE; is_write=TRUE; } if(needs_dcache_access){ Flag outcome=cache_access(sys->dcache, lineaddr, is_write, core_id); if(outcome==MISS){ cache_install(sys->dcache, lineaddr, is_write, core_id); } } // timing is not simulated in Part A return 0; }
void prefetch (struct cache_t *cp, md_addr_t addr) { md_addr_t set = CACHE_SET(cp, addr); md_addr_t tag = CACHE_TAG(cp, addr); md_addr_t baddr = CACHE_MK_BADDR(cp, tag, set); if (!cache_probe(cp, baddr)) { cache_access(cp, Read, baddr, NULL, cp->bsize, NULL, NULL, NULL, 1); } }
void warmup_handler(const struct predec_insn_t *pdi) { if (cache_il1) cache_access(cache_il1, mc_READ, regs.PC, sizeof(md_inst_t), 0, NULL, l1_miss_handler); if (itlb) cache_access(itlb, mc_READ, regs.PC, sizeof(md_inst_t), 0, NULL, tlb_miss_handler); if (pdi->iclass == ic_load || pdi->iclass == ic_store || pdi->iclass == ic_prefetch) { enum mem_cmd_t dl1_cmd = pdi->iclass == ic_load ? mc_READ : (pdi->iclass == ic_store ? mc_WRITE : mc_PREFETCH); enum mem_cmd_t dtlb_cmd = (pdi->iclass == ic_load || pdi->iclass == ic_store) ? mc_READ : mc_PREFETCH; bool_t miss_info[ct_NUM] = {FALSE, FALSE, FALSE, FALSE}; if (cache_dl1) cache_access(cache_dl1, dl1_cmd, regs.addr, regs.dsize, 0, miss_info, l1_miss_handler); if (dtlb) cache_access(dtlb, dtlb_cmd, regs.addr, regs.dsize, 0, NULL, tlb_miss_handler); } }
bool dcache_access(ADDRINT addr) { /** please change uint32_t to ADDRINT NEW-LAB2 */ /* For Lab #1, you assume that all D-cache hit */ /* For Lab #2, you need to connect cache here */ // NEW-LAB2 bool hit = FALSE; if (KNOB(KNOB_PERFECT_DCACHE)->getValue()) hit = TRUE; else { hit=cache_access(data_cache,addr); } return hit; }
/* l1 data cache l1 block miss handler function */ static unsigned int /* latency of block access */ l1_miss_handler(enum mem_cmd_t cmd, /* access cmd, Read or Write */ md_addr_t baddr, /* block address to access */ unsigned int bsize, /* size of block to access */ tick_t now, /* time of access */ bool_t miss_info[ct_NUM]) { if (cache_l2) cache_access(cache_l2, cmd, baddr, bsize, now, miss_info, l2_miss_handler); return /* access latency, ignored */0; }
bool dcache_access(ADDRINT addr) { /** please change uint32_t to ADDRINT NEW-LAB2 */ /* For Lab #1, you assume that all D-cache hit */ /* For Lab #2, you need to connect cache here */ // NEW-LAB2 // bool cache_hit; bool hit = FALSE; if (KNOB(KNOB_PERFECT_DCACHE)->getValue()) hit = TRUE; else { // cache_hit=(bool)cache_access(data_cache,addr); hit=(bool)cache_access(data_cache,addr); // std::cout<<"cache hit="<<cache_hit; // return cache_hit; } // std::cout<<"cache hit="<<hit; return hit; }
/* l1 inst cache l1 block miss handler function */ static unsigned int /* latency of block access */ il1_access_fn(enum mem_cmd cmd, /* access cmd, Read or Write */ md_addr_t baddr, /* block address to access */ int bsize, /* size of block to access */ struct cache_blk_t *blk, /* ptr to block in upper level */ tick_t now) /* time of access */ { if (cache_il2) { /* access next level of inst cache hierarchy */ return cache_access(cache_il2, cmd, baddr, NULL, bsize, /* now */now, /* pudata */NULL, /* repl addr */NULL); } else { /* access main memory, which is always done in the main simulator loop */ return /* access latency, ignored */1; } }
/* Next Line Prefetcher */ void next_line_prefetcher(struct cache_t *cp, md_addr_t addr) { //prefetch logic //get the next block of data from the addr assert(cp != NULL); md_addr_t new_addr = addr + cp->bsize; new_addr -= new_addr % cp->bsize; if(cache_probe(cp, new_addr) == 0){ cache_access(cp, /* cache to access */ Read, /* access type, Read or Write */ new_addr, /* address of access */ NULL, /* ptr to buffer for input/output */ cp->bsize, /* number of bytes to access */ 0, /* time of access */ NULL, /* for return of user data ptr */ NULL, /* for address of replaced block */ 1); } }
int main(int argc, char* argv[]) { int opt; uint64_t c = DEFAULT_C; uint64_t b = DEFAULT_B; uint64_t s = DEFAULT_S; uint64_t v = DEFAULT_V; char st = DEFAULT_ST; char r = DEFAULT_R; FILE* fin = stdin; /* Read arguments */ while(-1 != (opt = getopt(argc, argv, "c:b:s:t:i:v:r:h"))) { switch(opt) { case 'c': c = atoi(optarg); break; case 'b': b = atoi(optarg); break; case 's': s = atoi(optarg); break; case 't': if(optarg[0] == BLOCKING || optarg[0] == SUBBLOCKING) { st = optarg[0]; } break; case 'v': v = atoi(optarg); break; case 'r': if(optarg[0] == LRU || optarg[0] == NMRU_FIFO) { r = optarg[0]; } break; case 'i': fin = fopen(optarg, "r"); break; case 'h': /* Fall through */ default: print_help_and_exit(); break; } } printf("Cache Settings\n"); printf("C: %" PRIu64 "\n", c); printf("B: %" PRIu64 "\n", b); printf("S: %" PRIu64 "\n", s); printf("V: %" PRIu64 "\n", v); printf("F: %s\n", st == BLOCKING ? "BLOCKING" : "SUBBLOCKING"); printf("R: %s\n", r == LRU ? "LRU" : "NMRU_FIFO"); printf("\n"); /* Setup the cache */ setup_cache(c, b, s, v, st, r); /* Setup statistics */ cache_stats_t stats; memset(&stats, 0, sizeof(cache_stats_t)); /* Begin reading the file */ char rw; uint64_t address; while (!feof(fin)) { int ret = fscanf(fin, "%c %" PRIx64 "\n", &rw, &address); if(ret == 2) { cache_access(rw, address, &stats); } } complete_cache(&stats); print_statistics(&stats); return 0; }
// Returns the delay required to service a given request uns64 memsys_access_modeBC(Memsys *sys, Addr lineaddr, Access_Type type,uns core_id){ uns64 delay=0; Flag needs_icache_access=FALSE; Flag needs_dcache_access=FALSE; Flag needs_l2_access=FALSE; Flag is_write=FALSE; Flag outcome_L1; // local variable to know if it's a hit or not (miss) Flag outcome_L2; if(type == ACCESS_TYPE_IFETCH){ // YOU NEED TO WRITE THIS PART AND UPDATE DELAY // first see if it's a L1 cache hit, if yes then add ICACHE_HIT_LATENCY // If it's a miss then call memsys_L2_access().. [This function will take care // if there's a further L2 miss/hit] needs_icache_access = TRUE; needs_dcache_access = FALSE; is_write = FALSE; Flag is_writeback = FALSE; outcome_L1 = cache_access(sys->icache, lineaddr, is_write, core_id); // L1-ICACHE Access if (outcome_L1 == HIT) { delay = ICACHE_HIT_LATENCY; } else { // there's L1 miss // If there is a L1 MISS then we need to find that line in L2 outcome_L2 = cache_access(sys->l2cache, lineaddr, is_write, core_id); delay += L2CACHE_HIT_LATENCY; // If L2 is a hit.. then install the line in L1.. and if something get's // evicted due to this and is dirty.. install it in L2 mark is_writeback true, // if something get's evicted which is not dirty still install it in L2 // if nothing get's evicted.. don't install it in L2 if (outcome_L2 == HIT) { cache_install(sys->icache, lineaddr, is_write, core_id); // Would this result in eviction.. if yes install the evicted line in L2 // and if the evicted line is dirty mark 'is_writeback' true.. if (sys->icache->last_evicted_line.valid) { // First see if evicted line from L1 is dirty.. if yes then install it in L2 blindly // if not dirty then check if line is present in L2(L2-hit), if yes, then don't install // it, otherwise install it. if (sys->icache->last_evicted_line.dirty) { is_writeback = TRUE; cache_install(sys->l2cache, sys->icache->last_evicted_line.tag, is_write, core_id); // This installation may further result in L2 eviction.. if those eviction are dirty // install them in dram, otherwise don't install them! if ((sys->l2cache->last_evicted_line.valid) && (sys->l2cache->last_evicted_line.dirty)) { // Check: Do I need to but 'is_writeback' true here as well? dram_access(sys->dram, sys->l2cache->last_evicted_line.tag, true); // Check: this evicted line has been put in DRAM.. now put valid as false sys->l2cache->last_evicted_line.valid = FALSE; } } else { // If evicted line is not dirty // If evicted line is not dirty then check if it's L2 hit, if yes don't do anything // if not then install it in L2, again there will be eviction due to this installation // in L2, if the evicted line is dirty write-back to memory Flag outcome_L1_evic_L2 = cache_access(sys->l2cache, sys->icache->last_evicted_line.tag, is_write, core_id); if (outcome_L1_evic_L2 == HIT) { // Do nothing } else { // cache_install(sys->l2cache, sys->icache->last_evicted_line.tag, is_write, core_id); // This installation may further result in L2 eviction.. if those eviction are dirty // install them in dram, otherwise don't install them! if ((sys->l2cache->last_evicted_line.valid) && (sys->l2cache->last_evicted_line.dirty)) { // Check: Do I need to but 'is_writeback' true here as well? dram_access(sys->dram, sys->l2cache->last_evicted_line.tag, true); sys->l2cache->last_evicted_line.valid = FALSE; } } } // L1 evited line is taken care-of, now put evicted-line as false sys->icache->last_evicted_line.valid = FALSE; } } else { // If there's an L2 Miss // you first install the line both at L2 and L1 from DRAM (update delay) // check if evicted line from L2 is valid and dirty, if yes write it to dram // check if evicted line from L1 is dirty, if yes write it blindly to L2, again // if evicted line from L2 is valid and dirty, if yes write it to dram // if evicted line from L1 is not dirty, check if L2 already have it.. if it has, do nothing // if not put the line in L2 and if evicted line from L2 is valid and dirty, if yes write it to dram // got the line from DRAM delay += dram_access(sys->dram, lineaddr, is_write); // L2 install: cache_install(sys->l2cache, lineaddr, is_write, core_id); // L1 install: cache_install(sys->icache, lineaddr, is_write, core_id); // if evicted line from L2 is valid and dirty, if yes write it to dram if ((sys->l2cache->last_evicted_line.valid) && (sys->l2cache->last_evicted_line.dirty)) { // Check: Do I need to but 'is_writeback' true here as well? dram_access(sys->dram, sys->l2cache->last_evicted_line.tag, true); sys->l2cache->last_evicted_line.valid = FALSE; } // if evicted line from L1 is valid and dirty if (sys->icache->last_evicted_line.valid) { if (sys->icache->last_evicted_line.dirty) { cache_install(sys->l2cache, sys->icache->last_evicted_line.tag, is_write, core_id); if ((sys->l2cache->last_evicted_line.valid) && (sys->l2cache->last_evicted_line.dirty)) { dram_access(sys->dram, sys->l2cache->last_evicted_line.tag, true); sys->l2cache->last_evicted_line.valid = FALSE; } } else { Flag outcome_L1_evic_L2 = cache_access(sys->l2cache, sys->icache->last_evicted_line.tag, is_write, core_id); if (outcome_L1_evic_L2 == HIT) { // Do nothing } else { // cache_install(sys->l2cache, sys->icache->last_evicted_line.tag, is_write, core_id); if ((sys->l2cache->last_evicted_line.valid) && (sys->l2cache->last_evicted_line.dirty)) { // Check: Do I need to but 'is_writeback' true here as well? dram_access(sys->dram, sys->l2cache->last_evicted_line.tag, true); sys->l2cache->last_evicted_line.valid = FALSE; } } } // L1 evited line is taken care-of, now put evicted-line as false sys->icache->last_evicted_line.valid = FALSE; } } } // Do not forget to update the stat sys->stat_ifetch_access++; // Check: In 'stat_ifetch_delay' do we keep adding the whole delay parameter.. or just increment it // going with the former one sys->stat_ifetch_delay = delay + sys->stat_ifetch_delay; } if(type == ACCESS_TYPE_LOAD){ // YOU NEED TO WRITE THIS PART AND UPDATE DELAY Flag hit; hit = cache_access(sys->dcache, lineaddr, false /*is_write*/, core_id); // L1-DCACHE Access if (hit == HIT) { delay = DCACHE_HIT_LATENCY; } else { delay = DCACHE_HIT_LATENCY + memsys_L2_access(sys, lineaddr, false /*is_writeback*/, core_id); } // Do not forget to update the stat. sys->stat_load_access++; // Check: In 'stat_load_delay' do we keep adding the whole delay parameter.. or just increment it // going with the former one sys->stat_load_delay = delay + sys->stat_load_delay; } if(type == ACCESS_TYPE_STORE){ // YOU NEED TO WRITE THIS PART AND UPDATE DELAY Flag hit; hit = cache_access(sys->dcache, lineaddr, true /*is_write*/, core_id); // L1-DCACHE Access if (hit == HIT) { delay = DCACHE_HIT_LATENCY; } else { delay = DCACHE_HIT_LATENCY + memsys_L2_access(sys, lineaddr, true /*is_writeback*/, core_id); } // Do not forget to update the stat. sys->stat_store_access++; // Check: In 'stat_store_delay' do we keep adding the whole delay parameter.. or just increment it // going with the former one sys->stat_store_delay = delay + sys->stat_store_delay; } return delay; }
uns64 memsys_L2_access(Memsys *sys, Addr lineaddr, Flag is_writeback, uns core_id){ //To get the delay of L2 MISS, you must use the dram_access() function //To perform writebacks to memory, you must use the dram_access() function //This will help us track your memory reads and memory writes uns64 delay = L2CACHE_HIT_LATENCY; // initialized the delay with Hit latency Flag outcome_L2; if(is_writeback == 0) { //Reading <both for LD/ST> (requesting line in case of store as following WB strategy) // Read request from L1 outcome_L2 = cache_access(sys->l2cache, lineaddr, 0, core_id); // Reading line from L2 in case of L1 miss if (outcome_L2 == MISS) { // If there is L2 miss on read // Delay for DRAM access // Reading the cache-line from DRAM (Get the line from DRAM) delay += dram_access(sys->dram, lineaddr, 0); // cache_install() takes care of eviction stat cache_install(sys->l2cache, lineaddr, 0, core_id); // Install the line into L2.. it is not dirty // If the evicted line is dirty you need to write it to DRAM, otherwise no action required if(sys->l2cache->last_evicted_line.valid && sys->l2cache->last_evicted_line.dirty) { // Addr evit_L2_addr = sys->l2cache->last_evicted_line.tag; sys->l2cache->last_evicted_line.dirty = FALSE; sys->l2cache->last_evicted_line.valid = FALSE; Addr evit_L2_addr = sys->l2cache->last_evicted_line.tag; dram_access(sys->dram, evit_L2_addr, 1/*is_writeback*/); } } } if (is_writeback == 1) { // dirty evicted line from dcache has come to L2 outcome_L2 = cache_access(sys->l2cache, lineaddr, 1, core_id); // if line is present in L2 already which // which is stale.. you write-into that line // this is considered as hit and no eviction // from L2 would take place if (outcome_L2 == MISS) { // But if there's miss // Get the line from DRAM delay += dram_access(sys->dram, lineaddr, 0); // This is correct. Evicted entry is dirty.. it needs to write into L2 after // getting the stale-line from DRAM. // This is the case of 'Write-Allocate' & 'Write-Back'. cache_install(sys->l2cache, lineaddr, 1, core_id); // Eviction stat will be updated here // Due to this new install check if there is any dirty evicted entry that needs to be put // in DRAM if(sys->l2cache->last_evicted_line.valid && sys->l2cache->last_evicted_line.dirty) { // Addr evit_L2_addr = sys->l2cache->last_evicted_line.tag; sys->l2cache->last_evicted_line.dirty = FALSE; sys->l2cache->last_evicted_line.valid = FALSE; Addr evit_L2_addr = sys->l2cache->last_evicted_line.tag; // since line is dirty, put 'is_writeback' true is_writeback = TRUE; dram_access(sys->dram, evit_L2_addr, 1/*is_writeback*/); } } } return delay; }
uns64 memsys_access_modeBC(Memsys *sys, Addr lineaddr, Access_Type type,uns core_id){ uns64 delay=0; Flag needs_dcache_access = FALSE; Flag is_dirty = FALSE; Flag outcome_L1 = MISS; if(type == ACCESS_TYPE_IFETCH){ // YOU NEED TO WRITE THIS PART AND UPDATE DELAY outcome_L1 = cache_access(sys->icache, lineaddr, 0, core_id); // Reading line form L1 icache delay = ICACHE_HIT_LATENCY; // updated delay for the read if (outcome_L1 == MISS) { // In case there is a miss, we will read from L2 delay += memsys_L2_access(sys, lineaddr, 0, core_id); // put the delay of reading it from L2 // Install the line in L1, no writeback cache_install(sys->icache, lineaddr, 0, core_id); // Install the line } } if(type == ACCESS_TYPE_LOAD){ // YOU NEED TO WRITE THIS PART AND UPDATE DELAY needs_dcache_access = TRUE; is_dirty = FALSE; } if(type == ACCESS_TYPE_STORE){ // YOU NEED TO WRITE THIS PART AND UPDATE DELAY needs_dcache_access = TRUE; is_dirty = TRUE; } if(needs_dcache_access) { // We have LOAD/STORE instruction // Accessing L1 dcache(for reading/writing based on 'is_dirty') outcome_L1 = cache_access(sys->dcache, lineaddr, is_dirty, core_id); delay = DCACHE_HIT_LATENCY; // initialized the delay for DCACHE access if(outcome_L1 == MISS) { // L1 cache miss // We are following 'non-inclusive' policy here. // read from L2 // compensation for delay delay +=memsys_L2_access(sys, lineaddr, 0/*is_dirty*/, core_id); // because it is write back cache. // we will only write back on dirty // eviction // cache_install() function takes care of eviction_stat cache_install(sys->dcache, lineaddr, is_dirty, core_id); // if the evicted line is not dirty.. we do not put it in L2 if(sys->dcache->last_evicted_line.dirty && sys->dcache->last_evicted_line.valid) { sys->dcache->last_evicted_line.dirty = FALSE; sys->dcache->last_evicted_line.valid = FALSE; Addr evit_L1_addr = sys->dcache->last_evicted_line.tag; // we are writing back the evicted line to L2 which are 'Dirty': Write-back memsys_L2_access(sys, evit_L1_addr, 1, core_id); } } } return delay; }
int main(int argc, char* argv[]) { int opt; uint64_t c = DEFAULT_C; uint64_t b = DEFAULT_B; uint64_t s = DEFAULT_S; uint64_t v = DEFAULT_V; uint64_t k = DEFAULT_K; FILE* fin = stdin; FILE* fout = stdout; char inputfile[100]; char outputfile[100]; /* Read arguments */ while(-1 != (opt = getopt(argc, argv, "c:b:s:i:v:k:h"))) { switch(opt) { case 'i': strcpy(inputfile, optarg); strcpy(outputfile, optarg); strcat(outputfile, ".out"); break; case 'c': c = atoi(optarg); break; case 'b': b = atoi(optarg); break; case 's': s = atoi(optarg); break; case 'v': v = atoi(optarg); break; case 'k': k = atoi(optarg); break; case 'h': /* Fall through */ default: print_help_and_exit(); break; } } fout = fopen(outputfile, "w"); fprintf(fout, "%s:\n\n", inputfile); double AAT_min = AAT_MAX; uint64_t AAT_min_c = DEFAULT_C; uint64_t AAT_min_b = DEFAULT_B; uint64_t AAT_min_s = DEFAULT_S; uint64_t AAT_min_v = DEFAULT_V; uint64_t AAT_min_k = DEFAULT_K; for (c = 12; c <= 15; ++c) { for (b = 3; b <= 6; ++b) { for (s = 0; s <= c - b; ++s) { // for (v = 0; v <= 4; ++v) { // for (k = 0; k <= 4; ++k) { printf("%" PRIu64 "\t%" PRIu64 "\t%" PRIu64 "\t%" PRIu64 "\t%" PRIu64 "\t", c, b, s, v, k); fprintf(fout, "%" PRIu64 "\t%" PRIu64 "\t%" PRIu64 "\t%" PRIu64 "\t%" PRIu64 "\t", c, b, s, v, k); /* calculate memory budge */ uint64_t data_storage = (1 << b) * 8; // printf("data storage: %" PRIu64 "\n", data_storage); uint64_t cache_memory = (1 << (c - b)) * (64 - c + s + 1 + data_storage); // printf("cache memory: %" PRIu64 "\n", cache_memory); uint64_t vc_memory = v * (64 - b + 1 + data_storage); // printf("vc memory: %" PRIu64 "\n", vc_memory); double total_memory_kb = (cache_memory + vc_memory) / double((1 << 10) * 8); printf("%f\t", total_memory_kb); fprintf(fout, "%f\t", total_memory_kb); /* skip if memory limitation exceeded */ if (total_memory_kb > 48) { printf("\n"); fprintf(fout, "\n"); continue; } /* Setup the cache */ setup_cache(c, b, s, v, k); /* Setup statistics */ cache_stats_t stats; memset(&stats, 0, sizeof(cache_stats_t)); /* Begin reading the file */ fin = fopen(inputfile, "r"); char rw; uint64_t address; while (!feof(fin)) { int ret = fscanf(fin, "%c %" PRIx64 "\n", &rw, &address); if (ret == 2) { cache_access(rw, address, &stats); } } fclose(fin); complete_cache(&stats); printf("%f\n", stats.avg_access_time); fprintf(fout, "%f\n", stats.avg_access_time); // update optimal setting if (stats.avg_access_time < AAT_min) { AAT_min = stats.avg_access_time; AAT_min_c = c; AAT_min_b = b; AAT_min_s = s; AAT_min_v = v; AAT_min_k = k; } // } // } } } } printf("\nBest AAT: %f\n", AAT_min); fprintf(fout, "\nBest AAT: %f\n", AAT_min); printf("Setting: %" PRIu64 ", %" PRIu64 ", %" PRIu64 ", %" PRIu64 ", %" PRIu64 "\n", AAT_min_c, AAT_min_b, AAT_min_s, AAT_min_v, AAT_min_k); fprintf(fout, "Setting: %" PRIu64 ", %" PRIu64 ", %" PRIu64 ", %" PRIu64 ", %" PRIu64 "\n", AAT_min_c, AAT_min_b, AAT_min_s, AAT_min_v, AAT_min_k); fclose(fout); return 0; }
int main(int argc, char* argv[]) { int opt; uint64_t c = DEFAULT_C; uint64_t b = DEFAULT_B; uint64_t s = DEFAULT_S; uint64_t v = DEFAULT_V; uint64_t k = DEFAULT_K; FILE* fin = stdin; char* file_name; /* Read arguments */ while(-1 != (opt = getopt(argc, argv, "c:b:s:i:v:k:h"))) { switch(opt) { case 'c': c = atoi(optarg); break; case 'b': b = atoi(optarg); break; case 's': s = atoi(optarg); break; case 'v': v = atoi(optarg); break; case 'k': k = atoi(optarg); break; case 'i': fin = fopen(optarg, "r"); file_name = optarg; break; case 'h': /* Fall through */ default: //print_help_and_exit(); break; } } printf("Cache Settings\n"); printf("C: %" PRIu64 "\n", c); printf("B: %" PRIu64 "\n", b); printf("S: %" PRIu64 "\n", s); printf("V: %" PRIu64 "\n", v); printf("K: %" PRIu64 "\n", k); printf("\n"); // printf("C: %" PRIu64 ":: B: %" PRIu64 ":: S: %" PRIu64 ":: V: %" PRIu64 ":: K: %" PRIu64 "\n", c, b, s, v, k); if( (48*pow(2,10)*8) < ( pow(2,c-b)*pow(2,b)*8 + pow(2,c-b)*(64-(c-s)+2) + v*pow(2,b)*8 + v*(64-b+2) ) ) { return 0; } /* Setup the cache */ setup_cache(c, b, s, v, k); /* Setup statistics */ struct cache_stats_t stats; memset(&stats, 0, sizeof(struct cache_stats_t)); /* Begin reading the file */ char rw; uint64_t address; while (!feof(fin)) { int ret = fscanf(fin, "%c %" PRIx64 "\n", &rw, &address); if(ret == 2) { cache_access(rw, address, &stats); } } complete_cache(&stats); //printf("%" PRIu64 "|%" PRIu64 "|%" PRIu64 "|%" PRIu64 "|%" PRIu64 "|%s", c, b, s, v, k, file_name); print_statistics(&stats); return 0; }
int main(int argc, char* argv[]) { int opt; uint64_t c = DEFAULT_C; uint64_t b = DEFAULT_B; uint64_t s = DEFAULT_S; FILE* fin = stdin; /* Read arguments */ while(-1 != (opt = getopt(argc, argv, "c:b:s:i:h"))) { switch(opt) { case 'c': c = atoi(optarg); break; case 'b': b = atoi(optarg); break; case 's': s = atoi(optarg); break; case 'i': fin = fopen(optarg, "r"); break; case 'h': default: print_help_and_exit(); break; } } printf("Cache Settings\n"); printf("C: %" PRIu64 "\n", c); printf("B: %" PRIu64 "\n", b); printf("S: %" PRIu64 "\n", s); printf("\n"); /* Setup the cache */ cache_init(c, s, b); /* Setup statistics */ struct cache_stats_t stats; memset(&stats, 0, sizeof(struct cache_stats_t)); stats.miss_penalty = 100; stats.access_time = 2; /* Begin reading the file */ char rw; uint64_t address; while (!feof(fin)) { int ret = fscanf(fin, "%c %" PRIx64 "\n", &rw, &address); if(ret == 2) { cache_access(rw, address, &stats); } } /* Make sure to free up memory here */ cache_cleanup(&stats); print_statistics(&stats); fclose(fin); return 0; }
int main(int argc, char **argv) { struct trace_item *tr_entry; size_t size; char *trace_file_name; int trace_view_on, cache_size, block_size; int associativity, replacement_policy; enum cache_policy policy; struct cache_t *cp; struct timeval gettimeofdayreturnstruct; unsigned long long timestamp_in_microsec; int cache_access_status; FILE *file_results; //we will be writing our results out to a file //define default trace_view_on = 1; cache_size = 1; //1 KB block_size = 4; //4 bytes = 1 word associativity = 1; //1-way associativity replacement_policy = 0; //0 for LRU, 1 for FIFO if (argc == 1) { fprintf(stdout, "nUSAGE: tv <trace_file> <switch - any character>n"); fprintf(stdout, "n(switch) to turn on or off individual item view.nn"); exit(0); } trace_file_name = argv[1]; // here you should extract the cache parameters from the command line if (argc == 7) { trace_view_on = atoi(argv[2]) ; // here you should extract the cache parameters from the command line cache_size = atoi(argv[3]); //in kilobytes block_size = atoi(argv[4]); associativity = atoi(argv[5]); if ((cache_size != (cache_size & -cache_size)) || (block_size != (block_size & -block_size)) || (associativity != (associativity & -associativity))) { //should be restricted to the power of 2 fprintf(stdout, "Cache size, block size, and block associativity have to be a power of 2. (For example: 1, 2, 4, 8, 16, ..."); exit(0); } replacement_policy = atoi(argv[6]); if ( !(replacement_policy == 0 || replacement_policy == 1) ){ fprintf(stdout, "\nMake sure that you pick either 0 for LRU replacement or 1 for FIFO replacement."); fprintf(stdout, " %d is not a valid number.", replacement_policy); exit(0); } } if(replacement_policy){ policy = FIFO; } else{ policy = LRU; } fprintf(stdout, "n ** opening file %sn", trace_file_name); trace_fd = fopen(trace_file_name, "rb"); if (!trace_fd) { fprintf(stdout, "ntrace file %s not opened.nn", trace_file_name); exit(0); } trace_init(); file_results = fopen("./results.txt", "w"); //open text file for writing out results //print back all the parameters printf("Parameters:"); fprintf(file_results,"\n\nParameters:"); printf("\nTrace Name: %s", trace_file_name); fprintf(file_results, "\nTrace Name: %s", trace_file_name); printf("\nCache Size: %d KBYTES", cache_size); fprintf(file_results, "\nCache Size: %d KBYTES", cache_size); printf("\nBlock Size: %d BYTES", block_size); fprintf(file_results, "\nBlock Size: %d BYTES", block_size); printf("\nAssociativity: %d", associativity); fprintf(file_results, "\nAssociativity: %d", associativity); if (replacement_policy == 0) { printf("\nReplacement Policy: LRU"); fprintf(file_results, "\nReplacement Policy: LRU"); } else { printf("\nReplacement Policy: FIFO"); fprintf(file_results, "\nReplacement Policy: FIFO"); } // here should call cache_create(cache_size, block_size, associativity, replacement_policy) cp = cache_create(cache_size, block_size, associativity, policy); while(1) { size = trace_get_item(&tr_entry); if (!size) { /* no more instructions to simulate */ printf("\n\nResults:"); fprintf(file_results, "\n\nResults:"); printf("\nCache Accesses: %d", accesses); fprintf(file_results, "\nCache Accesses: %d", accesses); printf("\nCache Read Accesses: %d", read_accesses); fprintf(file_results, "\nCache Read Accesses: %d", read_accesses); printf("\nCache Write Accesses: %d", write_accesses); fprintf(file_results, "\nCache Write Accesses: %d", write_accesses); printf("\nCache Hits: %d", hits); fprintf(file_results, "\nCache Hits: %d", hits); printf("\nCache Misses: %d", misses); fprintf(file_results, "\nCache Misses: %d", misses); printf("\nCache Writebacks: %d", misses_with_writeback); fprintf(file_results, "\nCache Writebacks: %d", misses_with_writeback); break; } else{ /* process only loads and stores */; gettimeofday(&gettimeofdayreturnstruct, NULL); timestamp_in_microsec = (unsigned long long)(1000000ULL * gettimeofdayreturnstruct.tv_sec + gettimeofdayreturnstruct.tv_usec); if (tr_entry->type == ti_LOAD) { if (trace_view_on) { printf("\n\nLOAD %x n",tr_entry->Addr); fprintf(file_results, "\n\nLOAD %x n",tr_entry->Addr); } // call cache_access(struct cache_t *cp, tr_entry->Addr, access_type) cache_access_status = cache_access(cp, tr_entry->Addr, tr_entry->type, file_results, trace_view_on, timestamp_in_microsec); read_accesses = read_accesses + 1; accesses = accesses + 1; } else if (tr_entry->type == ti_STORE) { if (trace_view_on) { printf("\n\nSTORE %x n",tr_entry->Addr) ; fprintf(file_results, "\n\nSTORE %x n",tr_entry->Addr) ; } // call cache_access(struct cache_t *cp, tr_entry->Addr, access_type) cache_access_status = cache_access(cp, tr_entry->Addr, tr_entry->type, file_results, trace_view_on, timestamp_in_microsec); write_accesses = write_accesses + 1; accesses = accesses + 1; } else { cache_access_status = 100; //not a load or store } // based on the value returned, update the statisctics for hits, misses and misses_with_writeback if(cache_access_status == 0){ //0 if a hit, 1 if a miss or 2 if a miss_with_write_back hits = hits + 1; if (trace_view_on) { printf("\nStatus: hit"); fprintf(file_results, "\nStatus: hit"); } } else if (cache_access_status == 1) { misses = misses + 1; if (trace_view_on) { printf("\nStatus: miss"); fprintf(file_results, "\nStatus: miss"); } } else if (cache_access_status == 2) { misses_with_writeback = misses_with_writeback + 1; if (trace_view_on) { printf("\nStatus: miss with writeback"); fprintf(file_results, "\nStatus: miss with writeback"); } } } } fclose(file_results); //close output file trace_uninit(); exit(0); }
/* start simulation, program loaded, processor precise state initialized */ bool_t sim_sample(unsigned int n_insn) { md_inst_t inst; enum md_fault_t fault; struct predec_insn_t *pdi; counter_t sim_num_insn_begin = sim_num_insn; bool_t fdumpinsn; while (n_insn == 0 || sim_num_insn < sim_num_insn_begin + n_insn) { /* maintain $r0 semantics */ regs.regs[MD_REG_ZERO].q = 0; regs.regs[MD_FREG_ZERO].d = 0.0; /* get the next instruction to execute */ if (itlb) cache_access(itlb, mc_READ, regs.PC, sizeof(md_inst_t), 0, NULL, tlb_miss_handler); if (cache_il1) cache_access(cache_il1, mc_READ, regs.PC, sizeof(md_inst_t), 0, NULL, l1_miss_handler); mem_access(mem, mc_READ, regs.PC, &inst, sizeof(md_inst_t)); /* set default reference address and access mode */ regs.addr = 0; regs.dsize = 0; /* set default fault - none */ fault = md_fault_none; /* get the next instruction to execute */ pdi = predec_lookup(regs.PC); if (!pdi) { mem_access(mem, mc_READ, regs.PC, &inst, sizeof(md_inst_t)); pdi = predec_enter(regs.PC, inst); } /* keep an instruction count */ if (pdi->iclass != ic_nop) { sim_num_insn++; sim_sample_insn++; sim_sample_insn_split[pdi->iclass]++; } fdumpinsn = fdump && sim_num_insn >= insn_dumpbegin && sim_num_insn < insn_dumpend; inst = pdi->inst; /* execute the instruction */ switch (pdi->poi.op) { #define DEFINST(OP,MSK,NAME,OPFORM,RES,FLAGS,O1,O2,I1,I2,I3) \ case OP: \ SYMCAT(OP,_IMPL); \ break; #define DEFLINK(OP,MSK,NAME,MASK,SHIFT) \ case OP: \ panic("attempted to execute a linking opcode"); #define CONNECT(OP) #define DECLARE_FAULT(FAULT) \ { fault = (FAULT); break; } #include "machine.def" default: panic("attempted to execute a bogus opcode"); } if (fault != md_fault_none) fatal("fault (%d) detected @ 0x%08p", fault, regs.PC); if (pdi->iclass == ic_load || pdi->iclass == ic_store || pdi->iclass == ic_prefetch) { enum mem_cmd_t dl1_cmd = pdi->iclass == ic_store ? mc_WRITE : (pdi->iclass == ic_load ? mc_READ : mc_PREFETCH); enum mem_cmd_t dtlb_cmd = (pdi->iclass == ic_store || pdi->iclass == ic_load) ? mc_READ : mc_PREFETCH; bool_t miss_info[ct_NUM] = {FALSE, FALSE, FALSE, FALSE}; if (cache_dl1) cache_access(cache_dl1, dl1_cmd, regs.addr, regs.dsize, 0, miss_info, l1_miss_handler); if (dtlb) cache_access(dtlb, dtlb_cmd, regs.addr, regs.dsize, 0, NULL, tlb_miss_handler); } /* go to the next instruction */ regs.PC = regs.NPC; regs.NPC += sizeof(md_inst_t); if (verbose) { myfprintf(stderr, "%10n [xor: 0x%08x] @ 0x%08p: ", sim_num_insn, md_xor_regs(®s), regs.PC); md_print_insn(inst, regs.PC, stderr); if (MD_OP_HASFLAGS(pdi->poi.op, F_MEM)) myfprintf(stderr, " mem: 0x%08p", regs.addr); fprintf(stderr, "\n"); /* fflush(stderr); */ } if (fdumpinsn) { fprintf(fdump, "%-9u: 0x%08x ", (word_t)sim_num_insn, (word_t)regs.PC); if (LREG_ISDEP(pdi->lregnums[DEP_O1])) myfprintf(fdump, " O1: %016p", regs_value(pdi->lregnums[DEP_O1])); fprintf(fdump, "\n"); } if (fdump && sim_num_insn == insn_dumpend) { fflush(fdump); fclose(fdump); } /* finish early? */ if (insn_limit && sim_sample_insn >= insn_limit) { myfprintf(stderr, "Reached instruction limit: %u\n", insn_limit); return FALSE; } if (insn_progress && sim_sample_insn >= insn_progress) { sim_print_stats(stderr); fflush(stderr); while (sim_sample_insn >= insn_progress) insn_progress += insn_progress_update; } } return (sim_num_insn - sim_num_insn_begin == n_insn); }
/* start simulation, program loaded, processor precise state initialized */ void sim_main(void) { int i; md_inst_t inst; register md_addr_t addr; enum md_opcode op; register int is_write; enum md_fault_type fault; fprintf(stderr, "sim: ** starting functional simulation w/ caches **\n"); /* set up initial default next PC */ regs.regs_NPC = regs.regs_PC + sizeof(md_inst_t); /* check for DLite debugger entry condition */ if (dlite_check_break(regs.regs_PC, /* no access */0, /* addr */0, 0, 0)) dlite_main(regs.regs_PC - sizeof(md_inst_t), regs.regs_PC, sim_num_insn, ®s, mem); while (TRUE) { /* maintain $r0 semantics */ regs.regs_R[MD_REG_ZERO] = 0; #ifdef TARGET_ALPHA regs.regs_F.d[MD_REG_ZERO] = 0.0; #endif /* TARGET_ALPHA */ /* get the next instruction to execute */ if (itlb) cache_access(itlb, Read, IACOMPRESS(regs.regs_PC), NULL, ISCOMPRESS(sizeof(md_inst_t)), 0, NULL, NULL, 0); if (cache_il1) cache_access(cache_il1, Read, IACOMPRESS(regs.regs_PC), NULL, ISCOMPRESS(sizeof(md_inst_t)), 0, NULL, NULL, 0); MD_FETCH_INST(inst, mem, regs.regs_PC); /* keep an instruction count */ sim_num_insn++; /* set default reference address and access mode */ addr = 0; is_write = FALSE; /* set default fault - none */ fault = md_fault_none; /* decode the instruction */ MD_SET_OPCODE(op, inst); /* execute the instruction */ switch (op) { #define DEFINST(OP,MSK,NAME,OPFORM,RES,FLAGS,O1,O2,I1,I2,I3) \ case OP: \ SYMCAT(OP,_IMPL); \ break; #define DEFLINK(OP,MSK,NAME,MASK,SHIFT) \ case OP: \ panic("attempted to execute a linking opcode"); #define CONNECT(OP) #define DECLARE_FAULT(FAULT) \ { fault = (FAULT); break; } #include "machine.def" default: panic("attempted to execute a bogus opcode"); } if (fault != md_fault_none) fatal("fault (%d) detected @ 0x%08p", fault, regs.regs_PC); if (MD_OP_FLAGS(op) & F_MEM) { sim_num_refs++; if (MD_OP_FLAGS(op) & F_STORE) is_write = TRUE; } /* update any stats tracked by PC */ for (i=0; i < pcstat_nelt; i++) { counter_t newval; int delta; /* check if any tracked stats changed */ newval = STATVAL(pcstat_stats[i]); delta = newval - pcstat_lastvals[i]; if (delta != 0) { stat_add_samples(pcstat_sdists[i], regs.regs_PC, delta); pcstat_lastvals[i] = newval; } } /* check for DLite debugger entry condition */ if (dlite_check_break(regs.regs_NPC, is_write ? ACCESS_WRITE : ACCESS_READ, addr, sim_num_insn, sim_num_insn)) dlite_main(regs.regs_PC, regs.regs_NPC, sim_num_insn, ®s, mem); /* go to the next instruction */ regs.regs_PC = regs.regs_NPC; regs.regs_NPC += sizeof(md_inst_t); /* finish early? */ if (max_insts && sim_num_insn >= max_insts) return; } }
int main(int argc, char* argv[]) { int opt; uint64_t c = DEFAULT_C; uint64_t b = DEFAULT_B; uint64_t s = DEFAULT_S; char f = DEFAULT_F; char r = DEFAULT_R; /* Read arguments */ while(-1 != (opt = getopt(argc, argv, "c:b:s:f:r:h"))) { switch(opt) { case 'c': c = atoi(optarg); break; case 'b': b = atoi(optarg); break; case 's': s = atoi(optarg); break; case 'f': if(optarg[0] == BLOCKING || optarg[0] == EAGER) { f = optarg[0]; } break; case 'r': if(optarg[0] == LRU || optarg[0] == NMRU_FIFO) { r = optarg[0]; } break; case 'h': /* Fall through */ default: print_help_and_exit(); break; } } printf("Cache Settings\n"); printf("C: %llu\n", c); printf("B: %llu\n", b); printf("S: %llu\n", s); printf("F: %s\n", f == BLOCKING ? "BLOCKING" : "EAGER"); printf("R: %s\n", r == LRU ? "LRU" : "NMRU_FIFO"); printf("\n"); /* Setup the cache */ setup_cache(c, b, s, f, r); /* Setup statistics */ cache_stats_t stats; memset(&stats, 0, sizeof(cache_stats_t)); /* Begin reading the file */ char rw; uint64_t address; while (!feof(stdin)) { int ret = fscanf(stdin, "%c %llx\n", &rw, &address); if(ret == 2) { cache_access(rw, address, &stats); } } complete_cache(&stats); print_statistics(&stats); return 0; }
unsigned int /* latency of access in cycles */ cache_access(struct cache_t *cp, /* cache to access */ enum mem_cmd cmd, /* access type, Read or Write */ md_addr_t addr, /* address of access */ void *vp, /* ptr to buffer for input/output */ int nbytes, /* number of bytes to access */ tick_t now, /* time of access */ byte_t **udata, /* for return of user data ptr */ md_addr_t *repl_addr) /* for address of replaced block */ { acheck++; //printf("%d \n",acheck); byte_t *p = vp; md_addr_t tag; if (pseudo_check==1) tag = CACHE_TAG_PSEUDOASSOC(cp, addr); else tag= CACHE_TAG(cp,addr); md_addr_t set = CACHE_SET(cp, addr); md_addr_t bofs = CACHE_BLK(cp, addr); md_addr_t set1=HASH_MASK(set); md_addr_t addr1=addr; addr1 ^=1<<(cp->set_shift); //set1=CACHE_SET(cp,addr1); struct cache_blk_t *blk, *repl; int lat = 0; // if (cp->sets[set].rehash_bit==1) //printf("yo"); //printf("%d",cp->sets[set].way_head->rehash_bit ); /* default replacement address */ if (repl_addr) *repl_addr = 0; /* check alignments */ if ((nbytes & (nbytes-1)) != 0 || (addr & (nbytes-1)) != 0) fatal("cache: access error: bad size or alignment, addr 0x%08x", addr); /* access must fit in cache block */ /* FIXME: ((addr + (nbytes - 1)) > ((addr & ~cp->blk_mask) + (cp->bsize - 1))) */ if ((addr + nbytes) > ((addr & ~cp->blk_mask) + cp->bsize)) fatal("cache: access error: access spans block, addr 0x%08x", addr); /* permissions are checked on cache misses */ /* check for a fast hit: access to same block */ if (CACHE_TAGSET(cp, addr) == cp->last_tagset) { /* hit in the same block */ //printf("same block hit"); blk = cp->last_blk; //cp->last_blk->rehash_bit=0; goto cache_fast_hit; } if (cp->hsize) { //printf("different block hit"); /* higly-associativity cache, access through the per-set hash tables */ int hindex = CACHE_HASH(cp, tag); for (blk=cp->sets[set].hash[hindex]; blk; blk=blk->hash_next) { if (blk->tag == tag && (blk->status & CACHE_BLK_VALID)) goto cache_hit; } } else { //printf("different block hit"); /* low-associativity cache, linear search the way list */ for (blk=cp->sets[set].way_head; blk; blk=blk->way_next) { if (blk->tag == tag && (blk->status & CACHE_BLK_VALID)) { goto cache_hit; } } } /* cache block not found */ /* **MISS** */ /* select the appropriate block to replace, and re-link this entry to the appropriate place in the way list */ switch (cp->policy) { case LRU: case FIFO: repl = cp->sets[set].way_tail; update_way_list(&cp->sets[set], repl, Head); break; case Random: { int bindex = myrand() & (cp->assoc - 1); repl = CACHE_BINDEX(cp, cp->sets[set].blks, bindex); } break; default: panic("bogus replacement policy"); } if(pseudo_check==1) { //printf("%d",hash_check); if(cp->sets[set].way_head->rehash_bit==1 ) {//printf("hii"); if(hash_check==1) { cp->sets[set].way_head->rehash_bit=1; goto cache_missfinal; } else if(hash_check==0) { cp->sets[set].way_head->rehash_bit=0; goto cache_missfinal; } } if(cp->sets[set].way_head->rehash_bit==0) { //printf("hello"); if(hash_check==1) { cp->sets[set].way_head->rehash_bit=1; temp=cp->sets[set].way_head; goto cache_missfinal; } else if(hash_check==0) { hash_check=1; cache_access(cp,cmd,addr1,NULL,nbytes,now,NULL,NULL); //goto cache_missfinal; } } //unsigned int uff=0; temp1=cp->sets[set].way_head; temp1->tag=temp->tag; if(temp->status!=3) temp1->status=temp->status;//temp->status; //printf("%u",temp1->status); temp1->ready=temp->ready; temp->tag=cp->sets[set].way_head->tag; temp->status=cp->sets[set].way_head->status; temp->ready=cp->sets[set].way_head->ready; cp->sets[set].way_head->tag=temp1->tag; cp->sets[set].way_head->status=temp1->status; cp->sets[set].way_head->ready=temp1->ready; //printf("%d",temp->rehash_bit); } cache_missfinal: hash_check=0; cp->misses++; if (cp->hsize) unlink_htab_ent(cp, &cp->sets[set], repl); /* blow away the last block to hit */ cp->last_tagset = 0; cp->last_blk = NULL; /* write back replaced block data */ if (repl->status & CACHE_BLK_VALID) { cp->replacements++; if (repl_addr) *repl_addr = CACHE_MK_BADDR(cp, repl->tag, set); /* don't replace the block until outstanding misses are satisfied */ lat += BOUND_POS(repl->ready - now); /* stall until the bus to next level of memory is available */ lat += BOUND_POS(cp->bus_free - (now + lat)); /* track bus resource usage */ cp->bus_free = MAX(cp->bus_free, (now + lat)) + 1; if (repl->status & CACHE_BLK_DIRTY) { /* write back the cache block */ cp->writebacks++; lat += cp->blk_access_fn(Write, CACHE_MK_BADDR(cp, repl->tag, set), cp->bsize, repl, now+lat); } } /* update block tags */ repl->tag = tag; repl->status = CACHE_BLK_VALID; /* dirty bit set on update */ /* read data block */ lat += cp->blk_access_fn(Read, CACHE_BADDR(cp, addr), cp->bsize, repl, now+lat); /* copy data out of cache block */ if (cp->balloc) { CACHE_BCOPY(cmd, repl, bofs, p, nbytes); } /* update dirty status */ if (cmd == Write) repl->status |= CACHE_BLK_DIRTY; /* get user block data, if requested and it exists */ if (udata) *udata = repl->user_data; /* update block status */ repl->ready = now+lat; /* link this entry back into the hash table */ if (cp->hsize) link_htab_ent(cp, &cp->sets[set], repl); /* return latency of the operation */ return lat; cache_hit: /* slow hit handler */ /* **HIT** */ cp->hits++; /* copy data out of cache block, if block exists */ if (cp->balloc) { CACHE_BCOPY(cmd, blk, bofs, p, nbytes); } /* update dirty status */ if (cmd == Write) blk->status |= CACHE_BLK_DIRTY; /* if LRU replacement and this is not the first element of list, reorder */ if (blk->way_prev && cp->policy == LRU) { /* move this block to head of the way (MRU) list */ update_way_list(&cp->sets[set], blk, Head); } /* tag is unchanged, so hash links (if they exist) are still valid */ /* record the last block to hit */ cp->last_tagset = CACHE_TAGSET(cp, addr); cp->last_blk = blk; /* get user block data, if requested and it exists */ if (udata) *udata = blk->user_data; /* return first cycle data is available to access */ return (int) MAX(cp->hit_latency, (blk->ready - now)); cache_fast_hit: /* fast hit handler */ /* **FAST HIT** */ cp->hits++; /* copy data out of cache block, if block exists */ if (cp->balloc) { CACHE_BCOPY(cmd, blk, bofs, p, nbytes); } /* update dirty status */ if (cmd == Write) blk->status |= CACHE_BLK_DIRTY; /* this block hit last, no change in the way list */ /* tag is unchanged, so hash links (if they exist) are still valid */ /* get user block data, if requested and it exists */ if (udata) *udata = blk->user_data; /* record the last block to hit */ cp->last_tagset = CACHE_TAGSET(cp, addr); cp->last_blk = blk; /* return first cycle data is available to access */ return (int) MAX(cp->hit_latency, (blk->ready - now)); }
int main(int argc, char **argv) { struct trace_item *tr_entry; size_t size; char *trace_file_name; int trace_view_on ; if (argc == 1) { fprintf(stdout, "\nUSAGE: tv <trace_file> <switch - any character>\n"); fprintf(stdout, "\n(switch) to turn on or off individual item view.\n\n"); exit(0); } // here you should extract the cache parameters from the command line trace_file_name = argv[1]; trace_view_on = atoi(argv[2]); cache_size = atoi(argv[3]); block_size = atoi(argv[4]); associativity = atoi(argv[5]); policy = atoi(argv[6]); double log = log2(cache_size); cache_size = pow(2, 10) * pow(2,log ); size = cache_size; printf("size of cache is %d\n block size is %d\n associativity is %d\n", size, block_size, associativity); fprintf(stdout, "\n ** opening file %s\n", trace_file_name); trace_fd = fopen(trace_file_name, "rb"); if (!trace_fd) { fprintf(stdout, "\ntrace file %s not opened.\n\n", trace_file_name); exit(0); } trace_init(); // here should call cache_create(cache_size, block_size, associativity, replacement_policy) struct cache_t *cp = cache_create(size, block_size, associativity, policy); while(1) { size = trace_get_item(&tr_entry); if (!size) { /* no more instructions to simulate */ printf("+ number of accesses : %d \n", accesses); printf("+ number of reads : %d \n", read_accesses); printf("+ number of writes : %d \n", write_accesses); printf("+ number of hits : %d \n", hits); printf("+ number of misses : %d \n", misses); printf("+ number of misses with write back : %d \n", misses_with_writeback); break; } else{ /* process only loads and stores */; if (tr_entry->type == ti_LOAD) { if (trace_view_on) printf("LOAD %x \n",tr_entry->Addr) ; accesses ++; read_accesses++ ; load = cache_access(cp, tr_entry->Addr, 0, cycles); } if (tr_entry->type == ti_STORE) { if (trace_view_on) printf("STORE %x \n",tr_entry->Addr) ; accesses ++; write_accesses++ ; store = cache_access(cp, tr_entry->Addr, 1, cycles); } // based on the value returned, update the statisctics for hits, misses and misses_with_writeback if(load == 0) { hits++; load = -1; } if(store == 0) { hits++; store = -1; } if(load == 1) { misses++; load = -1; } if(store == 1) { misses++; store = -1; } if(load == 2) { misses_with_writeback++; load = -1; } if(store == 2) { misses_with_writeback++; store = -1; } } cycles++; } trace_uninit(); exit(0); }