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

📄 cache.c

📁 这个是LINUX下的GDB调度工具的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
  SI address = req->address;  /* If this address interferes with an existing request, then requeue it.  */  if (address_interference (cache, address, req, pipe))    {      pipeline_requeue_request (& cache->pipeline[pipe]);      return;    }  if (frv_cache_enabled (cache) && ! non_cache_access (cache, address))    {      int found = get_tag (cache, address, &tag);      /* If the data was found, return it to the caller.  */      if (found)	{	  set_most_recently_used (cache, tag);	  copy_line_to_return_buffer (cache, pipe, tag, address);	  set_return_buffer_reqno (cache, pipe, req->reqno);	  return;	}    }  /* The data is not in the cache or this is a non-cache access.  We need to     wait for the memory unit to fetch it.  Store this request in the WAR in     the meantime.  */  wait_in_WAR (cache, pipe, req);}static voidhandle_req_preload (FRV_CACHE *cache, int pipe, FRV_CACHE_REQUEST *req){  int found;  FRV_CACHE_WAR war;  FRV_CACHE_TAG *tag;  int length;  int lock;  int offset;  int lines;  int line;  SI address = req->address;  SI cur_address;  if (! frv_cache_enabled (cache) || non_cache_access (cache, address))    return;  /* preload at least 1 line.  */  length = req->u.preload.length;  if (length == 0)    length = 1;  /* Make sure that this request does not interfere with a pending request.  */  offset = address & (cache->line_size - 1);  lines = 1 + (offset + length - 1) / cache->line_size;  cur_address = address & ~(cache->line_size - 1);  for (line = 0; line < lines; ++line)    {      /* If this address interferes with an existing request,	 then requeue it.  */      if (address_interference (cache, cur_address, req, pipe))	{	  pipeline_requeue_request (& cache->pipeline[pipe]);	  return;	}      cur_address += cache->line_size;    }  /* Now process each cache line.  */  /* Careful with this loop -- length is unsigned.  */  lock = req->u.preload.lock;  cur_address = address & ~(cache->line_size - 1);  for (line = 0; line < lines; ++line)    {      /* If the data was found, then lock it if requested.  */      found = get_tag (cache, cur_address, &tag);      if (found)	{	  if (lock)	    tag->locked = 1;	}      else	{	  /* The data is not in the cache.  We need to wait for the memory	     unit to fetch it.  Store this request in the WAR in the meantime.	  */	  wait_in_WAR (cache, pipe, req);	}      cur_address += cache->line_size;    }}static voidhandle_req_store (FRV_CACHE *cache, int pipe, FRV_CACHE_REQUEST *req){  SIM_CPU *current_cpu;  FRV_CACHE_TAG *tag;  int found;  int copy_back;  SI address = req->address;  char *data = req->u.store.data;  int length = req->u.store.length;  /* If this address interferes with an existing request, then requeue it.  */  if (address_interference (cache, address, req, pipe))    {      pipeline_requeue_request (& cache->pipeline[pipe]);      return;    }  /* Non-cache access. Write the data directly to memory.  */  if (! frv_cache_enabled (cache) || non_cache_access (cache, address))    {      write_data_to_memory (cache, address, data, length);      return;    }  /* See if the data is in the cache.  */  found = get_tag (cache, address, &tag);  /* Write the data to the cache line if one was available and if it is     either a hit or a miss in copy-back mode.     The tag may be NULL if all ways were in use and locked on a miss.  */  current_cpu = cache->cpu;  copy_back = GET_HSR0_CBM (GET_HSR0 ());  if (tag != NULL && (found || copy_back))    {      int line_offset;      /* Load the line from memory first, if it was a miss.  */      if (! found)	{	  /* We need to wait for the memory unit to fetch the data.  	     Store this request in the WAR and requeue the store request.  */	  wait_in_WAR (cache, pipe, req);	  pipeline_requeue_request (& cache->pipeline[pipe]);	  /* Decrement the counts of accesses and hits because when the requeued	     request is processed again, it will appear to be a new access and	     a hit.  */	  --cache->statistics.accesses;	  --cache->statistics.hits;	  return;	}      line_offset = address & (cache->line_size - 1);      memcpy (tag->line + line_offset, data, length);      invalidate_return_buffer (cache, address);      tag->dirty = 1;      /* Update the LRU information for the tags in this set.  */      set_most_recently_used (cache, tag);    }  /* Write the data to memory if there was no line available or we are in     write-through (not copy-back mode).  */  if (tag == NULL || ! copy_back)    {      write_data_to_memory (cache, address, data, length);      if (tag != NULL)	tag->dirty = 0;    }}static voidhandle_req_invalidate (FRV_CACHE *cache, int pipe, FRV_CACHE_REQUEST *req){  FRV_CACHE_PIPELINE *pipeline = & cache->pipeline[pipe];  SI address = req->address;  SI interfere_address = req->u.invalidate.all ? -1 : address;  /* If this address interferes with an existing request, then requeue it.  */  if (address_interference (cache, interfere_address, req, pipe))    {      pipeline_requeue_request (pipeline);      return;    }  /* Invalidate the cache line now.  This function already checks for     non-cache access.  */  if (req->u.invalidate.all)    frv_cache_invalidate_all (cache, req->u.invalidate.flush);  else    frv_cache_invalidate (cache, address, req->u.invalidate.flush);  if (req->u.invalidate.flush)    {      pipeline->status.flush.reqno = req->reqno;      pipeline->status.flush.address = address;      pipeline->status.flush.valid = 1;    }}static voidhandle_req_unlock (FRV_CACHE *cache, int pipe, FRV_CACHE_REQUEST *req){  FRV_CACHE_PIPELINE *pipeline = & cache->pipeline[pipe];  SI address = req->address;  /* If this address interferes with an existing request, then requeue it.  */  if (address_interference (cache, address, req, pipe))    {      pipeline_requeue_request (pipeline);      return;    }  /* Unlock the cache line.  This function checks for non-cache access.  */  frv_cache_unlock (cache, address);}static voidhandle_req_WAR (FRV_CACHE *cache, int pipe, FRV_CACHE_REQUEST *req){  char *buffer;  FRV_CACHE_TAG *tag;  SI address = req->address;  if (frv_cache_enabled (cache) && ! non_cache_access (cache, address))    {      /* Look for the data in the cache.  The statistics of cache hit or	 miss have already been recorded, so save and restore the stats before	 and after obtaining the cache line.  */      FRV_CACHE_STATISTICS save_stats = cache->statistics;      tag = find_or_retrieve_cache_line (cache, address);      cache->statistics = save_stats;      if (tag != NULL)	{	  if (! req->u.WAR.preload)	    {	      copy_line_to_return_buffer (cache, pipe, tag, address);	      set_return_buffer_reqno (cache, pipe, req->reqno);	    }	  else 	    {	      invalidate_return_buffer (cache, address);	      if (req->u.WAR.lock)		tag->locked = 1;	    }	  return;	}    }  /* All cache lines in the set were locked, so just copy the data to the     return buffer directly.  */  if (! req->u.WAR.preload)    {      copy_memory_to_return_buffer (cache, pipe, address);      set_return_buffer_reqno (cache, pipe, req->reqno);    }}/* Resolve any conflicts and/or execute the given requests.  */static voidarbitrate_requests (FRV_CACHE *cache){  int pipe;  /* Simply execute the requests in the final pipeline stages.  */  for (pipe = LS; pipe < FRV_CACHE_PIPELINES; ++pipe)    {      FRV_CACHE_REQUEST *req	= pipeline_stage_request (& cache->pipeline[pipe], LAST_STAGE);      /* Make sure that there is a request to handle.  */      if (req == NULL)	continue;      /* Handle the request.  */      switch (req->kind)	{	case req_load:	  handle_req_load (cache, pipe, req);	  break;	case req_store:	  handle_req_store (cache, pipe, req);	  break;	case req_invalidate:	  handle_req_invalidate (cache, pipe, req);	  break;	case req_preload:	  handle_req_preload (cache, pipe, req);	  break;	case req_unlock:	  handle_req_unlock (cache, pipe, req);	  break;	case req_WAR:	  handle_req_WAR (cache, pipe, req);	  break;	default:	  abort ();	}    }}/* Move a waiting ARS register to a free WAR register.  */static voidmove_ARS_to_WAR (FRV_CACHE *cache, int pipe, FRV_CACHE_WAR *war){  /* If BARS is valid for this pipe, then move it to the given WAR. Move     NARS to BARS if it is valid.  */  if (cache->BARS.valid && cache->BARS.pipe == pipe)    {      war->address = cache->BARS.address;      war->reqno = cache->BARS.reqno;      war->priority = cache->BARS.priority;      war->preload = cache->BARS.preload;      war->lock = cache->BARS.lock;      war->latency = cache->memory_latency + 1;      war->valid = 1;      if (cache->NARS.valid)	{	  cache->BARS = cache->NARS;	  cache->NARS.valid = 0;	}      else	cache->BARS.valid = 0;      return;    }  /* If NARS is valid for this pipe, then move it to the given WAR.  */  if (cache->NARS.valid && cache->NARS.pipe == pipe)    {      war->address = cache->NARS.address;      war->reqno = cache->NARS.reqno;      war->priority = cache->NARS.priority;      war->preload = cache->NARS.preload;      war->lock = cache->NARS.lock;      war->latency = cache->memory_latency + 1;      war->valid = 1;      cache->NARS.valid = 0;    }}/* Decrease the latencies of the various states in the cache.  */static voiddecrease_latencies (FRV_CACHE *cache){  int pipe, j;  /* Check the WAR registers.  */  for (pipe = LS; pipe < FRV_CACHE_PIPELINES; ++pipe)    {      FRV_CACHE_PIPELINE *pipeline = & cache->pipeline[pipe];      for (j = 0; j < NUM_WARS; ++j)	{	  FRV_CACHE_WAR *war = & pipeline->WAR[j];	  if (war->valid)	    {	      --war->latency;	      /* If the latency has expired, then submit a WAR request to the		 pipeline.  */	      if (war->latency <= 0)		{		  add_WAR_request (pipeline, war);		  war->valid = 0;		  move_ARS_to_WAR (cache, pipe, war);		}	    }	}    }}/* Run the cache for the given number of cycles.  */voidfrv_cache_run (FRV_CACHE *cache, int cycles){  int i;  for (i = 0; i < cycles; ++i)    {      advance_pipelines (cache);      arbitrate_requests (cache);      decrease_latencies (cache);    }}intfrv_cache_read_passive_SI (FRV_CACHE *cache, SI address, SI *value){  SI offset;  FRV_CACHE_TAG *tag;  if (non_cache_access (cache, address))    return 0;  {    FRV_CACHE_STATISTICS save_stats = cache->statistics;    int found = get_tag (cache, address, &tag);    cache->statistics = save_stats;    if (! found)      return 0; /* Indicate non-cache-access.  */  }  /* A cache line was available for the data.     Extract the target data from the line.  */  offset = address & (cache->line_size - 1);  *value = T2H_4 (*(SI *)(tag->line + offset));  return 1;}/* Check the return buffers of the data cache to see if the requested data is   available.  */intfrv_cache_data_in_buffer (FRV_CACHE* cache, int pipe, SI address,			  unsigned reqno){  return cache->pipeline[pipe].status.return_buffer.valid    && cache->pipeline[pipe].status.return_buffer.reqno == reqno    && cache->pipeline[pipe].status.return_buffer.address <= address    && cache->pipeline[pipe].status.return_buffer.address + cache->line_size       > address;}/* Check to see if the requested data has been flushed.  */intfrv_cache_data_flushed (FRV_CACHE* cache, int pipe, SI address, unsigned reqno){  return cache->pipeline[pipe].status.flush.valid    && cache->pipeline[pipe].status.flush.reqno == reqno    && cache->pipeline[pipe].status.flush.address <= address    && cache->pipeline[pipe].status.flush.address + cache->line_size       > address;}

⌨️ 快捷键说明

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