Beispiel #1
0
void
scache_flush_cpu (SIM_CPU *cpu)
{
  int i,n;

  /* Don't bother if cache not in use.  */
  if (CPU_SCACHE_SIZE (cpu) == 0)
    return;

#if WITH_SCACHE_PBB
  /* It's important that this be reasonably fast as this can be done when
     the simulation is running.  */
  CPU_SCACHE_NEXT_FREE (cpu) = CPU_SCACHE_CACHE (cpu);
  n = CPU_SCACHE_NUM_HASH_CHAINS (cpu) * CPU_SCACHE_NUM_HASH_CHAIN_ENTRIES (cpu);
  /* ??? Might be faster to just set the first entry, then update the
     "last entry" marker during allocation.  */
  for (i = 0; i < n; ++i)
    CPU_SCACHE_HASH_TABLE (cpu) [i] . pc = UNUSED_ADDR;
#else
  {
    int elm_size = IMP_PROPS_SCACHE_ELM_SIZE (MACH_IMP_PROPS (CPU_MACH (cpu)));
    SCACHE *sc;

    /* Technically, this may not be necessary, but it helps debugging.  */
    memset (CPU_SCACHE_CACHE (cpu), 0,
	    CPU_SCACHE_SIZE (cpu) * elm_size);

    for (i = 0, sc = CPU_SCACHE_CACHE (cpu); i < CPU_SCACHE_SIZE (cpu);
	 ++i, sc = (SCACHE *) ((char *) sc + elm_size))
      {
	sc->argbuf.addr = UNUSED_ADDR;
      }
  }
#endif
}
Beispiel #2
0
int
cgen_cpu_max_extra_bytes (void)
{
  int i;
  int extra = 0;

  for (i = 0; sim_machs[i] != 0; ++i)
    {
      int size = IMP_PROPS_SIM_CPU_SIZE (MACH_IMP_PROPS (sim_machs[i]));
      if (size > extra)
	extra = size;
    }
  return extra;
}
Beispiel #3
0
static SIM_RC
scache_init (SIM_DESC sd)
{
  int c;

  for (c = 0; c < MAX_NR_PROCESSORS; ++c)
    {
      SIM_CPU *cpu = STATE_CPU (sd, c);
      int elm_size = IMP_PROPS_SCACHE_ELM_SIZE (MACH_IMP_PROPS (CPU_MACH (cpu)));

      /* elm_size is 0 if the cpu doesn't not have scache support */
      if (elm_size == 0)
	{
	  CPU_SCACHE_SIZE (cpu) = 0;
	  CPU_SCACHE_CACHE (cpu) = NULL;
	}
      else
	{
	  if (CPU_SCACHE_SIZE (cpu) == 0)
	    CPU_SCACHE_SIZE (cpu) = STATE_SCACHE_SIZE (sd);
	  CPU_SCACHE_CACHE (cpu) =
	    (SCACHE *) xmalloc (CPU_SCACHE_SIZE (cpu) * elm_size);
#if WITH_SCACHE_PBB
	  CPU_SCACHE_MAX_CHAIN_LENGTH (cpu) = MAX_CHAIN_LENGTH;
	  CPU_SCACHE_NUM_HASH_CHAIN_ENTRIES (cpu) = MAX_HASH_CHAIN_LENGTH;
	  CPU_SCACHE_NUM_HASH_CHAINS (cpu) = max (MIN_HASH_CHAINS,
						  CPU_SCACHE_SIZE (cpu)
						  / SCACHE_HASH_RATIO);
	  CPU_SCACHE_HASH_TABLE (cpu) =
	    (SCACHE_MAP *) xmalloc (CPU_SCACHE_NUM_HASH_CHAINS (cpu)
				    * CPU_SCACHE_NUM_HASH_CHAIN_ENTRIES (cpu)
				    * sizeof (SCACHE_MAP));
	  CPU_SCACHE_PBB_BEGIN (cpu) = (SCACHE *) zalloc (elm_size);
	  CPU_SCACHE_CHAIN_LENGTHS (cpu) =
	    (unsigned long *) zalloc ((CPU_SCACHE_MAX_CHAIN_LENGTH (cpu) + 1)
				      * sizeof (long));
#endif
	}
    }

  scache_flush (sd);

  return SIM_RC_OK;
}
Beispiel #4
0
SCACHE *
scache_lookup_or_alloc (SIM_CPU *cpu, IADDR pc, int n, SCACHE **bufp)
{
  /* FIXME: hash computation is wrong, doesn't take into account
     NUM_HASH_CHAIN_ENTRIES.  A lot of the hash table will be unused!  */
  unsigned int slot = HASH_PC (pc) & (CPU_SCACHE_NUM_HASH_CHAINS (cpu) - 1);
  int i, max_i = CPU_SCACHE_NUM_HASH_CHAIN_ENTRIES (cpu);
  SCACHE_MAP *scm;
  SCACHE *sc;

  scm = & CPU_SCACHE_HASH_TABLE (cpu) [slot];
  for (i = 0; i < max_i && scm->pc != UNUSED_ADDR; ++i, ++scm)
    {
      if (scm->pc == pc)
	{
	  PROFILE_COUNT_SCACHE_HIT (cpu);
	  return scm->sc;
	}
    }
  PROFILE_COUNT_SCACHE_MISS (cpu);

  /* The address we want isn't cached.  Bummer.
     If the hash chain we have for this address is full, throw out an entry
     to make room.  */

  if (i == max_i)
    {
      /* Rather than do something sophisticated like LRU, we just throw out
	 a semi-random entry.  Let someone else have the joy of saying how
	 wrong this is.  NEXT_FREE is the entry to throw out and cycles
	 through all possibilities.  */
      static int next_free = 0;

      scm = & CPU_SCACHE_HASH_TABLE (cpu) [slot];
      /* FIXME: This seems rather clumsy.  */
      for (i = 0; i < next_free; ++i, ++scm)
	continue;
      ++next_free;
      if (next_free == CPU_SCACHE_NUM_HASH_CHAIN_ENTRIES (cpu))
	next_free = 0;
    }

  /* At this point SCM points to the hash table entry to use.
     Now make sure there's room in the cache.  */
  /* FIXME: Kinda weird to use a next_free adjusted scm when cache is
     flushed.  */

  {
    int elm_size = IMP_PROPS_SCACHE_ELM_SIZE (MACH_IMP_PROPS (CPU_MACH (cpu)));
    int elms_used = (((char *) CPU_SCACHE_NEXT_FREE (cpu)
		      - (char *) CPU_SCACHE_CACHE (cpu))
		     / elm_size);
    int elms_left = CPU_SCACHE_SIZE (cpu) - elms_used;

    if (elms_left < n)
      {
	PROFILE_COUNT_SCACHE_FULL_FLUSH (cpu);
	scache_flush_cpu (cpu);
      }
  }

  sc = CPU_SCACHE_NEXT_FREE (cpu);
  scm->pc = pc;
  scm->sc = sc;

  *bufp = sc;
  return NULL;
}