?? flatmem.c
字號:
* Instruction fetched, No data fetched N
* Instruction fetched, data fetched S
* No instruction fetched, No data fetched I
* No instruction fetched, data fetched C
*/
if (acc_ACCOUNT(acc)) {
if (acc_OPC(acc)) {
/* End of cycle - account for access */
/* This access is either acc_LoadInstrN or acc_NoFetch */
if (top->sa_memacc_flag) {
/* data fetched */
top->sa_memacc_flag=0;
if (acc_MREQ(acc)) top->cycles.NumScycles++;
else top->cycles.NumCcycles++;
} else {
/* no data fetched */
if (acc_MREQ(acc)) top->cycles.NumNcycles++;
else top->cycles.NumIcycles++;
}
} else if (acc_MREQ(acc)) { /* should be */
top->sa_memacc_flag=1; /* flag */
}
}
if ((address >= top->LowestPeripheralAddress) &&
(address <= top->HighestPeripheralAddress) &&
(rv = peripheral_access(handle,address,data,acc)) != -2)
{
return rv;
}
pageno=address>>PAGEBITS;
page=top->mem.page[pageno];
if (page==NULL) {
top->mem.page[pageno]=page=NewPage(top,address);
}
offset = address & OFFSETBITS_WORD;
ptr=(ARMword *)((char *)(page->memory)+offset);
if (acc_MREQ(acc)) {
if (acc_READ(acc)) {
switch (acc & WIDTH_MASK) {
case BITS_8: /* read byte */
if (HostEndian!=top->read_bigend) address^=3;
*data = ((unsigned8 *)ptr)[address & 3];
break;
case BITS_16: { /* read half-word */
/* extract half-word */
#ifndef HOST_HAS_NO_16BIT_TYPE
/*
* unsigned16 is always a 16-bit type, but if there is no native
* 16-bit type (e.g. ARM!) then we can do something a bit more
* cunning.
*/
if (HostEndian!=top->read_bigend) address^=2;
*data = *((unsigned16 *)(((char *)ptr)+(address & 2)));
#else
unsigned32 datum;
datum=*ptr;
if (HostEndian!=top->read_bigend) address^=2;
if (address & 2) datum<<=16;
*data = (datum>>16);
#endif
}
break;
case BITS_32: /* read word */
*data=*ptr;
break;
default:
return_PERIP_DABORT;
}
} else {
switch (acc & WIDTH_MASK) {
/* extract byte */
case BITS_8: /* write_byte */
if (HostEndian!=top->write_bigend) address^=3;
((unsigned8 *)ptr)[address & 3]=(unsigned8)(*data);
break;
case BITS_16: /* write half-word */
if (HostEndian!=top->write_bigend) address^=2;
*((unsigned16 *)(((char *)ptr)+(address & 2)))=(unsigned16)(*data);
break;
case BITS_32: /* write word */
*ptr=*data;
break;
default:
return_PERIP_DABORT;
}
} /* internal cycle */
}
return 1;
}
/*
* Memory access function that supports byte lanes
*/
#ifndef NO_BYTELANES
static int MemAccessBL(void *handle,
ARMword address,
ARMword *data,
ARMul_acc acc)
{
toplevel *top=(toplevel *)handle;
unsigned int pageno;
mempage *page;
ARMword *ptr;
ARMword offset;
if (acc_ACCOUNT(acc)) {
if (acc_SEQ(acc)) {
if (acc_MREQ(acc)) top->cycles.NumScycles++;
else top->cycles.NumCcycles++;
} else if (acc_MREQ(acc)) top->cycles.NumNcycles++;
else top->cycles.NumIcycles++;
}
pageno=address>>PAGEBITS;
page=top->mem.page[pageno];
if (page==NULL) {
top->mem.page[pageno]=page=NewPage(top,address);
}
offset = address & OFFSETBITS_WORD;
ptr=(ARMword *)((char *)(page->memory)+offset);
if (acc_MREQ(acc)) {
if (acc_BYTELANE(acc)==BYTELANE_MASK) { /* word */
if (acc_READ(acc)) *data = *ptr;
else *ptr = *data;
} else {
unsigned32 mask;
static const unsigned32 masks[] = {
0x00000000, 0x000000ff,
0x0000ff00, 0x0000ffff,
0x00ff0000, 0x00ff00ff,
0x00ffff00, 0x00ffffff,
0xff000000, 0xff0000ff,
0xff00ff00, 0xff00ffff,
0xffff0000, 0xffff00ff,
0xffffff00, 0xffffffff,
};
mask=masks[acc_BYTELANE(acc)];
if (acc_READ(acc)) *data = *ptr & mask;
else *ptr = (*ptr & ~mask) | (*data & mask);
} /* internal cycle */
}
return 1;
}
#endif
static void MemAccessHarvard(void *handle,
ARMword daddr,ARMword *ddata, ARMul_acc dacc, int *drv,
ARMword iaddr,ARMword *idata, ARMul_acc iacc, int *irv)
{
toplevel *top=(toplevel *)handle;
unsigned int pageno;
mempage *page;
ARMword *ptr;
ARMword offset;
/* This call doesn't happen for debug accesses, so no need
* to check acc_ACCOUNT. */
/* top->p_ABus->bus_BusyUntil++; */
/* Update cycle counters - use the same scheme */
/* as the StrongARM model (see MemAccessSA()). */
if (acc_MREQ(iacc) && acc_MREQ(dacc)) {
top->cycles.NumScycles++;
}
else if (acc_MREQ(iacc) && acc_nMREQ(dacc)) {
top->cycles.NumNcycles++;
}
else if (acc_nMREQ(iacc) && acc_MREQ(dacc)) {
top->cycles.NumCcycles++;
}
else {
top->cycles.NumIcycles++;
}
/* Deal with Instruction side first */
if (acc_MREQ(iacc)) {
int rv;
if ((iaddr >= top->LowestPeripheralAddress) &&
(iaddr <= top->HighestPeripheralAddress) &&
(rv = peripheral_access(handle,iaddr,idata,iacc)) != -2)
{
*irv = rv; goto idone;
}
pageno=iaddr>>PAGEBITS;
page=top->mem.page[pageno];
if (page==NULL) {
top->mem.page[pageno]=page=NewPage(top,iaddr);
}
offset = iaddr & OFFSETBITS_WORD;
ptr=(ARMword *)((char *)(page->memory)+offset);
switch (iacc & WIDTH_MASK) {
case BITS_8: {
unsigned32 datum = *ptr;
if (HostEndian!=top->read_bigend) iaddr^=3;
datum<<=(3 *(iaddr & 3));
*idata = datum & 0xFF;
}
case BITS_16: { /* read half-word */
/* extract half-word */
#ifndef HOST_HAS_NO_16BIT_TYPE
/*
* unsigned16 is always a 16-bit type, but if there is no native
* 16-bit type (e.g. ARM!) then we can do something a bit more
* cunning.
*/
if (HostEndian!=top->read_bigend) iaddr^=2;
*idata = *((unsigned16 *)(((char *)ptr)+(iaddr & 2)));
#else
unsigned32 datum = *ptr;
if (HostEndian!=top->read_bigend) iaddr^=2;
if (iaddr & 2) datum<<=16;
*idata = (datum>>16);
#endif
}
break;
case BITS_32: /* read word */
*idata=*ptr;
break;
case BITS_64: /* read 2 words */
*idata=*ptr;
idata[1]=ptr[1];
break;
}
}
*irv = 1;
idone:
/* Now deal with data side */
if (acc_MREQ(dacc) /*dacc != acc_Icycle*/) {
int rv;
if ((daddr >= top->LowestPeripheralAddress) &&
(daddr <= top->HighestPeripheralAddress) &&
(rv = peripheral_access(handle,daddr,ddata,dacc)) != -2)
{
*drv = rv; goto ddone;
}
pageno=daddr>>PAGEBITS;
page=top->mem.page[pageno];
if (page==NULL) {
top->mem.page[pageno]=page=NewPage(top,daddr);
}
offset = daddr & OFFSETBITS_WORD;
ptr=(ARMword *)((char *)(page->memory)+offset);
if (acc_READ(dacc)) {
switch (dacc & WIDTH_MASK) {
case BITS_8: /* read byte */
if (HostEndian!=top->read_bigend) daddr^=3;
*ddata = ((unsigned8 *)ptr)[daddr & 3];
break;
case BITS_16: { /* read half-word */
/* extract half-word */
#ifndef HOST_HAS_NO_16BIT_TYPE
/*
* unsigned16 is always a 16-bit type, but if there is no native
* 16-bit type (e.g. ARM!) then we can do something a bit more
* cunning.
*/
if (HostEndian!=top->read_bigend) daddr^=2;
*ddata = *((unsigned16 *)(((char *)ptr)+(daddr & 2)));
#else
unsigned32 datum;
datum=*ptr;
if (HostEndian!=top->read_bigend) daddr^=2;
if (daddr & 2) datum<<=16;
*ddata = (datum>>16);
#endif
}
break;
case BITS_32: /* read word */
*ddata=*ptr;
break;
case BITS_64: /* read dword */
*ddata = *ptr;
ddata[1] = ptr[1];
break;
default:
break;
}
} else {
switch (dacc & WIDTH_MASK) {
/* extract byte */
case BITS_8: /* write_byte */
if (HostEndian!=top->write_bigend) daddr^=3;
((unsigned8 *)ptr)[daddr & 3]=(unsigned8)(*ddata);
break;
case BITS_16: /* write half-word */
if (HostEndian!=top->write_bigend) daddr^=2;
*((unsigned16 *)(((char *)ptr)+(daddr & 2))) = (unsigned16)(*ddata);
break;
case BITS_32: /* write word */
*ptr=*ddata;
break;
case BITS_64: /* write 2 words */
*ptr = *ddata;
ptr[1] = ddata[1];
break;
default:
break;
}
}
}
*drv = 1;
ddone:
;
}
#ifdef PIPELINED
static void NextDCycle(void *handle, ARMword addr, ARMul_acc acc)
{
NextCycle(handle, addr, acc);
}
static void NextICycle(void *handle, ARMword addr, ARMul_acc acc)
{
NextCycle(handle, addr, acc);
}
#endif
/*
* Utility functions:
*/
static unsigned Flat_MemInfo(void *handle, unsigned type, ARMword *pID,
uint64 *data)
{
toplevel *top=(toplevel *)handle;
if (ACCESS_IS_READ(type))
{
switch (*pID) {
case MemPropertyID_TotalCycles:
*data = (top->cycles.NumNcycles + top->cycles.NumScycles +
top->cycles.NumIcycles + top->cycles.NumCcycles);
return RDIError_NoError;
case MemPropertyID_CycleSpeed:
*data = top->clk_speed;
return RDIError_NoError;
case MemPropertyID_BaseMemoryRef: /* We are a LEAF */
*(ARMul_MemInterface**)data = top->mem_ref.mif;
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;
default:
return RDIError_UnimplementedMessage;
}
}
else
{
switch (*pID) {
case MemPropertyID_BaseMemoryEnable: /* We are a LEAF */
top->BaseMemoryEnabled = (bool)*data;
return RDIError_NoError;
default:
return RDIError_UnimplementedMessage;
}
}
}
static const ARMul_Cycles *Flat_ReadCycles(void *handle)
{
toplevel *top=(toplevel *)handle;
top->cycles.Total=(top->cycles.NumNcycles + top->cycles.NumScycles +
top->cycles.NumIcycles + top->cycles.NumCcycles);
return &(top->cycles);
}
static unsigned int DataCacheBusy(void *handle)
{
UNUSEDARG(handle);
return FALSE;
}
static unsigned long Flat_GetCycleLength(void *handle)
{
/* Returns the cycle length in tenths of a nanosecond */
toplevel *top=(toplevel *)handle;
return (unsigned long)(top->clk*10000.0);
}
/* For ARMulAgent_AddPeripheral */
extern void Target_add_names(toolconf tconf);
extern void Target_add_names(toolconf tconf)
{
(void)tconf;
}
BEGIN_EXIT(Flatmem)
{
/*
* Remove the memory interface
*/
ARMword page;
toplevel *top=state;
memory *mem=&top->mem;
/* free all truly allocated pages */
for (page=0; page<NUMPAGES; page++) {
mempage *pageptr= mem->page[page];
if (pageptr) {
free((char *)pageptr);
}
}
ClxList_Destroy((ClxList*)&top->NewPageAllocated,NULL);
ARMulAgent_Destroy(&top->agent);
/* top-level structure is freed by END_EXIT macro */
}
END_EXIT(Flatmem)
/*--- <SORDI STUFF> ---*/
#define SORDI_DLL_NAME_STRING "Flatmem"
#define SORDI_DLL_DESCRIPTION_STRING "Flatmem Leaf memory model"
#define SORDI_RDI_PROCVEC Flatmem_AgentRDI
#include "perip_sordi.h"
#include "perip_rdi_agent.h"
IMPLEMENT_AGENT_PROCS_NOEXE_NOMODULE(Flatmem)
IMPLEMENT_AGENT_PROCVEC_NOEXE(Flatmem)
/*--- </> ---*/
/* EOF flatmem.c */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -