📄 mapfile.c
字号:
case 7: /* S-Writes */
regval->reg32 = desc->stats.Swrites; break;
case 8: /* Time(ns) */
regval->reg32 = desc->stats.ns; break;
case 9: /* Time(s) */
regval->reg32 = desc->stats.s; break;
case 10: /* Region_Name */
regval->reg32 = num_state->index; break;
default:
return SIM_REGISTER_ACCESS;
}
return SIM_OK;
}
else return SIM_REGISTER_ACCESS; /* All items are read-only here. */
}
static Register_Definition mapfile_reg_defs[] = {
/* readonlyQ is 0=> read/write, 1=> readonly, 2=>writeonly */
#define S(symbol,buttonname,readonlyQ) \
{ 4, EECHGCASE_DOWN, TYPE_UNSIGNED_LONG, /* "@mapfile_" */ symbol, buttonname, readonlyQ, 0 }
#ifdef NotYet /* RVDebugger doesn't support 64-bits yet. */
#define D(symbol,buttonname,readonlyQ) \
{ 8, EECHGCASE_DOWN, TYPE_UNSIGNED_LONG_LONG, /* "@mapfile_" */ symbol, buttonname, readonlyQ, 0 }
#endif
/* These entries are orderred - treat as an enum whose
* values are the cases in function Mapfile_SimReg. */
S("Address", "Base address ", 1),
S("Limit", "Limit address ", 1),
S("Width", "Width in bytes ", 1),
S("Access", "ReadWriteAbility ", 1),
S("Reads_N", "Non-sequential Reads ", 1),
S("Reads_S", "Sequential Reads ", 1),
S("Writes_N", "Non-sequential Writes", 1),
S("Writes_S", "Sequential Writes ", 1),
S("Time_ns", "Time(ns) ", 1),
S("Time_s", "Time(s) ", 1),
S("Region_Name", "Region Name ", 1),
#undef S
};
#define NUM_ENUMS 2
char *mapfile_AccessTypeEnum[NUM_ENUMS] = {
"MapFileAccessType=None,ReadOnly,WriteOnly,All, *",
"MapFileRegionName=1,2,3,4,5,6," /* !We overwrite this! */
};
#define ADD_TO_NEW_TAB
#ifdef ADD_TO_NEW_TAB
/* Returns an allocated string, pre-FOE'd, (or NULL on out-of-memory). */
static char *make_enum_name(MapfileState *state)
{
char *str1 = NULL;
MemDescr *md = &state->desc; /* ! */
unsigned i;
for (i = 0; i < state->num_regions; i++)
{
if (str1 == NULL)
{
str1 = StrMultiCat("MapFileRegionName=",md->md_Name,NULL);
}
else
{
char *str2 = str1;
str1 = StrMultiCat(str1,",",md->md_Name,NULL);
free(str2);
}
md = md->next;
}
return FOE(str1);
}
static RegWin *new_RegWin(MapfileState *state)
{
RegWin *rw = (RegWin*)calloc(1,sizeof(RegWin));
if (rw != NULL)
{
MemDescr *md = &state->desc; /* ! */
unsigned i;
unsigned numrd = sizeof(mapfile_reg_defs)/sizeof(mapfile_reg_defs[0]);
/* {{{ Fill in the RegWin fields. */
/* !Todo: Use the instance-name in case we have a multi-core system! */
rw->tab_name = "Mapfile,Statistics from Mapfile Regions";
#define NUM_HEADER_LINES 1
rw->line_cnt = state->num_regions + NUM_HEADER_LINES;
rw->enum_cnt = NUM_ENUMS;
rw->lines = (char**)FOE(calloc(rw->line_cnt,sizeof(char *)));
rw->enum_list = FOE(calloc(NUM_ENUMS,sizeof(char*)));
rw->enum_list[0] = mapfile_AccessTypeEnum[0];
rw->enum_list[1] = make_enum_name(state);
/* {{ Fill in Lines */
rw->lines[0] = "_Address Limit Width Access "
"Reads_N Reads_S "
"Writes_N Writes_S Time_ns Time_s Region_Name ";
for (i = 0; i < state->num_regions; i++)
{
unsigned j;
char *str1 = NULL;
for (j=0; j<numrd; j++)
{
char *name = StrMultiCat("@mapfile_",md->md_Name,"_",
mapfile_reg_defs[j].name, NULL);
switch(j)
{
case 3: /* && i == 0 */ /* "Access" */
{
char *s2 = name;
name = StrMultiCat(name,"=MapFileAccessType", NULL);
free(s2);
break;
}
case 10: /* "Region_Name" */
{
char *s2 = name;
name = StrMultiCat(name,"=MapFileRegionName", NULL);
free(s2);
break;
}
}
if (str1 != NULL)
{
char *s2 = str1;
str1 = StrMultiCat(str1,",",name, NULL);
free(s2); free(name);
}
else
{
str1 = name;
}
}
rw->lines[i+ NUM_HEADER_LINES] = FOE(str1);
md = md->next;
}
/* }} Fill in Lines */
/* }}} */
}
return FOE(rw);
}
#endif
static void
Mapfile_SimRdiListener( SimRdiRegistrationProcVec* srpv,
void* handle )
{
MapfileState *state = (MapfileState *)handle;
SimRdiProcVec* spv = srpv->simrdiprocvec;
unsigned i;
MemDescr *md = &state->desc; /* ! */
state->simrdiprocvec = spv;
#ifdef VERBOSE_SIMRDI
Hostif_ConsolePrint(state->hostif,"\n** MAPFILE Mapfile_SimRdiListener num:%i **\n",
srpv->number);
#endif
if( srpv->number < 1
|| spv == NULL
|| spv->signature != SIMRDIPROCVEC_SIGNATURE
|| (spv->version.major) != 0x01
|| spv->null == NULL
|| spv->null->advertise == NULL
|| spv->null->c_new == NULL
)
{
#ifdef VERBOSE_SIMRDI
Hostif_ConsolePrint(state->hostif,"\n** MAPFILE Mapfile_SimRdiListener FAIL **\n");
#endif
return;
}
/* Q: Should a tree-view be
* + Region1
* | + Stat1 (.. Stat6)
* or
* + Stat1
* | + Region1
* Or should I supply both?
* A: A table-view would be best if possible, and the former is closest.
*/
/* #define ADD_TO_EXISTING_TAB */
/* Add the statistics to a pre-allocated tab. */
for (i = 0; i < state->num_regions; i++)
{
SimRdi_Uniregs_Advert* ad =
spv->uniregs->c_new( spv->uniregs );
/* }}} */
if( ad != NULL )
{
/* state->advert_regs = ad->x.id; */
/* "ButtonName" */
ad->x.name = md->md_Name; /* ? What's this for? */
ad->x.handle = state;
ad->x.coredesc = &state->coredesc;
ad->description = md->md_Name; /* Displayed in Tab with [+] next to it. */
ad->len = sizeof(mapfile_reg_defs)/sizeof(mapfile_reg_defs[0]);
/* Display in Cycle counters tab. */
ad->block_num = uniregs_cycle_counter;
{
unsigned s = sizeof(mapfile_reg_defs);
Register_Definition *rdefs = FOE(malloc(s));
if (rdefs == NULL) return;
memcpy(rdefs,mapfile_reg_defs,s);
{ unsigned j;
/* Make the names distinct - else it all fails horribly. */
for (j=0; j<(unsigned)ad->len; j++)
{
rdefs[j].name = FOE(StrMultiCat("@mapfile_",md->md_Name,"_",
rdefs[j].name, NULL));
}
}
ad->desc = rdefs;
}
/* We allocate some new state to distinguish each region. */
{
NumState *num_state = (NumState *)calloc(1,sizeof(NumState));
num_state->md = md;
num_state->clk = state->clk;
num_state->index = i;
ad->handle_for_function = (void*)num_state;
md->num_state = (void*)num_state; /* so we can free it */
}
ad->_SimReg = Mapfile_SimReg;
ad->start_reg_number = 0 /* i * 0x20 - for testing */;
#ifndef ADD_TO_EXISTING_TAB
ad->x.config_flags |= UNIREGS_DO_NOT_AUTO_GENERATE_REG_WIN;
#endif
spv->uniregs->advertise( spv->uniregs, ad );
}
md = md->next;
}
#ifdef ADD_TO_NEW_TAB
{
RegWin *rw = new_RegWin(state);
if (rw != NULL)
{
SimRdi_Regwin_Advert* ad =
spv->regwin->c_new( spv->regwin );
ad->regwin = rw;
state->mf_ad_to_destroy = ad->x.id;
spv->regwin->advertise( spv->regwin, ad );
}
}
#endif
}
BEGIN_INIT(Mapfile)
{
MapfileState *top=state;
memory *mem=&top->mem;
unsigned page, i;
unsigned long prop = 0;
Hostif_PrettyPrint(hostif, config, ", Mapfile");
/* Initialise a catch-all for the whole of memory */
top->desc.desc.handle = RDI_NoHandle;
top->desc.desc.start = 0l;
top->desc.desc.limit = 0xffffffffl;
top->desc.desc.width = 2;
top->desc.desc.access = 3;
top->desc.desc.Nread_ns =
top->desc.desc.Nwrite_ns =
top->desc.desc.Sread_ns =
top->desc.desc.Swrite_ns = 0;
memset(&top->desc.access_counts, 0, sizeof(top->desc.access_counts));
memset(&top->desc.counter, 0, sizeof(top->desc.counter));
top->desc.next = NULL;
#if USE_BASE_MEMORY
#else
top->BaseMemoryEnabled = ToolConf_DLookupBool(config,
(tag_t)"ENABLE_UNMAPPED_MEMORY",
TRUE);
#endif
{
/* Get cycle-length in 10ths of a nanosecond. */
uint32 bus_cycle_length =
ARMulif_GetCycleLength(&state->coredesc); /* !REVERT RENAME! */
if (!bus_cycle_length)
{
uint32 mclk = ARMul_GetMCLK(config);
if (mclk) {
bus_cycle_length = (uint32)(0.5 + 100000.0 * 100000.0 / mclk);
}
}
if (!bus_cycle_length)
{
Hostif_PrettyPrint(hostif, config,
"\n** Mapfile cannot get bus cycle-length from core."
"Defaulting to 20MHz.\n");
bus_cycle_length = 500; /* default to 20MHz */
}
top->mult=10; /* Convert ns to 10ths of ns */
top->period=bus_cycle_length;
top->clk=(double)bus_cycle_length / 10000.0; /* in microseconds */
}
for (i = 0; MapOption[i].option != NULL; i++) {
if (ToolConf_DLookupBool(config, MapOption[i].option,FALSE)) {
prop |= MapOption[i].flag;
}
}
if (prop & MAP_SPOTISCYCLES) {
char const *option = ToolConf_Lookup(config, ARMulCnf_ISTiming);
if (option != NULL && ToolConf_Cmp(option, "SPECULATIVE"))
prop |= MAP_IS_SPEC;
else if (option != NULL && ToolConf_Cmp(option, "EARLY"))
prop |= MAP_IS_EARLY;
else
prop |= MAP_IS_LATE;
}
top->prop = prop;
for (page=0; page<NUMPAGES; page++) {
mem->page[page]=NULL;
}
top->cycles.NumNcycles=0;
top->cycles.NumScycles=0;
top->cycles.NumIcycles=0;
top->cycles.NumCcycles=0;
top->cycles.NumFcycles=0;
top->d.wait_states=0;
top->d.cnt=0;
top->i.wait_states=0;
top->i.cnt=0;
top->harvard_data_flag = FALSE;
top->write_bigend = HostEndian ? 3 : 0; /* writes start littleendian */
top->read_bigend = top->write_bigend;
ARMulif_InstallUnkRDIInfoHandler(&state->coredesc,RDI_info,top);
ARMulif_InstallEventHandler(&state->coredesc,
(ConfigEventSel | DebugEventSel),
Mapfile_ConfigEvents, state);
{
char const *mfl = ToolConf_Lookup(config,(tag_t)"MAPFILETOLOAD");
if (mfl != NULL && mfl[0])
{
int errfl = ReadMemMap(mfl, InstallMemDescr, top);
switch (errfl)
{
case Error_OK:
top->mf_MapFileLoaded = mfl;
break;
case Error_MapFile_NotFound:
{
char buf[513];
memset(buf,0,513);
dir_getcwd(buf,512);
Hostif_ConsolePrint(hostif,"\n** MAPFILETOLOAD=%s not found, cwd=%s **\n", mfl, buf);
return RDIError_UnableToInitialise;
}
case Error_MapFile_Invalid:
/* !Todo: A line-number would be useful! */
Hostif_ConsolePrint(hostif,"\n** MAPFILETOLOAD=%s mapfile invalid. **\n", mfl);
return RDIError_UnableToInitialise;
default:
Hostif_ConsolePrint(hostif,"\n** MAPFILETOLOAD=%s unknown error **\n", mfl);
return RDIError_UnableToInitialise;
}
#ifdef VERBOSE_SIMRDI
Hostif_ConsolePrint(hostif,"\n** MAPFILE calling ARMulif_InstallSimRdiRegistration **\n");
#endif
ARMulif_InstallSimRdiRegistration( &state->coredesc,
Mapfile_SimRdiListener,
state );
}
}
}
END_INIT(Mapfile)
#if USE_BASE_MEMORY
#else
static mempage *NewPage(void *handle)
{
unsigned int i;
MapfileState *top=(MapfileState *)handle;
mempage *page=(mempage *)malloc(sizeof(mempage));
if ( page == NULL)
{
/* The malloc failed. we have to do a number of things.
1. call ARMulRaiseError
2. Call ARMul_ModelBroken
3. Return the zero page so that emulation continues
long enough for the halt to take effect
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -