|
|
|
# OP Environment
|
|
|
|
|
|
|
|
import cocotb
|
|
|
|
from cocotb.triggers import Timer
|
|
|
|
from cocotb.handle import Force
|
|
|
|
from cocotb.handle import Release
|
|
|
|
|
|
|
|
from dotmap import DotMap
|
|
|
|
|
|
|
|
# ------------------------------------------------------------------------------------------------
|
|
|
|
# Classes
|
|
|
|
|
|
|
|
class Sim(DotMap):
|
|
|
|
|
|
|
|
def msg(self, m):
|
|
|
|
self.dut._log.info(f'[{self.cycle:08d}] {m}') #wtf do multiline if /n in m
|
|
|
|
|
|
|
|
def __init__(self, dut, cfg=None):
|
|
|
|
super().__init__()
|
|
|
|
self.dut = dut
|
|
|
|
self.resetDone = False
|
|
|
|
|
|
|
|
# defaults
|
|
|
|
self.memFiles = ['../mem/boot_ieq1.bin.hex'] #wtf cmdline parm
|
|
|
|
self.threads = None
|
|
|
|
self.resetCycle = 10
|
|
|
|
self.hbCycles = 100
|
|
|
|
self.clk2x = True
|
|
|
|
self.clk4x = False
|
|
|
|
self.resetAddr = 0xFFFFFFFC
|
|
|
|
self.resetOp = 0x48000002
|
|
|
|
self.maxCycles = 500
|
|
|
|
self.memFiles = None
|
|
|
|
self.config = DotMap()
|
|
|
|
# these should be in a2 core class
|
|
|
|
self.config.core = DotMap({
|
|
|
|
'creditsLd': None,
|
|
|
|
'creditsSt': None,
|
|
|
|
'creditsLdStSingle': None,
|
|
|
|
'lsDataForward' : None,
|
|
|
|
'cpcr4_sq_cnt' : None
|
|
|
|
})
|
|
|
|
self.config.a2l2 = DotMap({
|
|
|
|
'badAddr': [('E0','E0', 'IRW')]
|
|
|
|
})
|
|
|
|
# json
|
|
|
|
if cfg is not None:
|
|
|
|
pass
|
|
|
|
|
|
|
|
# runtime
|
|
|
|
self.cycle = 0
|
|
|
|
self.ok = True
|
|
|
|
self.fail = None
|
|
|
|
self.done = False
|
|
|
|
|
|
|
|
if self.threads is None:
|
|
|
|
try:
|
|
|
|
v = dut.an_ac_pm_thread_stop[1].value
|
|
|
|
self.threads = 2
|
|
|
|
except:
|
|
|
|
self.threads = 1
|
|
|
|
self.msg(f'Set threads={self.threads}.')
|
|
|
|
|
|
|
|
# helpers
|
|
|
|
# wtf: assertFail doesn't work??#@#!!
|
|
|
|
def safeint(self, v, n=10, assertFail=True, rc=False):
|
|
|
|
try:
|
|
|
|
res = int(v, n)
|
|
|
|
ok = True
|
|
|
|
except:
|
|
|
|
self.ok = False
|
|
|
|
self.fail = f'Bad integer conversion: {v},{n}'
|
|
|
|
if assertFail:
|
|
|
|
assert(False, self.fail)
|
|
|
|
res = 0
|
|
|
|
ok = False
|
|
|
|
if rc:
|
|
|
|
return (ok, res)
|
|
|
|
else:
|
|
|
|
return res
|
|
|
|
|
|
|
|
|
|
|
|
class TransQ(DotMap):
|
|
|
|
def __init__(self):
|
|
|
|
super().__init__()
|
|
|
|
|
|
|
|
class Memory(DotMap):
|
|
|
|
|
|
|
|
def __init__(self, sim, default=0, logStores=True):
|
|
|
|
super().__init__()
|
|
|
|
self.sim = sim
|
|
|
|
self.data = {}
|
|
|
|
self.le = False
|
|
|
|
self.default = default # default word data for unloaded
|
|
|
|
self.logStores = logStores
|
|
|
|
|
|
|
|
def loadFile(self, filename, format='ascii', addr=0, le=0):
|
|
|
|
# format # binary, ascii, ascii w/addr
|
|
|
|
# le: reverse bytes
|
|
|
|
try:
|
|
|
|
if format == 'ascii':
|
|
|
|
with open(filename, 'r') as f:
|
|
|
|
lines = f.readlines()
|
|
|
|
for line in lines:
|
|
|
|
self.data[addr] = int(line, 16) # key is int
|
|
|
|
addr += 4
|
|
|
|
elif format == 'binary':
|
|
|
|
pass
|
|
|
|
elif format == 'addrdata':
|
|
|
|
pass
|
|
|
|
except Exception as e:
|
|
|
|
self.sim.msg(f'Error reading {filename}:\n{e}')
|
|
|
|
raise IOError
|
|
|
|
|
|
|
|
# word-aligned byte address
|
|
|
|
def read(self, addr):
|
|
|
|
try:
|
|
|
|
addr = addr + 0
|
|
|
|
except:
|
|
|
|
addr = int(addr, 16)
|
|
|
|
if addr in self.data:
|
|
|
|
return self.data[addr]
|
|
|
|
else:
|
|
|
|
return self.default
|
|
|
|
|
|
|
|
# word-aligned byte address + data
|
|
|
|
def write(self, addr, data):
|
|
|
|
try:
|
|
|
|
addr = addr + 0
|
|
|
|
except:
|
|
|
|
addr = int(addr, 16)
|
|
|
|
try:
|
|
|
|
data = data + 0
|
|
|
|
except:
|
|
|
|
data = int(data, 16)
|
|
|
|
if self.logStores:
|
|
|
|
if addr not in self.data:
|
|
|
|
self.sim.msg(f'Mem Update: @{addr:08X} XXXXXXXX->{data:08X}')
|
|
|
|
else:
|
|
|
|
self.sim.msg(f'Mem Update: @{addr:08X} {self.data[addr]:08X}->{data:08X}')
|
|
|
|
self.data[addr] = data
|
|
|
|
|
|
|
|
# ------------------------------------------------------------------------------------------------
|
|
|
|
# Functions
|
|
|
|
|
|
|
|
def hex(n, pad=0):
|
|
|
|
if pad:
|
|
|
|
return f'000000000000000000000000{n.value.hex()[2:].upper()}'[-pad:]
|
|
|
|
else:
|
|
|
|
return n.value.hex()[2:].upper()
|