URL
https://opencores.org/ocsvn/or1k_old/or1k_old/trunk
Subversion Repositories or1k_old
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 1385 to Rev 1386
- ↔ Reverse comparison
Rev 1385 → Rev 1386
/trunk/or1ksim/cpu/or32/execute.c
64,15 → 64,11
int multissue[20]; |
int issued_per_cycle = 4; |
|
/* Whether break was hit - so we can step over a break */ |
static int break_just_hit = 0; |
|
/* Completition queue */ |
struct iqueue_entry icomplet[20]; |
|
/* Program counter (and translated PC) */ |
oraddr_t pc; |
oraddr_t pc_phy; |
|
/* Previous program counter */ |
oraddr_t pcprev = 0; |
86,9 → 82,6
/* CCR */ |
int flag; |
|
/* CCR (for dependency calculation) */ |
char ccr_flag[10] = "flag"; |
|
/* Store buffer analysis - stores are accumulated and commited when IO is idle */ |
static int sbuf_head = 0, sbuf_tail = 0, sbuf_count = 0; |
static int sbuf_buf[MAX_SBUF_LEN] = {0}; |
287,32 → 280,28
/* Fetch returns nonzero if instruction should NOT be executed. */ |
static inline int fetch() |
{ |
/* Update the pc for pending exceptions, or get physical pc */ |
if (!pending.valid) |
pc_phy = immu_translate(pc); |
static int break_just_hit = 0; |
|
if(pending.valid) |
except_handle_backend(pending.type, pending.address, pending.saved); |
|
if (CHECK_BREAKPOINTS) { |
/* MM: Check for breakpoint. This has to be done in fetch cycle, |
because of peripheria. |
MM1709: if we cannot access the memory entry, we could not set the |
breakpoint earlier, so just chech the breakpoint list. */ |
if (has_breakpoint (pc_phy) && !break_just_hit) { |
breakpoint earlier, so just check the breakpoint list. */ |
if (has_breakpoint (peek_into_itlb (pc)) && !break_just_hit) { |
break_just_hit = 1; |
return 1; /* Breakpoint set. */ |
} |
break_just_hit = 0; |
} |
pc_phy &= ~ADDR_C(0x3); |
|
runtime.cpu.instructions++; |
|
breakpoint = 0; |
/* Fetch instruction. */ |
iqueue[0].insn_addr = pc; |
iqueue[0].insn = eval_insn (pc_phy, &breakpoint); |
iqueue[0].insn = eval_insn (pc, &breakpoint); |
|
if (!except_pending) |
runtime.cpu.instructions++; |
|
/* update_pc will be called after execution */ |
|
return 0; |
593,15 → 582,11
static inline void decode_execute_wrapper (struct iqueue_entry *current) |
{ |
breakpoint = 0; |
next_delay_insn = 0; |
|
#ifndef HAS_EXECUTION |
#error HAS_EXECUTION has to be defined in order to execute programs. |
#endif |
|
if(config.debug.enabled && CheckDebugUnit(DebugInstructionFetch, pc_phy)) |
breakpoint = 1; |
|
decode_execute (current); |
|
#if SET_OV_FLAG |
665,22 → 650,39
pcnext = 0x0; /* MM1409: All programs should start at reset vector entry! */ |
if (config.sim.verbose) PRINTF ("Starting at 0x%"PRIxADDR"\n", pcnext); |
pc = pcnext; |
pc_phy = pc; |
pcnext += 4; |
debug(1, "reset ...\n"); |
|
/* MM1409: All programs should set their stack pointer! */ |
except_handle(EXCEPT_RESET, 0); |
update_pc(); |
except_pending = 0; |
} |
|
/* Simulates one CPU clock cycle */ |
inline int cpu_clock () |
{ |
except_pending = 0; |
next_delay_insn = 0; |
if(fetch()) { |
PRINTF ("Breakpoint hit.\n"); |
runtime.sim.cont_run = 0; /* memory breakpoint encountered */ |
return 1; |
} |
|
if(except_pending) { |
update_pc(); |
except_pending = 0; |
return 0; |
} |
|
if(breakpoint) { |
except_handle(EXCEPT_TRAP, mfspr(SPR_EEAR_BASE)); |
update_pc(); |
except_pending = 0; |
return 0; |
} |
|
decode_execute_wrapper (&iqueue[0]); |
update_pc(); |
return 0; |
/trunk/or1ksim/cpu/or32/insnset.c
97,7 → 97,7
if (config.cpu.sbuf_len) sbuf_load (); |
val = eval_mem32(PARAM1, &breakpoint); |
/* If eval operand produced exception don't set anything */ |
if (!pending.valid) |
if (!except_pending) |
SET_PARAM0(val); |
} |
INSTRUCTION (l_lbs) { |
105,7 → 105,7
if (config.cpu.sbuf_len) sbuf_load (); |
val = eval_mem8(PARAM1, &breakpoint); |
/* If eval opreand produced exception don't set anything */ |
if (!pending.valid) |
if (!except_pending) |
SET_PARAM0(val); |
} |
INSTRUCTION (l_lbz) { |
113,7 → 113,7
if (config.cpu.sbuf_len) sbuf_load (); |
val = eval_mem8(PARAM1, &breakpoint); |
/* If eval opreand produced exception don't set anything */ |
if (!pending.valid) |
if (!except_pending) |
SET_PARAM0(val); |
} |
INSTRUCTION (l_lhs) { |
121,7 → 121,7
if (config.cpu.sbuf_len) sbuf_load (); |
val = eval_mem16(PARAM1, &breakpoint); |
/* If eval opreand produced exception don't set anything */ |
if (!pending.valid) |
if (!except_pending) |
SET_PARAM0(val); |
} |
INSTRUCTION (l_lhz) { |
129,7 → 129,7
if (config.cpu.sbuf_len) sbuf_load (); |
val = eval_mem16(PARAM1, &breakpoint); |
/* If eval opreand produced exception don't set anything */ |
if (!pending.valid) |
if (!except_pending) |
SET_PARAM0(val); |
} |
INSTRUCTION (l_movhi) { |
/trunk/or1ksim/cpu/common/abstract.c
349,10 → 349,9
memaddr); |
except_handle(EXCEPT_BUSERR, cur_vadd); |
temp = 0; |
} |
} else if (cur_area->log) |
fprintf (cur_area->log, "[%"PRIxADDR"] -> read %08"PRIx32"\n", memaddr, temp); |
|
if (!pending.valid && cur_area->log) |
fprintf (cur_area->log, "[%"PRIxADDR"] -> read %08"PRIx32"\n", memaddr, temp); |
if (config.debug.enabled) |
*breakpoint += CheckDebugUnit(DebugLoadData,temp); /* MM170901 */ |
return temp; |
380,7 → 379,7
cur_vadd = memaddr; |
|
memaddr = dmmu_translate(memaddr, 0); |
if (pending.valid) |
if (except_pending) |
return 0; |
|
if (config.dc.enabled) |
439,7 → 438,7
* |
* STATISTICS OK (only used for cpu_access, that is architectural access) |
*/ |
uint32_t eval_insn(oraddr_t memaddr,int* breakpoint) |
uint32_t eval_insn(oraddr_t memaddr, int* breakpoint) |
{ |
uint32_t temp; |
|
446,15 → 445,17
if (config.sim.mprofile) |
mprofile (memaddr, MPROF_32 | MPROF_FETCH); |
// memaddr = simulate_ic_mmu_fetch(memaddr); |
cur_vadd = pc; |
|
// I think this does not belong into eval_insn() 2004-01-30 HP |
// if (config.debug.enabled) |
// *breakpoint += CheckDebugUnit(DebugLoadAddress,memaddr); /* 28/05/01 CZ */ |
cur_vadd = memaddr; |
|
// We could place the CheckDebugUnit(DebugInstructionFetch) here, but it is currently done |
// in decode_execute_wrapper, so I leave it like this. 2004-01-30 HP |
|
memaddr = immu_translate(memaddr); |
|
if (except_pending) |
return 0; |
|
if (config.debug.enabled) |
*breakpoint += CheckDebugUnit(DebugLoadAddress,memaddr); |
|
if (config.ic.enabled) |
temp = ic_simulate_fetch(memaddr); |
else { |
467,9 → 468,8
} |
} |
|
// I think this does not belong into eval_insn() 2004-01-30 HP |
// if (config.debug.enabled) |
// *breakpoint += CheckDebugUnit(DebugLoadData,temp); /* MM170901 */ |
if (config.debug.enabled) |
*breakpoint += CheckDebugUnit(DebugLoadData,temp); |
return temp; |
} |
|
495,11 → 495,11
cur_vadd = memaddr; |
|
memaddr = dmmu_translate(memaddr, 0); |
if (pending.valid) |
if (except_pending) |
return 0; |
|
if (config.dc.enabled) |
temp = (unsigned short)dc_simulate_read(memaddr, 2); |
temp = (uint16_t)dc_simulate_read(memaddr, 2); |
else { |
temp = evalsim_mem16(memaddr); |
if (!cur_area) { |
567,11 → 567,11
cur_vadd = memaddr; |
|
memaddr = dmmu_translate(memaddr, 0); |
if (pending.valid) |
if (except_pending) |
return 0; |
|
if (config.dc.enabled) |
temp = (unsigned char)dc_simulate_read(memaddr, 1); |
temp = (uint8_t)dc_simulate_read(memaddr, 1); |
else { |
temp = evalsim_mem8(memaddr); |
if (!cur_area) { |
774,7 → 774,7
cur_vadd = memaddr; |
memaddr = dmmu_translate(memaddr, 1);; |
/* If we produced exception don't set anything */ |
if (pending.valid) |
if (except_pending) |
return; |
|
if (config.debug.enabled) { |
838,7 → 838,7
cur_vadd = memaddr; |
memaddr = dmmu_translate(memaddr, 1);; |
/* If we produced exception don't set anything */ |
if (pending.valid) |
if (except_pending) |
return; |
|
if (config.debug.enabled) { |
895,7 → 895,7
cur_vadd = memaddr; |
memaddr = dmmu_translate(memaddr, 1);; |
/* If we produced exception don't set anything */ |
if (pending.valid) return; |
if (except_pending) return; |
|
if (config.debug.enabled) { |
*breakpoint += CheckDebugUnit(DebugStoreAddress,memaddr); /* 28/05/01 CZ */ |
902,7 → 902,7
*breakpoint += CheckDebugUnit(DebugStoreData,value); |
} |
|
dc_simulate_write(memaddr, (unsigned long)value, 1); |
dc_simulate_write(memaddr, value, 1); |
|
if (cur_area && cur_area->log) |
fprintf (cur_area->log, "[%"PRIxADDR"] -> write %02"PRIx8"\n", memaddr, |
/trunk/or1ksim/cpu/or1k/sprs.c
68,8 → 68,6
{ |
extern int delay_insn; |
|
clear_pending_exception (); |
|
/* The debugger has redirected us to a new address */ |
/* This is usually done to reissue an instruction |
which just caused a breakpoint exception. */ |
/trunk/or1ksim/cpu/or1k/except.c
36,80 → 36,84
#include "debug_unit.h" |
#include "execute.h" |
|
extern int cont_run; |
extern struct iqueue_entry iqueue[20]; |
extern unsigned long pc_phy; |
extern struct iqueue_entry iqueue[]; |
|
extern int delay_insn; |
extern oraddr_t pcprev; |
extern oraddr_t pcdelay; |
|
struct _pending pending; |
int except_pending = 0; |
|
/* Discards all pending exceptions */ |
void clear_pending_exception() |
static const char *except_names[] = { |
NULL, |
"Reset", |
"Bus Error", |
"Data Page Fault", |
"Insn Page Fault", |
"Tick timer", |
"Alignment", |
"Illegal instruction", |
"Interrupt", |
"Data TLB Miss", |
"Insn TLB Miss", |
"Range", |
"System Call", |
"Trap" }; |
|
static const char *except_name(oraddr_t except) |
{ |
pending.valid = 0; |
pending.type = 0; |
pending.address = 0; |
pending.saved = 0; |
return except_names[except >> 8]; |
} |
|
/* Asserts OR1K exception. */ |
void except_handle(oraddr_t except, oraddr_t ea) |
{ |
if(debug_ignore_exception (except)) { |
clear_pending_exception (); |
} else { |
pending.valid = 1; |
pending.type = except; |
pending.address = ea; |
if (delay_insn) |
pending.saved = pc - 4; |
else |
pending.saved = pc; |
if (config.sim.verbose) |
PRINTF("Exception 0x%"PRIxADDR" (%s) at 0x%"PRIxADDR", EA: 0x%"PRIxADDR |
", ppc: 0x%"PRIxADDR", npc: 0x%"PRIxADDR", cycles %lld, #%lld\n", |
except, EXCEPT_NAME(except), iqueue[0].insn_addr, ea, pc, pcnext, |
runtime.sim.cycles, runtime.cpu.instructions); |
} |
} |
if(debug_ignore_exception (except)) |
return; |
|
/* Actually handles exception */ |
void except_handle_backend (oraddr_t except, oraddr_t ea, oraddr_t pc_saved) |
{ |
#if ONLY_VIRTUAL_MACHINE |
fprintf(stderr, "WARNING: No exception processing while ONLY_VIRTUAL_MACHINE is defined.\n"); |
cont_run = 0; |
#else |
except_pending = 1; |
|
if (delay_insn) { |
if (config.sim.verbose) PRINTF("INFO: Exception during execution of delay slot insn.\n"); |
pc -= 4; |
if (config.sim.verbose) |
PRINTF("Exception 0x%"PRIxADDR" (%s) at 0x%"PRIxADDR", EA: 0x%"PRIxADDR |
", ppc: 0x%"PRIxADDR", npc: 0x%"PRIxADDR", dpc: 0x%"PRIxADDR |
", cycles %lld, #%lld\n", |
except, except_name(except), pcprev, ea, pc, pcnext, pcdelay, |
runtime.sim.cycles, runtime.cpu.instructions); |
|
pcnext = except + (testsprbits (SPR_SR, SPR_SR_EPH) ? 0xf0000000 : 0x00000000); |
|
switch(except) { |
/* EPCR is irrelevent */ |
case EXCEPT_RESET: |
break; |
/* EPCR is loaded with address of instruction that caused the exception */ |
/* All these exceptions happen during a simulated instruction */ |
case EXCEPT_BUSERR: |
case EXCEPT_DPF: |
case EXCEPT_IPF: |
case EXCEPT_ALIGN: |
case EXCEPT_ILLEGAL: |
case EXCEPT_DTLBMISS: |
case EXCEPT_ITLBMISS: |
case EXCEPT_RANGE: |
case EXCEPT_TRAP: |
mtspr(SPR_EPCR_BASE, pc - (delay_insn ? 4 : 0)); |
break; |
/* EPCR is loaded with address of next not-yet-executed instruction */ |
case EXCEPT_SYSCALL: |
mtspr(SPR_EPCR_BASE, (pc + 4) - (delay_insn ? 4 : 0)); |
break; |
/* These exceptions happen AFTER (or before) an instruction has been |
* simulated, therefore the pc already points to the *next* instruction */ |
case EXCEPT_TICK: |
case EXCEPT_INT: |
mtspr(SPR_EPCR_BASE, pc - (delay_insn ? 4 : 0)); |
/* If we don't update the pc now, then it will only happen *after* the next |
* instruction (There would be serious problems if the next instruction just |
* happens to be a branch), when it should happen NOW. */ |
pc = pcnext; |
pcnext += 4; |
break; |
} |
|
pc_saved = pc & ~ADDR_C(0x3); |
if (except == EXCEPT_ILLEGAL) |
mtspr(SPR_EPCR_BASE, pending.saved); |
else if (except == EXCEPT_ALIGN) |
mtspr(SPR_EPCR_BASE, pending.saved); |
else if (except == EXCEPT_DTLBMISS) |
mtspr(SPR_EPCR_BASE, pending.saved); |
else if (except == EXCEPT_DPF) |
mtspr(SPR_EPCR_BASE, pending.saved); |
else if (except == EXCEPT_BUSERR) |
mtspr(SPR_EPCR_BASE, pending.saved); |
else if (except == EXCEPT_TRAP) |
mtspr(SPR_EPCR_BASE, pending.saved); |
else if (except == EXCEPT_RANGE) |
mtspr(SPR_EPCR_BASE, pending.saved); |
else if (except == EXCEPT_ITLBMISS) |
mtspr(SPR_EPCR_BASE, pending.saved); |
else if (except == EXCEPT_IPF) |
mtspr(SPR_EPCR_BASE, pending.saved); |
else |
mtspr(SPR_EPCR_BASE, pc_saved); |
|
mtspr(SPR_EEAR_BASE, ea); |
mtspr(SPR_ESR_BASE, mfspr(SPR_SR)); |
|
122,30 → 126,5
mtspr(SPR_SR, mfspr(SPR_SR) | SPR_SR_SM); /* SUPV mode */ |
mtspr(SPR_SR, mfspr(SPR_SR) & ~(SPR_SR_IEE | SPR_SR_TEE)); /* Disable interrupts. */ |
|
clear_pending_exception (); |
|
pc = (unsigned long)except + (testsprbits (SPR_SR, SPR_SR_EPH) ? 0xf0000000 : 0x00000000); |
|
/* This has been removed. All exceptions (not just SYSCALL) suffer |
from the same problem. The solution is to continue just like |
the pipeline would, and issue the exception on the next |
clock cycle. We assume now that this function is being called |
->BEFORE<- the instruction fetch and after the previous update |
which always yields the correct behavior. This has the added |
advantage that a debugger can prevent an exception from |
taking place by resetting the pc. */ |
#if 0 |
/* MM: We do pc update after the execute (in the simulator), so we |
decrease it by 4 so that next instruction points to first exception |
instruction. Do NOT comment this out. */ |
if (except == EXCEPT_SYSCALL) |
pc -= 4; |
#endif |
pcnext = pc + 4; |
|
/* Added by CZ 27/05/01 */ |
pc_phy = pc; /* An exception always turns off the MMU, so |
pc is always pc_phy */ |
|
#endif /* !ONLY_VIRUAL_MACHINE */ |
delay_insn = 0; |
} |
/trunk/or1ksim/cpu/or1k/except.h
42,34 → 42,10
/* Non maskable exceptions */ |
#define IS_NME(E) ((E) == EXCEPT_RESET) |
|
#define EXCEPT_NAME(E) E == EXCEPT_RESET ? "Reset" : \ |
E == EXCEPT_BUSERR ? "Bus Error" : \ |
E == EXCEPT_DPF ? "Data Page Fault" : \ |
E == EXCEPT_IPF ? "Insn Page Fault" : \ |
E == EXCEPT_TICK ? "Tick timer" : \ |
E == EXCEPT_ALIGN ? "Alignment" : \ |
E == EXCEPT_ILLEGAL ? "Illegal instruction" : \ |
E == EXCEPT_INT ? "Interrupt" : \ |
E == EXCEPT_DTLBMISS ? "Data TLB Miss" : \ |
E == EXCEPT_ITLBMISS ? "Insn TLB Miss" : \ |
E == EXCEPT_RANGE ? "Range" : \ |
E == EXCEPT_SYSCALL ? "System Call" : \ |
E == EXCEPT_TRAP ? "Trap" : "Unknown" |
|
extern struct _pending { |
int valid; |
oraddr_t type; |
oraddr_t address; |
oraddr_t saved; |
} pending; |
|
/* Prototypes */ |
void except_handle(oraddr_t except, oraddr_t ea); |
|
/* Actually handles exception */ |
void except_handle_backend (oraddr_t except, oraddr_t ea, oraddr_t pc_saved); |
/* Has an exception been raised in this cycle ? */ |
extern int except_pending; |
|
/* Discards all pending exceptions */ |
void clear_pending_exception(); |
|
#endif |
/trunk/or1ksim/tick/tick.c
76,7 → 76,7
if (ttmr & SPR_TTMR_IE) { |
setsprbits(SPR_TTMR, SPR_TTMR_IP, 1); |
/* be sure not to issue timer exception if an exception occured before it */ |
if (((mfspr(SPR_SR) & SPR_SR_TEE) == SPR_SR_TEE) && (!pending.valid)) |
if ((mfspr(SPR_SR) & SPR_SR_TEE) == SPR_SR_TEE) |
except_handle(EXCEPT_TICK, mfspr(SPR_EEAR_BASE)); |
else |
/* If TEE is currently not set we have to pend tick exception |
/trunk/or1ksim/cache/dcache_model.c
107,9 → 107,7
dataaddr); |
except_handle(EXCEPT_BUSERR, cur_vadd); |
return 0; |
} |
|
if (!pending.valid && cur_area->log) |
} else if (cur_area->log) |
fprintf (cur_area->log, "[%"PRIxADDR"] -> read %08"PRIx32"\n", dataaddr, |
tmp); |
|
169,8 → 167,7
dataaddr); |
except_handle(EXCEPT_BUSERR, cur_vadd); |
return 0; |
} |
if (!pending.valid && cur_area->log) |
} else if (cur_area->log) |
fprintf (cur_area->log, "[%"PRIxADDR"] -> read %08"PRIx32"\n", dataaddr, |
tmp); |
} |
/trunk/or1ksim/cache/icache_model.c
94,8 → 94,7
fetchaddr); |
except_handle(EXCEPT_BUSERR, cur_vadd); |
return 0; |
} |
if (!pending.valid && cur_area->log) |
} else if (cur_area->log) |
fprintf (cur_area->log, "[%"PRIxADDR"] -> read %08"PRIx32"\n", fetchaddr, |
tmp); |
return tmp; |
144,8 → 143,7
fetchaddr); |
except_handle(EXCEPT_BUSERR, cur_vadd); |
return 0; |
} |
if (!pending.valid && cur_area->log) |
} else if (cur_area->log) |
fprintf (cur_area->log, "[%"PRIxADDR"] -> read %08"PRIx32"\n", |
fetchaddr, tmp); |
} |