Line 127... |
Line 127... |
|
|
if (valid) {
|
if (valid) {
|
if (gie) attroff(A_BOLD);
|
if (gie) attroff(A_BOLD);
|
else attron(A_BOLD);
|
else attron(A_BOLD);
|
zipi_to_string(m_mem[pc], line);
|
zipi_to_string(m_mem[pc], line);
|
printw(" %-20s", &line[1]);
|
printw(" %-24s", &line[1]);
|
} else {
|
} else {
|
attroff(A_BOLD);
|
attroff(A_BOLD);
|
printw(" (0x%08x)%28s", m_mem[pc],"");
|
printw(" (0x%08x)%28s", m_mem[pc],"");
|
}
|
}
|
attroff(A_BOLD);
|
attroff(A_BOLD);
|
Line 222... |
Line 222... |
showreg(ln,41, "sR10", 10);
|
showreg(ln,41, "sR10", 10);
|
showreg(ln,61, "sR11", 11); ln++;
|
showreg(ln,61, "sR11", 11); ln++;
|
|
|
showreg(ln, 1, "sR12", 12);
|
showreg(ln, 1, "sR12", 12);
|
showreg(ln,21, "sSP ", 13);
|
showreg(ln,21, "sSP ", 13);
|
mvprintw(ln,41, "sCC :%s%s%s%s%s%s%s",
|
mvprintw(ln,41, "sCC :%s%s%s%s%s%s%s%s",
|
|
(m_core->v__DOT__thecpu__DOT__trap)?"TRP":" ",
|
(m_core->v__DOT__thecpu__DOT__step)?"STP":" ",
|
(m_core->v__DOT__thecpu__DOT__step)?"STP":" ",
|
(m_core->v__DOT__thecpu__DOT__sleep)?"SLP":" ",
|
(m_core->v__DOT__thecpu__DOT__sleep)?"SLP":" ",
|
(m_core->v__DOT__thecpu__DOT__gie)?"GIE":" ",
|
(m_core->v__DOT__thecpu__DOT__gie)?"GIE":" ",
|
(m_core->v__DOT__thecpu__DOT__iflags&8)?"V":" ",
|
(m_core->v__DOT__thecpu__DOT__iflags&8)?"V":" ",
|
(m_core->v__DOT__thecpu__DOT__iflags&4)?"N":" ",
|
(m_core->v__DOT__thecpu__DOT__iflags&4)?"N":" ",
|
Line 255... |
Line 256... |
showreg(ln,41, "uR10", 26);
|
showreg(ln,41, "uR10", 26);
|
showreg(ln,61, "uR11", 27); ln++;
|
showreg(ln,61, "uR11", 27); ln++;
|
|
|
showreg(ln, 1, "uR12", 28);
|
showreg(ln, 1, "uR12", 28);
|
showreg(ln,21, "uSP ", 29);
|
showreg(ln,21, "uSP ", 29);
|
mvprintw(ln,41, "uCC :%s%s%s%s%s%s%s",
|
mvprintw(ln,41, "uCC :%s%s%s%s%s%s%s%s",
|
|
(m_core->v__DOT__thecpu__DOT__trap)?"TRP":" ",
|
(m_core->v__DOT__thecpu__DOT__step)?"STP":" ",
|
(m_core->v__DOT__thecpu__DOT__step)?"STP":" ",
|
(m_core->v__DOT__thecpu__DOT__sleep)?"SLP":" ",
|
(m_core->v__DOT__thecpu__DOT__sleep)?"SLP":" ",
|
(m_core->v__DOT__thecpu__DOT__gie)?"GIE":" ",
|
(m_core->v__DOT__thecpu__DOT__gie)?"GIE":" ",
|
(m_core->v__DOT__thecpu__DOT__flags&8)?"V":" ",
|
(m_core->v__DOT__thecpu__DOT__flags&8)?"V":" ",
|
(m_core->v__DOT__thecpu__DOT__flags&4)?"N":" ",
|
(m_core->v__DOT__thecpu__DOT__flags&4)?"N":" ",
|
Line 336... |
Line 338... |
m_core->v__DOT__thecpu__DOT__alu_pc_valid,
|
m_core->v__DOT__thecpu__DOT__alu_pc_valid,
|
m_core->v__DOT__thecpu__DOT__alu_gie,
|
m_core->v__DOT__thecpu__DOT__alu_gie,
|
m_core->v__DOT__thecpu__DOT__alu_stall,
|
m_core->v__DOT__thecpu__DOT__alu_stall,
|
m_core->v__DOT__thecpu__DOT__alu_pc-1); ln++;
|
m_core->v__DOT__thecpu__DOT__alu_pc-1); ln++;
|
|
|
|
mvprintw(ln-5, 48,"%s %s",
|
|
(m_core->v__DOT__thecpu__DOT__op_break)?"OB":" ",
|
|
(m_core->v__DOT__thecpu__DOT__clear_pipeline)?"CLRP":" ");
|
mvprintw(ln-4, 48,
|
mvprintw(ln-4, 48,
|
(m_core->v__DOT__thecpu__DOT__new_pc)?"new-pc":" ");
|
(m_core->v__DOT__thecpu__DOT__new_pc)?"new-pc":" ");
|
printw("(%s:%02x,%x)",
|
printw("(%s:%02x,%x)",
|
(m_core->v__DOT__thecpu__DOT__set_cond)?"SET":" ",
|
(m_core->v__DOT__thecpu__DOT__set_cond)?"SET":" ",
|
(m_core->v__DOT__thecpu__DOT__opF&0x0ff),
|
(m_core->v__DOT__thecpu__DOT__opF&0x0ff),
|
Line 356... |
Line 361... |
mvprintw(ln-3, 48, "dcdI : 0x%08x",
|
mvprintw(ln-3, 48, "dcdI : 0x%08x",
|
m_core->v__DOT__thecpu__DOT__dcdI);
|
m_core->v__DOT__thecpu__DOT__dcdI);
|
mvprintw(ln-2, 48, "r_opB: 0x%08x",
|
mvprintw(ln-2, 48, "r_opB: 0x%08x",
|
m_core->v__DOT__thecpu__DOT__opB);
|
m_core->v__DOT__thecpu__DOT__opB);
|
*/
|
*/
|
mvprintw(ln-3, 48, "Op(%x)%8x %8x->%08x",
|
mvprintw(ln-3, 48, "Op(%x)%8x,%8x->",
|
m_core->v__DOT__thecpu__DOT__opn,
|
m_core->v__DOT__thecpu__DOT__opn,
|
m_core->v__DOT__thecpu__DOT__opA,
|
m_core->v__DOT__thecpu__DOT__r_opA,
|
m_core->v__DOT__thecpu__DOT__opB,
|
m_core->v__DOT__thecpu__DOT__r_opB);
|
m_core->v__DOT__thecpu__DOT__alu_result);
|
if (m_core->v__DOT__thecpu__DOT__alu_valid)
|
|
printw("%08x", m_core->v__DOT__thecpu__DOT__alu_result);
|
|
else
|
|
printw("%8s","");
|
mvprintw(ln-1, 48, "MEM: %s%s %s%s %s %-5s",
|
mvprintw(ln-1, 48, "MEM: %s%s %s%s %s %-5s",
|
(m_core->v__DOT__thecpu__DOT__opM)?"M":" ",
|
(m_core->v__DOT__thecpu__DOT__opvalid_mem)?"M":" ",
|
(m_core->v__DOT__thecpu__DOT__mem_ce)?"CE":" ",
|
(m_core->v__DOT__thecpu__DOT__mem_ce)?"CE":" ",
|
(m_core->v__DOT__thecpu__DOT__mem_we)?"Wr ":"Rd ",
|
(m_core->v__DOT__thecpu__DOT__mem_we)?"Wr ":"Rd ",
|
(m_core->v__DOT__thecpu__DOT__mem_stalled)?"PIPE":" ",
|
(m_core->v__DOT__thecpu__DOT__mem_stalled)?"PIPE":" ",
|
(m_core->v__DOT__thecpu__DOT__mem_valid)?"MEMV":" ",
|
(m_core->v__DOT__thecpu__DOT__mem_valid)?"MEMV":" ",
|
zop_regstr[(m_core->v__DOT__thecpu__DOT__mem_wreg&0x1f)^0x10]);
|
zop_regstr[(m_core->v__DOT__thecpu__DOT__mem_wreg&0x1f)^0x10]);
|
Line 387... |
Line 395... |
v);
|
v);
|
dbg_flag = false;
|
dbg_flag = false;
|
return v;
|
return v;
|
}
|
}
|
|
|
|
bool halted(void) {
|
|
return (m_core->v__DOT__cmd_halt != 0);
|
|
}
|
|
|
void read_state(void) {
|
void read_state(void) {
|
int ln= 0;
|
int ln= 0;
|
|
|
mvprintw(ln,0, "Peripherals-RS"); ln++;
|
mvprintw(ln,0, "Peripherals-RS"); ln++;
|
showval(ln, 1, "PIC ", cmd_read(32+ 0));
|
showval(ln, 1, "PIC ", cmd_read(32+ 0));
|
Line 633... |
Line 645... |
m_core->v__DOT__thecpu__DOT__alu_gie,
|
m_core->v__DOT__thecpu__DOT__alu_gie,
|
m_core->v__DOT__thecpu__DOT__alu_stall,
|
m_core->v__DOT__thecpu__DOT__alu_stall,
|
m_core->v__DOT__thecpu__DOT__alu_pc-1);
|
m_core->v__DOT__thecpu__DOT__alu_pc-1);
|
|
|
}
|
}
|
|
|
if (m_core->v__DOT__cpu_dbg_we) {
|
|
printf("WRITE-ENABLE!!\n");
|
|
bomb = true;
|
|
}
|
|
}
|
}
|
|
|
bool test_success(void) {
|
bool test_success(void) {
|
return ((!m_core->v__DOT__thecpu__DOT__gie)
|
return ((!m_core->v__DOT__thecpu__DOT__gie)
|
&&(m_core->v__DOT__thecpu__DOT__sleep));
|
&&(m_core->v__DOT__thecpu__DOT__sleep));
|
}
|
}
|
|
|
bool test_failure(void) {
|
bool test_failure(void) {
|
return ((m_core->v__DOT__thecpu__DOT__alu_pc_valid)
|
return ((m_core->v__DOT__thecpu__DOT__alu_pc_valid)
|
&&(!m_core->v__DOT__thecpu__DOT__alu_gie)
|
|
&&(m_mem[m_core->v__DOT__thecpu__DOT__alu_pc-1]
|
&&(m_mem[m_core->v__DOT__thecpu__DOT__alu_pc-1]
|
== 0x2f0f7fff));
|
== 0x2f0f7fff));
|
}
|
}
|
|
|
void wb_write(unsigned a, unsigned int v) {
|
void wb_write(unsigned a, unsigned int v) {
|
Line 708... |
Line 714... |
return v;
|
return v;
|
}
|
}
|
|
|
};
|
};
|
|
|
|
void usage(void) {
|
|
printf("USAGE: zippy_tb [-a] <testfile.out>\n");
|
|
printf("\n");
|
|
printf("\tWhere testfile.out is an output file from the assembler.\n");
|
|
printf("\t-a\tSets the testbench to run automatically without any\n");
|
|
printf("\t\tuser interaction.\n");
|
|
printf("\n");
|
|
printf("\tUser Commands:\n");
|
|
printf("\t\tWhen the test bench is run interactively, the following\n");
|
|
printf("\t\tkey strokes are recognized:\n");
|
|
printf("\t\t\'h\'\tHalt the processor using the external interface.\n");
|
|
printf("\t\t\'g\'\tLet the processor run at full throttle with no.\n");
|
|
printf("\t\t\tuser intervention.\n");
|
|
printf("\t\t\'q\'\tQuit the simulation.\n");
|
|
printf("\t\t\'r\'\tReset the processor.\n");
|
|
printf("\t\t\'s\'\tStep the CPU using the external stepping command\n");
|
|
printf("\t\t\tThis may consume more than one tick.\n");
|
|
printf("\t\t\'t\'\tClock a single tick through the system.\n");
|
|
}
|
|
|
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
Verilated::commandArgs(argc, argv);
|
Verilated::commandArgs(argc, argv);
|
ZIPPY_TB *tb = new ZIPPY_TB();
|
ZIPPY_TB *tb = new ZIPPY_TB();
|
ZPARSER zp;
|
bool autorun = false, exit_on_done = false;
|
|
|
printf("uCC = %d\n", (int)zp.ZIP_uCC);
|
|
printf("MOV CC,R0 = 0x%08x\n", zp.op_mov(0,zp.ZIP_uCC, zp.ZIP_R0));
|
|
// = 0x200e8000
|
|
// Op = 0x2
|
|
// Result = 0x0, R0 (Supervisor/default)
|
|
// Cond = 0x0
|
|
// BReg = 0xe (CC)
|
|
// BMap = 1, BReg = uCC
|
|
//
|
|
|
|
initscr();
|
|
raw();
|
|
noecho();
|
|
keypad(stdscr, true);
|
|
|
|
// mem[0x00000] = 0xbe000010; // Halt instruction
|
// mem[0x00000] = 0xbe000010; // Halt instruction
|
unsigned int mptr = 0;
|
unsigned int mptr = 0;
|
|
|
if (argc <= 1) {
|
if (argc <= 1) {
|
tb->m_mem[mptr++] = zp.op_clr(zp.ZIP_R0); // 0: CLR R0
|
usage();
|
tb->m_mem[mptr++] = zp.op_mov(zp.ZIP_R0,zp.ZIP_R1); // 1: MOV R0,R1
|
exit(-1);
|
tb->m_mem[mptr++] = zp.op_mov(1,zp.ZIP_R0,zp.ZIP_R2); // 2: MOV $1+R0,R2
|
|
tb->m_mem[mptr++] = zp.op_mov(2,zp.ZIP_R0,zp.ZIP_R3); // 3: MOV $2+R0,R3
|
|
tb->m_mem[mptr++] = zp.op_mov(0x022, zp.ZIP_R0, zp.ZIP_R4); // 4: MOV $22h+R0,R4
|
|
tb->m_mem[mptr++] = zp.op_mov(0x377, zp.ZIP_R0, zp.ZIP_uR5); // 5: MOV $377h+R0,uR5
|
|
tb->m_mem[mptr++] = zp.op_noop(); // 6: NOOP
|
|
tb->m_mem[mptr++] = zp.op_add(0,zp.ZIP_R2,zp.ZIP_R0); // 7: ADD R2,R0
|
|
tb->m_mem[mptr++] = zp.op_add(32,zp.ZIP_R0); // 8: ADD $32,R0
|
|
tb->m_mem[mptr++] = zp.op_add(-33,zp.ZIP_R0); // 9: ADD -$33,R0
|
|
tb->m_mem[mptr++] = zp.op_not(zp.ZIPC_Z, zp.ZIP_R0); // A: NOT.Z R0
|
|
tb->m_mem[mptr++] = zp.op_clrf(zp.ZIP_R0); // B: CLRF R0
|
|
tb->m_mem[mptr++] = zp.op_ldi(5,zp.ZIP_R1); // C: LDI $5,R1
|
|
tb->m_mem[mptr++] = zp.op_cmp(0,zp.ZIP_R0,zp.ZIP_R1); // D: CMP R0,R1
|
|
tb->m_mem[mptr++] = zp.op_not(zp.ZIPC_LT, zp.ZIP_R0); // E: NOT.LT R0
|
|
tb->m_mem[mptr++] = zp.op_not(zp.ZIPC_GE, zp.ZIP_R1); // F: NOT.GE R1
|
|
tb->m_mem[mptr++] = zp.op_lod(-7,zp.ZIP_PC, zp.ZIP_R2); // 10: LOD $-7(PC),R2
|
|
tb->m_mem[mptr++] = zp.op_ldihi(0xdead, zp.ZIP_R3); // 11: LODIHI $deadh,R3
|
|
tb->m_mem[mptr++] = zp.op_ldilo(0xbeef, zp.ZIP_R3); // 12: LODILO $beefh,R3
|
|
|
|
// Let's build a software test bench.
|
|
tb->m_mem[mptr++] = zp.op_clr(zp.ZIP_R12);// 0: CLR R12
|
|
tb->m_mem[mptr++] = zp.op_ldihi(0xc000,zp.ZIP_R12);
|
|
tb->m_mem[mptr++] = zp.op_mov(zp.ZIP_R12,zp.ZIP_uR12);
|
|
tb->m_mem[mptr++] = zp.op_mov(10,zp.ZIP_PC,zp.ZIP_uPC);
|
|
tb->m_mem[mptr++] = zp.op_clr(zp.ZIP_R0); // Clear R0, and disable ints
|
|
tb->m_mem[mptr++] = zp.op_sto(zp.ZIP_R0,0,zp.ZIP_R12);
|
|
tb->m_mem[mptr++] = zp.op_rtu(); // 7: RTU // Switch to user mode
|
|
tb->m_mem[mptr++] = zp.op_mov(0,zp.ZIP_uCC, zp.ZIP_R0); // Check result
|
|
tb->m_mem[mptr++] = zp.op_tst(-256,zp.ZIP_R0);
|
|
tb->m_mem[mptr++] = zp.op_bnz(1);
|
|
tb->m_mem[mptr++] = zp.op_halt();// On SUCCESS
|
|
tb->m_mem[mptr++] = zp.op_busy(); // On FAILURE
|
|
|
|
|
|
// Now for a series of tests. If the test fails, call the trap
|
|
// interrupt with the test number that failed. Upon completion,
|
|
// call the trap with #0.
|
|
|
|
// Now for a series of tests. If the test fails, call the trap
|
|
// interrupt with the test number that failed. Upon completion,
|
|
// call the trap with #0.
|
|
|
|
// Test LDI to PC
|
|
// Some data registers
|
|
tb->m_mem[mptr] = mptr + 5 + 0x0100000; mptr++;
|
|
tb->m_mem[mptr++] = zp.op_ldi(0x020,zp.ZIP_CC); // LDI $GIE,CC
|
|
tb->m_mem[mptr++] = zp.op_ldi(0x0200,zp.ZIP_R11); // LDI $200h,R11
|
|
tb->m_mem[mptr++] = zp.op_lod(-4,zp.ZIP_PC,zp.ZIP_PC); // 1: LOD $-3(PC),PC
|
|
tb->m_mem[mptr++] = zp.op_clr(zp.ZIP_R11); // 2: CLR R11
|
|
tb->m_mem[mptr++] = zp.op_noop(); // 3: NOOP
|
|
tb->m_mem[mptr++] = zp.op_cmp(0,zp.ZIP_R11); // 4: CMP $0,R11
|
|
tb->m_mem[mptr++] = zp.op_mov(zp.ZIPC_Z, 0, zp.ZIP_R11,zp.ZIP_R10); // 5: STO.Z R11,(R12)
|
|
tb->m_mem[mptr++] = zp.op_mov(zp.ZIPC_Z, 0, zp.ZIP_R11,zp.ZIP_CC); // 5: STO.Z R11,(R12)
|
|
tb->m_mem[mptr++] = zp.op_add(1,zp.ZIP_R0); // 6: ADD $1,R0
|
|
tb->m_mem[mptr++] = zp.op_add(1,zp.ZIP_R0); // 7: ADD $1,R0
|
|
|
|
// Let's test whether overflow works
|
|
tb->m_mem[mptr++] = zp.op_ldi(0x0300,zp.ZIP_R11); // 0: LDI $3,R11
|
|
tb->m_mem[mptr++] = zp.op_ldi(-1,zp.ZIP_R0); // 1: LDI $-1,R0
|
|
tb->m_mem[mptr++] = zp.op_lsr(1,zp.ZIP_R0); // R0 // R0 = max int
|
|
tb->m_mem[mptr++] = zp.op_add(1,zp.ZIP_R0); // Should set ovfl
|
|
tb->m_mem[mptr++] = zp.op_bv(1); // 4: BV $1+PC
|
|
tb->m_mem[mptr++] = zp.op_mov(0,zp.ZIP_R11, zp.ZIP_CC); // FAIL! if here
|
|
// Overflow set from subtraction
|
|
tb->m_mem[mptr++] = zp.op_ldi(0x0400,zp.ZIP_R11); // 6: LDI $4,R11
|
|
tb->m_mem[mptr++] = zp.op_ldi(1,zp.ZIP_R0); // 7: LDI $1,R0
|
|
tb->m_mem[mptr++] = zp.op_rol(31,zp.ZIP_R0); // 8: ROL $31,R0
|
|
tb->m_mem[mptr++] = zp.op_sub(1,zp.ZIP_R0); // Should set ovfl
|
|
tb->m_mem[mptr++] = zp.op_bv(1); // A: BV $1+PC
|
|
tb->m_mem[mptr++] = zp.op_mov(0,zp.ZIP_R11, zp.ZIP_CC); // FAIL! if here
|
|
// Overflow set from LSR
|
|
tb->m_mem[mptr++] = zp.op_ldi(0x0500,zp.ZIP_R11); // C: LDI $5,R11
|
|
tb->m_mem[mptr++] = zp.op_ldi(1,zp.ZIP_R0);
|
|
tb->m_mem[mptr++] = zp.op_rol(31,zp.ZIP_R0);
|
|
tb->m_mem[mptr++] = zp.op_lsr(1,zp.ZIP_R0);
|
|
tb->m_mem[mptr++] = zp.op_bv(1);
|
|
tb->m_mem[mptr++] = zp.op_mov(0,zp.ZIP_R11, zp.ZIP_CC); // FAIL! if here
|
|
// Overflow set from LSL
|
|
tb->m_mem[mptr++] = zp.op_ldi(0x0600,zp.ZIP_R11);
|
|
tb->m_mem[mptr++] = zp.op_ldi(1,zp.ZIP_R0);
|
|
tb->m_mem[mptr++] = zp.op_rol(30,zp.ZIP_R0);
|
|
tb->m_mem[mptr++] = zp.op_lsl(1,zp.ZIP_R0);
|
|
tb->m_mem[mptr++] = zp.op_bv(1);
|
|
tb->m_mem[mptr++] = zp.op_mov(0,zp.ZIP_R11, zp.ZIP_CC); // FAIL! if here
|
|
// Overflow set from LSL, negative to positive
|
|
tb->m_mem[mptr++] = zp.op_ldi(0x0700,zp.ZIP_R11);
|
|
tb->m_mem[mptr++] = zp.op_ldi(1,zp.ZIP_R0);
|
|
tb->m_mem[mptr++] = zp.op_rol(31,zp.ZIP_R0);
|
|
tb->m_mem[mptr++] = zp.op_lsl(1,zp.ZIP_R0);
|
|
tb->m_mem[mptr++] = zp.op_bv(1); // A: BV $1+PC
|
|
tb->m_mem[mptr++] = zp.op_mov(0,zp.ZIP_R11, zp.ZIP_CC); // FAIL! if here
|
|
|
|
|
|
// Test carry
|
|
tb->m_mem[mptr++] = zp.op_ldi(0x01000, zp.ZIP_R11); // 0: LDI $16,R11
|
|
tb->m_mem[mptr++] = zp.op_ldi(-1, zp.ZIP_R0); // 1: LDI $-1,R0
|
|
tb->m_mem[mptr++] = zp.op_add(1, zp.ZIP_R0); // 2: ADD $1,R0
|
|
tb->m_mem[mptr++] = zp.op_tst(2, zp.ZIP_CC); // 3: TST $2,CC // Is the carry set?
|
|
tb->m_mem[mptr++] = zp.op_mov(zp.ZIPC_Z,0,zp.ZIP_R11, zp.ZIP_CC); // FAIL! if here
|
|
// and carry from subtraction
|
|
tb->m_mem[mptr++] = zp.op_ldi(0x01100, zp.ZIP_R11); // 0: LDI $17,R11
|
|
tb->m_mem[mptr++] = zp.op_sub(1, zp.ZIP_R0); // 1: SUB $1,R0
|
|
tb->m_mem[mptr++] = zp.op_tst(2, zp.ZIP_CC); // 2: TST $2,CC // Is the carry set?
|
|
tb->m_mem[mptr++] = zp.op_mov(zp.ZIPC_Z,0,zp.ZIP_R11, zp.ZIP_CC); // FAIL! if here
|
|
|
|
|
|
|
|
// Let's try a loop: for i=0; i<5; i++)
|
|
// We'll use R0=i, Immediates for 5
|
|
tb->m_mem[mptr++] = zp.op_ldi(0x01200, zp.ZIP_R11); // 0: LDI $18,R11
|
|
tb->m_mem[mptr++] = zp.op_clr(zp.ZIP_R0); // 0: CLR R0
|
|
tb->m_mem[mptr++] = zp.op_noop();
|
|
tb->m_mem[mptr++] = zp.op_add(1, zp.ZIP_R0); // 2: R0 = R0 + 1
|
|
tb->m_mem[mptr++] = zp.op_cmp(5, zp.ZIP_R0); // 3: CMP $5,R0
|
|
tb->m_mem[mptr++] = zp.op_blt(-4); // 4: BLT PC-4
|
|
//
|
|
// Let's try a reverse loop. Such loops are usually cheaper to
|
|
// implement, and this one is no different: 2 loop instructions
|
|
// (minus setup instructions) vs 3 from before.
|
|
// R0 = 5; (from before)
|
|
// do {
|
|
// } while (R0 > 0);
|
|
tb->m_mem[mptr++] = zp.op_ldi(0x01300, zp.ZIP_R11); // 0: LDI $18,R11
|
|
tb->m_mem[mptr++] = zp.op_noop(); // 5: NOOP
|
|
tb->m_mem[mptr++] = zp.op_sub( 1, zp.ZIP_R0); // 6: R0 = R0 - 1
|
|
tb->m_mem[mptr++] = zp.op_bgt(-3); // 7: BGT PC-3
|
|
// How about the same thing with a >= comparison?
|
|
// R1 = 5; // Need to do this explicitly
|
|
// do {
|
|
// } while(R1 >= 0);
|
|
tb->m_mem[mptr++] = zp.op_ldi(0x01400, zp.ZIP_R11); // 0: LDI $18,R11
|
|
tb->m_mem[mptr++] = zp.op_ldi(5, zp.ZIP_R1);
|
|
tb->m_mem[mptr++] = zp.op_noop();
|
|
tb->m_mem[mptr++] = zp.op_sub(1, zp.ZIP_R1);
|
|
tb->m_mem[mptr++] = zp.op_bge(-3);
|
|
|
|
// Let's try the reverse loop again, only this time we'll store our
|
|
// loop variable in memory.
|
|
// R0 = 5; (from before)
|
|
// do {
|
|
// } while (R0 > 0);
|
|
tb->m_mem[mptr++] = zp.op_ldi(0x01500, zp.ZIP_R11); // 0: LDI $18,R11
|
|
tb->m_mem[mptr++] = zp.op_bra(1); // Give us a memory location
|
|
tb->m_mem[mptr++] = 5; // Loop five times
|
|
tb->m_mem[mptr++] = zp.op_mov(-2, zp.ZIP_PC, zp.ZIP_R1); // Get var adr
|
|
tb->m_mem[mptr++] = zp.op_clr(zp.ZIP_R2);
|
|
tb->m_mem[mptr++] = zp.op_ldi(5, zp.ZIP_R0);
|
|
tb->m_mem[mptr++] = zp.op_sto(zp.ZIP_R0,0,zp.ZIP_R1);
|
|
tb->m_mem[mptr++] = zp.op_add(1,zp.ZIP_R2);
|
|
tb->m_mem[mptr++] = zp.op_add(14,zp.ZIP_R0);
|
|
tb->m_mem[mptr++] = zp.op_lod(0,zp.ZIP_R1,zp.ZIP_R0);
|
|
tb->m_mem[mptr++] = zp.op_sub( 1, zp.ZIP_R0);
|
|
tb->m_mem[mptr++] = zp.op_bgt(-6);
|
|
tb->m_mem[mptr++] = zp.op_cmp( 5, zp.ZIP_R2);
|
|
tb->m_mem[mptr++] = zp.op_mov(zp.ZIPC_NZ, 0, zp.ZIP_R11, zp.ZIP_CC);
|
|
|
|
// Return success / Test the trap interrupt
|
|
tb->m_mem[mptr++] = zp.op_clr(zp.ZIP_R11); // 0: CLR R11
|
|
tb->m_mem[mptr++] = zp.op_mov(zp.ZIP_R11, zp.ZIP_CC);
|
|
tb->m_mem[mptr++] = zp.op_noop(); // 2: NOOP // Give it a chance to take
|
|
tb->m_mem[mptr++] = zp.op_noop(); // 3: NOOP // effect
|
|
|
|
// Go into an infinite loop if the trap fails
|
|
// Permanent loop instruction -- a busy halt if you will
|
|
tb->m_mem[mptr++] = zp.op_busy(); // 4: BRA PC-1
|
|
|
|
// And, in case we miss a halt ...
|
|
tb->m_mem[mptr++] = zp.op_halt(); // HALT
|
|
|
|
} else {
|
} else {
|
for(int argn=1; argn<argc; argn++) {
|
for(int argn=1; argn<argc; argn++) {
|
if (access(argv[argn], R_OK)==0) {
|
if (argv[argn][0] == '-') {
|
|
switch(argv[argn][1]) {
|
|
case 'a':
|
|
autorun = true;
|
|
break;
|
|
case 'e':
|
|
exit_on_done = true;
|
|
break;
|
|
case 'h':
|
|
usage();
|
|
exit(0);
|
|
break;
|
|
default:
|
|
usage();
|
|
exit(-1);
|
|
break;
|
|
}
|
|
} else if (access(argv[argn], R_OK)==0) {
|
FILE *fp = fopen(argv[argn], "r");
|
FILE *fp = fopen(argv[argn], "r");
|
if (fp == NULL) {
|
if (fp == NULL) {
|
printf("Cannot open %s\n", argv[argn]);
|
printf("Cannot open %s\n", argv[argn]);
|
perror("O/S Err: ");
|
perror("O/S Err: ");
|
exit(-1);
|
exit(-1);
|
Line 917... |
Line 776... |
fclose(fp);
|
fclose(fp);
|
}
|
}
|
}
|
}
|
}
|
}
|
|
|
|
if (autorun) {
|
|
bool done = false;
|
|
|
|
printf("Running in non-interactive mode\n");
|
|
tb->reset();
|
|
for(int i=0; i<2; i++)
|
|
tb->tick();
|
|
tb->m_core->v__DOT__cmd_halt = 0;
|
|
while(!done) {
|
|
tb->tick();
|
|
|
|
// tb->m_core->v__DOT__thecpu__DOT__step = 0;
|
|
// tb->m_core->v__DOT__cmd_halt = 0;
|
|
// tb->m_core->v__DOT__cmd_step = 0;
|
|
|
|
printf("PC = %08x:%08x (%08x)\n",
|
|
tb->m_core->v__DOT__thecpu__DOT__ipc,
|
|
tb->m_core->v__DOT__thecpu__DOT__upc,
|
|
tb->m_core->v__DOT__thecpu__DOT__alu_pc);
|
|
|
|
done = (tb->test_success())||(tb->test_failure());
|
|
}
|
|
} else { // Interactive
|
|
initscr();
|
|
raw();
|
|
noecho();
|
|
keypad(stdscr, true);
|
|
|
tb->reset();
|
tb->reset();
|
|
for(int i=0; i<2; i++)
|
|
tb->tick();
|
|
tb->m_core->v__DOT__cmd_halt = 0;
|
|
|
int chv = 'q';
|
int chv = 'q';
|
const bool live_debug_mode = true;
|
|
|
|
if (live_debug_mode) {
|
|
bool done = false, halted = true, manual = true;
|
bool done = false, halted = true, manual = true;
|
|
|
halfdelay(1);
|
halfdelay(1);
|
tb->wb_write(CMD_REG, CMD_HALT | CMD_RESET);
|
// tb->wb_write(CMD_REG, CMD_HALT | CMD_RESET);
|
// while((tb->wb_read(CMD_REG) & (CMD_HALT|CMD_STALL))==(CMD_HALT|CMD_STALL))
|
// while((tb->wb_read(CMD_REG) & (CMD_HALT|CMD_STALL))==(CMD_HALT|CMD_STALL))
|
// tb->show_state();
|
// tb->show_state();
|
|
|
while(!done) {
|
while(!done) {
|
chv = getch();
|
chv = getch();
|
Line 954... |
Line 843... |
tb->wb_write(CMD_REG, CMD_RESET|CMD_HALT);
|
tb->wb_write(CMD_REG, CMD_RESET|CMD_HALT);
|
halted = true;
|
halted = true;
|
erase();
|
erase();
|
break;
|
break;
|
case 's': case 'S':
|
case 's': case 'S':
|
|
if (manual)
|
|
erase();
|
tb->wb_write(CMD_REG, CMD_STEP);
|
tb->wb_write(CMD_REG, CMD_STEP);
|
manual = false;
|
manual = false;
|
break;
|
break;
|
case 't': case 'T':
|
case 't': case 'T':
|
|
if (!manual)
|
|
erase();
|
manual = true;
|
manual = true;
|
|
// tb->m_core->v__DOT__thecpu__DOT__step = 0;
|
|
// tb->m_core->v__DOT__cmd_halt = 0;
|
|
// tb->m_core->v__DOT__cmd_step = 0;
|
tb->tick();
|
tb->tick();
|
break;
|
break;
|
case ERR:
|
case ERR:
|
default:
|
default:
|
if (!manual)
|
if (!manual)
|
Line 980... |
Line 876... |
|
|
if (tb->m_core->i_rst)
|
if (tb->m_core->i_rst)
|
done =true;
|
done =true;
|
if (tb->bomb)
|
if (tb->bomb)
|
done = true;
|
done = true;
|
}
|
|
|
|
} else { // Manual stepping mode
|
if (exit_on_done) {
|
|
if (tb->test_success())
|
|
done = true;
|
|
if (tb->test_failure())
|
|
done = true;
|
|
}
|
|
}
|
|
endwin();
|
|
}
|
|
#ifdef MANUAL_STEPPING_MODE
|
|
else { // Manual stepping mode
|
tb->show_state();
|
tb->show_state();
|
|
|
while('q' != tolower(chv = getch())) {
|
while('q' != tolower(chv = getch())) {
|
tb->tick();
|
tb->tick();
|
tb->show_state();
|
tb->show_state();
|
Line 995... |
Line 900... |
break;
|
break;
|
else if (tb->test_failure())
|
else if (tb->test_failure())
|
break;
|
break;
|
}
|
}
|
}
|
}
|
|
#endif
|
|
|
endwin();
|
printf("Clocks used : %08x\n", tb->m_core->v__DOT__mtc_data);
|
|
printf("Instructions Issued : %08x\n", tb->m_core->v__DOT__mic_data);
|
|
if (tb->m_core->v__DOT__mtc_data != 0)
|
|
printf("Instructions / Clock: %.2f\n",
|
|
(double)tb->m_core->v__DOT__mic_data
|
|
/ (double)tb->m_core->v__DOT__mtc_data);
|
if (tb->test_success())
|
if (tb->test_success())
|
printf("SUCCESS!\n");
|
printf("SUCCESS!\n");
|
else if (tb->test_failure())
|
else if (tb->test_failure())
|
printf("TEST FAILED!\n");
|
printf("TEST FAILED!\n");
|
else if (chv == 'q')
|
else
|
printf("chv = %c\n", chv);
|
printf("User quit\n");
|
exit(0);
|
exit(0);
|
}
|
}
|
|
|
|
|
No newline at end of file
|
No newline at end of file
|