📄 armul_mem.h
字号:
#define MAH_FromLineFill MAH_Internal
#define MemAccessHit_ID_MASK 0xF0
#define MemAccessHit_ID_SHIFT 4
enum MemAccessHitID {
MAH_ID_Unknown = 0,
MAH_ID_Unified,
MAH_ID_Instr,
MAH_ID_Data
};
#define MAHID_Data (MAH_ID_Data << MemAccessHit_ID_SHIFT)
#define MAHID_Instr (MAH_ID_Instr << MemAccessHit_ID_SHIFT)
extern char const *MemAccessHit_NamesLong[MAH_ARRAY_SIZE];
extern char const *MemAccessHit_Names3[MAH_ARRAY_SIZE];
extern char const *MemAccessHit_Names1[MAH_ARRAY_SIZE];
/*
* Function to return a "time elapsed" counter in microseconds.
* If NULL, then Unix "clock()" is used.
*/
typedef ARMTime armul_ReadClock(void *handle);
/*
* Function to return a cycle count. Returns NULL if not available,
* or may be assigned to be NULL.
* On some processors cycle types may overlap (e.g. F cycles
* and I cycles overlap on cached processors, or additional wait-state
* cycles on a standard memory model). Hence there is a "total"
* field, which should be filled in as the total number of cycles on the
* model's primary clock.
*/
typedef struct {
/* This is incremented once per call to ARMflat or Mapfile. */
ARMTime Total; /* Bus-Cycles, used for ARMul_Time() */
ARMTime ac_counts[8]; /* 4..7 are non-accounted */
# define NumNcycles ac_counts[0]
# define NumScycles ac_counts[1]
# define NumIcycles ac_counts[2]
# define NumCcycles ac_counts[3]
# define COUNTCYCLES(c,acc) c.ac_counts[ (acc & 0xE0) >> 5 ]++
ARMTime ac_IWaits, ac_DWaits; /* 8,9 */
ARMTime ac_MergedIS; /* 10 */
ARMTime NumFcycles; /* Internal cycles not corrseponding to any of the above.
*/
ARMTime CoreCycles; /* #Times the core's pipeline has advanced
* as counted by ARM9/SA1's Fetch stage.*/
} ARMul_Cycles;
typedef const ARMul_Cycles *armul_ReadCycles(void *handle);
/*
* Function to return the number of core cycles in an individual memory
* access.
* On cached processors where the number of core cycles in a given memory
* cycle can vary this function is used to keep track of the number
* of core cycles required before the next external memory access.
*/
typedef unsigned long armul_ReadDeltaCycles(void *handle);
typedef unsigned long armul_MultiLayerReadDeltaCycles(void *handle, unsigned int layer);
/* For Multi-Layer AHB systems the following function is used to
* register a layer. The value returned should be used when the
* layer is accessed via other Multi-Layer access functions.
* The hint parameter can be used by a memory model for labeling
* purposes.
*/
typedef unsigned int armul_MultiLayerRegister(void *handle, tag_t hint);
/*
* For synchronous memory interfaces, this function returns the duration
* of a cycle, in tenths of a nanosecond. All calls to "MemAccess" are
* assumed to take this long by the caller. To insert wait states, return
* '0' from MemAccess, or use an asynchronous memory interface (not yet
* supported)
*/
typedef unsigned long armul_GetCycleLength(void *handle);
/*
* The MemAccess functions return the number of datums read, or -1 for an abort
* (N.B. 0 signifies "wait", so a successful idle cycle returns 1)
* - MemAccess2 can return up to two words
* - MemAccAsync fills in a counter for the time til the next memory cycle
*/
typedef int armul_MemAccess(void *handle,
ARMword address,
ARMword *data,
ARMul_acc access_type);
typedef int armul_MultiLayerMemAccess(void *handle,
unsigned int layer,
ARMword address,
ARMword *data,
ARMul_acc access_type);
typedef void armul_MemBurstCount(void *handle, unsigned Count, unsigned IsWrite);
/* Used by cycle based models which include two clock
* domains - eg , core clock and bus clock - to advance
* the bus clock one cycle
*/
typedef void armul_AdvanceBus(void *handle, ARMword phase);
/* This call provides information on the next cycle type, which enables
* the ARMulator to be used in logic simulation environments where
* pipelined address are required.
* LOCK & nTRANS are provided via callbacks - these APIs are
* called a cycle in advance when a pipelined ARMulator is used.
*/
typedef void armul_NextCycle(void *handle,
ARMword address,
ARMul_acc access_type);
typedef void armul_NextDataCycle(void *handle,
ARMword address,
ARMword data,
ARMul_acc access_type);
typedef void armul_MultiLayerNext(void *handle,
unsigned int layer,
ARMword address,
ARMword *data,
ARMul_acc access_type);
/* DRS 2000-09-24 MemAccess2 only needs one data-pointer.
* This makes it the same as a normal access-fn */
typedef int armul_MemAccess2(void *,ARMword,ARMword *,ARMul_acc);
/* Used for ARMISS core calling cache. */
typedef int armul_MemAccAsync(void *handle, ARMword address, ARMword *data,
ARMul_acc acc, ARMTime *abs_time);
/* Memory access function used for true Harvard models, where both busses */
/* present the required access parameters in the same function call. */
typedef void armul_HarvardMemAccess(void *, ARMword, ARMword *, ARMul_acc, int *,
ARMword, ARMword *, ARMul_acc, int *);
/* For GASP1020E, ARMul_MemType_PipelineARM10 */
typedef void armul_HarvardMemAccess64(
void *handle,
ARMword daddr, ARMword *ddata1, ARMword *ddata2, ARMul_acc dacc, int *drv,
ARMword iaddr, ARMword *idata1, ARMword *idata2, ARMul_acc iacc, int *irv);
typedef int armul_BytelanesMemAccess(void *,ARMword *addr, ARMword *data,
ARMword *lanes,
ARMul_acc);
/*
* When the core takes an exception - e.g. an access to the vectors in a
* 26-bit mode, on a processor which supports exporting such exceptions
* (i.e. an ARM8) this function is called if supplied. penc is the priority
* encoding for the exception in question.
*/
typedef void armul_CoreException(void *handle,ARMword address,
ARMword penc);
/*
* StrongARM has a tightly coupled data-cache, where the pipeline needs
* to know if the data cache is busy. This function provides that
* functionality.
*/
typedef unsigned int armul_DataCacheBusy(void *handle);
/*
* Function to return the grant status of the AMBA bus in cycle-based
* simulation (1=granted, 0=not-granted). This only applies to pipelined
* AMBA processors and will determine whether an access proceeds or not.
*
*/
typedef unsigned long armul_ArbitrateBus(void *handle, ARMword request);
typedef unsigned long armul_MultiLayerArbitrateBus(void *handle,
unsigned int layer,
ARMword request);
/*
* Function to indicate that the previous prediction has proven to be invalid
* as a result of data returned by the current cycle. Typically used for late
* kill signals on the bus of the ARM9 integer core.
*/
typedef void armul_KillAccess(void* handle, ARMword data_addr, ARMul_acc data_acc,
ARMword instr_addr, ARMul_acc instr_acc);
typedef struct armul_meminterface_ref {
/* This points to where a memory-model's armul_meminterface has
* been installed or moved to. */
struct armul_meminterface *mif;
/* This allows a memory to tell the cache or core something. */
void *handle;
armul_InfoProc *master_info;
} ARMul_MemInterfaceRef;
/* QQQ: Why isn't armul_MemAccess *[debug_]access;
* also outside the union?
*/
struct armul_meminterface {
void *handle;
/* armul_MemAccess *debug_access; */
/*
* This allows any memory object to keep track of where its
* interface has been moved to (so long as whatever moves it
* remembers to update this link). NB Only objects which switch themselves
* in and out need to do this.
*/
struct armul_meminterface_ref *mem_link;
/*
* This allows a watcher to know what type of veneer to insert
*/
ARMul_MemType memtype;
/* This allows a client to query or inform its memory. */
armul_InfoProc *mem_info;
armul_ReadClock *read_clock;
armul_ReadCycles *read_cycles;
armul_GetCycleLength *get_cycle_length;
union {
struct {
armul_MemAccess *access;
armul_NextCycle *next;
armul_ReadDeltaCycles *delta_cycles;
/* Cycle-based models have arbitrate */
armul_ArbitrateBus *arbitrate;
} pipe;
struct {
armul_MemAccess *debug_access;
armul_CoreException *core_exception;
armul_HarvardMemAccess *harvard_access;
armul_NextDataCycle *dside_next;
armul_NextCycle *iside_next;
/* ARM10 has delta_cycles */
armul_ReadDeltaCycles *delta_cycles;
/* These ifdef's are required to avoid expanding the size of
* this structure between ADS1.1 and ADS1.2, which causes
* pain when trying to build memory-models which work in either. */
/* #ifdef PIPELINED */
/* Cycle-based models have advance_bus and kill_access*/
armul_AdvanceBus *advance_bus;
armul_KillAccess *kill_access;
/* #endif */
} pipe_arm9;
struct {
armul_MemAccess *debug_access;
armul_CoreException *core_exception;
armul_MultiLayerRegister *register_layer;
armul_MultiLayerMemAccess *current_access;
armul_MultiLayerNext *next_access;
armul_MultiLayerReadDeltaCycles *delta_cycles;
/* #ifdef PIPELINED */
/* Cycle-based models have arbitrate */
armul_MultiLayerArbitrateBus *arbitrate;
/* #endif */
} pipe_multi_layer;
struct {
armul_MemAccess *access;
} basic;
struct {
armul_MemAccess *access;
armul_CoreException *core_exception;
armul_MemAccess2 *access2;
} arm8;
struct {
armul_MemAccess *access;
armul_CoreException *core_exception;
armul_DataCacheBusy *data_cache_busy;
} strongarm;
struct {
armul_MemAccess *access;
armul_CoreException *core_exception;
armul_DataCacheBusy *data_cache_busy;
armul_BytelanesMemAccess *bytelanes_access;
} bytelanes;
struct {
armul_MemAccess *access;
armul_CoreException *core_exception;
armul_HarvardMemAccess *harvard_access;
armul_DataCacheBusy *data_cache_busy_obsolete; /* Never called */
armul_MemBurstCount *burst_count;
} arm9;
/* ARM10+XScale core->cache. */
struct {
armul_MemAccess *debug_access;
armul_MemAccAsync *i_access;
armul_MemAccAsync *d_read;
armul_MemAccAsync *d_write;
} armiss_cache;
/* This structure is the same as basic, but the access-function
* must be capable of 64-bit transfers.
* Also, ICycles will not be generated.
*/
struct {
armul_MemAccess *access;
} armiss_ahb;
struct {
armul_MemAccess *debug_access;
armul_CoreException *core_exception;
armul_HarvardMemAccess64 *harvard_access;
/* !TODO: This may need to become NextDataCycle in gasp1020E! */
armul_NextCycle *dside_next;
armul_NextCycle *iside_next;
/* ARM10 has delta_cycles */
armul_ReadDeltaCycles *delta_cycles;
/* These ifdef's are required to avoid expanding the size of
* this structure between ADS1.1 and ADS1.2, which causes
* pain when trying to build memory-models which work in either. */
/* Cycle-based models have advance_bus and kill_access*/
#if 0
armul_AdvanceBus *advance_bus;
armul_KillAccess *kill_access;
#endif
} pipe_arm10;
} x;
};
/*
* Purpose: Given an existing interface connection,
* Insert a new one, copying the old one to 'newChild'.
*
* Parameters:
* Out:
* *newChild: memory owned by the caller. This call will fill that in
* with the function pointers of the downstream memory
* (copied from *mem).
* InOut:
* *mem: memory owned by someone soon to be upstream of
* the caller. Caller will write function-pointers into
* this after this call.
* In:
* *preparedEarlier: A set of function-pointers belonging to the caller
* to be given to the upstream owner of *mem
* (copied to *mem).
* newLink: Address of 'leash' to mem
* (newLink->mif will be updated if anyone
* plugs themselves in upstream of us).
* Note that only newLink->mem_link is changed - the other
* fields of *newLink are unchanged.
* (These are expected to be a callback for newChild
* to call through.)
*/
void ARMul_InsertMemInterface(ARMul_MemInterface *mem,
ARMul_MemInterface *newChild,
ARMul_MemInterfaceRef *newLink,
ARMul_MemInterface *preparedEarlier);
/* This is like the above, but also swaps the upwards ("master") memory-info
* callbacks at *newLink and *mem->mem_link.
*/
void ARMul_InsertMemInterface2(ARMul_MemInterface *mem,
ARMul_MemInterface *newChild,
ARMul_MemInterfaceRef *newLink,
ARMul_MemInterface *preparedEarlier);
/*
* This is called by the owner of the function-pointers,
* rather than the owner of the memory where they currently
* reside.
* Parameters:
* memref: Address of pointer to set of function-pointers the
* caller owns.
* child: Address of downstream set of function-pointers.
* NB: If the function-pointers at *memref are not saved, they are lost.
*/
void ARMul_RemoveMemInterface(ARMul_MemInterfaceRef *memref,
ARMul_MemInterface *child);
/* This is like the above, but also swaps the upwards ("master") memory-info
* callbacks at *newLink and *mem->mem_link.
*/
void ARMul_RemoveMemInterface2(ARMul_MemInterfaceRef *memref,
ARMul_MemInterface *child);
void ARMul_SwapMasterInfo(ARMul_MemInterfaceRef *my_ref,
ARMul_MemInterfaceRef *child_ref);
#if defined(__cplusplus) && !defined(CLX_CPP_LINKAGE)
}
#endif
#endif /* armul_mem__h */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -