1
0
Files
2022-09-29 17:59:04 +03:00

246 lines
7.4 KiB
C

#ifndef _sim_h_
#define _sim_h_
#include <sys/types.h>
#include <signal.h>
#include <sys/inst.h>
#include <ulocks.h>
typedef struct sigcontext SigContext_t;
typedef union mips_instruction Inst_t;
typedef __uint64_t Saddr_t;
/* Define simulated serial number */
#define SERIAL0 0x08;
#define SERIAL1 0x00;
#define SERIAL2 0xaa;
#define SERIAL3 0xbb;
#define SERIAL4 0xcc;
#define SERIAL5 0xdd;
/* Simulator modes */
enum { simExit, simSloader, simFW };
/*
* SIM interface
*
* client server
* process process
* +-------+ communication +-------+
* | | area | |
* | | +-------+ | |
* | | |shared | | |
* | | <---->| memory|<----> | |
* | | | | | |
* | | | | | |
* | | +-------+ | |
* | | | |
* | | | |
* | | | |
* +-------+ +-------+
*
*
* When the client code attempts to reference a simulated I/O space register
* it traps. Using the SIM interface, the trap code simulates the reference
* and execution continues. A coprocessor operation generates an illegal
* instruction trap and is similarly simulated. Also, some illegal
* instructions (mips3) are simulated.
*
* Some simulations are simple and are performed directly in the client
* code. Others are more complex and are forwarded to the server process.
* The shared memory communication area is used to pass information between
* the client and the server process.
*/
#define SIM_ARENA_ADDR 0x1000000
#define SIM_ARENA_FILE "SIMARENA"
#define SIM_SERVER "simServer"
typedef struct __sam_ SimAddrMap_t;
/*
* Note that we are not using the sys/sbd.h memory macros here
*/
#define TO_PHYSICAL(x) ((x)&0x1FFFFFFF)
/*
* Address match structure
*
* When an address faults, it is looked up using simMatchAddr(). If found,
* an index into the address match table is returned. The address match
* table itself is located via the SimControl_t structure.
*
* Depending on the match code, the client code either directly handles the
* trap or forwards it to the server process.
*
* Note that mask<ADDR_MATCH_STORE> and target<ADDR_MATCH_STORE> are
* "store" bits. That is, if the reference is a store to memory, this bit
* is set in target and masked by the corresponding bit in mask.
*
* A target "matches" an entry in the match table if:
*
* s = isStore(inst) ? 1 : 0;
* t = TO_PHYSICAL(addr) | ADDR_MATCH_STORE;
* match = (t & mask) == target;
*
* Note that because of the "store" bit, it is possible for the match
* table to contain two separate entries for an address, one for reads
* and one for writes.
*/
typedef struct{
__uint64_t mask; /* Mask used in matching */
__uint64_t target; /* Address match target */
int matchCode; /* Match code - interpreted by client */
int targetCode; /* Target code - interpreted by server */
SimAddrMap_t* mapping; /* Used to map references */
} SimAddrMatch_t;
#define ADDR_MATCH_STORE ((long long)1<<40)
int simMatchAddr(Saddr_t addr, int load);
/*
* Address mapping structure
*
* This structure is used by client and server code alike to map addresses
* from simulated I/O space to representation of I/O registers.
*
* Given a physical address in simulated space, it is remapped to the
* effective address of a representation by the following:
*
* eaddr = base + ((physAddr & mask)>>shift)*stride;
*
* NOTE: The "ignoreIfZero" is a hack. For now it makes it easy to silently
* discard transactions under the control of some "disable". For
* example, write control logic on the flash. If ignoreIfZero is
* itself zero, the transaction is always executed.
*/
struct __sam_{
char* base; /* Points to base of concrete "registers" */
int stride; /* Stride of "register" vector */
__uint64_t mask;
int shift;
long* ignoreIfZero;
};
/*
* Cop0 match structure
*
* Similar to the Address match structure except entries correspond to
* coprocessor registers, not memory addresses.
*
* Note that mask<COP0_MATCH_STORE> and target<COP0_MATCH_STORE> are
* "store" bits. That is, if the reference is a store to a coprocessor
* registers, this bit is set in the target and masked by the corresponding
* bit in mask.
*
* A target register "matches" an entry in the match table if:
*
* s = isStore(inst) ? 1 : 0;
* t = reg | COP0_MATCH_STORE;
* match = (t & mask) == target;
*
* Note that because of the "store" bit, it is possible for the match
* table to contain two separate entries for an address, one for reads
* and one for writes.
*/
typedef struct{
int mask; /* Mask used in matching */
int target; /* Register match target */
int matchCode; /* Match code -- interpreted by client */
int targetCode; /* Target code -- Interpreted by server */
} SimCop0Match_t;
#define COP0_MATCH_STORE (1<<6)
int simMatchCop0(int reg, int load);
/*
* Matchcode definitions
*
* The match codes returned in the SimAddrMatch_t and SimCop0Match_t
* structures specify what actions the clien code is to perform.
*/
enum{
SIM_nomatch, /* No match */
SIM_abort, /* Abort simulation */
SIM_loadStore, /* simLoadStore() [r/w]*/
SIM_fwd_loadStore, /* simForward();simLoadStore() [r] */
SIM_loadStore_fwd, /* simLoadStore();simForward() [w] */
SIM_cop0, /* simCop0() */
SIM_fwd_Cop0 /* simForwardCop0() */
};
/*
* simulation communication area
*
* The communication area is a shared memory area. The client code
* attaches to this area with clSimInit(). The server attaches to
* this area with svrSimInit().
*
* This area contains a control structure (accessed via usgetinfo())
* that points to other structures in the shared memory area.
*
* NOTE: For now, we assume that the communication area gets mapped at the
* same virtual address in both the client and the server. This doesn't
* really have to be the case but it's easier to do so.
*/
typedef struct{
SigContext_t* clSigCtx; /* Copy of client signal context. */
SimAddrMatch_t* addrTbl; /* Address of addr match table */
SimCop0Match_t* cop0Tbl; /* Address of cop0 match table */
long long* cop0Regs; /* Address of cop0 registers */
int matchIndex; /* Last match index */
int matchCode; /* Last match code*/
usema_t* sendSema; /* Client "sends" to server */
Inst_t inst; /* Trapping client instruction */
Saddr_t paddr; /* Trapping client physical addr */
usema_t* recvSema; /* Client "receives" from server */
int refs; /* Number of references */
pid_t clientPid; /* PID of client */
} SimControl_t;
extern SimControl_t* simControl;
/* Sim objects may access the shared memory arena using "arena" as handle */
extern usptr_t* arena;
int clSimInit(int,char**);
int svrSimInit(int,char**);
/* Define table sizes for communication area */
#define ADDR_TBL_SIZE 256
#define COP0_TBL_SIZE 64
/*
* Service functions
*/
void simLoadStore(Inst_t, SigContext_t*, Saddr_t, int);
void simCop0(SimCop0Match_t*);
void simForward(Inst_t, Saddr_t);
void simForwardCop0();
void simMessage(char*);
int simIsStore(Inst_t);
/*
* sim_assert is for client code.
*/
#define sim_assert(e) ((e)?((void)0):simAssert(#e, __FILE__, __LINE__))
void simAssert(char*, char*, int);
#endif