forked from M-Labs/artiq
drtio: structure
This commit is contained in:
parent
87ec333f55
commit
a40b39e9a2
@ -0,0 +1,2 @@
|
||||
from artiq.gateware.drtio.core import DRTIOSatellite, DRTIOMaster
|
||||
|
18
artiq/gateware/drtio/core.py
Normal file
18
artiq/gateware/drtio/core.py
Normal file
@ -0,0 +1,18 @@
|
||||
from migen import *
|
||||
|
||||
from artiq.gateware.drtio import link_layer, rt_packets, iot
|
||||
|
||||
|
||||
class DRTIOSatellite(Module):
|
||||
def __init__(self, transceiver, channels, full_ts_width=63, fine_ts_width=3):
|
||||
self.submodules.link_layer = link_layer.LinkLayer(
|
||||
transceiver.encoder, transceiver.decoders)
|
||||
self.submodules.rt_packets = rt_packets.RTPacketSatellite(
|
||||
self.link_layer)
|
||||
self.submodules.iot = iot.IOT(
|
||||
self.rt_packets, channels, full_ts_width, fine_ts_width)
|
||||
|
||||
|
||||
class DRTIOMaster(Module):
|
||||
def __init__(self):
|
||||
pass
|
9
artiq/gateware/drtio/iot.py
Normal file
9
artiq/gateware/drtio/iot.py
Normal file
@ -0,0 +1,9 @@
|
||||
from migen import *
|
||||
from migen.genlib.fifo import SyncFIFOBuffered
|
||||
|
||||
from artiq.gateware.rtio import rtlink
|
||||
|
||||
|
||||
class IOT(Module):
|
||||
def __init__(self, rt_packets, channels, full_ts_width, fine_ts_width):
|
||||
pass
|
@ -58,10 +58,8 @@ error_codes = {
|
||||
|
||||
|
||||
class ReceiveDatapath(Module):
|
||||
def __init__(self, ws, plm):
|
||||
# inputs
|
||||
self.frame = Signal()
|
||||
self.data = Signal(ws)
|
||||
def __init__(self, frame, data, plm):
|
||||
ws = len(data)
|
||||
|
||||
# control
|
||||
self.packet_buffer_load = Signal()
|
||||
@ -80,11 +78,11 @@ class ReceiveDatapath(Module):
|
||||
for i in range(len(plm.layouts))]
|
||||
packet_last_n = Signal(max=max(lastword_per_type)+1)
|
||||
self.sync += [
|
||||
self.frame_r.eq(self.frame),
|
||||
self.data_r.eq(self.data),
|
||||
If(self.frame & ~self.frame_r,
|
||||
self.packet_type.eq(self.data[:8]),
|
||||
packet_last_n.eq(Array(lastword_per_type)[self.data[:8]])
|
||||
self.frame_r.eq(frame),
|
||||
self.data_r.eq(data),
|
||||
If(frame & ~self.frame_r,
|
||||
self.packet_type.eq(data[:8]),
|
||||
packet_last_n.eq(Array(lastword_per_type)[data[:8]])
|
||||
)
|
||||
]
|
||||
|
||||
@ -115,7 +113,9 @@ class ReceiveDatapath(Module):
|
||||
|
||||
|
||||
class TransmitDatapath(Module):
|
||||
def __init__(self, ws, plm):
|
||||
def __init__(self, frame, data, plm):
|
||||
ws = len(data)
|
||||
assert ws % 8 == 0
|
||||
self.ws = ws
|
||||
self.plm = plm
|
||||
|
||||
@ -129,25 +129,21 @@ class TransmitDatapath(Module):
|
||||
self.stb = Signal()
|
||||
self.done = Signal()
|
||||
|
||||
# outputs
|
||||
self.frame = Signal()
|
||||
self.data = Signal(ws)
|
||||
|
||||
# # #
|
||||
|
||||
packet_buffer_count = Signal(max=w_in_packet+1)
|
||||
self.sync += [
|
||||
self.done.eq(0),
|
||||
self.frame.eq(0),
|
||||
frame.eq(0),
|
||||
packet_buffer_count.eq(0),
|
||||
|
||||
If(self.stb & ~self.done,
|
||||
If(packet_buffer_count == self.packet_len,
|
||||
self.done.eq(1)
|
||||
).Else(
|
||||
self.frame.eq(1),
|
||||
frame.eq(1),
|
||||
Case(packet_buffer_count,
|
||||
{i: self.data.eq(self.packet_buffer[i*ws:(i+1)*ws])
|
||||
{i: data.eq(self.packet_buffer[i*ws:(i+1)*ws])
|
||||
for i in range(w_in_packet)}),
|
||||
packet_buffer_count.eq(packet_buffer_count + 1)
|
||||
)
|
||||
@ -174,15 +170,7 @@ class TransmitDatapath(Module):
|
||||
|
||||
|
||||
class RTPacketSatellite(Module):
|
||||
def __init__(self, nwords):
|
||||
# link layer interface
|
||||
ws = 8*nwords
|
||||
self.rx_rt_frame = Signal()
|
||||
self.rx_rt_data = Signal(ws)
|
||||
self.tx_rt_frame = Signal()
|
||||
self.tx_rt_data = Signal(ws)
|
||||
|
||||
# I/O Timer interface
|
||||
def __init__(self, link_layer):
|
||||
self.tsc_load = Signal()
|
||||
self.tsc_value = Signal(64)
|
||||
|
||||
@ -200,24 +188,20 @@ class RTPacketSatellite(Module):
|
||||
self.write_underflow = Signal()
|
||||
self.write_underflow_ack = Signal()
|
||||
|
||||
|
||||
# # #
|
||||
|
||||
# RX/TX datapath
|
||||
assert len(link_layer.tx_rt_data) == len(link_layer.rx_rt_data)
|
||||
assert len(link_layer.tx_rt_data) % 8 == 0
|
||||
ws = len(link_layer.tx_rt_data)
|
||||
rx_plm = get_m2s_layouts(ws)
|
||||
rx_dp = ReceiveDatapath(ws, rx_plm)
|
||||
rx_dp = ReceiveDatapath(
|
||||
link_layer.rx_rt_frame, link_layer.rx_rt_data, rx_plm)
|
||||
self.submodules += rx_dp
|
||||
self.comb += [
|
||||
rx_dp.frame.eq(self.rx_rt_frame),
|
||||
rx_dp.data.eq(self.rx_rt_data)
|
||||
]
|
||||
tx_plm = get_s2m_layouts(ws)
|
||||
tx_dp = TransmitDatapath(ws, tx_plm)
|
||||
tx_dp = TransmitDatapath(
|
||||
link_layer.tx_rt_frame, link_layer.tx_rt_data, tx_plm)
|
||||
self.submodules += tx_dp
|
||||
self.comb += [
|
||||
self.tx_rt_frame.eq(tx_dp.frame),
|
||||
self.tx_rt_data.eq(tx_dp.data)
|
||||
]
|
||||
|
||||
# RX->TX
|
||||
echo_req = Signal()
|
||||
@ -259,10 +243,13 @@ class RTPacketSatellite(Module):
|
||||
rx_dp.packet_buffer_load.eq(1),
|
||||
If(rx_dp.packet_last,
|
||||
Case(rx_dp.packet_type, {
|
||||
# echo must have fixed latency, so there is no memory
|
||||
# mechanism
|
||||
rx_plm.types["echo_request"]: echo_req.eq(1),
|
||||
rx_plm.types["set_time"]: NextState("SET_TIME"),
|
||||
rx_plm.types["write"]: NextState("WRITE"),
|
||||
rx_plm.types["fifo_level_request"]: NextState("FIFO_LEVEL"),
|
||||
rx_plm.types["fifo_level_request"]:
|
||||
NextState("FIFO_LEVEL"),
|
||||
"default": [
|
||||
err_set.eq(1),
|
||||
NextValue(err_code, error_codes["unknown_type"])]
|
||||
|
@ -1,4 +1,5 @@
|
||||
import unittest
|
||||
from types import SimpleNamespace
|
||||
|
||||
from migen import *
|
||||
|
||||
@ -6,15 +7,15 @@ from artiq.gateware.drtio.rt_packets import *
|
||||
|
||||
|
||||
class PacketInterface:
|
||||
def __init__(self, direction, frame, data):
|
||||
def __init__(self, direction, ws):
|
||||
if direction == "m2s":
|
||||
self.plm = get_m2s_layouts(len(data))
|
||||
self.plm = get_m2s_layouts(ws)
|
||||
elif direction == "s2m":
|
||||
self.plm = get_s2m_layouts(len(data))
|
||||
self.plm = get_s2m_layouts(ws)
|
||||
else:
|
||||
raise ValueError
|
||||
self.frame = frame
|
||||
self.data = data
|
||||
self.frame = Signal()
|
||||
self.data = Signal(ws)
|
||||
|
||||
def send(self, ty, **kwargs):
|
||||
idx = 8
|
||||
@ -75,11 +76,17 @@ class PacketInterface:
|
||||
|
||||
|
||||
class TestSatellite(unittest.TestCase):
|
||||
def create_dut(self, nwords):
|
||||
pt = PacketInterface("m2s", nwords*8)
|
||||
pr = PacketInterface("s2m", nwords*8)
|
||||
dut = RTPacketSatellite(SimpleNamespace(
|
||||
rx_rt_frame=pt.frame, rx_rt_data=pt.data,
|
||||
tx_rt_frame=pr.frame, tx_rt_data=pr.data))
|
||||
return pt, pr, dut
|
||||
|
||||
def test_echo(self):
|
||||
for nwords in range(1, 8):
|
||||
dut = RTPacketSatellite(nwords)
|
||||
pt = PacketInterface("m2s", dut.rx_rt_frame, dut.rx_rt_data)
|
||||
pr = PacketInterface("s2m", dut.tx_rt_frame, dut.tx_rt_data)
|
||||
pt, pr, dut = self.create_dut(nwords)
|
||||
completed = False
|
||||
def send():
|
||||
yield from pt.send("echo_request")
|
||||
@ -94,8 +101,7 @@ class TestSatellite(unittest.TestCase):
|
||||
|
||||
def test_set_time(self):
|
||||
for nwords in range(1, 8):
|
||||
dut = RTPacketSatellite(nwords)
|
||||
pt = PacketInterface("m2s", dut.rx_rt_frame, dut.rx_rt_data)
|
||||
pt, _, dut = self.create_dut(nwords)
|
||||
tx_times = [0x12345678aabbccdd, 0x0102030405060708,
|
||||
0xaabbccddeeff1122]
|
||||
def send():
|
||||
@ -111,5 +117,5 @@ class TestSatellite(unittest.TestCase):
|
||||
if (yield dut.tsc_load):
|
||||
rx_times.append((yield dut.tsc_value))
|
||||
yield
|
||||
run_simulation(dut, [send(), receive()], vcd_name="foo.vcd")
|
||||
run_simulation(dut, [send(), receive()])
|
||||
self.assertEqual(tx_times, rx_times)
|
||||
|
Loading…
Reference in New Issue
Block a user