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

📄 memunit.cc

📁 ml-rsim 多处理器模拟器 支持类bsd操作系统
💻 CC
📖 第 1 页 / 共 4 页
字号:
  /* first do loads, then stores */  instance *memop;  int confstore = 0;  MemQLink<instance *> *stindex = NULL, *stindex2 = NULL;  /* NOTE: DON'T ISSUE ANY STORES SPECULATIVELY */  while ((proc->UnitsFree[uMEM]) &&	 ((stindex = proc->StoreQueue.GetNext(stindex)) != NULL))    {      memop = stindex->d;      /* Is the instruction already issued? */      if (memop->memprogress)   	continue;      /* All memory issues are prohibited? */      if (proc->MEMISSUEtag >= 0 &&	  memop->tag > proc->MEMISSUEtag) 	break;               if (!memop->mem_ready || confstore)	{	  if (CanPrefetch(proc, memop))	    /* Prefetch subsequent ones, regardless of whether we could or 	       couldn't for this one... */	    proc->prefrdy[proc->prefs++] = memop;	  	  continue;      	}      if (!memop->addr_ready)	{#ifdef COREFILE	  if (proc->curr_cycle > DEBUG_TIME)	    fprintf(corefile, "store tag %lld store ready but not address "		    "ready!\n", memop->tag);#endif	  /* Found the first non-read writes. We might be able to prefetch 	     some later ones, but don't issue any demand stores */	  confstore = 1;	  continue;      	}      int canissue = 1;      instance *conf;      stindex2 = NULL;      while ((stindex2 = proc->StoreQueue.GetNext(stindex2)) != NULL)	{	  conf = stindex2->d;	  if (conf->tag >= memop->tag)	    break;	  // block this one if there is a previous unissued one with	  // overlapping address....	  if (conf->memprogress == 0 && overlap(conf, memop))	    {	      canissue = 0;	      break;	    }	}      if (canissue)	{	  /* the following checks to implement MEMBAR consistency */	  if (((memop->tag > proc->SStag && proc->minstore < proc->SStag) ||	       (memop->tag > proc->LStag && proc->minload < proc->LStag) ||	       (IsRMW(memop) &&		(memop->tag > proc->SLtag && proc->minstore < proc->SLtag) ||		(memop->tag > proc->LLtag && proc->minload < proc->LLtag))))            {              canissue = 0;	      if (CanPrefetch(proc, memop))		proc->prefrdy[proc->prefs++] = memop;	      continue;   	    }	}      // Now we've passed all the semantic reasons why we can't issue it.      // So, now we need to check for hardware constraints       // check for structural hazards on input ports of cache      if (L1DQ_FULL[proc->proc_id])        {          canissue = 0;          memop->memprogress = 0;          break;        }      if (canissue)	{	  if (!IsRMW(memop))	    proc->StoresToMem++;	  	  if (simulate_ilp)	    proc->ReadyUnissuedStores--;	  	  IssueOp(memop, proc);	}    }}/*************************************************************************//* IssueLoads : Get elements from load queue and check for forwarding    *//*            : resource availability and issue it                       *//*************************************************************************/void IssueLoads(ProcState * proc){  instance *memop;  MemQLink<instance *> *stindex = NULL, *ldindex = NULL;  while ((proc->UnitsFree[uMEM]) &&	 ((ldindex = proc->LoadQueue.GetNext(ldindex)) != NULL))    {      memop = ldindex->d;      if (memop->memprogress)   // instruction is already issued	continue;      if (proc->MEMISSUEtag >= 0 &&	  memop->tag > proc->MEMISSUEtag)	break;      if ((IsUncached(memop)) &&          (((proc->SStag > 0) && (memop->tag > proc->SStag)) ||           ((proc->LStag > 0) && (memop->tag > proc->LStag)) ||           ((proc->LLtag > 0) && (memop->tag > proc->LLtag))))        break;      if (memop->addr_ready &&	  memop->truedep != 0)	{	  /* a load of an fp-half can have a true dependence on the rest of the	     fp register. In the future, it's possible that such a load should	     be allowed to issue but not to complete.  */	  /* The processor should try to prefetch it, if it has that support.	     Otherwise, this one can't issue yet. In the case of stat_sched,	     neither can anything after it. */	  if (CanPrefetch(proc, memop))	    {	      proc->prefrdy[proc->prefs++] = memop;	      continue;   /* can issue or prefetch later loads */	    }	  if (stat_sched)            break;	}      /*********************************************/      /* Memory operations that are ready to issue */      /*********************************************/      if ((memop->truedep == 0) &&          (memop->addr_ready) &&          ((IsUncached(memop) && memop->mem_ready) ||           (!IsUncached(memop))))        {	  int canissue = 1;	  int specing = 0;	  unsigned instaddr = memop->addr;	  instance *conf;	  unsigned confaddr;	  stindex = NULL;	  //-----------------------------------------------------------------	  // prefetches	  if (memop->code.instruction == iPREFETCH)	    {	      if (L1DQ_FULL[proc->proc_id])      /* ports are taken */		break;                // no further accesses will be allowed till ports free up 	      else		{		  ldindex = proc->LoadQueue.GetPrev(ldindex);      		  /* do this because we're going to be removing this entry 		     in the loadqueue in the IssueOp function */		  IssueOp(memop, proc);		  continue;		}	    }	  //-----------------------------------------------------------------	  // check for earlier (non-issued) stores	  while ((stindex = proc->StoreQueue.GetNext(stindex)) != NULL)	    {	      conf = stindex->d;	      if (conf->tag > memop->tag)		break;	      if (!conf->addr_ready)		{		  specing = 1;		  if (spec_stores == SPEC_STALL)		    {                      // now's the time to give up, if so		      memop->memprogress = 0;		      memop->vsbfwd = 0;		      return;		    }		  continue;		}	      confaddr = conf->addr;	      if (overlap(conf, memop))		{                  // ok, either we stall or we have a chance for a quick		  // forwarding.                  if (confaddr == instaddr &&                      conf->truedep == 0 &&                       MemMatch(memop, conf) &&                       !((!Speculative_Loads &&                         ((memop->tag > proc->SLtag && conf->tag < proc->SLtag) ||                          (memop->tag > proc->LLtag && proc->minload < proc->LLtag)))))		    		    // no forward across membar unless there is specload		    // support. note: specload membar is "speculative" across		    // a LL or SL, but we _actually_ enforce the MemIssue ones                    {		      if (conf->memprogress != 0)			{			  // a forward from VSB of something that actually			  // will be GloballyPerformed			  memop->vsbfwd = -conf->tag - 3;			  memop->memprogress = 0;			}		      else			{			  // if we accidentally counted it as a vsbfwd earlier,			  // count it properly now			  memop->vsbfwd = 0;         			  // varies from -3 on down!			  memop->memprogress = -conf->tag - 3; 			}		      canissue = 1;         // we can definitely use it		      continue;		    }		                    else if (conf->code.instruction == iSTDF &&                           memop->code.instruction == iLDUW &&                           conf->truedep == 0 &&                           ((memop->addr == conf->addr) ||                            (memop->addr == conf->addr + sizeof(int))) &&                           !((!Speculative_Loads &&                              ((memop->tag > proc->SLtag && conf->tag < proc->SLtag) ||                               (memop->tag > proc->LLtag && proc->minload < proc->LLtag)))))		    {                      // here's a case where we can forward just like the		      // regular case, even if it's a partial overlap.		      // I mention this case because it's                      // so common, appearing in some libraries all the time		      		      if (conf->memprogress != 0)			{			  // a forward from VSB of something that actually will be			  // GloballyPerformed -- only way it won't is if it gets			  // flushed			  memop->vsbfwd = -conf->tag - 3;			  memop->memprogress = 0;			}		      else			{			  // if we accidentally counted it as a vsbfwd earlier,			  // count it properly now			  memop->vsbfwd = 0; 			  // varies from -3 on down!			  memop->memprogress = -conf->tag - 3; 			}		      if (memop->addr == conf->addr)			{			  int *ip = (int*)(&conf->rs1valf);			  int *dp = &(memop->rdvali);			  *dp = *ip;			}		      else if (memop->addr == conf->addr + sizeof(int))			{			  int *ip = (int*)(&conf->rs1valf) + 1;			  int *dp = &(memop->rdvali);			  *dp = *ip;			  //			memop->rdvali = *(((int *) (&conf->rs1valf)) + 1);			}#ifdef DEBUG		      else			/* a partial overlap of STDF and LDUW that can't be			   handled. Most probably misalignment or other problems			   involved. Checked for this case before entering here. */			YS__errmsg(proc->proc_id / ARCH_cpus,				   "Partial overlap of STDF and LDUW which "				   "couldn't be recognized: should've been checked.\n");#endif		      		      canissue = 1;         // we can definitely use it		      continue;		    }		  else if (conf->memprogress == 0)		    {         // the store hasn't been issued yet		      memop->memprogress = 0;		      memop->vsbfwd = 0;		      canissue = 0;		      continue;		    }		  else if (IsRMW(conf))		    {  		      // you can't go in parallel with any RMW (except of		      // course for simple LDSTUBs which you forward)		      memop->memprogress = 0;		      memop->vsbfwd = 0;		      canissue = 0;		      continue;		    }		                    else if (!(((memop->tag > proc->SLtag &&                               proc->minstore < proc->SLtag) ||                              (memop->tag > proc->LLtag &&                               proc->minload < proc->LLtag))))		    {		      /* in other words, this isn't a case of trying to forward			 across a membar for now we'll actually block out partial			 overlaps (except for the special case we handled above			 STDF-LDUW), and count them when they graduate */		      		      memop->memprogress = 0;		      memop->vsbfwd = 0;		      canissue = 0;		      memop->partial_overlap = 1;#ifdef COREFILE		      if (YS__Simtime > DEBUG_TIME)			fprintf(corefile, "P%d @<%d>: Partially overlapping "				"load tag %d[%s] @(%d) conflicts with tag "				"%d[%s] @(%d)\n", proc->proc_id, proc->curr_cycle,				memop->tag, inames[memop->code.instruction], 				instaddr, conf->tag, 				inames[conf->code.instruction], confaddr);#endif		      continue;		    }		}	    }	  if (canissue && memop->memprogress > -3)	    {              if ((!Speculative_Loads &&		   ((memop->tag > proc->SLtag && proc->minstore < proc->SLtag) ||		    (memop->tag > proc->LLtag && proc->minload < proc->LLtag))))                {		  // so we're stuck at an ACQ membar well, if we have prefetch,		  // let's go ahead and prefetch reads		  memop->vsbfwd = 0;		  memop->memprogress = 0;		  canissue = 0;		  		  if (CanPrefetch(proc, memop))		    {		      proc->prefrdy[proc->prefs++] = memop;		      continue;		    }		  continue;        /* in case we have some prefetches or anything				      like that */		}	                    // Check if L1 ports are busy before issuing              if (L1DQ_FULL[proc->proc_id])                {                  canissue = 0;                  memop->vsbfwd = 0;                  memop->memprogress = 0;                  break;                }	    }	  if (canissue)	    {	      proc->ldissues++;	      	      if (specing)		proc->ldspecs++;	      if (memop->memprogress < 0)         // we got a quick forward		{		  proc->fwds++;		  memop->issuetime = proc->curr_cycle;		  // WE GET THE FORWARD VALUE IN THE MemMatch FUNCTION		  proc->MemDoneHeap.insert(proc->curr_cycle + 1, memop, memop->tag);		}	      else		IssueOp(memop, proc);	    }	}    }}#endif#ifdef COREFILE/*************************************************************************//* OpCompletionMessage : print debug information at inst completion time *//*************************************************************************/static void OpCompletionMessage(instance * inst, ProcState * proc){  if (proc->curr_cycle > DEBUG_TIME)    {      fprintf(corefile, "Completed executing tag = %lld, %s, ",               inst->tag, inames[inst->code.instruction]);      switch (inst->code.rd_regtype)	{	case REG_INT:	  fprintf(corefile, "rdi = %d, ", inst->rdvali);	  break;	case REG_FP:	  fprintf(corefile, "rdf = %f, ", inst->rdvalf);	  break;	case REG_FPHALF:	  fprintf(corefile, "rdfh = %f, ", double (inst->rdvalfh));	  break;	case REG_INTPAIR:	  fprintf(corefile, "rdp = %d/%d, ", inst->rdvalipair.a, 		  inst->rdvalipair.b);	  break;	case REG_INT64:	  fprintf(corefile, "rdll = %lld, ", inst->rdvalll);	  break;	default:	  fprintf(corefile, "rdX = XXX, ");	  break;	}      fprintf(corefile, "rccvali = %d \n", inst->rccvali);    }}static void IssueOpMessage(ProcState *proc, instance *memop){  if (proc->curr_cycle > DEBUG_TIME)    {      fprintf(corefile, "Consuming memunit for tag %lld\n", memop->tag);      fprintf(corefile, "Issue tag = %lld, %s, ", memop->tag,               inames[memop->code.instruction]);      switch (memop->code.rs1_regtype)	{	case REG_INT:	  fprintf(corefile, "rs1i = %d, ", memop->rs1vali);	  break;	case REG_FP:	  fprintf(corefile, "rs1f = %f, ", memop->rs1valf);	  break;	case REG_FPHALF:	  fprintf(corefile, "rs1fh = %f, ", double (memop->rs1valfh));	  break;	case REG_INTPAIR:	  fprintf(corefile, "rs1p = %d/%d, ", memop->rs1valipair.a, 		  memop->rs1valipair.b);	  break;	case REG_INT64:	  fprintf(corefile, "rs1ll = %lld, ", memop->rs1valll);	  break;	default:	  fprintf(corefile, "rs1X = XXX, ");	  break;	}      switch (memop->code.rs2_regtype)	{	case REG_INT:	  fprintf(corefile, "rs2i = %d, ", memop->rs2vali);	  break;	case REG_FP:	  fprintf(corefile, "rs2f = %f, ", memop->rs2valf);	  break;	case REG_FPHALF:	  fprintf(corefile, "rs2fh = %f, ", double (memop->rs2valfh));	  break;	case REG_INTPAIR:	  fprintf(corefile, "rs2pair unsupported");	  break;	case REG_INT64:	  fprintf(corefile, "rs2ll = %lld, ", memop->rs2valll);	  break;	default:	  fprintf(corefile, "rs2X = XXX, ");	  break;	}            fprintf(corefile, "rscc = %d, imm = %d\n", memop->rsccvali,               memop->code.imm);    }}#endif

⌨️ 快捷键说明

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