URL
https://opencores.org/ocsvn/fwrisc/fwrisc/trunk
Subversion Repositories fwrisc
[/] [fwrisc/] [trunk/] [ve/] [fwrisc/] [tests/] [fwrisc_instr_tests.cpp] - Rev 2
Compare with Previous | Blame | View Log
/* * fwrisc_instr_tests.cpp * * * Copyright 2018 Matthew Ballance * * Licensed under the Apache License, Version 2.0 (the * "License"); you may not use this file except in * compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in * writing, software distributed under the License is * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR * CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing * permissions and limitations under the License. * * Created on: Oct 28, 2018 * Author: ballance */ #include "fwrisc_instr_tests.h" #include "AsmTestCompiler.h" fwrisc_instr_tests::fwrisc_instr_tests(uint32_t max_instr) : m_max_instr(max_instr) { m_halt_addr = 0x80000004; } fwrisc_instr_tests::~fwrisc_instr_tests() { // TODO Auto-generated destructor stub } fwrisc_instr_tests *fwrisc_instr_tests::test = 0; void fwrisc_instr_tests::SetUp() { BaseT::SetUp(); Vfwrisc_tb_hdl *tbp = static_cast<Vfwrisc_tb_hdl *>(0); fprintf(stdout, "offset of clock: %d\n", &tbp->clock); test = this; m_icount = 0; m_end_of_test = false; for (uint32_t i=0; i<64; i++) { m_regs[i] = std::pair<uint32_t, bool>(0, false); } for (uint32_t i=0; i<1024; i++) { m_mem[i] = std::pair<uint32_t, bool>(0, false); } raiseObjection(this); addClock(top()->clock, 10); } void fwrisc_instr_tests::regwrite(uint32_t raddr, uint32_t rdata) { fprintf(stdout, "regwrite 0x%02x <= 0x%08x\n", raddr, rdata); if (raddr == 0) { fprintf(stdout, "ERROR: writing to $zero\n"); } m_regs[raddr].first = rdata; m_regs[raddr].second = true; } void fwrisc_instr_tests::memwrite(uint32_t addr, uint8_t mask, uint32_t data) { fprintf(stdout, "memwrite 0x%08x=0x%08x mask=%02x\n", addr, data, mask); if ((addr & 0xFFFF8000) == 0x80000000) { uint32_t offset = ((addr & 0x0000FFFF) >> 2); fprintf(stdout, "offset=%d\n", offset); m_mem[offset].second = true; // accessed if (mask & 1) { m_mem[offset].first &= ~0x000000FF; m_mem[offset].first |= (data & 0x000000FF); } if (mask & 2) { m_mem[offset].first &= ~0x0000FF00; m_mem[offset].first |= (data & 0x0000FF00); } if (mask & 4) { m_mem[offset].first &= ~0x00FF0000; m_mem[offset].first |= (data & 0x00FF0000); } if (mask & 8) { m_mem[offset].first &= ~0xFF000000; m_mem[offset].first |= (data & 0xFF000000); } fprintf(stdout, " mem=0x%08x\n", m_mem[offset].first); } else { fprintf(stdout, "Error: illegal access to address 0x%08x\n", addr); ASSERT_EQ((addr & 0xFFFFF000), 0x00000000); } } void fwrisc_instr_tests::exec(uint32_t addr, uint32_t instr) { fprintf(stdout, "EXEC: 0x%08x - 0x%08x\n", addr, instr); if (m_halt_addr != 0 && addr == m_halt_addr) { fprintf(stdout, "hit halt address 0x%08x\n", m_halt_addr); m_end_of_test = true; dropObjection(this); } if (++m_icount > m_max_instr) { fprintf(stdout, "test timeout\n"); dropObjection(this); } } void fwrisc_instr_tests::runtest( const std::string &program, reg_val_s *regs, uint32_t n_regs) { ASSERT_EQ(AsmTestCompiler::compile(testname(), program), true); run(); check(regs, n_regs); } void fwrisc_instr_tests::check(reg_val_s *regs, uint32_t n_regs) { bool accessed[64]; ASSERT_EQ(m_end_of_test, true); // Ensure we actually reached the end of the test memset(accessed, 0, sizeof(accessed)); // First, display all registers that were written fprintf(stdout, "Written Registers:\n"); for (uint32_t i=0; i<sizeof(m_regs)/sizeof(reg_val_s); i++) { if (m_regs[i].second) { fprintf(stdout, "R[%d] = 0x%08x\n", i, m_regs[i].first); } } fprintf(stdout, "Expected Registers:\n"); for (uint32_t i=0; i<n_regs; i++) { fprintf(stdout, "Expect R[%d] = 0x%08x\n", regs[i].addr, regs[i].val); } // Perform the affirmative test for (uint32_t i=0; i<n_regs; i++) { if (!m_regs[regs[i].addr].second) { fprintf(stdout, "Error: reg %d was not written\n", regs[i].addr); } ASSERT_EQ(m_regs[regs[i].addr].second, true); // Ensure we wrote the register if (m_regs[regs[i].addr].first != regs[i].val) { fprintf(stdout, "Error: reg %d regs.value='h%08x expected='h%08hx\n", regs[i].addr, m_regs[regs[i].addr].first, regs[i].val); } ASSERT_EQ(m_regs[regs[i].addr].first, regs[i].val); accessed[regs[i].addr] = true; } for (uint32_t i=0; i<63; i++) { // r63 is the CSR temp register if (m_regs[i].second != accessed[i]) { fprintf(stdout, "Error: reg %d: regs.accessed=%s accessed=%s\n", i, (m_regs[i].second)?"true":"false", (accessed[i])?"true":"false"); } ASSERT_EQ(m_regs[i].second, accessed[i]); } } extern "C" int unsigned fwrisc_tracer_bfm_register(const char *path) { fprintf(stdout, "register: %s\n", path); return 0; } extern "C" void fwrisc_tracer_bfm_regwrite(unsigned int id, unsigned int raddr, unsigned int rdata) { fwrisc_instr_tests::test->regwrite(raddr, rdata); } extern "C" void fwrisc_tracer_bfm_memwrite(unsigned int id, unsigned int addr, unsigned char mask, unsigned int data) { fwrisc_instr_tests::test->memwrite(addr, mask, data); } extern "C" void fwrisc_tracer_bfm_exec(unsigned int id, unsigned int addr, unsigned int instr) { fwrisc_instr_tests::test->exec(addr, instr); } TEST_F(fwrisc_instr_tests, lui) { reg_val_s exp[] = { {1, 0x00005000} }; const char *program = R"( entry: lui x1, 5 j done )"; runtest(program, exp, sizeof(exp)/sizeof(reg_val_s)); }