📄 l1d_cache.c
字号:
captr->procid); /* * Collect statistics if the mainreq is a late prefetch. */ if (pmshr->demand > 0) { if (pmshr->mainreq->prefetch == 1) captr->pstats->sl1.lateness += YS__Simtime - pmshr->demand; else if (pmshr->mainreq->prefetch == 4) captr->pstats->l1dp.lateness += YS__Simtime - pmshr->demand; pmshr->demand = -1; } cline = pmshr->cline; misscache = pmshr->misscache; req->wrb_req = 0; if (misscache == 0) /* line present in cache -- upgrade reply */ cline->state = PR_DY; else { /* line not present in cache */ if (misscache == 1) { /* "present" miss -- COHE miss */ Cache_pmiss_update(captr, req, cline->index, pmshr->only_prefs); CCD_InsertNewLine(captr->ccd, ADDR2BNUM1D(req->paddr)); req->miss_type1 = CACHE_MISS_COHE; } else { /* total miss: find a victim and updates ages */ if (!Cache_miss_update(captr, req, &cline, pmshr->only_prefs)) YS__errmsg(captr->nodeid, "L1WT should never see a NO_REPLACE"); /* We should determine COLD/CAP/CONF */ ccdres = CCD_InsertNewLine(captr->ccd, ADDR2BNUM1D(req->paddr)); req->miss_type1 = req->line_cold ? CACHE_MISS_COLD : ccdres; pmshr->cline = cline; } if (cline->state == SH_CL) captr->pstats->shcl_victims1d++; else if (cline->state == PR_CL) captr->pstats->prcl_victims1d++; else if (cline->state == PR_DY) { if (cparam.L1D_writeback) { req->wrb_req = Cache_make_req(captr, cline, WBACK); req->wrb_req->type = REQUEST; } captr->pstats->prdy_victims1d++; } /* * Now fill in the information for the new line */ cline->tag = req->paddr >> captr->tag_shift; cline->vaddr = req->vaddr & block_mask1d; if (pmshr->has_writes) cline->state = PR_DY; else cline->state = (req->req_type == REPLY_SH) ? SH_CL : PR_CL; } req->progress = 1; } if (req->progress == 1) { if (req->wrb_req) { LinkQueue *lq = &(captr->l2_partner->request_queue); if (lqueue_full(lq)) return 0; else { lqueue_add(lq, req->wrb_req, captr->nodeid); captr->l2_partner->inq_empty = 0; } } req->progress = 2; } /* * Now, resolve all requests coalesced into the MSHR in question. Send * them back to the processor for possible further handling. And if any * flush/purge transaction is pending, activate it. */ pmshr = req->l1mshr; L1DCache_uncoalesce_mshr(captr, pmshr); if (pmshr->pend_opers && pmshr->cline->state != INVALID) { if (pmshr->cline->pref == 1) captr->pstats->sl1.useless++; else if (pmshr->cline->pref == 4) captr->pstats->l1dp.useless++; pmshr->cline->state = INVALID; pmshr->cline->tag = -1; } /* * free up the MSHR, or release all coalesced requests. */ Cache_free_mshr(captr, pmshr); return 1;}/*============================================================================= * Uncoalesce each request coalesced in the specified MSHR. */int L1DCache_uncoalesce_mshr(CACHE *captr, MSHR *pmshr){ HIT_TYPE hit_type = pmshr->mainreq->hit_type; int latepf = (pmshr->demand > 0.0); int i; /* * If this MSHR had a late prefetch, set prefetched_late field to allow * system to count every access coalesced into the MSHR as part of "late PF" * time in statistics. Is this reasonable? */ pmshr->mainreq->prefetched_late = latepf; if (pmshr->mainreq->prefetch == 4) { if (!pmshr->mainreq->cohe_count) YS__PoolReturnObj(&YS__ReqPool, pmshr->mainreq); } else Cache_global_perform(captr, pmshr->mainreq, 1); for (i = 0; i < pmshr->counter; i++) { REQ *req = pmshr->coal_req[i]; /* * In addition to latepf, also set hit_type of each coalesced REQUEST * to be L1HIT. This allows all of these times to be counted as the * appropriate component of execution time. */ req->hit_type = L1DHIT; req->prefetched_late = latepf; if (req->prefetch == 4) YS__errmsg(captr->nodeid, "L1Cache_uncoalesce_msrh: coalesced L1 prefetch"); Cache_global_perform(captr, req, 1); } return 0;}/*============================================================================= * L1ProcessTagCohe: simulates coherence requests or invalidation * request to the L1 cache. An invalidation request is sent by the L2 * when a miss victim is casted out of L2 cache in order to ensure the * "inclusion property". */static int L1DProcessTagCohe(CACHE * captr, REQ * req){ cline_t *cline; int i, misscache; unsigned paddr; unsigned vaddr; unsigned eaddr; if (cparam.L1D_perfect) req->progress = 1; if (req->progress == 0) { paddr = req->paddr & block_mask2; vaddr = req->vaddr & block_mask2; eaddr = paddr + ARCH_linesz2; for (; paddr < eaddr; paddr += ARCH_linesz1d, vaddr += ARCH_linesz1d) { misscache = Cache_search(captr, vaddr, paddr, &cline); if (misscache == 0) { /* line in cache */ if (req->req_type == INVALIDATE) { if (captr->gid == req->src_proc) { /* * It's actually an invalidation request. Reset the tag * so it won't be taken as a victim of coherence check. */ cline->tag = -1; } if (cline->state == PR_DY) req->wb_count++; cline->state = INVALID; if (cline->pref == 1) captr->pstats->sl1.useless++; else if (cline->pref == 4) captr->pstats->l1dp.useless++; /* * Invalidated; check outstanding speculative loads. */ if (Speculative_Loads) SpecLoadBufCohe(captr->procid, paddr, SLB_Cohe); } else cline->state = SH_CL; } } req->progress = 1; } if (cparam.L1D_writeback) return L2ProcessL1Reply(captr->l2_partner, req); else { if (!req->cohe_count) YS__PoolReturnObj(&YS__ReqPool, req); return 1; }}/*============================================================================= * Start an L1-initiated prefetch. If L1Q is full, drop the prefetch. * Note that prefetch can not cross page boudary and no prefetch for * non-cacheable address. */static void L1DCache_start_prefetch(CACHE *captr, REQ *req){ REQ *newreq; unsigned newpaddr = req->paddr + captr->linesz; if (!SAMEPAGE(req->paddr, newpaddr) || tlb_uncached(req->memattributes)) return; captr->pstats->l1dp.total++; if (L1DQ_FULL[captr->gid]) { captr->pstats->l1dp.dropped++; return; } /* * General information */ newreq = (REQ *) YS__PoolGetObj(&YS__ReqPool); newreq->type = REQUEST; newreq->req_type = READ; newreq->prefetch = 4; newreq->node = captr->nodeid; newreq->src_proc = captr->procid; newreq->prcr_req_type = req->prcr_req_type; newreq->paddr = newpaddr; newreq->vaddr = req->vaddr + captr->linesz; newreq->ifetch = 0; newreq->l1mshr = 0; newreq->l2mshr = 0; newreq->memattributes = req->memattributes; newreq->line_cold = 0; /* * for statistics */ newreq->issue_time = YS__Simtime; newreq->hit_type = UNKHIT; newreq->line_cold = 0; /* * Add it to REQUEST input queue of L1 cache, which must then know that * there is something on its input queue so as to be activated by * cycle-by-cycle simulator. If this access fills up the port, the * L1Q_FULL variable is set so that the processor does not issue any * more memory references until the port clears up. */ lqueue_add(&(captr->request_queue), newreq, captr->nodeid); captr->inq_empty = 0; L1DQ_FULL[captr->gid] = lqueue_full(&(captr->request_queue));}#if 0void L1ProcessTagPipe(CACHE *captr, int pipenum){ Pipeline *pipe = captr->tag_pipe[pipenum]; int ctr = 0; REQ *req; while (1) { GetPipeElt(req, pipe); if (req == 0) break; if (L1ProcessTagReq(captr, req) == 1) { ClearPipeElt(pipe); captr->num_in_pipes--; } else ctr++; }}/* * L1ProcessTagReq: simulates accesses to the L1 cache. * Its behavior depends on the type of message (i.e. type) received * Returns 0 on failure; 1 on success. */static int L1ProcessTagReq(CACHE * captr, REQ * req){ switch (req->type) { case REQUEST: return L1ProcessTagRequest(captr, req); case REPLY: return L1ProcessTagReply(captr, req); case COHE: return L1ProcessTagCohe(captr, req); case COHE_REPLY: YS__errmsg("L1 cache should not get a COHE_REPLY!"); } YS__errmsg("Unreachable code in L1ProcessTagReq()!"); return 0;}/* * Macro that processes input queues of L1 cache. Used by L1CacheInSim. */#define ProcessInputQueue(lq, pipenum) \ while (req = (REQ *) lqueue_head(lq)) { \ if (AddToPipe(captr->tag_pipe[pipenum], req)) { \ req->progress = 0; \ lqueue_remove(lq, next, REQ *); \ captr->num_in_pipes++; \ } \ else { \ nothing_on_ports = 0; \ break; \ } \ }/* * Macro that processes pipelines of L1 cache. Used by L1CacheOutSim. */#define ProcessPipeline(pline, pfunc) \ pipe = pline; \ ctr = 0; \ while (1) { \ GetPipeElt(req, pipe, ctr); \ if (req == 0) \ break; \ if (pfunc(captr, req)) { \ ClearPipeElt(pipe, ctr); \ captr->num_in_pipes--; \ } \ else \ ctr++; \ }#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -