blob: 2520e2fdf59b703828499f3696e5986b1caa4339 [file] [log] [blame]
#include "Vupper_core.h"
#include "Vupper_core___024root.h"
#include <iostream>
#include <verilated_vcd_c.h>
#include <verilated.h>
#define MAX_TEST_TIME 200
uint64_t sim_time = 0;
uint64_t test_time = 0;
int req_time = 0;
typedef Vupper_core Vdut;
std::map <int, unsigned short> mem;
void tick(Vdut *dut, VerilatedVcdC* vcd) {
do {
dut->i_clk ^= 1;
dut->eval();
vcd->dump(sim_time++);
} while(dut->i_clk);
std::cout<<".";
}
void cpu_reset(Vdut* dut, VerilatedVcdC* v_vcd) {
dut->i_rst = 1;
for(int i=0; i<4; i++)
tick(dut, v_vcd);
dut->i_rst = 0;
req_time = 0;
mem.clear();
}
void sim_wishbone_mem(Vdut* d) {
if(d->wb_cyc && d->wb_stb && !d->wb_ack) {
if (!req_time) {
std::cout<<"newmemreq"<<'\n';
req_time = (rand()%3)+1;
}
if(--req_time <= 0) {
d->wb_ack = 1;
if(d->wb_we) {
mem[d->wb_adr] = d->wb_o_dat;
} else {
d->wb_i_dat = mem[d->wb_adr];
}
req_time = 0;
std::cout<<"memreqf "<<std::hex<<d->wb_adr<<' '<<(int)d->wb_we<<' '<<(d->wb_we ? d->wb_o_dat : d->wb_i_dat)<<'\n';
} else {
d->wb_ack = 0;
}
} else {
d->wb_ack = 0;
}
}
void load_bootjump() {
// disables mem paging and jumps to 0 (0x800000)
mem[0xffe000] = 0x0004;
mem[0xffe001] = 0x0000;
mem[0xffe002] = 0x0011;
mem[0xffe003] = 0x0002;
mem[0xffe004] = 0x000E;
mem[0xffe005] = 0x0000;
}
void load_mem(std::vector<int>& instr) {
load_bootjump();
for(int i=0; i<instr.size(); i++) {
mem[0x800000 + 2*i] = instr[i] & 0xffff;
mem[0x800000 + 2*i + 1] = instr[i] >> 16;
}
}
bool test_interupts(Vdut* dut, VerilatedVcdC* vcd) {
// This test is executed as currenly the most complex one
// take listing from tb_core.cpp
std::vector <int> instr = {
0x0002000E,
0x0011000E,
0x00000084,
0x00050004,
0x00010011,
0x00000004,
0x00100104,
0x00010008,
0x00020005,
0x03840004,
0x00020002,
0x0000000D,
0x000E030E,
0x03200004,
0x0000400C,
0x0007018E,
0x0019000E,
0x00040190,
0x00010488,
0x00040C11,
0x00000000,
0x0000001E,
0x00000000,
0x00050004,
0x01000011,
0x0019000E};
cpu_reset(dut, vcd);
load_mem(instr);
test_time = sim_time;
int irqc = 0;
while (sim_time-test_time < MAX_TEST_TIME*200) {
sim_wishbone_mem(dut);
if(rand() % 100 < 5 && !dut->i_irq && dut->dbg_pc != 0x14) {
std::cout<<"irq\n";
irqc++;
dut->i_irq = 1;
}
tick(dut, vcd);
if(dut->dbg_pc == 0x14) {
std::cout<<"cli\n";
dut->i_irq = 0; // cli
}
if(dut->dbg_pc >= instr.size()-1) {
std::cout<<"end";
break;
}
}
int r0 = dut->dbg_r0;
int r1 = dut->rootp->upper_core__DOT__core__DOT__execute__DOT__rf__DOT____Vcellout__rf_regs__BRA__1__KET____DOT__rf_reg__o_d;
std::cout<<"r0: "<<r0<<" r1: "<<r1<<" ex:"<<irqc<<'\n';
if(r0 != 0x10 || r1 != irqc) {
std::cout<<"test_interrupt failed\n";
return false;
}
std::cout<<"test_interrupt passed\n";
return true;
}
int main() {
Vdut *dut = new Vdut;
Verilated::traceEverOn(true);
VerilatedVcdC *v_vcd = new VerilatedVcdC;
dut->trace(v_vcd, 99);
v_vcd->open("waveform.vcd");
bool fail = false;
srand(3);
fail |= !test_interupts(dut, v_vcd);
dut->final();
v_vcd->close();
delete dut;
std::cout<<'\n';
if(fail)
std::cout<<"SOME TESTS FAILED\n";
else
std::cout<<"ALL TESTS PASSED\n";
std::cout<<'\n';
return fail;
}