blob: b8d7809ab990ce777019a19ab01162ca7c1243d9 [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 200000
uint64_t sim_time = 0;
uint64_t test_time = 0;
#define PASS_MAGIC 0x400
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) {
req_time = (rand()%3)+1;
}
if(--req_time <= 0) {
d->wb_ack = 1;
if(d->wb_we) {
if(d->wb_sel & 1) {
mem[d->wb_adr] &= 0xff00u;
mem[d->wb_adr] |= d->wb_o_dat & 0xffu;
}
if(d->wb_sel & 2) {
mem[d->wb_adr] &= 0xffu;
mem[d->wb_adr] |= d->wb_o_dat & 0xff00u;
}
} else {
d->wb_i_dat = mem[d->wb_adr];
}
req_time = 0;
std::cout<<std::hex<<d->wb_adr<<' ';
} 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;
}
}
void load_hex() {
load_bootjump();
std::string line;
while(std::cin>>line) {
if(line == ":00000001FF")
break;
if(line.size() != 19 || line[0] != ':') {
std::cerr<<"invalid input";
exit(1);
}
std::string addr = line.substr(3, 4);
std::string data = line.substr(9, 8);
mem[0x800000 | (std::stoul(addr, nullptr, 16)<<1)] = std::stoul(data, nullptr, 16) & 0xffff;
mem[0x800000 | ((std::stoul(addr, nullptr, 16)<<1)+1)] = std::stoul(data, nullptr, 16) >> 16;
std::cout<<std::hex<<(0x800000 | (std::stoul(addr, nullptr, 16)<<1))<<" to "<<(std::stoul(data, nullptr, 16) & 0xffff)<<'\n';
}
}
#define RF_REG(x) dut->rootp->upper_core__DOT__core__DOT__execute__DOT__rf__DOT____Vcellout__rf_regs__BRA__ ## x ## __KET____DOT__rf_reg__o_d
int main() {
Vdut *dut = new Vdut;
Verilated::traceEverOn(true);
VerilatedVcdC *vcd = new VerilatedVcdC;
dut->trace(vcd, 99);
vcd->open("waveform.vcd");
srand(8);
cpu_reset(dut, vcd);
load_hex();
int prev_pc = -1;
bool fail = true;
while (sim_time <= MAX_TEST_TIME) {
sim_wishbone_mem(dut);
tick(dut, vcd);
if(dut->dbg_pc != prev_pc) {
prev_pc = dut->dbg_pc;
std::cout<<'\n';
std::cout<<" pc:"<<dut->dbg_pc<<' ';
std::cout<<"r"<<0<<": "<<std::hex<<RF_REG(0)<<' ';
std::cout<<"r"<<1<<": "<<std::hex<<RF_REG(1)<<' ';
std::cout<<"r"<<2<<": "<<std::hex<<RF_REG(2)<<' ';
std::cout<<"r"<<3<<": "<<std::hex<<RF_REG(3)<<' ';
std::cout<<"r"<<4<<": "<<std::hex<<RF_REG(4)<<' ';
std::cout<<"r"<<5<<": "<<std::hex<<RF_REG(5)<<' ';
std::cout<<"r"<<6<<": "<<std::hex<<RF_REG(6)<<' ';
std::cout<<"r"<<7<<": "<<std::hex<<RF_REG(7)<<' ';
}
if(dut->dbg_pc == PASS_MAGIC) {
fail = false;
break;
}
}
dut->final();
vcd->close();
delete dut;
std::cout<<'\n';
if(fail)
std::cout<<"TEST FAILED\n";
else
std::cout<<"TEST PASSED\n";
std::cout<<'\n';
return fail;
}