Esempio n. 1
0
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;
}
Esempio n. 2
0
/* 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);
}
Esempio n. 3
0
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;
}
Esempio n. 4
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;
}
Esempio n. 5
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);
  }
}
Esempio n. 6
0
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; 
}
Esempio n. 8
0
/* 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;
}
Esempio n. 9
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; 
}
Esempio n. 10
0
/* 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;
    }
}
Esempio n. 11
0
/* 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;
}
Esempio n. 13
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;
}
Esempio n. 14
0
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;
}
Esempio n. 15
0
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;
}
Esempio n. 17
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;
}
Esempio n. 18
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;
}
Esempio n. 19
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);
}
Esempio n. 20
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(&regs), 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); 
}
Esempio n. 21
0
/* 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, &regs, 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, &regs, 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;
    }
}
Esempio n. 22
0
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;
}
Esempio n. 23
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));
}
Esempio n. 24
0
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);
}