📄 cache_init.c
字号:
static void L1ICache_init(CACHE *captr, int nodeid, int procid){ int i; if (cparam.L1I_size <= 0) YS__errmsg(nodeid, "L1 I-cache size must be greater then zero"); /* * Common fields: identity, configuration, etc. */ captr->nodeid = nodeid; captr->procid = procid; captr->gid = nodeid * ARCH_cpus + procid; captr->type = L1CACHE; captr->size = ARCH_cacsz1i; captr->linesz = ARCH_linesz1i; captr->setsz = ARCH_setsz1i; captr->replacement = LRU; /* * Initialize data array. For perfect cache, we always fake a hit * for each request, so no needs for data array. */ Cache_init_aux(captr); captr->data = (char*)memalign(sizeof(long long), ARCH_cacsz1i * (1024 / SIZE_OF_SPARC_INSTRUCTION) * SIZEOF_INSTR); if (captr->data == NULL) YS__errmsg(nodeid, "Malloc failed at %s:%i", __FILE__, __LINE__); /* * Initialize MSHRs (Miss Status Hold Register?). */ captr->max_mshrs = L1I_NUM_MSHRS; captr->mshrs = RSIM_CALLOC(MSHR, captr->max_mshrs); if (captr->mshrs == NULL) YS__errmsg(nodeid, "Malloc failed in %s:%i", __FILE__, __LINE__); for (i = 0; i < captr->max_mshrs; i++) captr->mshrs[i].valid = 0; captr->mshr_count = 0; /* counts WRBs in MSHRs, etc */ captr->reqmshr_count = 0; /* only counting data requests */ captr->reqs_at_mshr_count = 0; /* * Initialize input queues * 1. "request queue" contains request from processor. * 2. "reply queue" contains replies from L2 cache. * 3. "cohe queue" contains cohe request from other processor. */ lqueue_init(&(captr->request_queue), L1I_REQUEST_QUEUE_SIZE > MEM_UNITS ? L1I_REQUEST_QUEUE_SIZE : MEM_UNITS); lqueue_init(&(captr->reply_queue), L1I_REPLY_QUEUE_SIZE); lqueue_init(&(captr->cohe_queue), L1I_COHE_QUEUE_SIZE); captr->inq_empty = 1; /* * Tag pipelines. Unlike L2 cache, L1 cache has only a tag array. */ captr->tag_pipe = RSIM_CALLOC(Pipeline *, L1I_TAG_PIPES); if (captr->tag_pipe == NULL) YS__errmsg(nodeid, "Malloc failed at %s:%i", __FILE__, __LINE__); for (i = 0; i < L1I_TAG_PIPES; i++) captr->tag_pipe[i] = NewPipeline(L1I_TAG_PORTS[i], cparam.frequency * L1I_TAG_DELAY, cparam.frequency * L1I_TAG_REPEAT, L1I_TAG_DELAY / cparam.frequency); captr->num_in_pipes = 0; /* * Statistics related stuff: capacity/conflict miss detector, * prefetch earliness and lateness. */ captr->ccd = NewCapConfDetector(captr->num_lines); captr->pref_lateness = NewStatrec(nodeid, "Prefetch Lateness", POINT, MEANS, HIST, 20, 0, 200); captr->pref_earliness = NewStatrec(nodeid, "Prefetch Earlyness", POINT, MEANS, HIST, 20, 0, 200);}/*=========================================================================== * Initialization of the L1 D-cache. */static void L1DCache_init(CACHE *captr, int nodeid, int procid){ int i; if (cparam.L1D_size == 0) YS__errmsg(nodeid, "L1 D-cache size must be greater then zero"); /* * Common fields: identity, configuration, etc. */ captr->nodeid = nodeid; captr->procid = procid; captr->gid = nodeid * ARCH_cpus + procid; captr->type = L1CACHE; captr->size = ARCH_cacsz1d; captr->linesz = ARCH_linesz1d; captr->setsz = ARCH_setsz1d; captr->replacement = LRU; /* * Initialize data array. For perfect cache, we always fake a hit * for each request, so no needs for data array. */ if (cparam.L1D_perfect == 0) Cache_init_aux(captr); captr->data = NULL; /* * Initialize MSHRs (Miss Status Hold Register?). */ captr->max_mshrs = L1D_NUM_MSHRS; captr->mshrs = RSIM_CALLOC(MSHR, captr->max_mshrs); if (captr->mshrs == NULL) YS__errmsg(nodeid, "Malloc failed at %s:%i", __FILE__, __LINE__); for (i = 0; i < captr->max_mshrs; i++) captr->mshrs[i].valid = 0; captr->mshr_count = 0; /* counts WRBs in MSHRs, etc */ captr->reqmshr_count = 0; /* only counting data requests */ captr->reqs_at_mshr_count = 0; /* * Initialize input queues * 1. "request queue" contains request from processor. * 2. "reply queue" contains replies from L2 cache. * 3. "cohe queue" contains cohe request from other processor. */ lqueue_init(&(captr->request_queue), L1D_REQUEST_QUEUE_SIZE > MEM_UNITS ? L1D_REQUEST_QUEUE_SIZE : MEM_UNITS); lqueue_init(&(captr->reply_queue), L1D_REPLY_QUEUE_SIZE); lqueue_init(&(captr->cohe_queue), L1D_COHE_QUEUE_SIZE); captr->inq_empty = 1; /* * Tag pipelines. Unlike L2 cache, L1 cache has only a tag array. */ captr->tag_pipe = RSIM_CALLOC(Pipeline *, L1D_TAG_PIPES); if (captr->tag_pipe == NULL) YS__errmsg(nodeid, "Malloc failed at %s:%i", __FILE__, __LINE__); for (i = 0; i < L1D_TAG_PIPES; i++) captr->tag_pipe[i] = NewPipeline(L1D_TAG_PORTS[i], cparam.frequency * L1D_TAG_DELAY, cparam.frequency * L1D_TAG_REPEAT, L1D_TAG_DELAY / cparam.frequency); captr->num_in_pipes = 0; /* * Statistics related stuff: capacity/conflict miss detector, * prefetch earliness and lateness. */ captr->ccd = NewCapConfDetector(captr->num_lines); captr->pref_lateness = NewStatrec(nodeid, "Prefetch Lateness", POINT, MEANS, HIST, 20, 0, 200); captr->pref_earliness = NewStatrec(nodeid, "Prefetch Earlyness", POINT, MEANS, HIST, 20, 0, 200);}/*=========================================================================== * Initialize the L2 cache */static void L2Cache_init(CACHE *captr, int nodeid, int procid){ int i; /* * Common field: identity, configuration */ captr->nodeid = nodeid; captr->procid = procid; captr->gid = nodeid * ARCH_cpus + procid; captr->type = L2CACHE; captr->size = ARCH_cacsz2; captr->linesz = ARCH_linesz2; captr->setsz = ARCH_setsz2; captr->replacement = LRU; /* * Initialize data array. */ if (cparam.L2_perfect == 0) Cache_init_aux(captr); captr->data = 0; /* * Intialize MSHRs */ captr->max_mshrs = L2_NUM_MSHRS; captr->mshrs = RSIM_CALLOC(MSHR, captr->max_mshrs); if (captr->mshrs == NULL) YS__errmsg(nodeid, "Malloc failed at %s:%i", __FILE__, __LINE__); for (i = 0; i < captr->max_mshrs; i++) captr->mshrs[i].valid = 0; captr->mshr_count = 0; captr->reqmshr_count = 0; captr->reqs_at_mshr_count = 0; /* * Initialize input queues. As in L1 cache, it has three input queues. */ lqueue_init(&(captr->request_queue), L2_REQUEST_QUEUE_SIZE); lqueue_init(&(captr->reply_queue), L2_REPLY_QUEUE_SIZE); lqueue_init(&(captr->cohe_queue), L2_COHE_QUEUE_SIZE); lqueue_init(&(captr->noncohe_queue), IO_MAX_TRANS); captr->cohe_reply_queue = &(captr->cohe_queue); captr->inq_empty = 1; /* * Pipelines. Unlike L1 cache, L2 cache is split into a "tag SRAM" * array and a "data SRAM" array. */ captr->data_pipe = RSIM_CALLOC(Pipeline *, L2_DATA_PIPES); if (captr->data_pipe == NULL) YS__errmsg(nodeid, "Malloc failed at %s:%i", __FILE__, __LINE__); for (i = 0; i < L2_DATA_PIPES; i++) captr->data_pipe[i] = NewPipeline(L2_DATA_PORTS[i], cparam.frequency * L2_DATA_DELAY, cparam.frequency * L2_DATA_REPEAT, L2_DATA_REPEAT ? (L2_DATA_DELAY / cparam.frequency) : 1); captr->tag_pipe = RSIM_CALLOC(Pipeline*, L2_TAG_PIPES); if (captr->tag_pipe == NULL) YS__errmsg(nodeid, "Malloc failed at %s:%i", __FILE__, __LINE__); for (i = 0; i < L2_TAG_PIPES; i++) captr->tag_pipe[i] = NewPipeline(L2_TAG_PORTS[i], cparam.frequency * L2_TAG_DELAY, cparam.frequency * L2_TAG_REPEAT, L2_TAG_DELAY / cparam.frequency); captr->num_in_pipes = 0; /* * Interface to bus. (L1 cache doesn't have the equivalent part.) */ dqueue_init(&(captr->reqbuffer), REQUEST_BUFFER_SIZE); lqueue_init(&(captr->outbuffer), OUT_BUFFER_SIZE); lqueue_init(&(captr->arbwaiters), MAX_ARB_WAITERS); captr->arbwaiters_count = 0; captr->stall_request = 0; captr->stall_reply = 0; captr->stall_cohe = 0; captr->cohe_reply = 0; captr->data_cohe_pending = 0; captr->pending_writeback = 0; captr->pending_request = 0; /* * Statistics related stuffs: capacity/conflict miss detector; prefetch * earliness and lateness. */ captr->ccd = NewCapConfDetector(captr->num_lines); captr->pref_lateness = NewStatrec(nodeid, "Prefetch Lateness", POINT, MEANS, HIST, 20, 0, 200); captr->pref_earliness = NewStatrec(nodeid, "Prefetch Earlyness", POINT, MEANS, HIST, 20, 0, 200);}/*=========================================================================== * This routine initializes the tag SRAM array of a specified cache. * It allocates space for each cache line. Since there is no real data * flowing around in the memory system, each line is represented by * its associated control information: state, physical tag, age, and some * other information needed by the simulator to collect statistics. */void Cache_init_aux(CACHE * captr){ int i, j; int nof_sets, num_lines; int cachesize, blocksize, setsize; cachesize = captr->size; blocksize = captr->linesz; setsize = captr->setsz; /* * Sanity check on cache configuration. */ if (cachesize == INFINITE) YS__errmsg(captr->nodeid, "No infinite cache in this version."); if (blocksize < WORDSZ) YS__errmsg(captr->nodeid, "NewCache(): line size %d is too small.", blocksize); if (NumOfBits(blocksize, 1) < 0) YS__errmsg(captr->nodeid, "NewCache(): line size(%d) isn't a power of 2", blocksize); if (setsize != FULL_ASS) if (NumOfBits(setsize, 1) < 0) YS__errmsg(captr->nodeid, "NewCache(): set size(%d) isn't a power of 2", setsize); if ((cachesize * 1024) % blocksize) YS__errmsg(captr->nodeid, "NewCache(): cache-size(%dKbytes) / line-size(%dbytes) != 0", cachesize, blocksize); num_lines = (cachesize * 1024) / blocksize; if (setsize != FULL_ASS) /* set associativity */ { if (setsize > num_lines) YS__errmsg(captr->nodeid, "setsize(%d) > num_lines(%d)", setsize, num_lines); nof_sets = num_lines / setsize; } else { /* set size is fully associative; */ setsize = num_lines; captr->setsz = setsize; nof_sets = 1; } /* * Some facilitator variables to speed up the address manipulation * in cache search functions. */ captr->num_lines = num_lines; captr->set_mask = setsize - 1; captr->set_shift = NumOfBits(setsize, 1); captr->idx_mask = nof_sets - 1; captr->idx_shift = NumOfBits(nof_sets, 1); captr->block_mask = blocksize - 1; captr->block_shift = NumOfBits(blocksize, 1); captr->tag_shift = captr->block_shift + captr->idx_shift; /* * initialize the data SRAM array. */ captr->tags = RSIM_CALLOC(cline_t, num_lines); if (captr->tags == NULL) YS__errmsg(captr->nodeid, "NewCache(): malloc failed at %s:%i", __FILE__, __LINE__); for (i = 0; i < num_lines; i += setsize) for (j = 0; j < setsize; j++) { captr->tags[i+j].index = i+j; captr->tags[i+j].state = INVALID; captr->tags[i+j].tag = -1; captr->tags[i+j].age = setsize; captr->tags[i+j].mshr_out = 0; captr->tags[i+j].pref = 0; captr->tags[i+j].pref_tag_repl = -1; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -