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

📄 l2cache.c

📁 ml-rsim 多处理器模拟器 支持类bsd操作系统
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * Copyright (c) 2002 The Board of Trustees of the University of Illinois and *                    William Marsh Rice University * Copyright (c) 2002 The University of Utah * Copyright (c) 2002 The University of Notre Dame du Lac * * All rights reserved. * * Based on RSIM 1.0, developed by: *   Professor Sarita Adve's RSIM research group *   University of Illinois at Urbana-Champaign and     William Marsh Rice University *   http://www.cs.uiuc.edu/rsim and http://www.ece.rice.edu/~rsim/dist.html * ML-RSIM/URSIM extensions by: *   The Impulse Research Group, University of Utah *   http://www.cs.utah.edu/impulse *   Lambert Schaelicke, University of Utah and University of Notre Dame du Lac *   http://www.cse.nd.edu/~lambert *   Mike Parker, University of Utah *   http://www.cs.utah.edu/~map * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal with the Software without restriction, including without * limitation the rights to use, copy, modify, merge, publish, distribute, * sublicense, and/or sell copies of the Software, and to permit persons to * whom the Software is furnished to do so, subject to the following * conditions: * * 1. Redistributions of source code must retain the above copyright notice, *    this list of conditions and the following disclaimers.  * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimers in the *    documentation and/or other materials provided with the distribution. * 3. Neither the names of Professor Sarita Adve's RSIM research group, *    the University of Illinois at Urbana-Champaign, William Marsh Rice *    University, nor the names of its contributors may be used to endorse *    or promote products derived from this Software without specific prior *    written permission.  * 4. Neither the names of the ML-RSIM project, the URSIM project, the *    Impulse research group, the University of Utah, the University of *    Notre Dame du Lac, nor the names of its contributors may be used to *    endorse or promote products derived from this software without specific *    prior written permission.  * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS WITH THE SOFTWARE.  */#include <stdio.h>#include <malloc.h>#include "Processor/capconf.h"#include "Processor/simio.h"#include "Processor/memunit.h"#include "Processor/tlb.h"#include "sim_main/simsys.h"#include "Caches/system.h"#include "Caches/req.h"#include "Caches/pipeline.h"#include "Caches/cache.h"#include "Caches/ubuf.h"#include "Caches/syscontrol.h"#include "IO/addr_map.h"#include "Bus/bus.h"/* * Macros which specify which pipeline each type of access belongs to. * * A separate COHE tag pipe is added to avoid deadlock. Such a port may be * considered excessive in a real system; thus, it may be advisable to * reserve a certain number of MSHR-like buffers for incoming COHE messages * and simply withhold processing of additional COHEs until space opens up * in one of these buffers. */#define L2ReqDATAPIPE 		0#define L2ReplyTAGPIPE 		0#define L2CoheTAGPIPE 		1#define L2RequestTAGPIPE 	2/* * Functions to process request */static int  L2ProcessDataReq            (CACHE*, REQ*);static int  L2ProcessTagRequest         (CACHE*, REQ*);static int  L2ProcessTagReply           (CACHE*, REQ*);static int  L2ProcessTagCohe            (CACHE*, REQ*);static int  L2ProcessTagCoheReply       (CACHE*, REQ*);static int  L2ProcessFlushPurge         (CACHE*, REQ*);static REQ *Cache_make_wb_req           (CACHE*, REQ*, ReqType);static REQ *Cache_make_cohe_to_l1       (CACHE*, REQ*, int state);static int  Cache_add_repl_to_l1        (CACHE*, REQ*);static MSHR_Response L2Cache_check_mshr (CACHE*, REQ*);static void L2Cache_start_prefetch      (CACHE*, REQ*);static int  L2Cache_uncoalesce_mshr     (CACHE*, MSHR*);/*=========================================================================== * L2CacheInSim: function that brings new transactions from the ports into * the pipelines associated with the various cache parts. An operation can * be removed from its port as soon as pipeline space opens up for it. * Called whenever there may be something on an input port. */void L2CacheInSim(int gid){  CACHE *captr = L2Caches[gid];  REQ   *req;  int    nothing_on_ports = 1;  /* First check if there is a pending cache-to-cache copy ================*/  if (captr->data_cohe_pending)    if (AddToPipe(captr->data_pipe[L2ReqDATAPIPE], captr->data_cohe_pending))      {        captr->data_cohe_pending = 0;        captr->num_in_pipes++;      }	  /* Coherence queue first because somebody else is waiting for you =======*/  while (req = lqueue_head(&captr->cohe_queue))    {      if (AddToPipe(captr->tag_pipe[L2CoheTAGPIPE], req))	{	  req->progress = 0;	  lqueue_remove(&(captr->cohe_queue));	  captr->num_in_pipes++;	}      else	{	  nothing_on_ports = 0;	  break;	}    }  req = lqueue_head(&captr->noncohe_queue);  if (req != NULL)    {      if ((IsSysControl_external(req, gid % ARCH_cpus)) ||	  (IsSysControl_local(req)))	{	  if (SysControl_external_request(gid, req))	    {	      lqueue_remove(&(captr->noncohe_queue));	    }	  else	    nothing_on_ports = 0;	}         else	YS__errmsg(captr->nodeid,		   "Unknown request type in noncoherent queue\n");    }    /* Reply queue is always handled before request queue ===================*/  while (req = lqueue_head(&captr->reply_queue))    {      if (AddToPipe(captr->tag_pipe[L2ReplyTAGPIPE], req))	{	  req->progress = 0;	  lqueue_remove(&(captr->reply_queue));	  captr->num_in_pipes++;	}      else	{	  nothing_on_ports = 0;	  break;	}    }    /* Request queue ========================================================*/  while (req = lqueue_head(&captr->request_queue))    {      if (AddToPipe(captr->tag_pipe[L2RequestTAGPIPE], req))	{	  req->progress = 0;	  lqueue_remove(&(captr->request_queue));	  captr->num_in_pipes++;	}      else	{	  nothing_on_ports = 0;	  break;	}    }  if (nothing_on_ports)    captr->inq_empty = 1;}/*=========================================================================== * L2CacheOutSim: initiates actual processing of various REQ types * Called each cycle that there is something in pipes to be processed */void L2CacheOutSim(int gid){  CACHE    *captr = L2Caches[gid];  Pipeline *pipe;  REQ      *req;  int       pipenum, ctr, index, result;  /*   * NOTE: L2 is not a monolithic piece of SRAM like the L1. The L2 is split   * into a "tag SRAM" array and a "data SRAM" array. So, this function needs   * to look at both tag pipes and data pipes. It looks at data pipes first,   * as tag pipes might push something into data pipes, but never the other   * way around.   */  for (pipenum = 0; pipenum < L2_DATA_PIPES; pipenum++)    {      pipe = captr->data_pipe[pipenum];      for (ctr = 0; ctr < pipe->ports; ctr++)	{	  GetPipeElt(req, pipe);	  if (req == 0)	    break;	  result = L2ProcessDataReq(captr, req);	  if (result == 1)	    {	      ClearPipeElt(pipe);	      captr->num_in_pipes--;	    }	  else if (result == -1)	    {	      SetPipeElt(req->invl_req, pipe);	      req->invl_req = 0;	    }	}    }    /*-------------------------------------------------------------------------   * Process tag pipelines. First, process reply queue; then, process   * coherence request queue; Finally, it's request queue's turn.   */  if (!captr->stall_reply)    {      pipe = captr->tag_pipe[L2ReplyTAGPIPE];      for (ctr = 0; ctr < pipe->ports; ctr++)	{	  GetPipeElt(req, pipe);	  if (req == 0)	    break;	  result = L2ProcessTagReply(captr, req);          if (result == 1)	    {	      ClearPipeElt(pipe);	      captr->num_in_pipes--;	    }	  else if (result == -1)	    {	      SetPipeElt(req->invl_req, pipe);	      req->invl_req = 0;	    }	}    }  if (!captr->stall_cohe && !captr->cohe_reply)    {      pipe = captr->tag_pipe[L2CoheTAGPIPE];      for (ctr = 0; ctr < pipe->ports; ctr++)	{	  GetPipeElt(req, pipe);	  if (req == 0)	    break;	  if (L2ProcessTagCohe(captr, req))	    {	      ClearPipeElt(pipe);	      captr->num_in_pipes--;	      captr->pstats->snoop_requests++;	    }	}    }  /*-----------------------------------------------------------------------*/    if (!captr->stall_request)    {      pipe = captr->tag_pipe[L2RequestTAGPIPE];      for (ctr = 0; ctr < pipe->ports; ctr++)	{	  GetPipeElt(req, pipe);	  if (req == 0)	    break;          result = L2ProcessTagRequest(captr, req);          if (result == 0)  /* ?? */	    break;	  if (result == 1)	    {	      ClearPipeElt(pipe);	      captr->num_in_pipes--;	    }	  else if (result == -1)	    {	      SetPipeElt(req->invl_req, pipe);	      req->invl_req = 0;	    }	}    }}/*=========================================================================== * L2ProcessDataReq: simulates accesses to the L2 data SRAM array, * Returns 0 on failure; 1 on success. No equivalent function in L1. */int L2ProcessDataReq(CACHE *captr, REQ * req){  switch (req->type)    {    case REQUEST:      /*       * A cache hit that gets sent back to the L1. Change it to REPLY.       */      if (req->req_type == WBACK)	{	  YS__PoolReturnObj(&YS__ReqPool, req);	  return 1;	}      if (req->progress == 0)	{	  req->progress = 1;	  req->type     = REPLY;	}            /*       * Try to send it up to L1 cache. Cache_add_repl_to_l1 returns 1 on       * success, and 0 on failure. This request will be awoken in REPLY case,       * which just seeks to send up access also.       */      return Cache_add_repl_to_l1(captr, req);          case REPLY:      if (req->l2mshr == 0)	{	  /*	   * It's a stalled L2 hit (came from REQUEST).	   */	  return Cache_add_repl_to_l1(captr, req);	}      else	{	  MSHR *pmshr = req->l2mshr;	  REQ  *tmpreq;	  /*	   * It was an L2 miss. We have to release all the coalesced requests	   * one by one; and the flush/purge request if exists.	   */	  if (Cache_add_repl_to_l1(captr, req) == 0)	    return 0;	  pmshr->next_move++;	  for (; pmshr->next_move < pmshr->counter; pmshr->next_move++)	    {	      tmpreq = pmshr->coal_req[pmshr->next_move];	      if (Cache_add_repl_to_l1(captr, tmpreq) == 0)		{		  tmpreq->l2mshr = pmshr;		  req->invl_req = tmpreq;		  return -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++;		}	    }	            /*	   * All coalesced requests either have been sent back to L1 cache, or	   * have performed GlobalPerform. Release the MSHR now.	   */	  Cache_free_mshr(captr, pmshr);	  if (tmpreq)	    {	      if (!lqueue_full(&(captr->outbuffer)) ||		  !captr->pending_writeback)		{		  Cache_start_send_to_bus(captr, tmpreq);		  return 1;		}	      else		{		  req->invl_req = tmpreq;		  return -1;		}	    }	}      return 1;          case COHE:      /*       * This is a cache-to-cache copy. Only one cache-to-cache copy       * is allowed at one time.       */      if (captr->cohe_reply)	return 0;      else	{	  req->type = COHE_REPLY;	  Cache_start_send_to_bus(captr, req);	  return 1;	}    case WRITEBACK:      /*

⌨️ 快捷键说明

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