forked from M-Labs/artiq
1
0
Fork 0

drtio: structure

This commit is contained in:
Sebastien Bourdeauducq 2016-10-10 23:12:12 +08:00
parent 87ec333f55
commit a40b39e9a2
5 changed files with 71 additions and 49 deletions

View File

@ -0,0 +1,2 @@
from artiq.gateware.drtio.core import DRTIOSatellite, DRTIOMaster

View 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

View 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

View File

@ -58,10 +58,8 @@ error_codes = {
class ReceiveDatapath(Module): class ReceiveDatapath(Module):
def __init__(self, ws, plm): def __init__(self, frame, data, plm):
# inputs ws = len(data)
self.frame = Signal()
self.data = Signal(ws)
# control # control
self.packet_buffer_load = Signal() self.packet_buffer_load = Signal()
@ -80,11 +78,11 @@ class ReceiveDatapath(Module):
for i in range(len(plm.layouts))] for i in range(len(plm.layouts))]
packet_last_n = Signal(max=max(lastword_per_type)+1) packet_last_n = Signal(max=max(lastword_per_type)+1)
self.sync += [ self.sync += [
self.frame_r.eq(self.frame), self.frame_r.eq(frame),
self.data_r.eq(self.data), self.data_r.eq(data),
If(self.frame & ~self.frame_r, If(frame & ~self.frame_r,
self.packet_type.eq(self.data[:8]), self.packet_type.eq(data[:8]),
packet_last_n.eq(Array(lastword_per_type)[self.data[:8]]) packet_last_n.eq(Array(lastword_per_type)[data[:8]])
) )
] ]
@ -115,7 +113,9 @@ class ReceiveDatapath(Module):
class TransmitDatapath(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.ws = ws
self.plm = plm self.plm = plm
@ -129,25 +129,21 @@ class TransmitDatapath(Module):
self.stb = Signal() self.stb = Signal()
self.done = Signal() self.done = Signal()
# outputs
self.frame = Signal()
self.data = Signal(ws)
# # # # # #
packet_buffer_count = Signal(max=w_in_packet+1) packet_buffer_count = Signal(max=w_in_packet+1)
self.sync += [ self.sync += [
self.done.eq(0), self.done.eq(0),
self.frame.eq(0), frame.eq(0),
packet_buffer_count.eq(0), packet_buffer_count.eq(0),
If(self.stb & ~self.done, If(self.stb & ~self.done,
If(packet_buffer_count == self.packet_len, If(packet_buffer_count == self.packet_len,
self.done.eq(1) self.done.eq(1)
).Else( ).Else(
self.frame.eq(1), frame.eq(1),
Case(packet_buffer_count, 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)}), for i in range(w_in_packet)}),
packet_buffer_count.eq(packet_buffer_count + 1) packet_buffer_count.eq(packet_buffer_count + 1)
) )
@ -174,15 +170,7 @@ class TransmitDatapath(Module):
class RTPacketSatellite(Module): class RTPacketSatellite(Module):
def __init__(self, nwords): def __init__(self, link_layer):
# 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
self.tsc_load = Signal() self.tsc_load = Signal()
self.tsc_value = Signal(64) self.tsc_value = Signal(64)
@ -200,24 +188,20 @@ class RTPacketSatellite(Module):
self.write_underflow = Signal() self.write_underflow = Signal()
self.write_underflow_ack = Signal() self.write_underflow_ack = Signal()
# # # # # #
# RX/TX datapath # 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_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.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_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.submodules += tx_dp
self.comb += [
self.tx_rt_frame.eq(tx_dp.frame),
self.tx_rt_data.eq(tx_dp.data)
]
# RX->TX # RX->TX
echo_req = Signal() echo_req = Signal()
@ -259,10 +243,13 @@ class RTPacketSatellite(Module):
rx_dp.packet_buffer_load.eq(1), rx_dp.packet_buffer_load.eq(1),
If(rx_dp.packet_last, If(rx_dp.packet_last,
Case(rx_dp.packet_type, { 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["echo_request"]: echo_req.eq(1),
rx_plm.types["set_time"]: NextState("SET_TIME"), rx_plm.types["set_time"]: NextState("SET_TIME"),
rx_plm.types["write"]: NextState("WRITE"), 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": [ "default": [
err_set.eq(1), err_set.eq(1),
NextValue(err_code, error_codes["unknown_type"])] NextValue(err_code, error_codes["unknown_type"])]

View File

@ -1,4 +1,5 @@
import unittest import unittest
from types import SimpleNamespace
from migen import * from migen import *
@ -6,15 +7,15 @@ from artiq.gateware.drtio.rt_packets import *
class PacketInterface: class PacketInterface:
def __init__(self, direction, frame, data): def __init__(self, direction, ws):
if direction == "m2s": if direction == "m2s":
self.plm = get_m2s_layouts(len(data)) self.plm = get_m2s_layouts(ws)
elif direction == "s2m": elif direction == "s2m":
self.plm = get_s2m_layouts(len(data)) self.plm = get_s2m_layouts(ws)
else: else:
raise ValueError raise ValueError
self.frame = frame self.frame = Signal()
self.data = data self.data = Signal(ws)
def send(self, ty, **kwargs): def send(self, ty, **kwargs):
idx = 8 idx = 8
@ -75,11 +76,17 @@ class PacketInterface:
class TestSatellite(unittest.TestCase): 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): def test_echo(self):
for nwords in range(1, 8): for nwords in range(1, 8):
dut = RTPacketSatellite(nwords) pt, pr, dut = self.create_dut(nwords)
pt = PacketInterface("m2s", dut.rx_rt_frame, dut.rx_rt_data)
pr = PacketInterface("s2m", dut.tx_rt_frame, dut.tx_rt_data)
completed = False completed = False
def send(): def send():
yield from pt.send("echo_request") yield from pt.send("echo_request")
@ -94,8 +101,7 @@ class TestSatellite(unittest.TestCase):
def test_set_time(self): def test_set_time(self):
for nwords in range(1, 8): for nwords in range(1, 8):
dut = RTPacketSatellite(nwords) pt, _, dut = self.create_dut(nwords)
pt = PacketInterface("m2s", dut.rx_rt_frame, dut.rx_rt_data)
tx_times = [0x12345678aabbccdd, 0x0102030405060708, tx_times = [0x12345678aabbccdd, 0x0102030405060708,
0xaabbccddeeff1122] 0xaabbccddeeff1122]
def send(): def send():
@ -111,5 +117,5 @@ class TestSatellite(unittest.TestCase):
if (yield dut.tsc_load): if (yield dut.tsc_load):
rx_times.append((yield dut.tsc_value)) rx_times.append((yield dut.tsc_value))
yield yield
run_simulation(dut, [send(), receive()], vcd_name="foo.vcd") run_simulation(dut, [send(), receive()])
self.assertEqual(tx_times, rx_times) self.assertEqual(tx_times, rx_times)