⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 l2cache.c

📁 ml-rsim 多处理器模拟器 支持类bsd操作系统
💻 C
📖 第 1 页 / 共 4 页
字号:
    if (pmshr->releasing)    {      captr->pstats->l2stall.release++;      return MSHR_STALL_RELEASE;    }  /*   * Now we need to consider the possibility of a "WAR" stall. This is a   * case where an MSHR has an exclusive-mode request wants to merge with a   * shared-mode MSHR.  Even if this is a read request to an MSHR with an   * outstanding WAR, this request should be stalled, as otherwise the read   * would be processed out-of-order with respect to the stalled write   */  if (pmshr->stall_WAR)    {      captr->pstats->l2stall.war++;      return MSHR_STALL_WAR;    }  if ((req->prcr_req_type != READ) &&      (pmshr->mainreq->prcr_req_type == READ))    {      captr->pstats->l2stall.war++;      pmshr->stall_WAR = 1;      return MSHR_STALL_WAR;    }  /*   * Too many requests coalesced with MSHR   */  if (pmshr->counter == MAX_COALS-1)    {      captr->pstats->l2stall.coal++;      return MSHR_STALL_COAL;    }  /*   * No problems with coalescing the request, so coalesce it   */  pmshr->coal_req[pmshr->counter++] = req;  if (req->req_type == WRITE || req->req_type == RMW)    pmshr->has_writes = 1;  else    pmshr->has_writes = 0;  if (pmshr->only_prefs && !(req->prefetch & 10))    {      /*       * Hit a late prefetch.       */      if (pmshr->mainreq->prefetch == 2)	{	  captr->pstats->sl2.late++;	  captr->pstats->sl2.useful++;	}      else if (pmshr->mainreq->prefetch == 8)	{	  captr->pstats->l2p.late++;	  captr->pstats->l2p.useful++;	}            pmshr->demand = YS__Simtime; /* use this to compute lateness factor */      pmshr->only_prefs = 0;    }    return MSHR_COAL;}/*=========================================================================== * Simulates access replies to the L2 cache tag array. *  progress = 0: initial state *  progress = 1: reply has been processed, but hasn't sent anything out. *  progress = 2: the invalidation request has been sent up, if any. *  progress = 3: the write-back request has been sent down, if any. * Returns 0 on failure; 1 on success. */static int L2ProcessTagReply(CACHE * captr, REQ * req){  int        misscache, i;  MISS_TYPE  ccdres;  cline_t   *cline;  MSHR      *pmshr;  REQ       *ireq;  if (req->type == WRITEBACK)    {      if (captr->pending_writeback)	return 0;      else	{	  Cache_start_send_to_bus(captr, req);	  return 1;	}    }  if (captr->stall_reply)    return 0;  if (req->progress == 0)    {      pmshr = req->l2mshr;      if (pmshr == 0)	YS__errmsg(captr->nodeid,		   "L2 Cache %i received a reply (0x%p 0x%08X) for a nonexistent MSHR\n",		   captr->procid, req, req->paddr);      /*       * Collect statistics about late prefetch.       */      if (pmshr->demand > 0)	{	  if (pmshr->mainreq->prefetch == 2)            captr->pstats->sl2.lateness += YS__Simtime - pmshr->demand;	  else if (pmshr->mainreq->prefetch == 8)            captr->pstats->l2p.lateness += YS__Simtime - pmshr->demand;	  pmshr->demand = -1;	}      /*       * Does the MSHR have a coherence message merged into it? This happens       * when MSHR receives a certain type of COHE while outstanding. In       * this case, the line must transition to a different state than the       * REPLY itself would indicate. Note: such merging is only allowed if       * the merge will not require a copyback of any sort. And are there       * any writes with this MSHR? If so, make sure to transition to       * dirty....       */      cline         = pmshr->cline;      misscache     = pmshr->misscache;      req->invl_req = NULL;      req->wrb_req  = NULL;      if (misscache == 0)	{ /* this was for an upgrade */	  cline->state    = PR_DY;	  cline->mshr_out = 0;	}      else	{	  if (misscache == 1)	    { /* present miss */	      Cache_pmiss_update(captr, req, cline->index, pmshr->only_prefs);	      req->miss_type2 = CACHE_MISS_COHE;	    }	  else	    { /* misscache == 2 : total miss */	      /*	       * Finds a victim and updates ages. If no places are available,	       * wait.	       */	      if (!Cache_miss_update(captr, req, &cline, pmshr->only_prefs))		{		  YS__warnmsg(captr->nodeid,			      "No replace for L2 cache_miss, possible deadlock");		  return 0;		}	      /*	       * capacity/conflict miss detector	       */	      ccdres = CCD_InsertNewLine(captr->ccd, ADDR2BNUM2(req->paddr));	      req->miss_type2 = req->line_cold ? CACHE_MISS_COLD : ccdres;	      pmshr->cline = cline;	    }	  if (cline->state != INVALID)	    {	      /*	       * In this case, some sort of replacement is needed. Gather all	       * information about line being replaced	       */	      if (cline->state == SH_CL)		captr->pstats->shcl_victims2++;	      else if (cline->state == PR_CL)		captr->pstats->prcl_victims2++;	      else if (cline->state == PR_DY)		captr->pstats->prdy_victims2++;	      if (cline->state == PR_DY)		{		  /*		   * Need to send the private dirty line back to main memory.		   */		  req->wrb_req = Cache_make_req(captr, cline, REPLY_EXCL);		  req->wrb_req->type   = WRITEBACK;		  req->wrb_req->parent = 0; /* not associated with any cohe*/		}	      /*	       * Also an invalidation message is sent up to the L1 caches.	       */              req->invl_req = Cache_make_req(captr, cline, INVALIDATE);	      req->invl_req->type = COHE;	      req->invl_req->parent = req;	      ireq = Cache_make_req(captr, cline, INVALIDATE);	      ireq->type = COHE;	      ireq->parent = req;	    }	  /*	   * Set tags and states to reflect new line	   */	  cline->tag   = req->paddr >> captr->tag_shift;	  cline->vaddr = req->vaddr & block_mask2;	  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->invl_req)	{	  if ((lqueue_full(&(captr->l1i_partner->cohe_queue))) ||	      (lqueue_full(&(captr->l1d_partner->cohe_queue))))	    return 0;	  else	    {	      ireq->prcr_req_type = 0;	      ireq->wb_count = 0;	      lqueue_add(&(captr->l1i_partner->cohe_queue), ireq,			 captr->nodeid);	      captr->l1i_partner->inq_empty = 0;	      req->invl_req->prcr_req_type = 0;	      req->invl_req->wb_count = 0;	      lqueue_add(&(captr->l1d_partner->cohe_queue),			 req->invl_req, captr->nodeid);	      captr->l1d_partner->inq_empty = 0;	    }	}      if (cparam.L1D_writeback && req->invl_req)         req->progress = 2;      else         req->progress = 3;    }  if (req->progress == 2)    return 0;    if (req->progress == 3)    {      /*       * ready to send out a WRB to Data pipe or a REPL down, if any       */      if (req->wrb_req)	{	  if (AddToPipe(captr->data_pipe[L2ReqDATAPIPE], req->wrb_req))	    {	      req->wrb_req->progress = 0;	      captr->num_in_pipes++;	    }	  else	    return 0;	}      req->progress = 4;     /* ready to send REPLY to data pipe */    }  if (AddToPipe(captr->data_pipe[L2ReqDATAPIPE], req))    {      captr->num_in_pipes++;      req->progress = 0;      /*       * Prepare release the request one by one, starting from the mainreq       * (indicated by "next_move = -1". All the requests share the reply       * type (REPLY_SH, REPLY_PR, or UPGRADE).       */      pmshr = req->l2mshr;      pmshr->next_move = -1;      pmshr->releasing = 1;      for (i = 0; i < pmshr->counter; i++)	{	  REQ *tmpreq = pmshr->coal_req[i];	  if ((tmpreq->hit_type != L1IHIT) && (tmpreq->hit_type != L1DHIT))            tmpreq->hit_type = L2HIT;	  tmpreq->req_type  = req->req_type;	  tmpreq->line_cold = 0;	}      return 1;    }  /* couldn't go to Data pipe */  return 0;}int L2ProcessTagInvlReply(CACHE *captr, REQ *rtn_req){  REQ *req = rtn_req->parent;   if (rtn_req->wb_count && req->wrb_req == 0)    {      req->wrb_req = Cache_make_req(captr, req->l2mshr->cline, REPLY_EXCL);      req->wrb_req->type   = WRITEBACK;      req->wrb_req->parent = 0; /* not associated with any cohe */    }    if (req)    req->progress = 3;   if (!req->cohe_count)    YS__PoolReturnObj(&YS__ReqPool, rtn_req);  return 1;}/*=========================================================================== * Uncoalesce each request coalesced in the specified MSHR. */static int L2Cache_uncoalesce_mshr(CACHE *captr, MSHR *pmshr){  HIT_TYPE  hit_type = pmshr->mainreq->hit_type;  int       latepf   = (pmshr->demand > 0.0);  int       i;  REQ       *tmpreq;  /*   * 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 == 8)    {      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.       */      if (req->ifetch)	req->hit_type = L1IHIT;      else	req->hit_type = L1DHIT;      req->prefetched_late = latepf;      if (req->prefetch == 8)	YS__errmsg(captr->nodeid,		   "L1Cache_uncoalesce_msrh: coalesced L1 prefetch");      Cache_global_perform(captr, req, 1);    }  /*   * Take care of pending flush/purge requests. Generate a write-back   * if flush hits a private dirty line.   */  tmpreq = NULL;  if (pmshr->pend_opers)    {      cline_t *cline = pmshr->cline;      if (pmshr->pend_opers == FLUSHC && cline->state == PR_DY)	{	  tmpreq = Cache_make_req(captr, cline, REPLY_EXCL);	  tmpreq->type   = WRITEBACK;	  tmpreq->parent = 0; /* not associated with any cohe */	}            if (cline->state != INVALID)	{	  cline->state = INVALID;	  cline->tag = -1;	  if (cline->pref == 2)	    captr->pstats->sl2.useless++;	  else if (cline->pref == 8)	    captr->pstats->l2p.useless++;	}    }  Cache_free_mshr(captr, pmshr);  if (tmpreq)    {      if (lqueue_full(&(captr->outbuffer)) && captr->pending_writeback)	{	  pmshr->mainreq->invl_req = tmpreq;	  return -1;	}      else	Cache_start_send_to_bus(captr, tmpreq);    }  return 1;}/*=========================================================================== * L2ProcessTagReq: simulates accesses to the L2 cache tag array. * Its behavior depends on the type of message (i.e. type) received * This is very similar to L1ProcessTagReq, except where noted. * Returns 0 on failure; 1 on success. */int L2ProcessTagCohePipe(CACHE *captr, REQ *req){   switch (req->type)     {     case COHE:     case REQUEST:       return L2ProcessTagCohe(captr, req);      case COHE_REPLY:       if (req->prcr_req_type == FLUSHC)         return L2ProcessTagFlushReply(captr, req);       else if (captr->procid == req->src_proc)         return L2ProcessTagInvlReply(captr, req);       else         return L2ProcessTagCoheReply(captr, req);     }   YS__errmsg(captr->nodeid, "L2TagProcessCohePipe: req not handled\n");   return 0;} int L2ProcessL1Reply(CACHE *captr, REQ *req){  if (req->prcr_req_type == FLUSHC)    return L2ProcessTagFlushReply(captr, req);  else if (captr->procid == req->src_proc)    return L2ProcessTagInvlReply(captr, req);  else    return L2ProcessTagCoheReply(captr, req);} int L2ProcessTagCoheReply(CACHE *captr, REQ *req){  ReqType finalstate;  if (req->parent->prcr_req_type == READ)    finalstate = REPLY_SH;  else    finalstate = REPLY_EXCL;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -