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

📄 cache.c

📁 这个是LINUX下的GDB调度工具的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
    {      if (item->lru != 0 && item->lru < tag->lru)	++item->lru;      ++item;    }  tag->lru = 0; /* Mark as least recently used.  */}/* Find the line containing the given address and load it if it is not   already loaded.   Returns the tag of the requested line.  */static FRV_CACHE_TAG *find_or_retrieve_cache_line (FRV_CACHE *cache, SI address){  /* See if this data is already in the cache.  */  FRV_CACHE_TAG *tag;  int found = get_tag (cache, address, &tag);  /* Fill the line from memory, if it is not valid.  */  if (! found)    {      /* The tag could be NULL is all ways in the set were used and locked.  */      if (tag == NULL)	return tag;      fill_line_from_memory (cache, tag, address);      tag->dirty = 0;    }  /* Update the LRU information for the tags in this set.  */  set_most_recently_used (cache, tag);  return tag;}static voidcopy_line_to_return_buffer (FRV_CACHE *cache, int pipe, FRV_CACHE_TAG *tag,			    SI address){  /* A cache line was available for the data.     Copy the data from the cache line to the output buffer.  */  memcpy (cache->pipeline[pipe].status.return_buffer.data,	  tag->line, cache->line_size);  cache->pipeline[pipe].status.return_buffer.address    = address & ~(cache->line_size - 1);  cache->pipeline[pipe].status.return_buffer.valid = 1;}static voidcopy_memory_to_return_buffer (FRV_CACHE *cache, int pipe, SI address){  address &= ~(cache->line_size - 1);  read_data_from_memory (cache->cpu, address,			 cache->pipeline[pipe].status.return_buffer.data,			 cache->line_size);  cache->pipeline[pipe].status.return_buffer.address = address;  cache->pipeline[pipe].status.return_buffer.valid = 1;}static voidset_return_buffer_reqno (FRV_CACHE *cache, int pipe, unsigned reqno){  cache->pipeline[pipe].status.return_buffer.reqno = reqno;}/* Read data from the given cache.   Returns the number of cycles required to obtain the data.  */intfrv_cache_read (FRV_CACHE *cache, int pipe, SI address){  FRV_CACHE_TAG *tag;  if (non_cache_access (cache, address))    {      copy_memory_to_return_buffer (cache, pipe, address);      return 1;    }	  tag = find_or_retrieve_cache_line (cache, address);  if (tag == NULL)    return 0; /* Indicate non-cache-access.  */  /* A cache line was available for the data.     Copy the data from the cache line to the output buffer.  */  copy_line_to_return_buffer (cache, pipe, tag, address);  return 1; /* TODO - number of cycles unknown */}/* Writes data through the given cache.   The data is assumed to be in target endian order.   Returns the number of cycles required to write the data.  */intfrv_cache_write (FRV_CACHE *cache, SI address, char *data, unsigned length){  int copy_back;  /* See if this data is already in the cache.  */  SIM_CPU *current_cpu = cache->cpu;  USI hsr0 = GET_HSR0 ();  FRV_CACHE_TAG *tag;  int found;  if (non_cache_access (cache, address))    {      write_data_to_memory (cache, address, data, length);      return 1;    }  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.  */  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)	fill_line_from_memory (cache, tag, address);      line_offset = address & (cache->line_size - 1);      memcpy (tag->line + line_offset, data, length);      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;    }  return 1; /* TODO - number of cycles unknown */}/* Preload the cache line containing the given address. Lock the   data if requested.   Returns the number of cycles required to write the data.  */intfrv_cache_preload (FRV_CACHE *cache, SI address, USI length, int lock){  int offset;  int lines;  if (non_cache_access (cache, address))    return 1;  /* preload at least 1 line.  */  if (length == 0)    length = 1;  offset = address & (cache->line_size - 1);  lines = 1 + (offset + length - 1) / cache->line_size;  /* Careful with this loop -- length is unsigned.  */  for (/**/; lines > 0; --lines)    {      FRV_CACHE_TAG *tag = find_or_retrieve_cache_line (cache, address);      if (lock && tag != NULL)	tag->locked = 1;      address += cache->line_size;    }  return 1; /* TODO - number of cycles unknown */}/* Unlock the cache line containing the given address.   Returns the number of cycles required to unlock the line.  */intfrv_cache_unlock (FRV_CACHE *cache, SI address){  FRV_CACHE_TAG *tag;  int found;  if (non_cache_access (cache, address))    return 1;  found = get_tag (cache, address, &tag);  if (found)    tag->locked = 0;  return 1; /* TODO - number of cycles unknown */}static voidinvalidate_return_buffer (FRV_CACHE *cache, SI address){  /* If this address is in one of the return buffers, then invalidate that     return buffer.  */  address &= ~(cache->line_size - 1);  if (address == cache->pipeline[LS].status.return_buffer.address)    cache->pipeline[LS].status.return_buffer.valid = 0;  if (address == cache->pipeline[LD].status.return_buffer.address)    cache->pipeline[LD].status.return_buffer.valid = 0;}/* Invalidate the cache line containing the given address. Flush the   data if requested.   Returns the number of cycles required to write the data.  */intfrv_cache_invalidate (FRV_CACHE *cache, SI address, int flush){  /* See if this data is already in the cache.  */  FRV_CACHE_TAG *tag;  int found;  /* Check for non-cache access.  This operation is still perfromed even if     the cache is not currently enabled.  */  if (non_cache_access (cache, address))    return 1;  /* If the line is found, invalidate it. If a flush is requested, then flush     it if it is dirty.  */  found = get_tag (cache, address, &tag);  if (found)    {      SIM_CPU *cpu;      /* If a flush is requested, then flush it if it is dirty.  */      if (tag->dirty && flush)	write_line_to_memory (cache, tag);      set_least_recently_used (cache, tag);      tag->valid = 0;      tag->locked = 0;      /* If this is the insn cache, then flush the cpu's scache as well.  */      cpu = cache->cpu;      if (cache == CPU_INSN_CACHE (cpu))	scache_flush_cpu (cpu);    }  invalidate_return_buffer (cache, address);  return 1; /* TODO - number of cycles unknown */}/* Invalidate the entire cache. Flush the data if requested.  */intfrv_cache_invalidate_all (FRV_CACHE *cache, int flush){  /* See if this data is already in the cache.  */  int elements = cache->sets * cache->ways;  FRV_CACHE_TAG *tag = cache->tag_storage;  SIM_CPU *cpu;  int i;  for(i = 0; i < elements; ++i, ++tag)    {      /* If a flush is requested, then flush it if it is dirty.  */      if (tag->valid && tag->dirty && flush)	write_line_to_memory (cache, tag);      tag->valid = 0;      tag->locked = 0;    }  /* If this is the insn cache, then flush the cpu's scache as well.  */  cpu = cache->cpu;  if (cache == CPU_INSN_CACHE (cpu))    scache_flush_cpu (cpu);  /* Invalidate both return buffers.  */  cache->pipeline[LS].status.return_buffer.valid = 0;  cache->pipeline[LD].status.return_buffer.valid = 0;  return 1; /* TODO - number of cycles unknown */}/* ---------------------------------------------------------------------------   Functions for operating the cache in cycle accurate mode.   -------------------------------------------------------------------------  *//* Convert a VLIW slot to a cache pipeline index.  */static intconvert_slot_to_index (int slot){  switch (slot)    {    case UNIT_I0:    case UNIT_C:      return LS;    case UNIT_I1:      return LD;    default:      abort ();    }  return 0;}/* Allocate free chains of cache requests.  */#define FREE_CHAIN_SIZE 16static FRV_CACHE_REQUEST *frv_cache_request_free_chain = NULL;static FRV_CACHE_REQUEST *frv_store_request_free_chain = NULL;static voidallocate_new_cache_requests (void){  int i;  frv_cache_request_free_chain = xmalloc (FREE_CHAIN_SIZE					  * sizeof (FRV_CACHE_REQUEST));  for (i = 0; i < FREE_CHAIN_SIZE - 1; ++i)    {      frv_cache_request_free_chain[i].next	= & frv_cache_request_free_chain[i + 1];     }  frv_cache_request_free_chain[FREE_CHAIN_SIZE - 1].next = NULL;}/* Return the next free request in the queue for the given cache pipeline.  */static FRV_CACHE_REQUEST *new_cache_request (void){  FRV_CACHE_REQUEST *req;  /* Allocate new elements for the free chain if necessary.  */  if (frv_cache_request_free_chain == NULL)    allocate_new_cache_requests ();  req = frv_cache_request_free_chain;  frv_cache_request_free_chain = req->next;  return req;}/* Return the given cache request to the free chain.  */static voidfree_cache_request (FRV_CACHE_REQUEST *req){  if (req->kind == req_store)    {      req->next = frv_store_request_free_chain;      frv_store_request_free_chain = req;    }  else    {      req->next = frv_cache_request_free_chain;      frv_cache_request_free_chain = req;    }}/* Search the free chain for an existing store request with a buffer that's   large enough.  */static FRV_CACHE_REQUEST *new_store_request (int length){  FRV_CACHE_REQUEST *prev = NULL;  FRV_CACHE_REQUEST *req;  for (req = frv_store_request_free_chain; req != NULL; req = req->next)    {      if (req->u.store.length == length)	break;      prev = req;    }  if (req != NULL)    {      if (prev == NULL)	frv_store_request_free_chain = req->next;      else	prev->next = req->next;      return req;    }  /* No existing request buffer was found, so make a new one.  */  req = new_cache_request ();  req->kind = req_store;  req->u.store.data = xmalloc (length);  req->u.store.length = length;  return req;}/* Remove the given request from the given pipeline.  */static voidpipeline_remove_request (FRV_CACHE_PIPELINE *p, FRV_CACHE_REQUEST *request){  FRV_CACHE_REQUEST *next = request->next;  FRV_CACHE_REQUEST *prev = request->prev;  if (prev == NULL)    p->requests = next;  else    prev->next = next;  if (next != NULL)    next->prev = prev;}/* Add the given request to the given pipeline.  */static voidpipeline_add_request (FRV_CACHE_PIPELINE *p, FRV_CACHE_REQUEST *request){  FRV_CACHE_REQUEST *prev = NULL;  FRV_CACHE_REQUEST *item;  /* Add the request in priority order.  0 is the highest priority.  */  for (item = p->requests; item != NULL; item = item->next)    {      if (item->priority > request->priority)	break;      prev = item;    }  request->next = item;  request->prev = prev;  if (prev == NULL)    p->requests = request;  else    prev->next = request;  if (item != NULL)    item->prev = request;}

⌨️ 快捷键说明

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