diff --git a/artiq/gateware/drtio/__init__.py b/artiq/gateware/drtio/__init__.py index e69de29bb..7e3143e30 100644 --- a/artiq/gateware/drtio/__init__.py +++ b/artiq/gateware/drtio/__init__.py @@ -0,0 +1,2 @@ +from artiq.gateware.drtio.core import DRTIOSatellite, DRTIOMaster + diff --git a/artiq/gateware/drtio/core.py b/artiq/gateware/drtio/core.py new file mode 100644 index 000000000..d8bd1d165 --- /dev/null +++ b/artiq/gateware/drtio/core.py @@ -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 diff --git a/artiq/gateware/drtio/iot.py b/artiq/gateware/drtio/iot.py new file mode 100644 index 000000000..93e008796 --- /dev/null +++ b/artiq/gateware/drtio/iot.py @@ -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 diff --git a/artiq/gateware/drtio/rt_packets.py b/artiq/gateware/drtio/rt_packets.py index 9dbc825fb..93e7781eb 100644 --- a/artiq/gateware/drtio/rt_packets.py +++ b/artiq/gateware/drtio/rt_packets.py @@ -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"])] diff --git a/artiq/test/gateware/drtio/test_rt_packets.py b/artiq/test/gateware/drtio/test_rt_packets.py index 594c37f15..8709c596b 100644 --- a/artiq/test/gateware/drtio/test_rt_packets.py +++ b/artiq/test/gateware/drtio/test_rt_packets.py @@ -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)