cpu_state.h
10.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
/*
* Copyright (C) 1996-1998 by the Board of Trustees
* of Leland Stanford Junior University.
*
* This file is part of the SimOS distribution.
* See LICENSE file for terms of the license.
*
*/
/*****************************************************************
* cpu_state.h
*
* Complete state of a PE... this structure is to be used by all cpu
* simulators so that switching between them is simple.
*
* Author: $Author: blythe $
* Date: $Date: 2002/05/29 01:09:10 $
*****************************************************************/
#ifndef CPU_STATE_H
#define CPU_STATE_H
#include "mips_arch.h"
#include "simtypes.h"
#include "cpu_interface.h"
#define LOG_TLB_HASH_SIZE 12
#define TLB_HASH_SIZE (1<<LOG_TLB_HASH_SIZE)
#if defined(SIM_MIPS64)
#define EMBRA_USE_QC64
#define QC64_INVALID_VPN -1
#define QC64_NUM_ENTRIES 4096
#define QC64_READ 0
#define QC64_WRITE 2
#endif
#ifndef _LANGUAGE_ASSEMBLY
#if defined(SIM_MIPS64)
typedef struct {
VA vpn;
MA ma;
uint writable;
} QC64HashEntry;
#endif
#include "list.h"
typedef enum BranchStatus {
BranchStatus_none,
BranchStatus_nottaken,
BranchStatus_taken,
BranchStatus_bd} BranchStatus;
/* Used for TLB hashing */
typedef struct {
List_Links links;
short index;
short onList;
} IndexListLink;
typedef List_Links IndexHeaders[TLB_HASH_SIZE];
typedef union {
int fgrInt[2];
float fgr[2];
double fpr;
uint64 fgrLL;
} FPReg;
typedef struct CPUState {
Reg R[NUM_GP_REGS];
Reg FPR[NUM_FP_REGS];
Reg32 FCR[NUM_FC_REGS];
Reg CP0[NUM_CP0_REGS];
Reg PC; /* Current Program Counter */
Reg HI;
Reg LO;
/**** EMBRA Specific ****/
volatile int cycleCountdown; /* Used to optimize interventions & timing */
volatile int blockCycleCountdown; /* cycleCountdown at end of block */
int timeQuantum; /* Interleave procs in MPinUP by this amt */
/* These are memory areas to save certain embra registers */
/* We restore all of them (because we want to return to the TC from */
/* any point in C code which could have trashed our values), but we */
/* only store a couple (like the clock and cache hit counts) on callout */
#ifdef EMBRA_USE_QC64
QC64HashEntry *mmu; /* 64bit MMU hash table */
#else
MA *mmu; /* MMU relocation array */
#endif
PLN* cache_tag; /* Embra cache tags */
uint Sdhit_count;
uint Sihit_count;
/* This is the original stack pointer. We restore this as a crude, */
/* but effective way of unwinding the stack when C code calls back */
/* into the TC */
uint Sstack_base;
uint Ssreg2;
uint Sorig_stack;
int myNum; /* Processor number */
struct CPUState *next; /* Fast processor switch (really CPUState*)*/
Reg oldPC; /* Used to make chaining decisions */
uint jumpPC; /* Translation cache address of last jump */
SimTime *eventQueueTimePtr; /* Addr of event Q time */
/* XXX - Achtung. DONT put an odd number of 4 byte fields above */
/* this value because then its not 8 byte aligned and the compiler */
/* alignment invalidates my assembly offsets down below */
uint64 cycleCount;/* Total number of cycles executed */
uint qcra; /* Save ra here for outlined QC */
uint stalled; /* Boolean, are we stalled? */
char* cache_ax; /* Base for a Physarray or qc_v access */
int _pad0; /* Allow LLC to start on dbl word allignment */
Reg LLContents; /* Embra: Contents of location of last
LL */
Reg hackedSavedVaddr; /* Embra: used in 64bit hacked MMU lookup */
PA LLAddr; /* Memory Address address of last LL */
int LLBit; /* Set when an LL has been issued */
bool fpLoaded; /* Embra: is FP reg file loaded? */
volatile int outTC; /* Embra: Used to optimize interventions */
#ifdef EMBRA_USE_QC64
QC64HashEntry *kernelMMU;
QC64HashEntry *userMMU;
VA *QC64TLBBackMap;
#else
MA *kernelMMU; /* Embra: starting addresses of the mmus */
MA *userMMU;
#endif
Reg nPC;
int myBit; /* Processor number in bitmask format */
int outOfSlaveLoop; /* Damn slave loop */
struct CPUState *prev; /* Complement to next */
bool clockStarted;
uint clockInterval;
int *intrBitsPtr;
uint cp0savearea[5]; /* Base mode stores the kregs here */
uint clockTimeLeft;
uint memSize; /* Size of main memory in bytes */
char *memoryPtr; /* Main memory array */
TLBEntry tlbEntry[MAX_NTLBENTRIES]; /* All of the CPU's TLB entries */
IndexListLink indexList[MAX_NTLBENTRIES]; /* Hash table for TLB */
IndexHeaders tlbIndexHeaders; /* Hash table for TLB */
char* pa_p; /* Base of physarray */
char* qc_v; /* Base of virt quick check */
uint* qc_p; /* XXX - really phys_info_t* */
/*************************
* MIPSY ADDITIONS *
*************************/
SimTime timerCycleCount; /* Used for the R4000 timer counter */
CPUStatus cpuStatus;
Inst stalledInst;
BranchStatus branchStatus; /* Used to keep main loop clean... if this stuff */
VA branchTarget; /* isn't set, you just move PC forward by 4 */
bool takeInterrupt; /* Take interrupt when cache stall completes */
/*
* We speed up ICache references by caching the last line.
*/
PA cachedILine; /* Cache of current Icache line - quick check */
byte *cachedILineData;
uint cachedSetIndex;
/*
* We speed up all references by caching the last translation.
*/
uint pcVPNcache; /* Cache of last PC translation VPN */
PA pcPaddrcache; /* Cache of last PC translation PPN */
int LLbit; /* True if an LL instruction is active. */
uint cpuMode; /* Mode of the CPU - KERNEL or USER or IDLE */
int numTlbEntries; /* Number of TLB entries */
unsigned char tlbEntrySize[MAX_NTLBENTRIES]; /* Size index of TLB entry */
/**********************************
* Parameters for supporting SOLO *
**********************************/
/* Flag to charge stall time to barrier rather than to the locks from which
the barrier is constructed */
uint inBarrier;
/* need the next two variables to track the return status from the
solo emulation of system calls. syscallResult will probably have
to become an union eventually */
int syscallResult;
int syscallStatus;
FPReg fpReg[32];
int is32bitMode; /* true in running in 32bit mode */
int notFRbit; /* inverse of the FR bit in the status reg -
* tell us if we have 32 or 16 FP regs. */
/**********************************
* Parameters for supporting MXS. *
**********************************/
struct s_cpu_state *st; /* MXS CPU state */
int inMXS; /* TRUE if we should use MXS otherwise MIPSY does the work */
int switchToMXS; /* Should we switch to MXS */
int switchToMIPSY; /* Should we switch to MIPSY */
#define MAX_NUM_EXCEPTIONS 128 /* This needs to be bigger than the IWIN */
int lastException;
struct { /* LAST exception buffer */
Reg32 cause;
Reg vec;
Reg badaddr;
Reg hireg;
Reg ctxtreg;
Reg xctxtreg;
} exception[MAX_NUM_EXCEPTIONS];
} CPUState;
/* Macros used by both mipsy and embra */
#define SET_CPU_MODE(_proc, _mode) ((_proc)->cpuMode = (_mode))
#define CURRENT_MODE(_proc) ((_proc)->cpuMode)
#define IS_KERNEL_MODE(_proc) ((_proc)->cpuMode == KERNEL_MODE)
#define IS_USER_MODE(_proc) ((_proc)->cpuMode == USER_MODE)
#define IS_SUPERV_MODE(_proc) ((_proc)->cpuMode == SUPERVISOR_MODE)
#define SET_CPU_STATUS(_cpuNum, _status) (pePtr[_cpuNum]->cpuStatus = _status)
/* Routines for supporting MXS. */
extern bool InterruptIsPending(struct s_cpu_state *st);
extern void HandleException(struct s_cpu_state *st, int exnum, int in_delay);
extern void PrintException(struct s_cpu_state *st, int exnum);
extern int GetLastException(struct s_cpu_state *st);
extern bool DoPrivInst(struct s_cpu_state *st, uint instr,
uint srcreg, uint *dstreg, bool *hack);
extern int DoUncachedRead(struct s_cpu_state *st, uint vAddr, uint pAddr,
int size,void *dataPtr);
extern int DoUncachedWrite(struct s_cpu_state *st, uint vAddr, uint pAddr,
int size, int accel, void *dataPtr);
extern int FPusable(struct s_cpu_state *st);
extern void CopyFromMXS(CPUState *P);
extern void CopyToMXS(CPUState *P);
extern void RecordMxsMemsysStall(struct s_cpu_state *st, SimTime stallTime);
#endif /* _LANGUAGE_ASSEMBLY */
#define _INT_SIZE 4
#define _PTR_SIZE 4
#define GP_OFF (0 * REG_SIZE)
#define FP_OFF (NUM_GP_REGS * REG_SIZE)
#define FCR_OFF (FP_OFF + (NUM_FP_REGS * REG_SIZE))
#define CP0_OFF (FCR_OFF + (NUM_FC_REGS * _INT_SIZE))
#define PC_OFF (CP0_OFF + (NUM_CP0_REGS * REG_SIZE))
#define HI_OFF (PC_OFF + REG_SIZE)
#define LO_OFF (HI_OFF + REG_SIZE)
#define CCD_OFF (LO_OFF + REG_SIZE)
#define BCCD_OFF (CCD_OFF + _INT_SIZE)
#define TQ_OFF (BCCD_OFF + _INT_SIZE)
#define MMU_OFF (TQ_OFF + _INT_SIZE)
#define CACHE_OFF (MMU_OFF + _PTR_SIZE)
#define SDHIT_OFF (CACHE_OFF + _PTR_SIZE)
#define SIHIT_OFF (SDHIT_OFF + _INT_SIZE)
#define SSTACK_OFF (SIHIT_OFF + _INT_SIZE)
#define SSREG2_OFF (SSTACK_OFF + _INT_SIZE)
#define SORIGSTACK_OFF (SSREG2_OFF + _INT_SIZE)
#define MYNUM_OFF (SORIGSTACK_OFF + _PTR_SIZE)
#define NEXT_OFF (MYNUM_OFF + _INT_SIZE)
#define OLDPC_OFF (NEXT_OFF + _PTR_SIZE)
#define JUMPPC_OFF (OLDPC_OFF + REG_SIZE)
#define CALL_OFF (JUMPPC_OFF + _INT_SIZE)
#define HICC_OFF (CALL_OFF + _INT_SIZE)
#define LOCC_OFF (HICC_OFF + _INT_SIZE)
#define QCRA_OFF (LOCC_OFF + _INT_SIZE)
#define STALLED_OFF (QCRA_OFF + _INT_SIZE)
#define CACHE_AX_OFF (STALLED_OFF + _INT_SIZE)
#define LLCONTENTS_OFF (CACHE_AX_OFF + _PTR_SIZE+_INT_SIZE)
#define HACKADDR_OFF (LLCONTENTS_OFF + REG_SIZE)
#define LLADDR_OFF (HACKADDR_OFF + REG_SIZE)
#define LLBIT_OFF (LLADDR_OFF + PHYS_ADDR_SIZE)
#define FPLOADED_OFF (LLBIT_OFF + _INT_SIZE)
#define OUTTC_OFF (FPLOADED_OFF + _INT_SIZE)
#endif /* CPU_STATE_H */