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

📄 memunit.cc

📁 ml-rsim 多处理器模拟器 支持类bsd操作系统
💻 CC
📖 第 1 页 / 共 4 页
字号:
      if (!simulate_ilp && IsStore(inst) && !IsRMW(inst))	{	  proc->active_list.mark_done_in_active_list(inst->tag, 						     inst->exception_code,						     proc->curr_cycle - 1);	  return 0;	}#endif      proc->MemDoneHeap.insert(proc->curr_cycle + 1, inst, inst->tag);      return 0;    }#ifndef STORE_ORDERING  if (!simulate_ilp && IsStore(inst) && !IsRMW(inst))    {      inst->in_memunit = 0;      instance *memop = new instance(inst);      proc->StoreQueue.Replace(inst, memop);      inst = memop;    }#endif  if (inst->code.instruction == iPREFETCH)    { // send out a prefetch      int excl  = inst->code.aux2 == PREF_1WT || inst->code.aux2 == PREF_NWT;      int level = 1 + (Prefetch == 2 || inst->code.aux2 == PREF_1WT ||                        inst->code.aux2 == PREF_1RD);      if (!drop_all_sprefs)	IssuePrefetch(proc, inst->addr, level, excl, inst->tag);      // the prefetch instruction itself should return instantly a pref isn't      // like other memops; it can return even without paying cache time      inst->memprogress = 1;      PerformMemOp(inst, proc);#if 0#ifdef COREFILE      OpCompletionMessage(inst, proc);#endif#endif      proc->DoneHeap.insert(proc->curr_cycle + 1, inst, inst->tag);      return 0;    }  if (StartUpMemRef(proc, inst) == -1)    /* not accepted -- should never happen */    YS__errmsg(proc->proc_id / ARCH_cpus,	       "StartUpMemRef rejected an operation.\n");  return 0;}/*=========================================================================== * Takes entries off the MemDoneHeap and if they are valid, inserts them  * on the running queue called by RSIM_EVENT(). */void CompleteMemQueue(ProcState * proc){  instance *inst;  long long inst_tag;  if ((proc->MemDoneHeap.num() == 0) ||      (proc->MemDoneHeap.PeekMin() > proc->curr_cycle))    return;  do    {      proc->MemDoneHeap.GetMin(inst, inst_tag);       if (inst->tag == inst_tag)             // hasn't been flushed        CompleteMemOp(inst, proc);           // this will insert completions                                             // on running q#ifdef COREFILE      else        {          if (proc->curr_cycle > DEBUG_TIME)            fprintf(corefile,		    "Got nonmatching tag %lld off memheap\n",		    inst_tag);        }#endif     }  while (proc->MemDoneHeap.num() != 0 &&         proc->MemDoneHeap.PeekMin() <= proc->curr_cycle);}/**************************************************************************//* CompleteMemOp : Perform the operations on completion of a memory instr *//*               : and add to DoneHeap                                    *//**************************************************************************/int CompleteMemOp(instance * inst, ProcState * proc){#ifdef DEBUG  if (inst->memprogress == 2)    YS__errmsg(proc->proc_id / ARCH_cpus,	       "Flushed operation should not come to CompleteMemOp.");#endif   if (IsStore(inst))     {       //--------------------------------------------------------------------       // STORE: Completes perfectly. Mark it done in some way, and if it's       // the first instruction in the store q, mark all in-order dones       // possible       // -- Note that in the SC world, all Stores are like RMWs#ifdef DEBUG      if (inst->memprogress == 2)               // it has been flushed        YS__errmsg(proc->proc_id / ARCH_cpus,		   "Flushed operation %s (tag=%lld) should never come to CompleteMemOp.\n",		   inames[inst->code.instruction], inst->tag);#endif            inst->memprogress = 1;      #ifdef DEBUG      if (!inst->global_perform && inst->exception_code == OK)        YS__errmsg(proc->proc_id / ARCH_cpus,		   "Tag %lld (0x%08X) Processor %d was never globally performed! (addr 0x%08X)\n",		   inst->tag, inst->pc, proc->proc_id, inst->addr);#endif       // we need to move this to the issue stage,      // to handle proper simulation of RAW, etc       if (IsRMW(inst)#ifdef STORE_ORDERING          || (!SC_NBWrites && !Processor_Consistency)#endif          )        {          if (inst->memprogress <= 0)            {              inst->issuetime = LLONG_MAX;              return 0; // not yet accepted            }          PerformMemOp(inst, proc);          // use this so that it's clearly done in the memory unit#if 0 #ifdef COREFILE          OpCompletionMessage(inst,proc);#endif#endif          proc->DoneHeap.insert(proc->curr_cycle, inst, inst->tag);        }       else                  // an ordinary write in RC or PC or SC w/nb writes        {#ifndef STORE_ORDERING          proc->StoresToMem--;#endif          PerformMemOp(inst, proc);          // use this so that it's clearly done in the memory unit#if 0 #ifdef COREFILE          OpCompletionMessage(inst, proc);#endif#endif      	  if (inst->inuse == 2)	    {	      inst->inuse = 0;	      proc->meminstances.Putback(inst);	    }	  else	    DeleteInstance(inst, proc);	}            return 0;     }      else    {      //---------------------------------------------------------------------      // LOAD: On completion, first see if there are any items in      // store q with lower tag that has same addr or unknown addr. If      // so, we may need to redo operation. If not, mark it done and      // if first instr in store q, mark all in-order completes possible#ifdef DEBUG      if (inst->memprogress == 2)	YS__errmsg(proc->proc_id / ARCH_cpus,		   "Flushed operation should not come to CompleteMemOp.\n");      else#endif      if (inst->code.instruction == iPREFETCH)        {          YS__logmsg(proc->proc_id / ARCH_cpus,		     "Why did we enter Complete Mem Op on a prefetch???\n");          inst->memprogress = 1;     // don't check limbos, spec_stores, etc.          PerformMemOp(inst, proc);        }       else        {          if (inst->exception_code == SOFT_SL_COHE ||              inst->exception_code == SOFT_SL_REPL ||              inst->exception_code == SOFT_LIMBO)            // footnote 5 implementation -- we'll need to redo it.            {              if (inst->exception_code == SOFT_LIMBO)                proc->redos++;               inst->prefetched = 0;              inst->memprogress = 0;              inst->vsbfwd = 0;              inst->global_perform = 0;              inst->exception_code = OK;              inst->issuetime = LLONG_MAX;              return 0;            }                    int redo = 0;                    instance *sts;          long long lowambig;          if (inst->kill == 1)            {              redo = 1;              inst->kill = 0;            }          if (spec_stores == SPEC_LIMBO &&              proc->ambig_st_tags.GetMin(lowambig) &&              lowambig < inst->tag)      // ambiguous store before this load...            {              proc->limbos++;              inst->limbo++;  // Set the limbo bit on to remember to check for this            }          // if so, this is all taken care of before Issue          if (spec_stores != SPEC_STALL)            {              MemQLink<instance *> *stindex = NULL;#ifndef STORE_ORDERING              while ((stindex = proc->StoreQueue.GetNext(stindex)) != NULL)#else	      while ((stindex = proc->MemQueue.GetNext(stindex)) != NULL)#endif                {                  sts = stindex->d;                  if (sts->tag > inst->tag)                    break;#ifdef STORE_ORDERING                  if (!IsStore(sts))                    continue;#endif                  // if we got a forward, then we can ignore the other cases here                  if (inst->memprogress <= -sts->tag-3)                    // we got a forward from an op with greater tag                    continue;                  if (!sts->addr_ready && spec_stores == SPEC_EXCEPT)                    {		      if (inst->limbo == 0)			proc->limbos++;		      inst->limbo++;#ifdef COREFILE                      if (proc->curr_cycle > DEBUG_TIME)                        fprintf(corefile,                                "P%d,%lld Gambling to avoid a limbo on %lld\n",                                proc->proc_id,                                inst->tag,                                sts->tag);#endif                      continue;                    }                  if (overlap(sts, inst) &&		      (inst->issuetime < sts->issuetime))                    {                      proc->redos++;                      redo = 1;                      break;                    }		}	    }          	  if (redo)	    {	      inst->memprogress = 0;         // in other words, start all over	      inst->vsbfwd = 0;	      inst->issuetime = LLONG_MAX;	      inst->limbo--;	      return 0;	    }           else	    {#ifdef DEBUG	      if (inst->memprogress == -1 )         // non-forwarded		{		  if (!inst->global_perform && inst->exception_code == OK)		    YS__errmsg(proc->proc_id / ARCH_cpus,			       "Tag %lld (0x%08X) Processor %d was never globally performed (addr 0x%08X)!\n",			       inst->tag,			       inst->pc, 			       proc->proc_id,			       inst->addr);		}	                    if (inst->memprogress == 0)             // should not ever happen		YS__errmsg(proc->proc_id / ARCH_cpus,			   "How is memprogress 0 at Complete?\n");#endif	      	      if (!inst->limbo || spec_stores == SPEC_EXCEPT)     // only_specs		{		  if (!inst->limbo)		    inst->memprogress = 1; 		  PerformMemOp(inst, proc);		  if (!inst->limbo)		    {#if 0#ifdef COREFILE		      OpCompletionMessage(inst, proc);#endif#endif		      proc->DoneHeap.insert(proc->curr_cycle, inst, inst->tag);		    }		}	    }	}      return 0;    }}/*************************************************************************//* PerformMemOp : Possibly remove memory operation from queue and free   *//*              : up slot in memory system. If aggressive use of load    *//*              : values supported past ambiguous stores, update         *//*              : register values, but keep load in queue                *//*************************************************************************/void PerformMemOp(instance * inst, ProcState * proc){#ifdef STORE_ORDERING  instance *i;#endif#ifndef STORE_ORDERING  if (IsRMW(inst))                 // RMW -----------------------------------    {      proc->rmw_tags.Remove(inst->tag);      proc->StoreQueue.Remove(inst);      inst->in_memunit = 0;    }  else if (IsStore(inst))          // stores --------------------------------    {      proc->st_tags.Remove(inst->tag);      proc->StoreQueue.Remove(inst);      // Don't add anything to memory system here because this wasn't still      // sitting in the "real" memory queue in RC    }  else                             // loads ---------------------------------    {      if (inst->code.instruction == iPREFETCH ||	  (!inst->limbo && (!Speculative_Loads ||			    (!(proc->minstore < proc->SLtag &&			       inst->tag > proc->SLtag) &&			     !(proc->minload < proc->LLtag &&			       inst->tag > proc->LLtag)))))	// we enter here ordinarily, for loads that are only preceded by	// disambiguated stores and which are not speculative	{          proc->LoadQueue.Remove(inst);	  inst->in_memunit = 0;	}#else /* Is STORE_ORDERING! */  if (IsStore(inst))    { // RMW is nothing special here....      // In sequential consistency, memory operations are not removed      // from the memory queue until the operations above them have      // all finished.      int keepgoing = proc->MemQueue.GetMin(i);       while (keepgoing)          // find other ones to remove also	{	  if (i->memprogress > 0)	    {	      proc->MemQueue.Remove(i);              	      if (simulate_ilp && !Processor_Consistency && IsStore(i))		proc->ReadyUnissuedStores--; 	      i->in_memunit = 0;	    }	  else	    break;              	  keepgoing = proc->MemQueue.GetMin(i);	}    }  //-------------------------------------------------------------------------  // Load Instruction   else    {      if (!inst->limbo || inst->code.instruction == iPREFETCH)	{	  // we enter here ordinarily, for accesses past	  // disambiguated stores	  MemQLink<instance *> *stepper = NULL, *oldstepper;	  i = stepper->d;	  while (stepper = proc->MemQueue.GetNext(stepper))	    {	      if (i->memprogress > 0)		{		  if (simulate_ilp && !Processor_Consistency && IsStore(i))		    proc->ReadyUnissuedStores--;		  oldstepper = stepper;		  stepper = proc->MemQueue.GetPrev(stepper);		  proc->MemQueue.Remove(oldstepper);		  i->in_memunit = 0;		}	      else if (!(Processor_Consistency && IsStore(i) && !IsRMW(i)))		break; 	      if ((stepper=proc->MemQueue.GetNext(stepper)) != NULL)		i = stepper->d;	    }	}#endif // STORE_ORDERING      else	{	  // when we do have a limbo, we need to just pass the value on, by	  // setting the dest reg val. The instance remains in the MemQueus#ifdef DEBUG	  if (inst->limbo && spec_stores != SPEC_EXCEPT)	    /* We come here only for SPEC_EXCEPT */	    YS__errmsg(proc->proc_id / ARCH_cpus,		       "%s:%d -- should only be entered with SPEC_EXCEPT."		       " P%d,%lld\n",		       __FILE__,		       __LINE__,		       proc->proc_id,		       inst->tag);#endif	  #ifdef COREFILE	  if (proc->curr_cycle > DEBUG_TIME)	    fprintf(corefile, "Sending value down from %s-load tag %lld\n",		    inst->limbo ? "limbo" : "spec", inst->tag);#endif	  switch (inst->code.rd_regtype)	    {	    case REG_INT: 	    case REG_INT64:	      if (inst->prd != 0)		proc->phy_int_reg_file[inst->prd] = inst->rdvali;	      proc->intregbusy[inst->prd] = 0;	      proc->dist_stallq_int[inst->prd].ClearAll(proc);	      break;	    case REG_FP:	      proc->phy_fp_reg_file[inst->prd] = inst->rdvalf;	      proc->fpregbusy[inst->prd] = 0;	      proc->dist_stallq_fp[inst->prd].ClearAll(proc);	      break;	    case REG_FPHALF: 	      {		proc->phy_fp_reg_file[inst->prd] = inst->rsdvalf;		float *address = (float *) (&proc->phy_fp_reg_file[inst->prd]);		if (inst->code.rd & 1) /* the odd half */		  address += 1;		*address = inst->rdvalfh;		proc->fpregbusy[inst->prd] = 0;		proc->dist_stallq_fp[inst->prd].ClearAll(proc);		break;	      }	    case REG_INTPAIR:

⌨️ 快捷键说明

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