182 lines
6.8 KiB
Python
182 lines
6.8 KiB
Python
from amaranth import *
|
|
from amaranth.sim import Simulator
|
|
from manta.logic_analyzer import LogicAnalyzerTriggerBlock
|
|
from manta.utils import *
|
|
from random import randint, sample
|
|
|
|
|
|
# Make random number of random width probes
|
|
probes = [Signal(randint(1, 32), name=str(i)) for i in range(randint(1, 32))]
|
|
trig_blk = LogicAnalyzerTriggerBlock(probes, base_addr=0, interface=None)
|
|
|
|
|
|
def write_trig_blk_register(name, value):
|
|
strobe_addr = trig_blk.r.base_addr
|
|
yield from write_register(trig_blk, strobe_addr, 0)
|
|
|
|
addrs = trig_blk.r.mmap[f"{name}_buf"]["addrs"]
|
|
datas = value_to_words(value, len(addrs))
|
|
for addr, data in zip(addrs, datas):
|
|
yield from write_register(trig_blk, addr, data)
|
|
|
|
yield from write_register(trig_blk, strobe_addr, 1)
|
|
yield from write_register(trig_blk, strobe_addr, 0)
|
|
|
|
|
|
def test():
|
|
def testbench():
|
|
# Step through each probe and perform all functions in random order
|
|
for p in trig_blk.probes:
|
|
ops = trig_blk.triggers[0].operations
|
|
for op in sample(list(ops.keys()), len(ops)):
|
|
# Program operation register with selected register
|
|
yield from write_trig_blk_register(f"{p.name}_op", ops[op])
|
|
|
|
if op == "DISABLE":
|
|
# Argument can be anything, since it's not used for this operation
|
|
yield from write_trig_blk_register(
|
|
f"{p.name}_arg", randint(0, (2**p.width) - 1)
|
|
)
|
|
yield p.eq(randint(0, (2**p.width) - 1))
|
|
yield
|
|
|
|
if (yield trig_blk.trig):
|
|
raise ValueError("Trigger raised when disabled!")
|
|
|
|
if op == "RISING":
|
|
# Argument can be anything, since it's not used for this operation
|
|
yield from write_trig_blk_register(
|
|
f"{p.name}_arg", randint(0, (2**p.width) - 1)
|
|
)
|
|
yield p.eq(0)
|
|
yield
|
|
yield p.eq(randint(1, (2**p.width) - 1))
|
|
yield
|
|
|
|
if not (yield trig_blk.trig):
|
|
raise ValueError(f"Trigger not raised on probe {p.name}!")
|
|
|
|
if op == "FALLING":
|
|
# Argument can be anything, since it's not used for this operation
|
|
yield from write_trig_blk_register(
|
|
f"{p.name}_arg", randint(0, (2**p.width) - 1)
|
|
)
|
|
yield p.eq(randint(1, (2**p.width) - 1))
|
|
yield
|
|
yield p.eq(0)
|
|
yield
|
|
|
|
if not (yield trig_blk.trig):
|
|
raise ValueError(f"Trigger not raised on probe {p.name}!")
|
|
pass
|
|
|
|
if op == "CHANGING":
|
|
# Argument can be anything, since it's not used for this operation
|
|
yield from write_trig_blk_register(
|
|
f"{p.name}_arg", randint(0, (2**p.width) - 1)
|
|
)
|
|
yield p.eq(randint(1, (2**p.width) - 1))
|
|
yield
|
|
|
|
if not (yield trig_blk.trig):
|
|
raise ValueError(f"Trigger not raised on probe {p.name}!")
|
|
pass
|
|
|
|
if op == "GT":
|
|
upper = randint(1, (2**p.width) - 1)
|
|
lower = randint(0, upper - 1)
|
|
|
|
yield from write_trig_blk_register(f"{p.name}_arg", lower)
|
|
yield p.eq(upper)
|
|
yield
|
|
|
|
if not (yield trig_blk.trig):
|
|
raise ValueError(f"Trigger not raised on probe {p.name}!")
|
|
pass
|
|
|
|
if op == "LT":
|
|
upper = randint(1, (2**p.width) - 1)
|
|
lower = randint(0, upper - 1)
|
|
|
|
yield from write_trig_blk_register(f"{p.name}_arg", upper)
|
|
yield p.eq(lower)
|
|
yield
|
|
|
|
if not (yield trig_blk.trig):
|
|
raise ValueError(f"Trigger not raised on probe {p.name}!")
|
|
pass
|
|
|
|
if op == "GEQ":
|
|
upper = randint(1, (2**p.width) - 1)
|
|
lower = randint(0, upper - 1)
|
|
|
|
# test that the case where it's equal
|
|
yield from write_trig_blk_register(f"{p.name}_arg", lower)
|
|
yield p.eq(lower)
|
|
yield
|
|
|
|
if not (yield trig_blk.trig):
|
|
raise ValueError(f"Trigger not raised on probe {p.name}!")
|
|
pass
|
|
|
|
# test the case where it's greater than
|
|
yield p.eq(upper)
|
|
yield
|
|
|
|
if not (yield trig_blk.trig):
|
|
raise ValueError(f"Trigger not raised on probe {p.name}!")
|
|
pass
|
|
|
|
if op == "LEQ":
|
|
upper = randint(1, (2**p.width) - 1)
|
|
lower = randint(0, upper - 1)
|
|
|
|
# test that the case where it's equal
|
|
yield from write_trig_blk_register(f"{p.name}_arg", upper)
|
|
yield p.eq(upper)
|
|
yield
|
|
|
|
if not (yield trig_blk.trig):
|
|
raise ValueError(f"Trigger not raised on probe {p.name}!")
|
|
pass
|
|
|
|
# test the case where it's less than
|
|
yield p.eq(lower)
|
|
yield
|
|
|
|
if not (yield trig_blk.trig):
|
|
raise ValueError(f"Trigger not raised on probe {p.name}!")
|
|
pass
|
|
|
|
if op == "EQ":
|
|
value = randint(0, (2**p.width) - 1)
|
|
yield from write_trig_blk_register(f"{p.name}_arg", value)
|
|
yield p.eq(value)
|
|
yield
|
|
|
|
if not (yield trig_blk.trig):
|
|
raise ValueError(f"Trigger not raised on probe {p.name}!")
|
|
pass
|
|
|
|
if op == "NEQ":
|
|
upper = randint(1, (2**p.width) - 1)
|
|
lower = randint(0, upper - 1)
|
|
|
|
# test that the case where it's equal
|
|
yield from write_trig_blk_register(f"{p.name}_arg", upper)
|
|
yield p.eq(lower)
|
|
yield
|
|
|
|
if not (yield trig_blk.trig):
|
|
raise ValueError(f"Trigger not raised on probe {p.name}!")
|
|
pass
|
|
|
|
|
|
# disable probe once complete
|
|
yield
|
|
yield from write_trig_blk_register(f"{p.name}_op", ops["DISABLE"])
|
|
yield from write_trig_blk_register(f"{p.name}_arg", 0)
|
|
yield p.eq(0)
|
|
|
|
simulate(trig_blk, testbench, "out.vcd")
|