From a788c17e3d34af648e6801eb8958c79482749ac1 Mon Sep 17 00:00:00 2001
From: Donald Sebastian Leung
Date: Fri, 25 Sep 2020 13:26:01 +0800
Subject: [PATCH] Add artiq.gateware.rtio.sed.layouts
---
README.md | 2 +-
artiq/gateware/rtio/sed/layouts.py | 79 ++++++++++++++++++++++++++++++
2 files changed, 80 insertions(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 17daf20..3e76597 100644
--- a/README.md
+++ b/README.md
@@ -11,7 +11,7 @@ Formally verified implementation of the ARTIQ RTIO core in nMigen
- - [x] `artiq.gateware.rtio.rtlink`
- - [x] `artiq.gateware.rtio.channel`
- - [ ] `artiq.gateware.rtio.sed.core`
-- - [ ] `artiq.gateware.rtio.sed.layouts`
+- - [x] `artiq.gateware.rtio.sed.layouts`
- - [ ] `artiq.gateware.rtio.sed.lane_distributor`
- - [ ] `artiq.gateware.rtio.sed.fifos`
- - [ ] `artiq.gateware.rtio.sed.gates`
diff --git a/artiq/gateware/rtio/sed/layouts.py b/artiq/gateware/rtio/sed/layouts.py
index e69de29..4930af6 100644
--- a/artiq/gateware/rtio/sed/layouts.py
+++ b/artiq/gateware/rtio/sed/layouts.py
@@ -0,0 +1,79 @@
+from nmigen import *
+from nmigen.utils import *
+from nmigen.hdl.rec import *
+
+from artiq.gateware.rtio import rtlink
+
+
+def fifo_payload(channels):
+ address_width = max(rtlink.get_address_width(channel.interface.o)
+ for channel in channels)
+ data_width = max(rtlink.get_data_width(channel.interface.o)
+ for channel in channels)
+
+ layout = [
+ ("channel", bits_for(len(channels)-1)),
+ ("timestamp", 64)
+ ]
+ if address_width:
+ layout.append(("address", address_width))
+ if data_width:
+ layout.append(("data", data_width))
+
+ return layout
+
+
+def seqn_width(lane_count, fifo_depth):
+ # There must be a unique sequence number for every possible event in every FIFO.
+ # Plus 2 bits to detect and handle wraparounds.
+ return bits_for(lane_count*fifo_depth-1) + 2
+
+
+def fifo_ingress(seqn_width, layout_payload):
+ return [
+ ("we", 1, DIR_FANOUT),
+ ("writable", 1, DIR_FANIN),
+ ("seqn", seqn_width, DIR_FANOUT),
+ ("payload", [(a, b, DIR_FANOUT) for a, b in layout_payload])
+ ]
+
+
+def fifo_egress(seqn_width, layout_payload):
+ return [
+ ("re", 1, DIR_FANIN),
+ ("readable", 1, DIR_FANOUT),
+ ("seqn", seqn_width, DIR_FANOUT),
+ ("payload", [(a, b, DIR_FANOUT) for a, b in layout_payload])
+ ]
+
+
+# We use glbl_fine_ts_width in the output network so that collisions due
+# to insufficiently increasing timestamps are always reliably detected.
+# We can still have undetected collisions on the address by making it wrap
+# around, but those are more rare and easier to debug, and addresses are
+# not normally exposed directly to the ARTIQ user.
+def output_network_payload(channels, glbl_fine_ts_width):
+ address_width = max(rtlink.get_address_width(channel.interface.o)
+ for channel in channels)
+ data_width = max(rtlink.get_data_width(channel.interface.o)
+ for channel in channels)
+
+ layout = [("channel", bits_for(len(channels)-1))]
+ if glbl_fine_ts_width:
+ layout.append(("fine_ts", glbl_fine_ts_width))
+ if address_width:
+ layout.append(("address", address_width))
+ if data_width:
+ layout.append(("data", data_width))
+
+ return layout
+
+
+def output_network_node(seqn_width, layout_payload):
+ return [
+ ("valid", 1),
+ ("seqn", seqn_width),
+ ("replace_occured", 1),
+ ("nondata_replace_occured", 1),
+ ("payload", layout_payload)
+ ]