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

📄 cache.c

📁 这个是LINUX下的GDB调度工具的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* frv cache model.   Copyright (C) 1999, 2000, 2001, 2003 Free Software Foundation, Inc.   Contributed by Red Hat.This file is part of the GNU simulators.This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public License alongwith this program; if not, write to the Free Software Foundation, Inc.,59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */#define WANT_CPU frvbf#define WANT_CPU_FRVBF#include "libiberty.h"#include "sim-main.h"#include "cache.h"#include "bfd.h"voidfrv_cache_init (SIM_CPU *cpu, FRV_CACHE *cache){  int elements;  int i, j;  SIM_DESC sd;  /* Set defaults for fields which are not initialized.  */  sd = CPU_STATE (cpu);  switch (STATE_ARCHITECTURE (sd)->mach)    {    case bfd_mach_fr400:    case bfd_mach_fr450:      if (cache->configured_sets == 0)	cache->configured_sets = 512;      if (cache->configured_ways == 0)	cache->configured_ways = 2;      if (cache->line_size == 0)	cache->line_size = 32;      if (cache->memory_latency == 0)	cache->memory_latency = 20;      break;    case bfd_mach_fr550:      if (cache->configured_sets == 0)	cache->configured_sets = 128;      if (cache->configured_ways == 0)	cache->configured_ways = 4;      if (cache->line_size == 0)	cache->line_size = 64;      if (cache->memory_latency == 0)	cache->memory_latency = 20;      break;    default:      if (cache->configured_sets == 0)	cache->configured_sets = 64;      if (cache->configured_ways == 0)	cache->configured_ways = 4;      if (cache->line_size == 0)	cache->line_size = 64;      if (cache->memory_latency == 0)	cache->memory_latency = 20;      break;    }  frv_cache_reconfigure (cpu, cache);  /* First allocate the cache storage based on the given dimensions.  */  elements = cache->sets * cache->ways;  cache->tag_storage = (FRV_CACHE_TAG *)    zalloc (elements * sizeof (*cache->tag_storage));  cache->data_storage = (char *) xmalloc (elements * cache->line_size);  /* Initialize the pipelines and status buffers.  */  for (i = LS; i < FRV_CACHE_PIPELINES; ++i)    {      cache->pipeline[i].requests = NULL;      cache->pipeline[i].status.flush.valid = 0;      cache->pipeline[i].status.return_buffer.valid = 0;      cache->pipeline[i].status.return_buffer.data	= (char *) xmalloc (cache->line_size);      for (j = FIRST_STAGE; j < FRV_CACHE_STAGES; ++j)	cache->pipeline[i].stages[j].request = NULL;    }  cache->BARS.valid = 0;  cache->NARS.valid = 0;  /* Now set the cache state.  */  cache->cpu = cpu;  cache->statistics.accesses = 0;  cache->statistics.hits = 0;}voidfrv_cache_term (FRV_CACHE *cache){  /* Free the cache storage.  */  free (cache->tag_storage);  free (cache->data_storage);  free (cache->pipeline[LS].status.return_buffer.data);  free (cache->pipeline[LD].status.return_buffer.data);}/* Reset the cache configuration based on registers in the cpu.  */voidfrv_cache_reconfigure (SIM_CPU *current_cpu, FRV_CACHE *cache){  int ihsr8;  int icdm;  SIM_DESC sd;  /* Set defaults for fields which are not initialized.  */  sd = CPU_STATE (current_cpu);  switch (STATE_ARCHITECTURE (sd)->mach)    {    case bfd_mach_fr550:      if (cache == CPU_INSN_CACHE (current_cpu))	{	  ihsr8 = GET_IHSR8 ();	  icdm = GET_IHSR8_ICDM (ihsr8);	  /* If IHSR8.ICDM is set, then the cache becomes a one way cache.  */	  if (icdm)	    {	      cache->sets = cache->sets * cache->ways;	      cache->ways = 1;	      break;	    }	}      /* fall through */    default:      /* Set the cache to its original settings.  */      cache->sets = cache->configured_sets;      cache->ways = cache->configured_ways;      break;    }}/* Determine whether the given cache is enabled.  */intfrv_cache_enabled (FRV_CACHE *cache){  SIM_CPU *current_cpu = cache->cpu;  int hsr0 = GET_HSR0 ();  if (GET_HSR0_ICE (hsr0) && cache == CPU_INSN_CACHE (current_cpu))    return 1;  if (GET_HSR0_DCE (hsr0) && cache == CPU_DATA_CACHE (current_cpu))    return 1;  return 0;}/* Determine whether the given address is RAM access, assuming that HSR0.RME   is set.  */static intram_access (FRV_CACHE *cache, USI address) {  int ihsr8;  int cwe;  USI start, end, way_size;  SIM_CPU *current_cpu = cache->cpu;  SIM_DESC sd = CPU_STATE (current_cpu);  switch (STATE_ARCHITECTURE (sd)->mach)    {    case bfd_mach_fr550:      /* IHSR8.DCWE or IHSR8.ICWE deternines which ways get RAM access.  */      ihsr8 = GET_IHSR8 ();      if (cache == CPU_INSN_CACHE (current_cpu))	{	  start = 0xfe000000;	  end = 0xfe008000;	  cwe = GET_IHSR8_ICWE (ihsr8);	}      else	{	  start = 0xfe400000;	  end = 0xfe408000;	  cwe = GET_IHSR8_DCWE (ihsr8);	}      way_size = (end - start) / 4;      end -= way_size * cwe;      return address >= start && address < end;    default:      break;    }  return 1; /* RAM access */}/* Determine whether the given address should be accessed without using   the cache.  */static intnon_cache_access (FRV_CACHE *cache, USI address) {  int hsr0;  SIM_DESC sd;  SIM_CPU *current_cpu = cache->cpu;  sd = CPU_STATE (current_cpu);  switch (STATE_ARCHITECTURE (sd)->mach)    {    case bfd_mach_fr400:    case bfd_mach_fr450:      if (address >= 0xff000000	  || address >= 0xfe000000 && address <= 0xfeffffff)	return 1; /* non-cache access */      break;    case bfd_mach_fr550:      if (address >= 0xff000000	  || address >= 0xfeff0000 && address <= 0xfeffffff)	return 1; /* non-cache access */      if (cache == CPU_INSN_CACHE (current_cpu))	{	  if (address >= 0xfe000000 && address <= 0xfe007fff)	    return 1; /* non-cache access */	}      else if (address >= 0xfe400000 && address <= 0xfe407fff)	return 1; /* non-cache access */      break;    default:      if (address >= 0xff000000	  || address >= 0xfeff0000 && address <= 0xfeffffff)	return 1; /* non-cache access */      if (cache == CPU_INSN_CACHE (current_cpu))	{	  if (address >= 0xfe000000 && address <= 0xfe003fff)	    return 1; /* non-cache access */	}      else if (address >= 0xfe400000 && address <= 0xfe403fff)	return 1; /* non-cache access */      break;    }  hsr0 = GET_HSR0 ();  if (GET_HSR0_RME (hsr0))    return ram_access (cache, address);  return 0; /* cache-access */}/* Find the cache line corresponding to the given address.   If it is found then 'return_tag' is set to point to the tag for that line   and 1 is returned.   If it is not found, 'return_tag' is set to point to the tag for the least   recently used line and 0 is returned.*/static intget_tag (FRV_CACHE *cache, SI address, FRV_CACHE_TAG **return_tag){  int set;  int way;  int bits;  USI tag;  FRV_CACHE_TAG *found;  FRV_CACHE_TAG *available;  ++cache->statistics.accesses;  /* First calculate which set this address will fall into. Do this by     shifting out the bits representing the offset within the line and     then keeping enough bits to index the set.  */  set = address & ~(cache->line_size - 1);  for (bits = cache->line_size - 1; bits != 0; bits >>= 1)    set >>= 1;  set &= (cache->sets - 1);    /* Now search the set for a valid tag which matches this address.  At the     same time make note of the least recently used tag, which we will return     if no match is found.  */  available = NULL;  tag = CACHE_ADDRESS_TAG (cache, address);  for (way = 0; way < cache->ways; ++way)    {      found = CACHE_TAG (cache, set, way);      /* This tag is available as the least recently used if it is the	 least recently used seen so far and it is not locked.  */      if (! found->locked && (available == NULL || available->lru > found->lru))	available = found;      if (found->valid && found->tag == tag)	{	  *return_tag = found;	  ++cache->statistics.hits;	  return 1; /* found it */	}    }  *return_tag = available;  return 0; /* not found */}/* Write the given data out to memory.  */static voidwrite_data_to_memory (FRV_CACHE *cache, SI address, char *data, int length){  SIM_CPU *cpu = cache->cpu;  IADDR pc = CPU_PC_GET (cpu);  int write_index = 0;  switch (length)    {    case 1:    default:      PROFILE_COUNT_WRITE (cpu, address, MODE_QI);      break;    case 2:      PROFILE_COUNT_WRITE (cpu, address, MODE_HI);      break;    case 4:      PROFILE_COUNT_WRITE (cpu, address, MODE_SI);      break;    case 8:      PROFILE_COUNT_WRITE (cpu, address, MODE_DI);      break;    }  for (write_index = 0; write_index < length; ++write_index)    {      /* TODO: Better way to copy memory than a byte at a time?  */      sim_core_write_unaligned_1 (cpu, pc, write_map, address + write_index,				  data[write_index]);    }}/* Write a cache line out to memory.  */static voidwrite_line_to_memory (FRV_CACHE *cache, FRV_CACHE_TAG *tag){  SI address = tag->tag;  int set = CACHE_TAG_SET_NUMBER (cache, tag);  int bits;  for (bits = cache->line_size - 1; bits != 0; bits >>= 1)    set <<= 1;  address |= set;  write_data_to_memory (cache, address, tag->line, cache->line_size);}static voidread_data_from_memory (SIM_CPU *current_cpu, SI address, char *buffer,		       int length){  PCADDR pc = CPU_PC_GET (current_cpu);  int i;  PROFILE_COUNT_READ (current_cpu, address, MODE_QI);  for (i = 0; i < length; ++i)    {      /* TODO: Better way to copy memory than a byte at a time?  */      buffer[i] = sim_core_read_unaligned_1 (current_cpu, pc, read_map,					     address + i);    }}/* Fill the given cache line from memory.  */static voidfill_line_from_memory (FRV_CACHE *cache, FRV_CACHE_TAG *tag, SI address){  PCADDR pc;  int line_alignment;  SI read_address;  SIM_CPU *current_cpu = cache->cpu;  /* If this line is already valid and the cache is in copy-back mode, then     write this line to memory before refilling it.     Check the dirty bit first, since it is less likely to be set.  */  if (tag->dirty && tag->valid)    {      int hsr0 = GET_HSR0 ();      if (GET_HSR0_CBM (hsr0))	write_line_to_memory (cache, tag);    }  else if (tag->line == NULL)    {      int line_index = tag - cache->tag_storage;      tag->line = cache->data_storage + (line_index * cache->line_size);    }  pc = CPU_PC_GET (current_cpu);  line_alignment = cache->line_size - 1;  read_address = address & ~line_alignment;  read_data_from_memory (current_cpu, read_address, tag->line,			 cache->line_size);  tag->tag = CACHE_ADDRESS_TAG (cache, address);  tag->valid = 1;}/* Update the LRU information for the tags in the same set as the given tag.  */static voidset_most_recently_used (FRV_CACHE *cache, FRV_CACHE_TAG *tag){  /* All tags in the same set are contiguous, so find the beginning of the     set by aligning to the size of a set.  */  FRV_CACHE_TAG *item = cache->tag_storage + CACHE_TAG_SET_START (cache, tag);  FRV_CACHE_TAG *limit = item + cache->ways;  while (item < limit)    {      if (item->lru > tag->lru)	--item->lru;      ++item;    }  tag->lru = cache->ways; /* Mark as most recently used.  */}/* Update the LRU information for the tags in the same set as the given tag.  */static voidset_least_recently_used (FRV_CACHE *cache, FRV_CACHE_TAG *tag){  /* All tags in the same set are contiguous, so find the beginning of the     set by aligning to the size of a set.  */  FRV_CACHE_TAG *item = cache->tag_storage + CACHE_TAG_SET_START (cache, tag);  FRV_CACHE_TAG *limit = item + cache->ways;  while (item < limit)

⌨️ 快捷键说明

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