Line 50... |
Line 50... |
/* Is current insn in execution a delay insn? */
|
/* Is current insn in execution a delay insn? */
|
int delay_insn;
|
int delay_insn;
|
|
|
/* Benchmark multi issue execution */
|
/* Benchmark multi issue execution */
|
int multissue[20];
|
int multissue[20];
|
int supercycles;
|
|
int issued_per_cycle = 4;
|
int issued_per_cycle = 4;
|
int hazardwait = 0;
|
|
|
|
/* Whether break was hit - so we can step over a break */
|
/* Whether break was hit - so we can step over a break */
|
static int break_just_hit = 0;
|
static int break_just_hit = 0;
|
|
|
/* freemem 'pointer' */
|
/* freemem 'pointer' */
|
Line 82... |
Line 80... |
int flag;
|
int flag;
|
|
|
/* CCR (for dependency calculation) */
|
/* CCR (for dependency calculation) */
|
char ccr_flag[10] = "flag";
|
char ccr_flag[10] = "flag";
|
|
|
/* Cycles counts fetch stages */
|
|
int cycles;
|
|
|
|
/* Each cycle has counter of mem_cycles; this value is joined with cycles
|
|
at the end of the cycle; no sim originated memory accesses should be
|
|
performed inbetween. */
|
|
int mem_cycles;
|
|
|
|
/* Instructions executed */
|
|
int instructions;
|
|
|
|
/* Load and store stalls */
|
|
int loadcycles, storecycles;
|
|
|
|
/* Store buffer analysis - stores are accumulated and commited when IO is idle */
|
/* 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_head = 0, sbuf_tail = 0, sbuf_count = 0;
|
static int sbuf_buf[MAX_SBUF_LEN] = {0};
|
static int sbuf_buf[MAX_SBUF_LEN] = {0};
|
static int sbuf_prev_cycles = 0;
|
static int sbuf_prev_cycles = 0;
|
|
|
Line 125... |
Line 109... |
{
|
{
|
if (regno < MAX_GPRS) {
|
if (regno < MAX_GPRS) {
|
return reg[regno];
|
return reg[regno];
|
} else {
|
} else {
|
printf("\nABORT: read out of registers\n");
|
printf("\nABORT: read out of registers\n");
|
cont_run = 0;
|
runtime.sim.cont_run = 0;
|
return 0;
|
return 0;
|
}
|
}
|
}
|
}
|
|
|
/* Implementation specific.
|
/* Implementation specific.
|
Line 142... |
Line 126... |
|
|
if (regno < MAX_GPRS) {
|
if (regno < MAX_GPRS) {
|
reg[regno] = value;
|
reg[regno] = value;
|
} else {
|
} else {
|
printf("\nABORT: write out of registers\n");
|
printf("\nABORT: write out of registers\n");
|
cont_run = 0;
|
runtime.sim.cont_run = 0;
|
}
|
}
|
}
|
}
|
|
|
/* Implementation specific.
|
/* Implementation specific.
|
Get an actual value of a specific register. */
|
Get an actual value of a specific register. */
|
|
|
inline static unsigned long eval_reg32(int regno)
|
inline static unsigned long eval_reg32(int regno)
|
{
|
{
|
if (regno < MAX_GPRS) {
|
if (regno < MAX_GPRS) {
|
#if RAW_RANGE_STATS
|
#if RAW_RANGE_STATS
|
int delta = (cycles - raw_stats.reg[regno]);
|
int delta = (runtime.sim.cycles - raw_stats.reg[regno]);
|
if ((unsigned long)delta < (unsigned long)MAX_RAW_RANGE)
|
if ((unsigned long)delta < (unsigned long)MAX_RAW_RANGE)
|
raw_stats.range[delta]++;
|
raw_stats.range[delta]++;
|
#endif /* RAW_RANGE */
|
#endif /* RAW_RANGE */
|
return reg[regno];
|
return reg[regno];
|
} else {
|
} else {
|
printf("\nABORT: read out of registers\n");
|
printf("\nABORT: read out of registers\n");
|
cont_run = 0;
|
runtime.sim.cont_run = 0;
|
return 0;
|
return 0;
|
}
|
}
|
}
|
}
|
|
|
/* Implementation specific.
|
/* Implementation specific.
|
Line 185... |
Line 169... |
#endif
|
#endif
|
|
|
if (regno < MAX_GPRS) {
|
if (regno < MAX_GPRS) {
|
reg[regno] = value;
|
reg[regno] = value;
|
#if RAW_RANGE_STATS
|
#if RAW_RANGE_STATS
|
raw_stats.reg[regno] = cycles;
|
raw_stats.reg[regno] = runtime.sim.cycles;
|
#endif /* RAW_RANGE */
|
#endif /* RAW_RANGE */
|
} else {
|
} else {
|
printf("\nABORT: write out of registers\n");
|
printf("\nABORT: write out of registers\n");
|
cont_run = 0;
|
runtime.sim.cont_run = 0;
|
}
|
}
|
}
|
}
|
|
|
/* Does srcoperand depend on computation of dstoperand? Return
|
/* Does srcoperand depend on computation of dstoperand? Return
|
non-zero if yes.
|
non-zero if yes.
|
Line 280... |
Line 264... |
break_just_hit = 1;
|
break_just_hit = 1;
|
return 1; /* Breakpoint set. */
|
return 1; /* Breakpoint set. */
|
}
|
}
|
break_just_hit = 0;
|
break_just_hit = 0;
|
}
|
}
|
instructions++;
|
runtime.cpu.instructions++;
|
|
|
pc_phy &= ~0x03;
|
pc_phy &= ~0x03;
|
|
|
/* Fetch instruction. */
|
/* Fetch instruction. */
|
iqueue[0].insn_addr = pc;
|
iqueue[0].insn_addr = pc;
|
Line 320... |
Line 304... |
addsstats(current->insn_index, 1);
|
addsstats(current->insn_index, 1);
|
}
|
}
|
|
|
if (config.cpu.superscalar) {
|
if (config.cpu.superscalar) {
|
if ((current->func_unit == it_branch) || (current->func_unit == it_jump))
|
if ((current->func_unit == it_branch) || (current->func_unit == it_jump))
|
storecycles += 0;
|
runtime.sim.storecycles += 0;
|
|
|
if (current->func_unit == it_store)
|
if (current->func_unit == it_store)
|
storecycles += 1;
|
runtime.sim.storecycles += 1;
|
|
|
if (current->func_unit == it_load)
|
if (current->func_unit == it_load)
|
loadcycles += 1;
|
runtime.sim.loadcycles += 1;
|
#if 0
|
#if 0
|
if ((icomplet[0].func_unit == it_load) && check_depend())
|
if ((icomplet[0].func_unit == it_load) && check_depend())
|
loadcycles++;
|
runtime.sim.loadcycles++;
|
#endif
|
#endif
|
|
|
/* Pseudo multiple issue benchmark */
|
/* Pseudo multiple issue benchmark */
|
if ((multissue[current->func_unit] < 1) || (check_depend())
|
if ((multissue[current->func_unit] < 1) || (check_depend())
|
|| (issued_per_cycle < 1)) {
|
|| (issued_per_cycle < 1)) {
|
int i;
|
int i;
|
for (i = 0; i < 20; i++)
|
for (i = 0; i < 20; i++)
|
multissue[i] = 2;
|
multissue[i] = 2;
|
issued_per_cycle = 2;
|
issued_per_cycle = 2;
|
supercycles++;
|
runtime.cpu.supercycles++;
|
if (check_depend())
|
if (check_depend())
|
hazardwait++;
|
runtime.cpu.hazardwait++;
|
multissue[it_unknown] = 2;
|
multissue[it_unknown] = 2;
|
multissue[it_shift] = 2;
|
multissue[it_shift] = 2;
|
multissue[it_compare] = 1;
|
multissue[it_compare] = 1;
|
multissue[it_branch] = 1;
|
multissue[it_branch] = 1;
|
multissue[it_jump] = 1;
|
multissue[it_jump] = 1;
|
Line 377... |
Line 361... |
if (config.sim.exe_log) dump_exe_log();
|
if (config.sim.exe_log) dump_exe_log();
|
}
|
}
|
|
|
/* Store buffer analysis - stores are accumulated and commited when IO is idle */
|
/* Store buffer analysis - stores are accumulated and commited when IO is idle */
|
static inline sbuf_store (int cyc) {
|
static inline sbuf_store (int cyc) {
|
int delta = cycles - sbuf_prev_cycles;
|
int delta = runtime.sim.cycles - sbuf_prev_cycles;
|
sbuf_total_cyc += cyc;
|
sbuf_total_cyc += cyc;
|
sbuf_prev_cycles = cycles;
|
sbuf_prev_cycles = runtime.sim.cycles;
|
|
|
//printf (">STORE %i,%i,%i,%i,%i\n", delta, sbuf_count, sbuf_tail, sbuf_head, sbuf_buf[sbuf_tail], sbuf_buf[sbuf_head]);
|
//printf (">STORE %i,%i,%i,%i,%i\n", delta, sbuf_count, sbuf_tail, sbuf_head, sbuf_buf[sbuf_tail], sbuf_buf[sbuf_head]);
|
//printf ("|%i,%i\n", sbuf_total_cyc, sbuf_wait_cyc);
|
//printf ("|%i,%i\n", sbuf_total_cyc, sbuf_wait_cyc);
|
/* Take stores from buffer, that occured meanwhile */
|
/* Take stores from buffer, that occured meanwhile */
|
while (sbuf_count && delta >= sbuf_buf[sbuf_tail]) {
|
while (sbuf_count && delta >= sbuf_buf[sbuf_tail]) {
|
Line 395... |
Line 379... |
sbuf_buf[sbuf_tail] -= delta;
|
sbuf_buf[sbuf_tail] -= delta;
|
|
|
/* Store buffer is full, take one out */
|
/* Store buffer is full, take one out */
|
if (sbuf_count >= config.cpu.sbuf_len) {
|
if (sbuf_count >= config.cpu.sbuf_len) {
|
sbuf_wait_cyc += sbuf_buf[sbuf_tail];
|
sbuf_wait_cyc += sbuf_buf[sbuf_tail];
|
mem_cycles += sbuf_buf[sbuf_tail];
|
runtime.sim.mem_cycles += sbuf_buf[sbuf_tail];
|
sbuf_prev_cycles += sbuf_buf[sbuf_tail];
|
sbuf_prev_cycles += sbuf_buf[sbuf_tail];
|
sbuf_tail = (sbuf_tail + 1) % MAX_SBUF_LEN;
|
sbuf_tail = (sbuf_tail + 1) % MAX_SBUF_LEN;
|
sbuf_count--;
|
sbuf_count--;
|
}
|
}
|
/* Put newest store in the buffer */
|
/* Put newest store in the buffer */
|
Line 409... |
Line 393... |
//printf ("|STORE %i,%i,%i,%i,%i\n", delta, sbuf_count, sbuf_tail, sbuf_head, sbuf_buf[sbuf_tail], sbuf_buf[sbuf_head]);
|
//printf ("|STORE %i,%i,%i,%i,%i\n", delta, sbuf_count, sbuf_tail, sbuf_head, sbuf_buf[sbuf_tail], sbuf_buf[sbuf_head]);
|
}
|
}
|
|
|
/* Store buffer analysis - previous stores should commit, before any load */
|
/* Store buffer analysis - previous stores should commit, before any load */
|
static inline sbuf_load () {
|
static inline sbuf_load () {
|
int delta = cycles - sbuf_prev_cycles;
|
int delta = runtime.sim.cycles - sbuf_prev_cycles;
|
sbuf_prev_cycles = cycles;
|
sbuf_prev_cycles = runtime.sim.cycles;
|
|
|
//printf (">LOAD %i,%i,%i,%i,%i\n", delta, sbuf_count, sbuf_tail, sbuf_head, sbuf_buf[sbuf_tail], sbuf_buf[sbuf_head]);
|
//printf (">LOAD %i,%i,%i,%i,%i\n", delta, sbuf_count, sbuf_tail, sbuf_head, sbuf_buf[sbuf_tail], sbuf_buf[sbuf_head]);
|
//printf ("|%i,%i\n", sbuf_total_cyc, sbuf_wait_cyc);
|
//printf ("|%i,%i\n", sbuf_total_cyc, sbuf_wait_cyc);
|
/* Take stores from buffer, that occured meanwhile */
|
/* Take stores from buffer, that occured meanwhile */
|
while (sbuf_count && delta >= sbuf_buf[sbuf_tail]) {
|
while (sbuf_count && delta >= sbuf_buf[sbuf_tail]) {
|
Line 426... |
Line 410... |
sbuf_buf[sbuf_tail] -= delta;
|
sbuf_buf[sbuf_tail] -= delta;
|
|
|
/* Wait for all stores to complete */
|
/* Wait for all stores to complete */
|
while (sbuf_count > 0) {
|
while (sbuf_count > 0) {
|
sbuf_wait_cyc += sbuf_buf[sbuf_tail];
|
sbuf_wait_cyc += sbuf_buf[sbuf_tail];
|
mem_cycles += sbuf_buf[sbuf_tail];
|
runtime.sim.mem_cycles += sbuf_buf[sbuf_tail];
|
sbuf_prev_cycles += sbuf_buf[sbuf_tail];
|
sbuf_prev_cycles += sbuf_buf[sbuf_tail];
|
sbuf_tail = (sbuf_tail + 1) % MAX_SBUF_LEN;
|
sbuf_tail = (sbuf_tail + 1) % MAX_SBUF_LEN;
|
sbuf_count--;
|
sbuf_count--;
|
}
|
}
|
//printf ("|LOAD %i,%i,%i,%i,%i\n", delta, sbuf_count, sbuf_tail, sbuf_head, sbuf_buf[sbuf_tail], sbuf_buf[sbuf_head]);
|
//printf ("|LOAD %i,%i,%i,%i,%i\n", delta, sbuf_count, sbuf_tail, sbuf_head, sbuf_buf[sbuf_tail], sbuf_buf[sbuf_head]);
|
Line 440... |
Line 424... |
void dump_exe_log ()
|
void dump_exe_log ()
|
{
|
{
|
unsigned long i = iqueue[0].insn_addr;
|
unsigned long i = iqueue[0].insn_addr;
|
|
|
if (i == 0xffffffff) return;
|
if (i == 0xffffffff) return;
|
if (config.sim.exe_log_start <= instructions && (config.sim.exe_log_end <= 0 || instructions <= config.sim.exe_log_end)) {
|
if (config.sim.exe_log_start <= runtime.cpu.instructions && (config.sim.exe_log_end <= 0 || runtime.cpu.instructions <= config.sim.exe_log_end)) {
|
if (config.sim.exe_log_marker && instructions % config.sim.exe_log_marker == 0) {
|
if (config.sim.exe_log_marker && runtime.cpu.instructions % config.sim.exe_log_marker == 0) {
|
fprintf (runtime.sim.fexe_log, "--------------------- %8i instruction ---------------------\n", instructions);
|
fprintf (runtime.sim.fexe_log, "--------------------- %8i instruction ---------------------\n", runtime.cpu.instructions);
|
}
|
}
|
switch (config.sim.exe_log_type) {
|
switch (config.sim.exe_log_type) {
|
case EXE_LOG_HARDWARE:
|
case EXE_LOG_HARDWARE:
|
fprintf (runtime.sim.fexe_log, "\nEXECUTED(): %.8lx: ", i);
|
fprintf (runtime.sim.fexe_log, "\nEXECUTED(): %.8lx: ", i);
|
fprintf (runtime.sim.fexe_log, "%.2x%.2x", evalsim_mem8(i), evalsim_mem8(i + 1));
|
fprintf (runtime.sim.fexe_log, "%.2x%.2x", evalsim_mem8(i), evalsim_mem8(i + 1));
|
Line 498... |
Line 482... |
{
|
{
|
int i;
|
int i;
|
char temp[100];
|
char temp[100];
|
|
|
dumpmemory(iqueue[0].insn_addr, iqueue[0].insn_addr + 4, 1, 0);
|
dumpmemory(iqueue[0].insn_addr, iqueue[0].insn_addr + 4, 1, 0);
|
generate_time_pretty (temp, cycles);
|
generate_time_pretty (temp, runtime.sim.cycles);
|
printf(" (executed) [time %s, #%i]\n", temp, instructions);
|
printf(" (executed) [time %s, #%i]\n", temp, runtime.cpu.instructions);
|
if (config.cpu.superscalar)
|
if (config.cpu.superscalar)
|
printf ("Superscalar CYCLES: %u", supercycles);
|
printf ("Superscalar CYCLES: %u", runtime.cpu.supercycles);
|
if (config.cpu.hazards)
|
if (config.cpu.hazards)
|
printf (" HAZARDWAIT: %u\n", hazardwait);
|
printf (" HAZARDWAIT: %u\n", runtime.cpu.hazardwait);
|
else
|
else
|
if (config.cpu.superscalar)
|
if (config.cpu.superscalar)
|
printf ("\n");
|
printf ("\n");
|
|
|
dumpmemory(pc, pc + 4, 1, 0);
|
dumpmemory(pc, pc + 4, 1, 0);
|
Line 550... |
Line 534... |
|
|
/* Reset the CPU */
|
/* Reset the CPU */
|
void cpu_reset()
|
void cpu_reset()
|
{
|
{
|
int i;
|
int i;
|
cycles = 0;
|
runtime.sim.cycles = 0;
|
instructions = 0;
|
runtime.sim.loadcycles = 0;
|
supercycles = 0;
|
runtime.sim.storecycles = 0;
|
loadcycles = 0;
|
runtime.cpu.instructions = 0;
|
storecycles = 0;
|
runtime.cpu.supercycles = 0;
|
|
runtime.cpu.hazardwait = 0;
|
for (i = 0; i < MAX_GPRS; i++)
|
for (i = 0; i < MAX_GPRS; i++)
|
set_reg32 (i, 0);
|
set_reg32 (i, 0);
|
memset(iqueue, 0, sizeof(iqueue));
|
memset(iqueue, 0, sizeof(iqueue));
|
memset(icomplet, 0, sizeof(icomplet));
|
memset(icomplet, 0, sizeof(icomplet));
|
|
|
Line 587... |
Line 572... |
/* Simulates one CPU clock cycle */
|
/* Simulates one CPU clock cycle */
|
inline int cpu_clock ()
|
inline int cpu_clock ()
|
{
|
{
|
if(fetch()) {
|
if(fetch()) {
|
printf ("Breakpoint hit.\n");
|
printf ("Breakpoint hit.\n");
|
cont_run = 0; /* memory breakpoint encountered */
|
runtime.sim.cont_run = 0; /* memory breakpoint encountered */
|
return 1;
|
return 1;
|
}
|
}
|
decode_execute_wrapper (&iqueue[0]);
|
decode_execute_wrapper (&iqueue[0]);
|
update_pc();
|
update_pc();
|
return 0;
|
return 0;
|