📄 mapfile.c
字号:
/* mapfile.c - - Memory model that supports an "armsd.map" file
* Formerly known as armmap.c
* Copyright (C) Advanced RISC Machines Limited, 1995. All rights reserved.
* Copyright (C) ARM Limited, 1999-2003. All rights reserved.
*/
#define MODEL_NAME Mapfile
/*
* RCS $Revision: 1.16.4.23.18.8 $
* Checkin $Date: 2003/05/12 14:32:06 $
* Revising $Author: dsinclai $
*/
/* !Todo:
* + Respond to some forms of Reset by clearing the cycle-counters?
* + Free the StrDup'd md_Name's at the end, and md->num_state.
*/
#include <string.h>
#include <ctype.h>
#include "minperip.h"
#include "armul_mem.h" /* Mix'n match */
#include "armul_callbackid.h"
#include "addcounter.h"
#define ACDTEST(FUNC,RET) if (FUNC == RDIError_BufferFull) \
RET = RDIError_BufferFull
#include "armul_cyc.h"
#include "armul_lib.h" /* for ARMul_SIRange() */
#include "rdi_conf.h"
#include "armul_cnf.h"
#include "dir.h" /* for dir_getcwd */
#include "stringx.h" /* for StrDup */
#include "mini_simrdi_manager.h" /* for SIMABS awareness */
/* ---- IMPLEMENTATION DECISIONS ---- */
/*
* In order to allow FPE to work with mapfile, mapfile must
* enable the base memory and allow all non-aborting accesses to fall
* through to the base memory
*/
#define USE_BASE_MEMORY 1
/* NUL_BIU owns the bus. */
#define MAPFILE_OWNS_BUS 0
#if MAPFILE_OWNS_BUS
# define ADVANCE_BUS_TIME top->pABus->bus_BusyUntil++
#else
# define ADVANCE_BUS_TIME
#endif
#ifndef NDEBUG
# if 1
# else
# define VERBOSE_Mapfile_MemAccessHarvard
# define VERBOSE_TIMES
# define VERBOSE_BUS
# define VERBOSE_MEMLOOKUP
# define VERBOSE_DABORT
# define VERBOSE_ACCESS
# define VERBOSE_ENDIAN
# define VERBOSE_CYCLE_DESC
# define VERBOSE_INIT
# define VERBOSE_ACCOUNTED_ACCESS
# endif
#endif
#ifdef HOST_ENDIAN_BIG
# define HostEndian 1
#elif defined(HOST_ENDIAN_LITTLE)
# define HostEndian 0
#else
# error "HOST_ENDIAN_UNKNOWN"
#endif
#include "rdi_stat.h"
#include "clxlist.h"
/* Possibly inline some functions */
#ifndef INLINE
# error "INLINE not defined"
#endif
#define ModelName (tag_t)"MapFile"
#define FOE(a) Mapfile_FreeOnExit(state,a)
/* armmap.c */
/* #define ARMulCnf_CountWaitStates (tag_t)"COUNTWAITSTATES" */
#define ARMulCnf_AMBABusCounts (tag_t)"AMBABUSCOUNTS"
#define ARMulCnf_SpotISCycles (tag_t)"SPOTISCYCLES"
#define ARMulCnf_ISTiming (tag_t)"ISTIMING"
struct NumState;
typedef struct MemDescr {
struct MemDescr *next; /* So we can put these in a list */
/* cycle counters */
/* @@@ N.B. this table RELIES on the bit positions in acc words.
* for indexing and for it's size.
*/
#if (WIDTH_MASK | acc_Nrw | acc_seq | acc_Nmreq) == 0x7f
unsigned long access_counts[0x60]; /* number of accesses to this region */
/* This is build by interpreting the RDI_MemDescr */
int counter[0x60]; /* wait states - -ve for "special" */
#else
# error Code relies on things about ARMul_accs
#endif
RDI_MemDescr desc;
/* Cache of the stats computations. */
bool_int stats_are_valid;
RDI_MemAccessStats stats;
/* Added for when we load the map-file ourselves. */
char *md_Name;
/* To be freed at the end */
struct NumState *num_state;
} MemDescr;
#define NUMPAGES 64 * 1024
#define ARMMAP_PAGESIZE 64 * 1024
#define PAGEBITS 16
#define OFFSETBITS 0xffff
#define OFFSETBITS_WORD 0xfffc
typedef struct {
ARMword memory[ARMMAP_PAGESIZE/4];
} mempage;
typedef struct {
mempage *page[NUMPAGES];
} memory;
typedef struct {
ARMTime wait_states; /* counter for wait states */
ARMul_acc last_acc; /* last cycle flag */
int cnt; /* cycle-by-cycle counter */
} Bus;
/* was typedef ... toplevel; */
BEGIN_STATE_DECL(Mapfile)
unsigned read_bigend, write_bigend;
ARMword byteAddrXor,hwordAddrXor; /* for reads */
MemDescr desc;
ARMul_Cycles cycles;
ARMul_Cycles saved_cycles;
unsigned long IS_cycles; /* counter for IS_cycles */
unsigned long saved_IS_cycles;
Bus i, d, saved_i, saved_d;
bool harvard_data_flag;
memory mem;
unsigned num_regions;
/* Three values give the clock speed:
* clk - clockspeed, as cycle length in us
* mult/period - integer representation of the same, for determining
* the waitstates. The clock period is period*mult ns. This is done to
* try to keep precision in division.
*/
double clk;
unsigned long mult,period;
unsigned long prop;
#if USE_BASE_MEMORY
#else
bool BaseMemoryEnabled;
#endif
ARMul_MemInterface bus_mem,
child; /* the base memory we override */
ARMul_MemInterfaceRef mem_ref;
ARMTime clk_speed;
bool FailedToInstal;
char *mf_CycleNames[16];
int memtype;
ARMul_Bus *pABus;
bool pABus_isMine; /* Did we allocate the above? */
/* Name of mapfile we loaded, else NULL. */
char const *mf_MapFileLoaded;
/*
* SIMABS awareness:
*
* We need for semihosting exit to return RDIError_TargetStopped if we hit
* the semihosting stop vector. Otherwise there is no way for a step call
* to figure out that it has stopped.
*/
SimRdiProcVec* simrdiprocvec; /* non-null if running under a SimRdi_Manager */
/* To avoid memory-leaks... */
#ifdef OldCode
SimRdi_Regwin_Advert* mf_ad_to_destroy;
#else
Advert_ID mf_ad_to_destroy;
#endif
END_STATE_DECL(Mapfile)
/* Type of an argument to function Mapfile_SimReg which reads
* numeric values to display in the Cycle-counts Tab in RVDebugger. */
typedef struct NumState {
MemDescr *md;
/* MapfileState *state; */
double clk; /* This is all we need from state! */
unsigned index; /* So we can use an enum to display the region-name. */
} NumState;
/* #define MAP_COUNTWAIT 0x0001 */
#define MAP_AMBABUSCOUNTS 0x0002
#define MAP_SPOTISCYCLES 0x0004
#define MAP_HARVARD 0x0008
/*
* When spotting I-S cycles, a memory controller can either:
* - speculatively decode all I cycles. This gives 2 cycles to do the I-S
* access.
* - check for nMREQ in the middle of I cycles. This gives 1.5 cycles to do
* the access.
* - process each cycle in turn. This gives only 1 cycle to do the access.
* armmap.c can model each of these, "SPECULATIVE", "EARLY" or "LATE"
*/
#define MAP_ISMODE 0x0030
#define MAP_IS_SPEC 0x0010
#define MAP_IS_EARLY 0x0020
#define MAP_IS_LATE 0x0030
#define MAP_FIXEDSEX 0x0040 /* memory bytesex is fixed */
static const struct {
tag_t option;
unsigned long flag;
} MapOption[] = {
/* ARMulCnf_CountWaitStates, MAP_COUNTWAIT, */
ARMulCnf_AMBABusCounts, MAP_AMBABUSCOUNTS,
ARMulCnf_SpotISCycles, MAP_SPOTISCYCLES,
NULL, 0
};
static int Mapfile_MemAccess(void *handle, ARMWord address, ARMWord *data,
unsigned acc);
static int Mapfile_MemAccessSA(void *handle,ARMWord address, ARMWord *data,
unsigned acc);
static void Mapfile_MemAccessHarvard(void *handle,
ARMword daddr,ARMword *ddata, ARMul_acc dacc, int *drv,
ARMword iaddr,ARMword *idata, ARMul_acc iacc, int *irv);
static const ARMul_Cycles *Mapfile_ReadCycles(void *handle);
#define toplevel MapfileState
/* {{{ Helper functions */
/* returns an RDI_Error, or 0 if OK */
typedef int MemConfigCBFunc(void *handle, RDI_MemDescr *mc, char *region_name);
typedef struct {
RDI_MemDescr md;
} MemConfig;
typedef enum { Error_OK = 0, Error_MapFile_NotFound, Error_MapFile_Invalid } Dbg_Error;
/* This is the original ReadMemMap function from armdbg/dbg_stat.c.
* Modifications:
* . allow width=8 for ARM10,ARM11.
* . call a callback-function instead of allocating a list.
*/
static Dbg_Error ReadMemMap(char const *fname,
MemConfigCBFunc *func, void *handle)
{
char line_buffer[256], name[256], prot[256];
MemConfig m;
#ifdef OldCode
MemConfig *ml = NULL;
#endif
FILE *fp = fopen(fname, "r");
#ifdef OldCode
if (memconfig) *memconfig = 0;
#endif
if (fp == NULL) return Error_MapFile_NotFound; /* BGC - Was Error_MemConfig */
for (;;) {
int c, n = 0;
char *s, *line = line_buffer;
unsigned long width;
int flags;
while (isspace(c = fgetc(fp))) continue;
while (c != EOF && c != '\n') {
if (n < 255) line[n++] = c;
c = fgetc(fp);
}
if (c == EOF && n == 0) break;
line[n] = 0;
/* DE34315 - allow ;; comments at the start of lines */
if( n>=2 && (line[0] == ';') && (line[1] == ';') )
continue;
c = sscanf(line, "%lx %lx %s %lu %s %n",
&m.md.start, &m.md.limit, name, &width, prot, &n);
if (c < 5) return Error_MapFile_Invalid; /* BGC - Was Error_BadCfg */
for (s = prot; (c = *s) != 0; s++) *s = safe_toupper(*s);
flags = 0;
if (strcmp(prot, "none") != 0 && strcmp(prot, "-") != 0)
for (s = prot; (c = *s++) != 0; ) {
if (c == 'R' && !(flags & 1))
flags |= 1;
else if (c == 'W' && !(flags & 2))
flags |= 2;
else if (c == '*' && !(flags & 4))
flags |= 4;
else
return Error_MapFile_Invalid; /* BGC - Was Error_BadCfg */
}
m.md.access = flags;
if (width == 1) width = 0;
else if (width == 2) width = 1;
else if (width == 4) width = 2;
else if (width == 8) width = 3; /* For ARM10 or ARM11. */
else return Error_MapFile_Invalid; /* BGC - Was Error_BadCfg */
m.md.width = (unsigned char)width;
line += n;
c = sscanf(line, "%lu %n", &m.md.Nread_ns, &n);
if (c < 1) return Error_MapFile_Invalid; /* BGC - Was Error_BadCfg */
m.md.Sread_ns = m.md.Nread_ns;
line += n;
if (*line == '/') {
line++;
c = sscanf(line, "%lu %n", &m.md.Sread_ns, &n);
if (c < 1) return Error_MapFile_Invalid; /* BGC - Was Error_BadCfg */
line += n;
}
c = sscanf(line, "%lu %n", &m.md.Nwrite_ns, &n);
if (c < 1) return Error_MapFile_Invalid; /* BGC - Was Error_BadCfg */
m.md.Swrite_ns = m.md.Nwrite_ns;
line += n;
if (*line == '/') {
line++;
c = sscanf(line, "%lu %n", &m.md.Swrite_ns, &n);
if (c < 1) return Error_MapFile_Invalid; /* BGC - Was Error_BadCfg */
line += n;
}
{
int rv = func(handle, &m.md, name);
if (rv != 0)
{
fclose(fp);
return rv;
}
}
}
fclose(fp);
return Error_OK;
}
/* }}} */
static unsigned int Mapfile_DataCacheBusy(void *handle)
{
UNUSEDARG(handle);
return FALSE;
}
/* If we are a leaf memory, we don't need to pass this along.
* We are NOT a leaf memory, but we never go between a core
* and its cache.
*/
#define Mapfile_CoreException NULL
static unsigned long Mapfile_GetCycleLength(void *handle)
{
/* Returns the cycle length in tenths of a nanosecond */
MapfileState *top=(MapfileState *)handle;
return (unsigned long)(top->clk*10000.0);
}
/* Needed for MSVC++6 */
static double u64_to_dbl(uint64 v)
{
int64 v2 = (int64)v;
return (double)v2;
}
static ARMTime Mapfile_ReadClock(void *handle)
{
/* returns a us count */
toplevel *top=(toplevel *)handle;
double t;
Mapfile_ReadCycles(handle);
t=(u64_to_dbl(top->cycles.NumNcycles) +
u64_to_dbl(top->cycles.NumScycles) +
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -