forked from M-Labs/artiq
rtio/sed: add output driver simulation unittest
This commit is contained in:
parent
00ff3f5b0d
commit
a2b7894134
|
@ -0,0 +1,125 @@
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from migen import *
|
||||||
|
|
||||||
|
from artiq.gateware import rtio
|
||||||
|
from artiq.gateware.rtio.sed import output_network, output_driver
|
||||||
|
from artiq.gateware.rtio.phy import ttl_simple
|
||||||
|
from artiq.gateware.rtio import rtlink
|
||||||
|
|
||||||
|
|
||||||
|
LANE_COUNT = 8
|
||||||
|
|
||||||
|
|
||||||
|
class BusyPHY(Module):
|
||||||
|
def __init__(self):
|
||||||
|
self.rtlink = rtlink.Interface(rtlink.OInterface(1))
|
||||||
|
self.comb += self.rtlink.o.busy.eq(1)
|
||||||
|
|
||||||
|
|
||||||
|
class DUT(Module):
|
||||||
|
def __init__(self):
|
||||||
|
self.ttl0 = Signal()
|
||||||
|
self.ttl1 = Signal()
|
||||||
|
self.ttl2 = Signal()
|
||||||
|
|
||||||
|
self.submodules.phy0 = ttl_simple.Output(self.ttl0)
|
||||||
|
self.submodules.phy1 = ttl_simple.Output(self.ttl1)
|
||||||
|
self.submodules.phy2 = ttl_simple.Output(self.ttl2)
|
||||||
|
self.phy2.rtlink.o.enable_replace = False
|
||||||
|
self.submodules.phy3 = BusyPHY()
|
||||||
|
|
||||||
|
rtio_channels = [
|
||||||
|
rtio.Channel.from_phy(self.phy0, ofifo_depth=4),
|
||||||
|
rtio.Channel.from_phy(self.phy1, ofifo_depth=4),
|
||||||
|
rtio.Channel.from_phy(self.phy2, ofifo_depth=4),
|
||||||
|
rtio.Channel.from_phy(self.phy3, ofifo_depth=4),
|
||||||
|
]
|
||||||
|
|
||||||
|
self.submodules.output_driver = output_driver.OutputDriver(
|
||||||
|
rtio_channels, LANE_COUNT, 4*LANE_COUNT)
|
||||||
|
|
||||||
|
|
||||||
|
def simulate(input_events):
|
||||||
|
dut = DUT()
|
||||||
|
|
||||||
|
def gen():
|
||||||
|
for n, input_event in enumerate(input_events):
|
||||||
|
yield dut.output_driver.input[n].valid.eq(1)
|
||||||
|
yield dut.output_driver.input[n].seqn.eq(n)
|
||||||
|
for k, v in input_event.items():
|
||||||
|
yield getattr(dut.output_driver.input[n].payload, k).eq(v)
|
||||||
|
yield
|
||||||
|
for n in range(len(input_events)):
|
||||||
|
yield dut.output_driver.input[n].valid.eq(0)
|
||||||
|
for i in range(output_network.latency(LANE_COUNT) + 2):
|
||||||
|
yield
|
||||||
|
for i in range(3):
|
||||||
|
yield
|
||||||
|
|
||||||
|
output = ""
|
||||||
|
|
||||||
|
@passive
|
||||||
|
def monitor():
|
||||||
|
nonlocal output
|
||||||
|
|
||||||
|
ttls = [dut.ttl0, dut.ttl1, dut.ttl2]
|
||||||
|
prev_ttl_values = [0, 0, 0]
|
||||||
|
while True:
|
||||||
|
ttl_values = []
|
||||||
|
for ttl in ttls:
|
||||||
|
ttl_values.append((yield ttl))
|
||||||
|
for n, (old, new) in enumerate(zip(prev_ttl_values, ttl_values)):
|
||||||
|
if old != new:
|
||||||
|
output += "TTL{} {}->{}\n".format(n, old, new)
|
||||||
|
prev_ttl_values = ttl_values
|
||||||
|
|
||||||
|
if (yield dut.output_driver.collision):
|
||||||
|
output += "collision ch{}\n".format((yield dut.output_driver.collision_channel))
|
||||||
|
if (yield dut.output_driver.busy):
|
||||||
|
output += "busy ch{}\n".format((yield dut.output_driver.busy_channel))
|
||||||
|
|
||||||
|
yield
|
||||||
|
|
||||||
|
run_simulation(dut, {"sys": [gen(), monitor()]},
|
||||||
|
{"sys": 5, "rio": 5, "rio_phy": 5}, vcd_name="foo.vcd")
|
||||||
|
return output
|
||||||
|
|
||||||
|
|
||||||
|
class TestOutputNetwork(unittest.TestCase):
|
||||||
|
def test_one_ttl(self):
|
||||||
|
self.assertEqual(
|
||||||
|
simulate([{"data": 1}]),
|
||||||
|
"TTL0 0->1\n")
|
||||||
|
|
||||||
|
def test_simultaneous_ttl(self):
|
||||||
|
self.assertEqual(
|
||||||
|
simulate([{"channel": 0, "data": 1},
|
||||||
|
{"channel": 1, "data": 1},
|
||||||
|
{"channel": 2, "data": 1}]),
|
||||||
|
"TTL0 0->1\n"
|
||||||
|
"TTL1 0->1\n"
|
||||||
|
"TTL2 0->1\n")
|
||||||
|
|
||||||
|
def test_replace(self):
|
||||||
|
self.assertEqual(
|
||||||
|
simulate([{"data": 0},
|
||||||
|
{"data": 1},
|
||||||
|
{"data": 0}]),
|
||||||
|
"")
|
||||||
|
self.assertEqual(
|
||||||
|
simulate([{"data": 1},
|
||||||
|
{"data": 0},
|
||||||
|
{"data": 1}]),
|
||||||
|
"TTL0 0->1\n")
|
||||||
|
|
||||||
|
def test_collision(self):
|
||||||
|
self.assertEqual(
|
||||||
|
simulate([{"channel": 2},
|
||||||
|
{"channel": 2}]),
|
||||||
|
"collision ch2\n")
|
||||||
|
|
||||||
|
def test_busy(self):
|
||||||
|
self.assertEqual(
|
||||||
|
simulate([{"channel": 3}]),
|
||||||
|
"busy ch3\n")
|
Loading…
Reference in New Issue