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

📄 memunit.cc

📁 ml-rsim 多处理器模拟器 支持类bsd操作系统
💻 CC
📖 第 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 <sys/time.h>#include <limits.h>extern "C"{#include "sim_main/simsys.h"#include "Caches/system.h"#include "Caches/ubuf.h"}                    #include "Processor/procstate.h"#include "Processor/exec.h"#include "Processor/memunit.h"#include "Processor/memq.h"#include "Processor/mainsim.h"#include "Processor/branchpred.h"#include "Processor/simio.h"#include "Processor/fastnews.h"#include "Processor/memunit.hh"#include "Processor/tagcvt.hh"#include "Processor/stallq.hh"#include "Processor/active.hh"#include "Processor/procstate.hh"#ifdef sgi#define LLONG_MAX LONGLONG_MAX#endif#if !defined(LLONG_MAX)#  define LLONG_MAX 9223372036854775807LL#endifstatic int  MemMatch       (instance * ld, instance * st);static void IssueOp        (instance * memop, ProcState * proc);static void IssueOpMessage (ProcState *proc, instance *memop);int INSTANT_ADDRESS_GENERATE = 0;/* * Overlap: returns 1 if there is overlap between addresse *        : accessed by references a and b. */#define overlap(a,b) ((a->finish_addr >= b->finish_addr && \                       b->finish_addr >= a->addr) || \                      (b->finish_addr >= a->finish_addr && \                       a->finish_addr >= b->addr))/*  * What inst->memprogress means *    2            flushed *    1            completed *    0            unissued *    -1           issued *    -3 to -inf   forwarded *//*#######################################################################*/#ifdef STORE_ORDERING/**************************************************************************//* IssueMem  : Get elements from memory queue and check for dependences,  *//*           : resource availability and issue it                         *//**************************************************************************/int IssueMem(ProcState * proc){                         instance *memop;  MemQLink<instance *> *index, *confindex;  int ctr = 0, readctr = 0;  proc->prefs = 0;     // zero prefetches so far this cycle   index = proc->MemQueue.GetNext(NULL);  do    {       ctr++;      memop = index->d;       if ((IsLoad(memop) || IsRMW(memop)) &&           (memop->code.instruction != iPREFETCH))	readctr++;      if (memop->memprogress)	{   // already issued or dead	  if (!Speculative_Loads)            break;	  else            continue;	}       /* address has to be ready before going to memory unit */      if (!memop->addr_ready || memop->truedep)	continue;       if (IsStore(memop))	{	  /* treat stores a certain way -- need to be at head of active list.	     make sure that not only is st_ready set, but also store 	     should be at top of memory unit. */	  if (memop->mem_ready && ctr == 1)	    {	      if (L1Q_FULL[proc->proc_id]) 		break;	      else		{		  if (simulate_ilp && Processor_Consistency)		    proc->ReadyUnissuedStores--;		  IssueOp(memop, proc);		  if (CanPrefetch(proc, memop))		    proc->prefrdy[proc->prefs++] = memop;    		}	    }	  	  if (!Speculative_Loads)            break;	}      else	{ // this is where we handle loads 	  if (memop->code.instruction == iPREFETCH)	    {	      /* software prefetch */	      if (L1Q_FULL[proc->proc_id])		break;	      else		{		  // do this because we're going to be removing this entry		  // in the MemQueue in the IssueOp() function. */		  index = proc->MemQueue.GetPrev(index);		  ctr--;		  IssueOp(memop, proc);		  continue;		}	    } 	  if (!(Speculative_Loads || (Processor_Consistency && readctr == 1)))	    {	      if (ctr == 1)		{		  if (L1Q_FULL[proc->proc_id])		    break;		  else		    {		      IssueOp(memop, proc);		      if (CanPrefetch(proc, memop))			proc->prefrdy[proc->prefs++] = memop;		    }		}	      else		break;	    }	  else	    {	      // in this case, we do have speculative load execution or this is	      // processor consistency but there are only writes ahead of us. 	      int canissue = 1;	      int specing = 0;	      unsigned instaddr;	      unsigned confaddr;	      instance *conf;	      confindex = NULL; 	      confindex = index;	      while (confindex = proc->MemQueue.GetPrev(confindex))		{		  conf = confindex->d;		  if (IsLoad(conf))		    continue; 		  if (conf->addrdep || !conf->addr_ready)		    {		      specing = 1;		      continue;		    } 		  /* either stall or have a chance for a quick forwarding */		  if (overlap(conf, memop))		    {		      confaddr = conf->addr;		      instaddr = memop->addr;		      if (confaddr == instaddr && conf->truedep == 0 && 			  MemMatch(memop, conf))			{			  // varies from -3 on down!			  memop->memprogress = -3 - conf->tag;    			  canissue = 1; 			}		      else if (conf->code.instruction == iSTDF &&			       memop->code.instruction == iLDUW &&			       conf->truedep == 0 &&			       ((instaddr == confaddr) ||				(instaddr == confaddr + sizeof(int))))			{			  /* here's a case where we can forward just like the			     regular case, even if it's a partial overlap. */			  if (instaddr == confaddr)			    {			      unsigned *p = (unsigned*)&(conf->rs1valf);			      memop->rdvali = *p;			    }			  else // (instaddr == confaddr + sizeof(int))			    {			      unsigned int *p = (unsigned*)&(conf->rs1valf);			      memop->rdvali = *(p + 1);			    } 			  memop->memprogress = -3 - conf->tag;			  canissue = 1;   // we can definitely use it			}		      else			{       			  // we would be expecting a partial forward at the cache			  memop->partial_overlap = 1;			  memop->memprogress = 0;			  canissue = 0;			}		      break;		    }		} 	      if (canissue && memop->memprogress > -3)		{		  if (L1Q_FULL[proc->proc_id])		    {		      memop->memprogress = 0;		      canissue = 0;		      break;		    }		} 	      if (canissue)		{		  proc->ldissues++;		  if (specing)		    proc->ldspecs++;		  if (memop->memprogress < 0)		    { // we got a quick forward		      memop->issuetime = proc->curr_cycle;		      proc->MemDoneHeap.insert(proc->curr_cycle + 1, memop, 					       memop->tag);		    }		  else		    {		      IssueOp(memop, proc);		      if (CanPrefetch(proc, memop))			proc->prefrdy[proc->prefs++] = memop;		    }		}	    }	}  /* load */    }  while ((index = proc->MemQueue.GetNext(index)) && 	 proc->UnitsFree[uMEM]);   if (Prefetch)     StartPrefetch(proc);   return 0;}#endif  /* StoreOrdering ##################################################*//* * Check for match between load and store and also forward values where  * possible. Returns 1 on success, 0 on failure call this function after  * matching load and store's address. */static int MemMatch(instance * ld, instance * st) {  INSTRUCTION load = ld->code.instruction;  INSTRUCTION store = st->code.instruction;  switch (store)    {    case iSTW:      if ((load == iLDUW) || (load == iLDSW) || (load == iLDUWA))	{	  if (load == iLDSW)	    ld->rdvali = (int)st->rs1vali;	  else	    ld->rdvali = (unsigned)st->rs1vali;	  return 1;	}      else if (load == iLDF)	{	  int *addr = (int *) &(st->rs1vali);	  *((int*)&(ld->rdvalfh)) = *addr;	  return 1;	}      return 0;    case iSTD:      if (load == iLDD)	{	  ld->rdvalipair.a = st->rs1valipair.a;	  ld->rdvalipair.b = st->rs1valipair.b;	  return 1;	}      else	return 0;   case iSTB:     if ((load == iLDUB) || (load == iLDSB))       {	 if (load == iLDSB)	   ld->rdvali=(char)st->rs1vali;	 else	   ld->rdvali=(unsigned char)st->rs1vali;	 	 return 1;       }     else       return 0;        case iLDSTUB:     if (load == iLDUB)       {         ld->rdvali = 255;         return 1;       }     else       return 0;         case iSTH:      if ((load == iLDUH) || (load == iLDSH))	{          if (load == iLDSH)            ld->rdvali=(short)st->rs1vali;          else            ld->rdvali=(unsigned short)st->rs1vali;	  return 1;	}      else	return 0;         case iSTDF:      if (load == iLDDF)	{	  ld->rdvalf = st->rs1valf;	  return 1;	}      else	return 0;         case iSTF:      if (load == iLDF)	{	  ld->rdvalfh = st->rs1valfh;	  return 1;	}      else if (load == iLDSW || load == iLDUW)	{	  int *p = (int*)&(st->rs1valfh);          if (load == iLDSW)            ld->rdvali = *p;          else            ld->rdvali = (unsigned int)*p;	  return 1;	}      else	return 0;          default:      break;    }    return 0;}/*************************************************************************//* IssueOp : Issue a memory operation to the cache or the perfect memory *//*         : system                                                      *//*************************************************************************/static void IssueOp(instance * memop, ProcState * proc){  if (memop->vsbfwd < 0)    proc->vsbfwds++;  proc->UnitsFree[uMEM]--;  memop->memprogress = -1;  memop->issuetime   = proc->curr_cycle;  memop->time_issued = YS__Simtime;#ifdef COREFILE  IssueOpMessage(proc, memop);#endif  memory_latency(memop, proc);}struct MemoryRequestState{  instance *inst;  ProcState*proc;  MemoryRequestState(instance * i, ProcState * p):inst(i), proc(p) {}};/*************************************************************************//* memory_latency : models the effect of latency spent on memory issue   *//*                : use StartUpMemReference to interface with MemSys     *//*************************************************************************/ int memory_latency(instance * inst, ProcState * proc){  /* just to see if we should execute it at all -- or does it      give a seg fault */  if (inst->exception_code == ITLB_MISS ||      inst->exception_code == DTLB_MISS ||      inst->exception_code == INSTR_FAULT ||      inst->exception_code == DATA_FAULT ||      inst->exception_code == BUSERR ||      inst->exception_code == PRIVILEGED ||      (!simulate_ilp && IsStore(inst) && inst->exception_code != OK))    {      // the last condition takes care of places that mark_stores_ready would      // have handled for an ILP processor      proc->FreeingUnits.insert(proc->curr_cycle, uMEM);#ifdef COREFILE      if (proc->curr_cycle > DEBUG_TIME)	fprintf(corefile, "Freeing memunit for tag %lld\n", inst->tag);#endif#ifndef STORE_ORDERING

⌨️ 快捷键说明

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