blob: 0e49ee4b3f8ec4d6418dd261b163a94087c8e532 [file] [log] [blame]
'''
Created on Nov 20, 2019
@author: ballance
'''
import cocotb
from cocotb.triggers import RisingEdge, Event
from cocotb.bfms import BfmMgr
from fwrisc_tracer_bfm import FwriscTracerBfmIF
from elftools.elf.elffile import ELFFile
from elftools.elf.sections import SymbolTableSection
from fwrisc_tracer_bfm.fwrisc_tracer_signal_bfm import FwriscTracerSignalBfm
class InstrTests(FwriscTracerBfmIF):
def __init__(self, tracer_bfm, mem_size=1024, halt_addr=0x80000004, max_instr=1000000):
self.instr_count = 0
self.test_done_ev = Event()
self.halt_addr = halt_addr
self.max_instr = max_instr
self.complete = False
self.tracer_bfm = tracer_bfm
self.mem = [0] * mem_size
self.trace_instr = "trace_instr" in cocotb.plusargs
self.trace_memwrite = "trace_memwrite" in cocotb.plusargs
def init_mem(self):
pass
def configure_tracer(self):
self.tracer_bfm.set_trace_reg_writes(0)
self.tracer_bfm.set_trace_instr(1, 1, 1)
self.tracer_bfm.set_trace_all_memwrite(1)
def instr_exec(self, pc, instr):
if self.trace_instr:
cocotb.log.info("[InstrExec] addr=0x%08x instr=0x%08x" % (pc, instr))
self.instr_count += 1
if self.halt_addr != -1 and pc == self.halt_addr:
print("Done!")
self.complete = True
self.test_done_ev.set()
if self.max_instr != 0 and self.instr_count >= self.max_instr:
print("TIMEOUT")
self.test_done_ev.set()
def mem_write(self, maddr, mstrb, mdata):
if self.trace_memwrite:
cocotb.log.info("[MemWrite] maddr=%08x mstrb=%x mdata=%08x" % (maddr, mstrb, mdata))
if ((maddr & 0xFFFF8000) == 0x80000000):
offset = ((maddr & 0x0000FFFF) >> 2)
for i in range(4):
if (mstrb & (1 << i)) != 0:
self.mem[offset] &= ~(0xFF << (8*i))
self.mem[offset] |= (mdata & (0xFF << (8*i)))
else:
print("Error: out-of-bounds access")
@cocotb.coroutine
def run(self):
self.configure_tracer()
self.init_mem()
yield self.test_done_ev.wait()
yield self.check()
@cocotb.coroutine
def check(self):
reg_data = []
sw_image = cocotb.plusargs["SW_IMAGE"]
testname = cocotb.plusargs["TESTNAME"]
print("SW_IMAGE=" + sw_image)
with open(sw_image, "rb") as f:
elffile = ELFFile(f)
symtab = elffile.get_section_by_name('.symtab')
start_expected = symtab.get_symbol_by_name("start_expected")[0]["st_value"]
end_expected = symtab.get_symbol_by_name("end_expected")[0]["st_value"]
section = None
for i in range(elffile.num_sections()):
shdr = elffile._get_section_header(i)
if (start_expected >= shdr['sh_addr']) and (end_expected <= (shdr['sh_addr'] + shdr['sh_size'])):
start_expected -= shdr['sh_addr']
end_expected -= shdr['sh_addr']
section = elffile.get_section(i)
break
data = section.data()
exp_l = []
for i in range(start_expected,end_expected,8):
reg = data[i+0] | (data[i+1] << 8) | (data[i+2] << 16) | (data[i+3] << 24)
exp = data[i+4] | (data[i+5] << 8) | (data[i+6] << 16) | (data[i+7] << 24)
exp_l.append([reg, exp])
for i in range(64):
info = yield self.tracer_bfm.get_reg_info(i)
reg_data.append(info)
if not self.complete:
print("FAIL: " + testname)
else:
print("PASS: " + testname)
@cocotb.test()
def runtest(dut):
# print("--> runtest")
# yield RisingEdge(dut.clock)
# print("<-- runtest")
#
# BfmMgr.init()
#
# bfms = BfmMgr.get_bfms()
# for b in bfms:
# print("BFM: " + b.bfm_info.inst_name)
#
tracer_bfm = BfmMgr.find_bfm(".*u_tracer")
test = InstrTests(tracer_bfm)
tracer_bfm.add_listener(test)
# signal_tracer = FwriscTracerSignalBfm(dut.u_tracer)
yield test.run()