From 7c742dc2d16bdcf721af9c9d581aa1cb545ecc48 Mon Sep 17 00:00:00 2001 From: Donald Sebastian Leung Date: Mon, 28 Sep 2020 16:01:43 +0800 Subject: [PATCH] Add rtio.sed.lane_distributor --- README.md | 2 +- rtio/sed/lane_distributor.py | 66 +++++++++++++++++++++++++++++++++--- 2 files changed, 62 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 6f66d9e..0dfe53f 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Formally verified implementation of the ARTIQ RTIO core in nMigen - - [x] `rtio.channel` - - [ ] `rtio.sed.core` - - [x] `rtio.sed.layouts` -- - [ ] `rtio.sed.lane_distributor` +- - [x] `rtio.sed.lane_distributor` - - [ ] `rtio.sed.fifos` - - [ ] `rtio.sed.gates` - - [ ] `rtio.sed.output_driver` diff --git a/rtio/sed/lane_distributor.py b/rtio/sed/lane_distributor.py index 64d217e..a770a43 100644 --- a/rtio/sed/lane_distributor.py +++ b/rtio/sed/lane_distributor.py @@ -31,6 +31,7 @@ class LaneDistributor(Elaboratable): self.glbl_fine_ts_width = glbl_fine_ts_width self.quash_channels = quash_channels self.compensation = compensation + self.enable_spread = enable_spread def elaborate(self, platform): m = Module() @@ -101,14 +102,69 @@ class LaneDistributor(Elaboratable): m.d.comb += latency_compensation_rdport.addr.eq(self.cri.chan_sel[:16]) # cycle #2, write - # TODO + compensation = Signal(Shape(14, True)) + m.d.comb += compensation.eq(latency_compensation_rdport.data) + timestamp_above_min = Signal() + timestamp_above_last = Signal() + timestamp_above_laneA_min = Signal() + timestamp_above_laneB_min = Signal() + timestamp_above_lane_min = Signal() + force_laneB = Signal() + use_laneB = Signal() + use_lanen = Signal(range(self.lane_count)) + + do_write = Signal() + do_underflow = Signal() + do_sequence_error = Signal() + m.d.comb += timestamp_above_min.eq(min_minus_timestamp - compensation < 0) + m.d.comb += timestamp_above_laneA_min.eq(laneAmin_minus_timestamp - compensation < 0) + m.d.comb += timestamp_above_laneB_min.eq(laneBmin_minus_timestamp - compensation < 0) + m.d.comb += timestamp_above_last.eq(last_minus_timestamp - compensation < 0) + with m.If(force_laneB | ~timestamp_above_last): + m.d.comb += use_lanen.eq(current_lane_plus_one) + m.d.comb += use_laneB.eq(1) + with m.Else(): + m.d.comb += use_lanen.eq(current_lane) + m.d.comb += use_laneB.eq(0) + + m.d.comb += timestamp_above_lane_min.eq(Mux(use_laneB, timestamp_above_laneB_min, timestamp_above_laneA_min)) + with m.If(~quash & (self.cri.cmd == cri.commands["write"])): + with m.If(timestamp_above_min): + with m.If(timestamp_above_lane_min): + m.d.comb += do_write.eq(1) + with m.Else(): + m.d.comb += do_sequence_error.eq(1) + with m.Else(): + m.d.comb += do_underflow.eq(1) + m.d.comb += Array(lio.we for lio in self.output)[use_lanen].eq(do_write) + compensated_timestamp = Signal(64) + m.d.comb += compensated_timestamp.eq(self.cri.o_timestamp + (compensation << self.glbl_fine_ts_width)) + with m.If(do_write): + m.d.sync += current_lane.eq(use_lanen) + m.d.sync += last_coarse_timestamp.eq(compensated_timestamp[self.glbl_fine_ts_width:]) + m.d.sync += last_lane_coarse_timestamps[use_lanen].eq(compensated_timestamp[self.glbl_fine_ts_width:]) + m.d.sync += seqn.eq(seqn + 1) + for lio in self.output: + m.d.comb += lio.payload.timestamp.eq(compensated_timestamp) # cycle #3, read status - # TODO + current_lane_writable = Signal() + m.d.comb += current_lane_writable.eq(Array(lio.writable for lio in self.output)[current_lane]) + m.d.comb += o_status_wait.eq(~current_lane_writable) + with m.If(self.cri.cmd == cri.commands["write"]): + m.d.sync += o_status_underflow.eq(0) + with m.If(do_underflow): + m.d.sync += o_status_underflow.eq(1) + m.d.sync += self.sequence_error.eq(do_sequence_error) + m.d.sync += self.sequence_error_channel.eq(self.cri.chan_sel[:16]) # current lane has been full, spread events by switching to the next. - # TODO + if self.enable_spread: + current_lane_writable_r = Signal(reset=1) + m.d.sync += current_lane_writable_r.eq(current_lane_writable) + with m.If(~current_lane_writable_r & current_lane_writable): + m.d.sync += force_laneB.eq(1) + with m.If(do_write): + m.d.sync += force_laneB.eq(0) return m - -# LaneDistributor(1, 1, [('channel', 16), ('timestamp', 64)], [], 1).elaborate(None)