📄 flatmem.c
字号:
"\n Flatmem connecting to CORE having failed to get BUS.\n");
#endif
}
if (!interf)
{
Hostif_PrettyPrint(hostif,config,
"\n Flatmem cannot get memory-interface.\n");
return RDIError_UnableToInitialise;
}
#ifdef VERBOSE_GETMIF
Hostif_PrettyPrint(hostif,config, "Flatmem got memory-interface %p.\n",
interf);
#endif
#ifdef NotInADS11
/* Ask the downstream memory for its bus. */
{
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)
{
Hostif_PrettyPrint(ts->hostif,ts->config,
"\n** Flatmem got no response to query for MemPropertyID_Bus **\n");
ts->pABus = calloc(1,sizeof(ARMul_Bus));
/* Later, construct such a bus? (*/
return RDIError_UnableToInitialise;
}
}
#endif
ARMulif_QueryBus(&state->coredesc,"A",&state->p_ABus);
if (!state->p_ABus)
{
Hostif_PrettyPrint(hostif,config,"\n** Flatmem failed to get bus from "
"core model. **\n");
return RDIError_UnableToInitialise;
}
/* Ask the host's built-in ARMFlat to disable its RDIInfo. */
if (interf->mem_info)
{
uint64 data = FALSE;
uint32 ID[2]; ID[0]=MemPropertyID_BaseMemoryEnable; ID[1]=0;
interf->mem_info(interf->handle,
ACCESS_WRITE|ACCESS_WORD,&ID[0],&data);
}
state->memtype = memtype = interf->memtype;
interf->mem_info=Flat_MemInfo;
interf->read_clock=Flat_ReadClock;
interf->read_cycles=Flat_ReadCycles;
interf->get_cycle_length=Flat_GetCycleLength;
#ifdef VERBOSE_MEM_TYPE
printf("\nArmflat.c MemInit Type 0x%04x=%u\n",
(unsigned)type,(unsigned)type);
#endif
/* Fill in my functions */
switch (memtype) {
#ifdef PIPELINED
case ARMul_MemType_PipelinedBasic:
interf->x.pipe.next=NextCycle;
interf->x.pipe.access=MemAccessCached;
interf->x.pipe.delta_cycles = NULL;
break;
case ARMul_MemType_PipelinedAMBA:
interf->x.pipe.next=NextCycle;
interf->x.pipe.access=MemAccessCached;
interf->x.pipe.delta_cycles = NULL;
break;
case ARMul_MemType_PipelinedARM9:
interf->x.pipe_arm9.dside_next = NextDCycle;
interf->x.pipe_arm9.iside_next = NextICycle;
interf->x.pipe_arm9.harvard_access = MemAccessHarvard;
interf->x.pipe_arm9.debug_access = MemAccess;
break;
#endif
case ARMul_MemType_Basic:
case ARMul_MemType_16Bit:
interf->x.basic.access=MemAccess;
state->p_ABus->bus_Type = BT_Endian;
break;
case ARMul_MemType_Thumb:
interf->x.basic.access=MemAccessThumb;
state->p_ABus->bus_Type = BT_Endian;
break;
case ARMul_MemType_AHB:
case ARMul_MemType_16BitCached:
case ARMul_MemType_ThumbCached:
case ARMul_MemType_ARMissAHB:
interf->x.basic.access=MemAccessCached;
state->p_ABus->bus_Type = BT_Endian;
break;
case ARMul_MemType_ARM8:
interf->x.arm8.access=MemAccess;
#ifdef MEM_ACCESS2_DISTINCT
interf->x.arm8.access2=MemAccess2;
#else
interf->x.arm8.access2=MemAccess;
#endif
state->p_ABus->bus_Type = BT_Endian;
Hostif_PrettyPrint(hostif,config,", double-bandwidth");
break;
case ARMul_MemType_StrongARM:
interf->x.strongarm.access=MemAccessSA;
interf->x.strongarm.data_cache_busy=DataCacheBusy;
state->p_ABus->bus_Type = BT_Endian | BT_Harvard;
Hostif_PrettyPrint(hostif,config,", StrongARM dual-ported");
break;
#ifndef NO_BYTELANES
case ARMul_MemType_ByteLanes:
interf->x.basic.access=MemAccessBL;
Hostif_PrettyPrint(hostif,config,", byte-laned");
break;
#endif
case ARMul_MemType_ARM9:
interf->x.arm9.access = MemAccess; /* used by debugger */
interf->x.arm9.harvard_access = MemAccessHarvard;
state->p_ABus->bus_Type = BT_Endian | BT_Harvard;
break;
#ifdef OldCode
case ARMul_MemType_ARMissAHB:
Hostif_PrettyPrint(hostif,config,", AHB");
interf->x.armiss_ahb.debug_access=MemAccess;
interf->x.armiss_ahb.ahb_access=MemAccessAsync;
state->p_ABus->bus_Type = BT_Endian;
break;
#endif
case ARMul_MemType_ARMissCache: /* NOT HANDLED */
default:
Hostif_PrettyPrint(hostif,config,"\n Cannot handle memory-type 0x%x.\n",
memtype);
return RDIError_UnableToInitialise;
}
/* If we were inserting ourselves into the chain, we'd use
* ARMul_SwapMasterInfo (called by ARMul_InsertMemInterface2).
*/
top->mem_ref.handle = interf->mem_link->handle;
top->mem_ref.master_info = interf->mem_link->master_info;
top->mem_ref.mif = interf;
interf->mem_link = &top->mem_ref;
{ uint32 busClockDivisor =
ToolConf_DLookupUInt(config, ARMulCnf_MCCfg, 0);
if (0 == busClockDivisor)
{
assert(0);
busClockDivisor = 1;
}
if (top->p_ABus->bus_RegisterPeripHandle == NULL)
{
ARMul_Bus_Initialise(top->p_ABus,
busClockDivisor,
ARMul_BusAccess, /* bus_decoderFunc */
state, /* bus_DecoderHandle */
ARMul_BusRegisterPerip, /* bus_registerPeripFunc */
NULL, /* bus_RegisterPeripHandle */
NULL
);
}
else
{
top->p_ABus->bus_CycleLength = busClockDivisor;
}
}
top->p_ABus->bus_LogWidth =
flatmem_log2(ToolConf_DLookupUInt(config, (tag_t)"BUS_WIDTH", 32));
#ifdef VERBOSE_BUS
printf("After calling ARMul_Bus_Initialise : LogWidth=%u\n.",
(unsigned)top->p_ABus->bus_LogWidth);
#endif
mem=&top->mem;
top->BaseMemoryEnabled = TRUE;
option=ToolConf_Lookup(config,ARMulCnf_MCLK);
if (option != NULL) clk_speed = ToolConf_Power(option,FALSE);
if (option == NULL || clk_speed == 0) {
/* We cannot really tell now, but assume that we have a cached core. */
char const *opt1 = ToolConf_Lookup(config,(tag_t)"FCLK");
uint32 cpuspeed = opt1 ? ToolConf_Power(opt1,FALSE) : 0;
uint32 mccfg = ToolConf_DLookupUInt(config,(tag_t)"MCCFG",0);
if (!cpuspeed)
{
option=ToolConf_Lookup(config,(tag_t)"CPUSPEED");
cpuspeed = option ? ToolConf_Power(option,FALSE) : 0;
}
if (!cpuspeed)
{
option=ToolConf_Lookup(config,(tag_t)"DEFAULT_CPUSPEED");
cpuspeed = option ? ToolConf_Power(option,FALSE) : 0;
}
clk_speed = (mccfg != 0) ? cpuspeed / mccfg : 0;
Hostif_PrettyPrint(hostif,config,
"\n*** Core failed to define MCLK - guessing %lu.\n",
(unsigned long)clk_speed);
}
if (clk_speed == 0) {
top->clk=0.0;
} else {
top->clk=1000000.0/clk_speed; /* in microseconds */
}
top->clk_speed = clk_speed;
/* only report the speed if "CPU Speed" has been set in the config */
if (ARMul_ClockIsEmulated(config)) {
char *fac;
double clk=ARMul_SIRange(clk_speed,&fac,FALSE);
if (clk) /* Don't print this if it is zero */
Hostif_PrettyPrint(hostif,config,", %.1f%sHz",clk,fac);
}
for (page=0; page<NUMPAGES; page++) {
mem->page[page]=NULL;
}
Hostif_PrettyPrint(hostif,config, ", 4GB");
top->cycles.NumNcycles=0;
top->cycles.NumScycles=0;
top->cycles.NumIcycles=0;
top->cycles.NumCcycles=0;
top->cycles.NumFcycles=0;
assert(top->memtype == memtype);
option = ToolConf_Lookup(config, ARMulCnf_MemoryByteSex);
if (option == NULL) {
top->memory_byte_sex = FALSE; /* follow bigendSig on core */
} else switch (safe_toupper(option[0])) {
case 'B':
top->memory_byte_sex = TRUE;
top->write_bigend = TRUE; /* writes always bigendian */
break;
case 'L':
top->memory_byte_sex = TRUE;
top->write_bigend = FALSE; /* writes always littleendian */
break;
default:
top->memory_byte_sex = FALSE; /* follow bigendSig on core */
break;
}
assert(top == state);
if (!(type & RDIOpen_ByteSexMask))
{ /* We are being told, rather than asked */
ConfigChange(state, !!(type & 4));
}
/* Also handles ConfigChange and DebugEvents!...*/
ARMulif_InstallEventHandler(&state->coredesc,
(ConfigEventSel | DebugEventSel),
Flatmem_ConfigEvents, state);
ARMulif_InstallUnkRDIInfoHandler(&state->coredesc,UnkRDIInfo,top);
interf->handle=top;
top->HighestPeripheralAddress = ~(ARMword)0;
top->NewPageAllocated = calloc(1,sizeof(GenericAccessCallback));
top->NewPageAllocated->func = flat_newPage;
top->NewPageAllocated->handle = top;
#ifdef VERBOSE_INIT
printf("END_INIT(Flatmem)\n.");
#endif
/* Tell the Core we provide a Bus.
* This shall allow it to know when we need to be called.
* Flatmem does this before loading its children, so they can
* access this bus.
*/
{ static ARMword ID[2] = {BMPropertyID_NewBusConnected,0};
void *a_pointer = top->p_ABus;
flatmem_masterInfo(top,ACCESS_WRITE,ID,(uint64*)&a_pointer);
}
assert(dbg_state != NULL);
assert(((RDI_DbgStateForSubAgent *)dbg_state)->size == sizeof(RDI_DbgStateForSubAgent));
assert(((RDI_DbgStateForSubAgent *)dbg_state)->lib_handle != NULL);
ARMulAgent_Create(&state->agent, hostif, config,
dbg_state,
NULL, /*dll_name*/
NULL /*ARMul_RDIProcs*/,
NULL /*((RDI_DbgStateForSubAgent *)dbg_state)->agent_desc.rdi*/);
if (verbose)
{
Hostif_PrettyPrint(hostif,config,"\nFLAT LOADS PERIPHERALS...\n");
}
{
toolconf child = ToolConf_Child(config,(tag_t)"PERIPHERALS");
ARMul_Agent *agent = (ARMul_Agent *)state->agent;
agent->module_desc = *dsa->agent_desc; /* Core */
agent->subagent_desc = *dsa->parent_desc; /* Transparent Agent */
agent->init_type = type; /* ? Can I add this to the constructor? */
if (child)
{
int err = ToolConf_IterateTags(child, ARMulAgent_AddPeripheral,
state->agent);
if (err != RDIError_NoError)
{
#ifdef VERBOSE_INIT
printf("\nARMul_AddComponent returned err=%i.\n", err);
/* ToolConf_WriteTo(tconf,stderr); */
/*fprintf(stderr,"\n>>>>\n");*/
#endif
Hostif_PrettyPrint(hostif,config,
"\n A child of Flatmem failed to initialize, error %i.\n",
err);
return(RDIError_UnableToInitialise);
}
if (verbose)
{
Hostif_PrettyPrint(hostif,config,"\nFLAT LOADED\n");
}
}
else
{
if (verbose)
{
Hostif_PrettyPrint(hostif,config,"\nFLAT HAS NO PERIPHERALS\n");
}
}
}
#ifdef VERBOSE_INIT
printf("END_INIT(Flatmem)\n.");
#endif
}
END_INIT(Flatmem)
/* --- BEGIN PERIPHERAL-ACCESS --- */
#include "rdi_err.h"
static int peripheral_access(void *handle,
ARMword address,
ARMword *data,
ARMul_acc acc)
{
toplevel *ts=(toplevel *)handle;
/* See if any peripheral registered on ABus,
* unless we have an I- or C-cycle. */
#ifdef VERBOSE_PERIPHERAL_ICYCLES
if (ACCESS_IS_IDLE(acc))
printf("armflat.c:peripheral_access(A:%08lx T:%08lx)\n",
(unsigned long)address, (unsigned long)acc);
#endif
#ifdef NO_IDLES_TO_PERIPHERALS
if (!(acc & acc_Nmreq))
#endif
{
ARMul_Bus *bus = ts->p_ABus;
ARMul_AccessRequest req;
int err;
memset(&req,0,sizeof(req));
req.req_access_type = acc;
req.req_addr_size = 1;
req.req_address[0] = address;
req.req_data = data;
err = bus->bus_decoderFunc(bus, &req);
return Perip2Memret(err);
}
return -2; /* Pass Idles back to memory. */
}
/* --- END PERIPHERAL-ACCESS --- */
static unsigned flat_newPage(struct GenericAccessCallback *myCB,
ARMword address,
ARMword*data, unsigned access_type)
{
toplevel *top=(toplevel *)myCB->handle;
unsigned i;
unsigned nw = access_type / sizeof(ARMword);
assert(access_type == ARMFLAT_PAGESIZE);
(void)access_type; (void)address; (void)top;
/*
* We fill the new page with data that, if the ARM tried to execute
* it, it will cause an undefined instruction trap (whether ARM or
* Thumb)
*/
for (i=0;i<nw;) {
data[i++]=0xe7ff0010; /* an ARM undefined instruction */
/* The ARM undefined insruction has been chosen such that the
* first halfword is an innocuous Thumb instruction (B 0x2)
*/
data[i++]=0xe800e800; /* a Thumb undefined instruction */
}
/* We are the last in the chain, registered first. */
assert(myCB->next == NULL);
return 0;
}
static mempage *NewPage(void *handle,ARMword address)
{
toplevel *top=(toplevel *)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
*/
Hostif_DebugPrint(top->hostif, "OUT OF MEMORY\n");
ARMulif_StopExecution(&top->coredesc, RDIError_OutOfStore);
return top->mem.page[0];
}
top->NewPageAllocated->func(top->NewPageAllocated,address,
page->memory,ARMFLAT_PAGESIZE);
return page;
}
/*
* Generic memory interface.
*/
/*
* This is the most basic memory access function - an ARM6/ARM7 interface.
*/
static int MemAccess(void *handle,
ARMword address,
ARMword *data,
ARMul_acc acc)
{
toplevel *top=(toplevel *)handle;
unsigned int pageno;
mempage *page;
ARMword *ptr;
ARMword offset;
int rv;
if (acc_ACCOUNT(acc)) {
COUNTCYCLES(top->cycles,acc);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -