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

📄 excache.c

📁 ARM ADS 外设仿真的一个例子
💻 C
字号:
/* excache.c - Memory veneer that models a simple cache. * Copyright (C) Advanced RISC Machines Limited, 1997. * All rights reserved. */#include "armdefs.h"#include "armcnf.h"#define ModelName (tag_t)"ExampleCache"#define CACHELINES 128#define LINESIZE 4#define TAGMASK ( ~((LINESIZE-1) << 2) )typedef struct {  unsigned int bigendSig;  /* fetchingLine contains the line and current word   * being fetched */  unsigned int fetchingLine;#define FETCHINGFLAG 0x80000000L  struct {    ARMword tag;    ARMword word[LINESIZE];  } line[CACHELINES];  ARMul_MemInterface child;} cache_state;#define INVALIDTAG 0xffffffffL/* * ARMulator callbacks */static void ConfigChange(void *handle, ARMword old, ARMword new){  cache_state *cache = (cache_state *)handle;  IGNORE(old);  cache->bigendSig = ((new & MMU_B) != 0);}static void Interrupt(void *handle,unsigned int which){  cache_state *cache = (cache_state *)handle;  if (which & ARMul_InterruptUpcallReset) {    /* On reset, invalidate all the cache entries */    unsigned int i;    for (i = 0; i < CACHELINES; i++)      cache->line[i].tag = INVALIDTAG;    /* Stop any pending line fetch */    cache->fetchingLine = 0;  }}/* * Cache model functions */static int CacheLineReplace(cache_state *cache){  /* start/continue a line fetch */  unsigned int fetching = cache->fetchingLine;  /* extract word/line from 'fetching' */  unsigned int word = fetching % LINESIZE;  unsigned int line =(fetching / LINESIZE) % CACHELINES;  ARMword addr, *ptr;  ARMul_acc acc;  /* construct address from cache tag */  addr = cache->line[line].tag | (word << 2);  /* first fetch is non-sequential */  if (word == 0)    acc = acc_LoadWordN;  else    acc = acc_LoadWordS;  /* Call the external memory system */  ptr = &cache->line[line].word[word];  switch (cache->child.x.basic.access(cache->child.handle, addr, ptr, acc)) {  case 1:    /* fetch successful */    if (word == LINESIZE-1)      cache->fetchingLine = 0;    else      cache->fetchingLine = fetching+1;    return 0;  case 0:    /* wait - try again next cycle */    return 0;  case -1: default:    /* abort line fetch, abort core */    cache->line[line].tag = INVALIDTAG;    cache->fetchingLine = 0;    return -1;  }}/* Read and write to the cache *//* * Read a word from cache, doing an idle cycle on * the external bus */static int ReadFromCacheLine(    cache_state *cache, ARMword addr, ARMword *word,    ARMul_acc acc, unsigned int line){  /* addr has been found in line 'line' - perform access   * and return */  ARMword *ptr;  ptr = &(cache->line[line].word[(addr >> 2) % LINESIZE]);  /* do an idle cycle on the external bus */  if (acc_ACCOUNT(acc))    cache->child.x.basic.access(cache->child.handle, addr, word, acc_Icycle);  /* Standard read code [from armflat.c] */  switch (acc & WIDTH_MASK) {  case BITS_8:              /* read byte */    if (HostEndian != cache->bigendSig)      addr ^= 3;    *word = ((unsigned8 *)ptr)[addr & 3];    break;  case BITS_16: {           /* read half-word */    /* extract half-word */#ifndef HOST_HAS_NO_16BIT_TYPE    /*     * unsigned16 is always a 16-bit type, but if there is     * no native 16-bit type (e.g. ARM!) then we can do     * something a bit more cunning.     */    if (HostEndian != cache->bigendSig)      addr ^= 2;    *word = *((unsigned16 *)(((char *)ptr)+(addr & 2)));#else    unsigned32 datum;    datum=*ptr;    if (HostEndian != cache->bigendSig)      addr ^= 2;    if (addr & 2) datum <<= 16;    *word = (datum >> 16);#endif  }    break;  case BITS_32:             /* read word */    *word = *ptr;    break;  default:    return -1;  }  return 1;}/* * Write to data that's in the cache. * Update the cache entry, but don't do any external * activity (done at the higher level). */static int WriteToCacheLine(    cache_state *cache, ARMword addr, ARMword *word,    ARMul_acc acc, unsigned int line){  /* addr has been found in line 'line' - update cache   * and return */  ARMword *ptr;  ptr = &(cache->line[line].word[(addr >> 2) % LINESIZE]);  /* Standard 'write' code [from armflat.c] */  switch (acc & WIDTH_MASK) {    /* extract byte */  case BITS_8:              /* write_byte */    if (HostEndian != cache->bigendSig)      addr ^= 3;    ((unsigned8 *)ptr)[addr & 3] = (unsigned8)(*word);    break;  case BITS_16:             /* write half-word */    if (HostEndian != cache->bigendSig)      addr ^= 2;    *((unsigned16 *)(((char *)ptr) + (addr & 2))) =      (unsigned16)(*word);    break;  case BITS_32:             /* write word */    *ptr = *word;    break;  default:    return -1;  }  return 1;}/* * Memory veneer functions */static int MemAccess(void *handle, ARMword addr, ARMword *word, ARMul_acc acc){  cache_state *cache = (cache_state *)handle;  ARMword tag;  unsigned int line;  /* check if we're in the middle of a line fetch */  if (acc_ACCOUNT(acc) && cache->fetchingLine != 0)    return CacheLineReplace(cache);  if (acc_MREQ(acc)) {    /* search through the cache tags */    tag = addr & TAGMASK;    for (line = 0; line < CACHELINES; line++)      if (cache->line[line].tag == tag) {	/* cache hit! */	if (acc_READ(acc))	  return ReadFromCacheLine(				   cache, addr, word, acc, line);	else	  WriteToCacheLine(cache, addr, word, acc, line);	/* and fall through to update external memory */      }    /* fall through from searching cache */    if (acc_READ(acc)) {      if (acc_ACCOUNT(acc)) {	/* cache miss - choose a victim to replace */	/* Unix rand() has the bad property that	 * rand() % 4 is cyclic */	line = ((rand() >> 2) % CACHELINES);	/* set up fetchingLine with the line number.	 * FETCHINGFLAG is used to ensure the result	 * is non-zero. start with word 0.	 */	cache->fetchingLine = ( (line * LINESIZE) +				FETCHINGFLAG );	cache->line[line].tag = tag;	/* start a line fetch */	return CacheLineReplace(cache);      }      /* else read from memory - fall through */    }    /* else write to physical memory - cache already     * updated */    /* fall through */  }  /* else do idle cycle on external bus - fall through */  return cache->child.x.basic.access(cache->child.handle, addr, word, acc);}/* Dummy veneer functions *//* These functions pass on their calls directly to the * child model. We can't use the child functions directly, * as we need to lookup the child's handle */static unsigned long GetCycleLength(void *handle){  cache_state *cache = (cache_state *)handle;  return cache->child.x.basic.get_cycle_length(cache->child.handle);}static unsigned long ReadClock(void *handle){  cache_state *cache = (cache_state *)handle;  return cache->child.read_clock(cache->child.handle);}static const ARMul_Cycles *ReadCycles(void *handle){  cache_state *cache = (cache_state *)handle;  return cache->child.read_cycles(cache->child.handle);}/* * Initialize the memory interface */static ARMul_Error MemInit(    ARMul_State *state, ARMul_MemInterface *interf,    ARMul_MemType type, toolconf config){  cache_state *cache;  ARMul_MemInterface *child_interf;  armul_MemInit *child_init = NULL;  tag_t child_name;  toolconf child_config;  ARMul_Error err;  /* Find the name of the child memory interface */  child_name = (tag_t)ToolConf_Lookup(config, ARMulCnf_Memory);  /* Now locate it using ARMul_FindMemoryInterface.   * This also locates it's config for us */  if (child_name)    child_init = ARMul_FindMemoryInterface(state, child_name, &child_config);  if (child_name == NULL ||      child_init == NULL || child_init == MemInit)    return ARMul_RaiseError(state, ARMulErr_NoMemoryChild,			    ModelName);  /* Allocate the cache state */  cache = (cache_state *)malloc(sizeof(cache_state));  if (cache == NULL)    return ARMul_RaiseError(state,ARMulErr_OutOfMemory);  /* Initialize the child model */  child_interf = &cache->child;  err = child_init(state, child_interf, type, child_config);  if (err != ARMulErr_NoError) {    free(cache);    return err;  }  /* Set up our interface with the ARMulator */  interf->handle = cache;  interf->read_clock = (child_interf->read_clock != NULL)    ? ReadClock    : NULL;  interf->read_cycles = (child_interf->read_cycles != NULL)    ? ReadCycles    : NULL;  switch (type) {  case ARMul_MemType_Basic:  case ARMul_MemType_16Bit:  case ARMul_MemType_Thumb:    /* supported */    interf->x.basic.access=MemAccess;    interf->x.basic.get_cycle_length =      (child_interf->x.basic.get_cycle_length != NULL) ? GetCycleLength : NULL;    break;  default:    *interf = *child_interf;    free(cache);    ARMul_ConsolePrint(state,"\Cannot use cache on this type of memory interface.\n");    return ARMulErr_NoError;  }  ARMul_PrettyPrint(state,", Simple cache");  /* Install callbacks */  ARMul_InstallExitHandler(state, free, cache);  ARMul_InstallInterruptHandler(state, Interrupt, cache);  ARMul_InstallConfigChangeHandler(state, ConfigChange, cache);  /* Initialize the model - we should get a reset anyway,   * but better safe than sorry */  Interrupt((void *)cache, ARMul_InterruptUpcallReset);  return ARMulErr_NoError;}ARMul_MemStub ARMul_ExampleCache = {  MemInit,  ModelName};/* end of file excache.c */

⌨️ 快捷键说明

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