📄 mapfile.c
字号:
u64_to_dbl(top->cycles.NumIcycles) +
u64_to_dbl(top->cycles.NumCcycles) +
u64_to_dbl(top->d.wait_states))*top->clk;
#ifdef VERBOSE_TIMES
printf("Mapfile_ReadClock->%f (clk=%f)\n Ncycles = %d\n, scycles = %d\n, Icycles = %d\n, ccycles = %d\n wait states = %d\n",
t,top->clk,
(unsigned int)top->cycles.NumNcycles,
(unsigned int)top->cycles.NumScycles,
(unsigned int)top->cycles.NumIcycles,
(unsigned int)top->cycles.NumCcycles,
(unsigned int)top->d.wait_states);
#endif
return (ARMTime)(int64)t;
}
static unsigned Mapfile_MemInfo(void *handle, unsigned type, ARMword *pID,
uint64 *data)
{
MapfileState *top=(MapfileState *)handle;
if (ACCESS_IS_READ(type))
{
switch (*pID) {
case MemPropertyID_TotalCycles:
*data = top->cycles.Total;
return RDIError_NoError;
case MemPropertyID_CycleSpeed:
*data = top->clk_speed;
return RDIError_NoError;
#if USE_BASE_MEMORY
#else
case MemPropertyID_BaseMemoryRef: /* We are a LEAF */
*(ARMul_MemInterfaceRef*)data = top->mem_ref;
assert(top->mem_ref.mif->mem_link == &top->mem_ref);
return RDIError_NoError;
case MemPropertyID_BaseMemoryEnable: /* We are a LEAF */
*data = top->BaseMemoryEnabled;
return RDIError_NoError;
#endif
default:
break;
}
}
else
{
switch (*pID) {
#if USE_BASE_MEMORY
#else
case MemPropertyID_BaseMemoryEnable: /* We are a LEAF */
top->BaseMemoryEnabled = (bool)*data;
return RDIError_NoError;
#endif
default:
break;
}
}
/* Ask Flatmem. */
if (top->child.mem_info)
{
return top->child.mem_info(top->child.handle,type,pID,data);
}
else
{
return RDIError_UnimplementedMessage;
}
}
static bool Mapfile_InsertMemory(toplevel *ts)
{
/* First, get the bus */
/* Then a reference to the start of the (non-cache)memory-chain */
ARMword *pprop = &ts->prop;
ARMul_MemInterface *mif;
uint32 ID[2];
ID[0] = ARMulBusID_Bus;
ID[1] = 0;
mif = ARMulif_QueryMemInterface(&ts->coredesc, &ID[0]);
if (!mif)
{
ID[0] = ARMulBusID_Core;
mif = ARMulif_QueryMemInterface(&ts->coredesc, &ID[0]);
}
/* Ask for the last reference in the chain. */
if (mif)
{
ARMul_MemInterface *mif2 = NULL;
uint32 ID[2]; ID[0]=MemPropertyID_BaseMemoryRef; ID[1]=0;
mif->mem_info(mif->handle,
ACCESS_WRITE|ACCESS_WORD,&ID[0],(uint64*)&mif2);
if (mif2)
{
mif = mif2;
}
}
#ifdef VERBOSE_BUS
printf("Mapfile::mif=%p ID:%u\n",mif,(unsigned)ID[0]);
#endif
if (mif)
{
/* Ask the downstream memory for its bus.
* If that fails (because the bus is now owned by BIU instead
* of Flatmem) ask the core.
* !TODO: Ask >upstream< memory.
*/
{
uint32 ID[2]; ID[0]=MemPropertyID_Bus; ID[1]=0;
mif->mem_info(mif->handle,
ACCESS_READ|ACCESS_WORD,&ID[0],
(uint64*)&ts->pABus);
if (!ts->pABus)
{
ARMulif_QueryBus(&ts->coredesc,"",&ts->pABus);
}
if (!ts->pABus)
{
Hostif_PrettyPrint(ts->hostif,ts->config,
"\n** Mapfile got no response to query for MemPropertyID_Bus **\n");
ts->pABus = calloc(1,sizeof(ARMul_Bus));
/* Later, construct such a bus? (*/
ts->FailedToInstal = TRUE;
return FALSE; /*RDIError_UnableToInitialise;*/
}
}
ts->bus_mem.handle = ts;
ts->bus_mem.x.basic.access = Mapfile_MemAccess;
/* <Copy info thru. */
ts->bus_mem.mem_info=Mapfile_MemInfo;
/* If not emulated time, don't offer one */
if (mif->read_clock)
ts->bus_mem.read_clock=Mapfile_ReadClock;
ts->bus_mem.read_cycles=Mapfile_ReadCycles;
ts->bus_mem.get_cycle_length = Mapfile_GetCycleLength;
ts->memtype = mif->memtype;
switch(ts->memtype)
{
case ARMul_MemType_Basic:
case ARMul_MemType_16Bit:
case ARMul_MemType_Thumb:
/* case ARMul_MemType_BasicCached: */
case ARMul_MemType_16BitCached:
case ARMul_MemType_ThumbCached:
case ARMul_MemType_ARMissAHB:
break;
case ARMul_MemType_AHB:
break;
case ARMul_MemType_StrongARM:
*pprop |= MAP_HARVARD;
ts->bus_mem.x.strongarm.access = Mapfile_MemAccessSA;
ts->bus_mem.x.strongarm.core_exception = Mapfile_CoreException;
ts->bus_mem.x.strongarm.data_cache_busy = Mapfile_DataCacheBusy;
break;
case ARMul_MemType_ARM8:
ts->bus_mem.x.arm8.core_exception = Mapfile_CoreException;
ts->bus_mem.x.arm8.access2 = Mapfile_MemAccess; /* MemAccess2 */
break;
case ARMul_MemType_ARM9: /* ARM9 Harvard */
*pprop |= MAP_HARVARD;
ts->bus_mem.x.arm9.harvard_access = Mapfile_MemAccessHarvard;
break;
case ARMul_MemType_ARMissCache:
case ARMul_MemType_ByteLanes:
default:
Hostif_ConsolePrint(ts->hostif,
"Mapfile cannot handle this type of MemoryInterface.\n");
return FALSE;
}
ARMul_InsertMemInterface(mif,
&ts->child,
&ts->mem_ref,
&ts->bus_mem);
return TRUE;
}
else
{
Hostif_ConsolePrint(ts->hostif,
"Core didn't give Mapfile a MemoryInterface.\n");
return FALSE;
}
}
/*
* RDIInfo proc for installing the memory map.
* Adds to the HEAD of the list
*
* Returns 0:Ok else error.
*/
static int InstallMemDescr(void *handle, RDI_MemDescr *md, char *region_name)
{
MapfileState *top=(MapfileState *)handle;
long cnt = 1, seq = 1, counter;
int i, limit;
unsigned long mult=top->mult,period=top->period;
MemDescr *list = top->FailedToInstal ? NULL:calloc(1,sizeof(MemDescr));
if (list==NULL)
{
return (top->FailedToInstal=TRUE);
}
if (top->num_regions == 0) {
if (Mapfile_InsertMemory(top))
Hostif_ConsolePrint(top->hostif,"Memory map:\n");
else
{
Hostif_ConsolePrint(top->hostif,"Memory map cannot start-up.\n");
top->FailedToInstal = TRUE;
return RDIError_Error;
}
}
++top->num_regions;
*list = top->desc;
top->desc.next = list;
list = &top->desc;
list->md_Name = StrDup(region_name);
list->desc=*md;
list->desc.limit+=list->desc.start-1;
list->desc.width+=BITS_8; /* 0->8 bits, 1->16, 2->32 */
Hostif_ConsolePrint(top->hostif,"\
%08x..%08x, %.2d-Bit, %c%c%c, wait states:",
list->desc.start,list->desc.limit,
1<<list->desc.width,
(list->desc.access & 4) ? '*' : ' ',
(list->desc.access & 2) ? 'w' : '-',
(list->desc.access & 1) ? 'r' : '-');
/*
* Cycle counts are kept in an array so that the mem_access function only
* has to do an array lookup to get the cycle count. The work is done
* here in setting up the array.
* When spotting I-S cycles, the mem_access function uses an otherwise
* unused entry (that for an idle cycle) to get the number of wait states.
*/
limit = (top->prop & MAP_SPOTISCYCLES) ? 0x60 : 0x40;
/* Many times around this loop correspond to illegal values of
* acc_WIDTH.
* Two values -- cnt and seq -- are used to say how many cycles are
* needed for this type of access (N/S/I-S, Read or Write), cnt being
* the number of cycles for the access, seq being for any sequential
* cycles needed when accessing a value wider than the bus.
* These values are invariant across the different bus widths, so are
* set up the first time around the loop for a particular access type,
* when the bus width is the illegal value '0'
*/
for (i = 0; i < limit; i++) {
counter=1;
switch (acc_WIDTH(i)) {
case BITS_64:
counter=((list->desc.width==BITS_8) ? (cnt + seq * (8-1)) :
(list->desc.width==BITS_16) ? (cnt + seq * (4-1)) :
(list->desc.width==BITS_32) ? (cnt + seq * (2-1)) : cnt);
if (acc_nSEQ(i) && acc_MREQ(i) && counter &&
(top->prop & MAP_AMBABUSCOUNTS)) {
counter++; /* AMBA decode cycle for N */
}
break;
case BITS_32:
counter=((list->desc.width==BITS_8) ? (cnt + seq * 3) :
(list->desc.width==BITS_16) ? (cnt + seq) : cnt);
if (acc_nSEQ(i) && acc_MREQ(i) && counter &&
(top->prop & MAP_AMBABUSCOUNTS)) {
counter++; /* AMBA decode cycle for N */
}
break;
case BITS_16:
counter=((list->desc.width==BITS_8) ? (cnt + seq) : cnt);
if (!acc_SEQ(i) && counter && top->prop & MAP_AMBABUSCOUNTS)
counter++; /* AMBA decode cycle for N */
if (acc_READ(i) && acc_SEQ(i) && (list->desc.access & 4) &&
counter > 1) {
/* latched read possibly */
counter = -counter;
}
break;
default:
case BITS_8:
counter=cnt;
if (!acc_SEQ(i) && counter && top->prop & MAP_AMBABUSCOUNTS)
counter++; /* AMBA decode cycle for N */
break;
case 0:
/* First time round for this access type - get the base figures. */
if (acc_nMREQ(i)) {
/* Time for I-S cycles, if spotting them */
if (acc_READ(i)) {
if ((list->desc.access & 1) != 0) { /* read okay */
/* number of ticks needed for a sequential access */
seq = list->desc.Sread_ns * mult;
/* now divide by 'period' to get number of cycles, and add one
* more cycle if there's any remainder */
seq = (seq / period) + ((seq % period) != 0 || (seq == 0));
/* cnt is set to the number of ticks needed for a non-seq
* access. */
cnt = list->desc.Nread_ns * mult;
/* The number of wait-states needed for an I-S access depends
* on the mode being used, which determines how many cycles there
* are to start with.
*/
switch (top->prop & MAP_ISMODE) {
case MAP_IS_SPEC:
/* For speculative decode, there are 2 cycles to start with */
/* divide by the period to get the number of cycles, add one
* more if there's any remainder, then take off the one free
* we have from the speculative decode */
cnt = (cnt / period) + ((cnt % period) != 0) - 1;
break;
case MAP_IS_EARLY:
/* For the early decode, there are 1.5 cycles to start with */
/* divide by the period to get the number of cycles, and add
* one if the remainder is greater than half-a-cycle. */
cnt = (cnt / period) + ((cnt % period) >= (period / 2));
break;
case MAP_IS_LATE: /* one + wait cycle */
/* For the late decode, there's only 1 cycle to start with */
/* now divide by 'period' to get number of cycles, and add one
* more cycle if there's any remainder */
cnt = (cnt / period) + ((cnt % period) != 0);
break;
}
/* Make sure we have at least 1 cycle! */
if (cnt <= 0) cnt = 1;
} else {
seq = cnt = 0; /* zero cycles signals 'abort' */
}
} else { /* write */
if ((list->desc.access & 1) != 0) { /* read okay */
/* see above */
seq = list->desc.Swrite_ns * mult;
seq = (seq / period) + ((seq % period) != 0 || (seq == 0));
cnt = list->desc.Nwrite_ns * mult;
switch (top->prop & MAP_ISMODE) {
case MAP_IS_SPEC: /* two cycles */
cnt = (cnt / period) + ((cnt % period) != 0) - 1;
break;
case MAP_IS_EARLY: /* 1.5 cycles */
cnt = (cnt / period) + ((cnt % period) >= (period / 2));
break;
case MAP_IS_LATE: /* one cycle */
cnt = (cnt / period) + ((cnt % period) != 0);
break;
}
if (cnt <= 0) cnt = 1;
} else {
seq = cnt = 0;
}
}
} else if (acc_READ(i)) { /* read */
if (list->desc.access & 1) { /* read access okay */
/* see above */
seq = list->desc.Sread_ns * mult;
seq = (seq / period) + ((seq % period) != 0 || (seq == 0));
if (acc_SEQ(i)) {
cnt = seq;
} else {
/* see above */
cnt = list->desc.Nread_ns * mult;
cnt = (cnt / period) + ((cnt % period) != 0 || (cnt == 0));
}
} else {
seq = cnt = 0;
}
} else { /* write */
if (list->desc.access & 2) { /* write access okay */
/* see above */
seq = list->desc.Swrite_ns * mult;
seq = (seq / period) + ((seq % period) != 0 || (seq == 0));
if (acc_SEQ(i)) {
cnt = seq;
} else {
/* see above */
cnt = list->desc.Nwrite_ns * mult;
cnt = (cnt / period) + ((cnt % period) != 0 || (cnt == 0));
}
} else {
seq = cnt = 0;
}
}
/* report the wait states */
Hostif_ConsolePrint(top->hostif, " %c", acc_READ(i) ? 'R' : 'W');
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -