From 21188094ff80a91de355037f0505a6e7f5ac72ca Mon Sep 17 00:00:00 2001 From: ollie-etl <72926894+ollie-etl@users.noreply.github.com> Date: Sat, 6 May 2023 15:45:30 +0100 Subject: [PATCH 1/9] Optional deinterleaving of AxiS in AxisStreamSink Where the dut may output interleaved transactions, the current sink returns frames delimited by tlast, but contvain data from multiple transactions. This commit adds an opt in paramater which allows transactions to be sorted, prior to insertion in the rx queue. This causes recv() / read() calls to return frames containing deinterleaved transations, with the return order determined by occurance of tlast within each transaction. If tlast is not presence, this has no effect --- README.md | 5 +++++ cocotbext/axi/axis.py | 27 ++++++++++++++++++++++++--- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e6ccd51..60cdb78 100644 --- a/README.md +++ b/README.md @@ -246,6 +246,11 @@ To receive data with an `AxiStreamSink` or `AxiStreamMonitor`, call `recv()`/`re data = await axis_sink.recv() +To de-interleave receive data, for example the `deinterleave` parameter can be set on the `AxiStreamSink` constructor. This causes calls to `read()` and `recv()` to return data sorted by `tid` ot `tdest`, returned in order of transaction completion time. + + axis_sink = AxiStreamSink(AxiStreamBus.from_prefix(dut, "m_axis"), dut.clk, dut.rst, deinterleave="tid") + data = await axis_sink.recv() + #### Signals * `tdata`: data, required diff --git a/cocotbext/axi/axis.py b/cocotbext/axi/axis.py index aa83d1d..59c2156 100644 --- a/cocotbext/axi/axis.py +++ b/cocotbext/axi/axis.py @@ -33,6 +33,8 @@ from .version import __version__ from .reset import Reset +from functools import reduce + class AxiStreamFrame: def __init__(self, tdata=b'', tkeep=None, tid=None, tdest=None, tuser=None, tx_complete=None): @@ -736,8 +738,9 @@ class AxiStreamSink(AxiStreamMonitor, AxiStreamPause): _ready_init = 0 def __init__(self, bus, clock, reset=None, reset_active_level=True, - byte_size=None, byte_lanes=None, *args, **kwargs): + byte_size=None, byte_lanes=None, deinterleave=None, *args, **kwargs): + self.deinterleave = deinterleave self.queue_occupancy_limit_bytes = -1 self.queue_occupancy_limit_frames = -1 @@ -765,7 +768,14 @@ def _dequeue(self, frame): self.wake_event.set() async def _run(self): - frame = None + if self.deinterleave is None: + num_frames = 1 + if self.deinterleave is "tid": + num_frames = len(self.bus.tid) + if self.deinterleave is "tdest": + num_frames = len(self.bus.tdest) + + frames = [None for _ in range(num_frames)] self.active = False has_tready = hasattr(self.bus, "tready") @@ -790,6 +800,15 @@ async def _run(self): tvalid_sample = (not has_tvalid) or self.bus.tvalid.value if tready_sample and tvalid_sample: + if self.deinterleave is None: + qid = 0 + if self.deinterleave is "tid": + qid = self.bus.tid.value + if self.deinterleave is "tdest": + qid = self.bus.tdest.value + + frame = frames[qid] + if not frame: if self.byte_size == 8: frame = AxiStreamFrame(bytearray(), [], [], [], []) @@ -820,8 +839,10 @@ async def _run(self): self.active_event.set() frame = None + + frames[qid] = frame else: - self.active = bool(frame) + self.active = reduce(lambda r, f: r or bool(f), frames, False) if has_tready: self.bus.tready.value = (not self.full() and not pause_sample) From 65724af8c86bcb74169eac0a74d4556f64f48eee Mon Sep 17 00:00:00 2001 From: ollie <72926894+ollie-etl@users.noreply.github.com> Date: Sat, 6 May 2023 15:52:45 +0100 Subject: [PATCH 2/9] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 60cdb78..b2000f9 100644 --- a/README.md +++ b/README.md @@ -246,7 +246,7 @@ To receive data with an `AxiStreamSink` or `AxiStreamMonitor`, call `recv()`/`re data = await axis_sink.recv() -To de-interleave receive data, for example the `deinterleave` parameter can be set on the `AxiStreamSink` constructor. This causes calls to `read()` and `recv()` to return data sorted by `tid` ot `tdest`, returned in order of transaction completion time. +To deinterleave receive data the `deinterleave` parameter can be set on the `AxiStreamSink` constructor. This causes calls to `read()` and `recv()` to return data sorted by `tid` ot `tdest`, returned in order of transaction completion time. axis_sink = AxiStreamSink(AxiStreamBus.from_prefix(dut, "m_axis"), dut.clk, dut.rst, deinterleave="tid") data = await axis_sink.recv() From 8859e22077760d28b0ee3de12cf6667ac6e123df Mon Sep 17 00:00:00 2001 From: ollie <72926894+ollie-etl@users.noreply.github.com> Date: Sat, 6 May 2023 15:54:45 +0100 Subject: [PATCH 3/9] Update cocotbext/axi/axis.py --- cocotbext/axi/axis.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cocotbext/axi/axis.py b/cocotbext/axi/axis.py index 59c2156..b2bf4c7 100644 --- a/cocotbext/axi/axis.py +++ b/cocotbext/axi/axis.py @@ -771,9 +771,9 @@ async def _run(self): if self.deinterleave is None: num_frames = 1 if self.deinterleave is "tid": - num_frames = len(self.bus.tid) + num_frames = pow(2, len(self.bus.tid)) if self.deinterleave is "tdest": - num_frames = len(self.bus.tdest) + num_frames = pow(2, len(self.bus.tdest)) frames = [None for _ in range(num_frames)] self.active = False From f2c987e20eaef1b106b17e202289dd6fe674af35 Mon Sep 17 00:00:00 2001 From: Oliver Bunting <72926894+ollie-etl@users.noreply.github.com> Date: Thu, 16 Nov 2023 10:17:33 +0000 Subject: [PATCH 4/9] Support interleave on all axis --- README.md | 6 +- cocotbext/axi/axis.py | 141 ++++++++++++++++++++++++---------------- tests/axis/Makefile | 2 +- tests/axis/test_axis.py | 13 ++-- 4 files changed, 97 insertions(+), 65 deletions(-) diff --git a/README.md b/README.md index b2000f9..d8c7d30 100644 --- a/README.md +++ b/README.md @@ -229,6 +229,8 @@ To use these modules, import the one you need and connect it to the DUT: The first argument to the constructor accepts an `AxiStreamBus` object. This object is a container for the interface signals and includes class methods to automate connections. +To allow `AxiStreamSource` to interleave data set the interleave parameter a dictionary containing `tid` and / or `tdest`. THe maximum interleave depth can also be set with `max_interleave_depth`. By default is is unbound. + To send data into a design with an `AxiStreamSource`, call `send()`/`send_nowait()` or `write()`/`write_nowait()`. Accepted data types are iterables or `AxiStreamFrame` objects. Optionally, call `wait()` to wait for the transmit operation to complete. Example: await axis_source.send(b'test data') @@ -246,9 +248,9 @@ To receive data with an `AxiStreamSink` or `AxiStreamMonitor`, call `recv()`/`re data = await axis_sink.recv() -To deinterleave receive data the `deinterleave` parameter can be set on the `AxiStreamSink` constructor. This causes calls to `read()` and `recv()` to return data sorted by `tid` ot `tdest`, returned in order of transaction completion time. +To deinterleave receive data the `interleave` parameter can be set on the `AxiStreamSink` constructor. This causes calls to `read()` and `recv()` to return data sorted by `tid` ot `tdest`, returned in order of transaction completion time. - axis_sink = AxiStreamSink(AxiStreamBus.from_prefix(dut, "m_axis"), dut.clk, dut.rst, deinterleave="tid") + axis_sink = AxiStreamSink(AxiStreamBus.from_prefix(dut, "m_axis"), dut.clk, dut.rst, interleave="tid") data = await axis_sink.recv() #### Signals diff --git a/cocotbext/axi/axis.py b/cocotbext/axi/axis.py index b2bf4c7..16ea3d4 100644 --- a/cocotbext/axi/axis.py +++ b/cocotbext/axi/axis.py @@ -34,6 +34,7 @@ from .reset import Reset from functools import reduce +from random import choice class AxiStreamFrame: @@ -263,9 +264,10 @@ class AxiStreamBase(Reset): _ready_init = None def __init__(self, bus, clock, reset=None, reset_active_level=True, - byte_size=None, byte_lanes=None, *args, **kwargs): + byte_size=None, byte_lanes=None, interleave=None, *args, **kwargs): self.bus = bus + self.interleave = interleave self.clock = clock self.reset = reset self.log = logging.getLogger(f"cocotb.{bus._entity._name}.{bus._name}") @@ -277,10 +279,15 @@ def __init__(self, bus, clock, reset=None, reset_active_level=True, super().__init__(*args, **kwargs) + if "tid" in self.interleave and not hasattr(self.bus, "tid"): + raise ValueError("Cannot interleave with tid on a bus without tid") + if "tdest" in self.interleave and not hasattr(self.bus, "tdest"): + raise ValueError("Cannot interleave with tdest on a bus without tdest") + self.active = False self.queue = Queue() self.dequeue_event = Event() - self.current_frame = None + self.current_frames = {} self.idle_event = Event() self.idle_event.set() self.active_event = Event() @@ -427,14 +434,20 @@ class AxiStreamSource(AxiStreamBase, AxiStreamPause): _ready_init = None def __init__(self, bus, clock, reset=None, reset_active_level=True, - byte_size=None, byte_lanes=None, *args, **kwargs): + byte_size=None, byte_lanes=None, interleave=None, max_interleave_depth=None, *args, **kwargs): - super().__init__(bus, clock, reset, reset_active_level, byte_size, byte_lanes, *args, **kwargs) + super().__init__(bus, clock, reset, reset_active_level, byte_size, byte_lanes, interleave, *args, **kwargs) + self.max_interleave_depth = max_interleave_depth self.queue_occupancy_limit_bytes = -1 self.queue_occupancy_limit_frames = -1 async def send(self, frame): + # If interleaving enabled, check provided frame has the required parameter(s) + if "tid" in self.interleave and (frame.tid is None or type(frame.tid) is list): + raise ValueError("Sending a frame with interleaving on tid requires single tid be associated with the frame") + if "dest" in self.interleave and (frame.tdest is None or type(frame.tdest) is list): + raise ValueError("Sending a frame with interleaving on tdest requires single tdest be associated with the frame") while self.full(): self.dequeue_event.clear() await self.dequeue_event.wait() @@ -446,6 +459,11 @@ async def send(self, frame): self.queue_occupancy_frames += 1 def send_nowait(self, frame): + # If interleaving enabled, check provided frame has the required parameter(s) + if "tid" in self.interleave and (frame.tid is None or type(frame.tid) is list): + raise ValueError("Sending a frame with interleaving on tid requires single tid be associated with the frame") + if "dest" in self.interleave and (frame.tdest is None or type(frame.tdest) is list): + raise ValueError("Sending a frame with interleaving on tdest requires single tdest be associated with the frame") if self.full(): raise QueueFull() frame = AxiStreamFrame(frame) @@ -493,14 +511,19 @@ def _handle_reset(self, state): if hasattr(self.bus, "tuser"): self.bus.tuser.value = 0 - if self.current_frame: - self.log.warning("Flushed transmit frame during reset: %s", self.current_frame) - self.current_frame.handle_tx_complete() - self.current_frame = None + for current_frame in self.current_frames.values(): + self.log.warning("Flushed transmit frame during reset: %s", current_frame) + current_frame.handle_tx_complete() + self.current_frames = {} async def _run(self): - frame = None - frame_offset = 0 + # next frame hold the most recently popped frame from the Queue + # It may be held if the number of entries in frames is >= max_interleave_depth + next_frame = None + # Frames holds the in-flight frame for each of the interleaved stream + frames = {} + frame_offsets = {} + self.active = False has_tready = hasattr(self.bus, "tready") @@ -521,18 +544,35 @@ async def _run(self): tvalid_sample = (not has_tvalid) or self.bus.tvalid.value if (tready_sample and tvalid_sample) or not tvalid_sample: - if not frame and not self.queue.empty(): - frame = self.queue.get_nowait() - self.dequeue_event.set() - self.queue_occupancy_bytes -= len(frame) - self.queue_occupancy_frames -= 1 - self.current_frame = frame - frame.sim_time_start = get_sim_time() - frame.sim_time_end = None - self.log.info("TX frame: %s", frame) - frame.normalize() - self.active = True - frame_offset = 0 + + # Pop a frame from the queue if we have space + if not next_frame and not self.queue.empty(): + next_frame = self.queue.get_nowait() + + # Schedule the previously popped frame if that doesn't exceed our limits + if next_frame and (self.max_interleave_depth is None or len(frames) < self.max_interleave_depth): + k = (next_frame.tid if "tid" in self.interleave else None, next_frame.tdest if "tdest" in self.interleave else None) + if frames.get(k) == None: + frame = next_frame + next_frame = None + self.dequeue_event.set() + self.queue_occupancy_bytes -= len(frame) + self.queue_occupancy_frames -= 1 + self.current_frames[k] = frame + frame.sim_time_start = get_sim_time() + frame.sim_time_end = None + self.log.info("TX frame: %s", frame) + frame.normalize() + self.active = True + frames[k] = frame + frame_offsets[k] = 0 + + frame = None + k = None + frame_offset = 0 + if frames: + k, frame = choice(frames) + frame_offset = frame_offsets[k] if frame and not self.pause: tdata_val = 0 @@ -549,15 +589,17 @@ async def _run(self): tdest_val = frame.tdest[frame_offset] tuser_val = frame.tuser[frame_offset] frame_offset += 1 + frame_offsets[k] = frame_offset if frame_offset >= len(frame.tdata): tlast_val = 1 frame.sim_time_end = get_sim_time() frame.handle_tx_complete() - frame = None - self.current_frame = None + del frames[k] + del self.current_frames[k] + del frame_offsets[k] break - + self.bus.tdata.value = tdata_val if has_tvalid: self.bus.tvalid.value = 1 @@ -576,8 +618,8 @@ async def _run(self): self.bus.tvalid.value = 0 if has_tlast: self.bus.tlast.value = 0 - self.active = bool(frame) - if not frame and self.queue.empty(): + self.active = bool(frames) + if not frames and self.empty(): self.idle_event.set() self.active_event.clear() @@ -594,9 +636,9 @@ class AxiStreamMonitor(AxiStreamBase): _ready_init = None def __init__(self, bus, clock, reset=None, reset_active_level=True, - byte_size=None, byte_lanes=None, *args, **kwargs): + byte_size=None, byte_lanes=None, interleave=None, *args, **kwargs): - super().__init__(bus, clock, reset, reset_active_level, byte_size, byte_lanes, *args, **kwargs) + super().__init__(bus, clock, reset, reset_active_level, byte_size, byte_lanes, interleave, *args, **kwargs) self.read_queue = [] @@ -668,7 +710,7 @@ async def _run_tready_monitor(self): self.wake_event.set() async def _run(self): - frame = None + frames = {} self.active = False has_tready = hasattr(self.bus, "tready") @@ -691,6 +733,9 @@ async def _run(self): tvalid_sample = (not has_tvalid) or self.bus.tvalid.value if tready_sample and tvalid_sample: + k = (self.bus.tid.value if "tid" in self.interleave else None, self.bus.tdest.value if "tdest" in self.interleave else None) + frame = frames.pop(k) + if not frame: if self.byte_size == 8: frame = AxiStreamFrame(bytearray(), [], [], [], []) @@ -719,8 +764,8 @@ async def _run(self): self.queue.put_nowait(frame) self.active_event.set() - - frame = None + else: + frames[k] = frame else: self.active = bool(frame) @@ -738,13 +783,12 @@ class AxiStreamSink(AxiStreamMonitor, AxiStreamPause): _ready_init = 0 def __init__(self, bus, clock, reset=None, reset_active_level=True, - byte_size=None, byte_lanes=None, deinterleave=None, *args, **kwargs): + byte_size=None, byte_lanes=None, interleave=None, *args, **kwargs): - self.deinterleave = deinterleave self.queue_occupancy_limit_bytes = -1 self.queue_occupancy_limit_frames = -1 - super().__init__(bus, clock, reset, reset_active_level, byte_size, byte_lanes, *args, **kwargs) + super().__init__(bus, clock, reset, reset_active_level, byte_size, byte_lanes, interleave *args, **kwargs) def full(self): if self.queue_occupancy_limit_bytes > 0 and self.queue_occupancy_bytes > self.queue_occupancy_limit_bytes: @@ -768,14 +812,7 @@ def _dequeue(self, frame): self.wake_event.set() async def _run(self): - if self.deinterleave is None: - num_frames = 1 - if self.deinterleave is "tid": - num_frames = pow(2, len(self.bus.tid)) - if self.deinterleave is "tdest": - num_frames = pow(2, len(self.bus.tdest)) - - frames = [None for _ in range(num_frames)] + frames = {} self.active = False has_tready = hasattr(self.bus, "tready") @@ -800,15 +837,9 @@ async def _run(self): tvalid_sample = (not has_tvalid) or self.bus.tvalid.value if tready_sample and tvalid_sample: - if self.deinterleave is None: - qid = 0 - if self.deinterleave is "tid": - qid = self.bus.tid.value - if self.deinterleave is "tdest": - qid = self.bus.tdest.value - - frame = frames[qid] - + k = (self.bus.tid.value if "tid" in self.interleave else None, self.bus.tdest.value if "tdest" in self.interleave else None) + frame = frames.pop(k) + if not frame: if self.byte_size == 8: frame = AxiStreamFrame(bytearray(), [], [], [], []) @@ -837,10 +868,8 @@ async def _run(self): self.queue.put_nowait(frame) self.active_event.set() - - frame = None - - frames[qid] = frame + else: + frames[k] = frame else: self.active = reduce(lambda r, f: r or bool(f), frames, False) diff --git a/tests/axis/Makefile b/tests/axis/Makefile index 7b4a37b..10fc915 100644 --- a/tests/axis/Makefile +++ b/tests/axis/Makefile @@ -20,7 +20,7 @@ TOPLEVEL_LANG = verilog -SIM ?= icarus +SIM ?= verilator WAVES ?= 0 COCOTB_HDL_TIMEUNIT = 1ns diff --git a/tests/axis/test_axis.py b/tests/axis/test_axis.py index 7ed0aab..18cd50f 100644 --- a/tests/axis/test_axis.py +++ b/tests/axis/test_axis.py @@ -39,7 +39,7 @@ class TB: - def __init__(self, dut): + def __init__(self, dut, interleave): self.dut = dut self.log = logging.getLogger("cocotb.tb") @@ -47,9 +47,9 @@ def __init__(self, dut): cocotb.start_soon(Clock(dut.clk, 2, units="ns").start()) - self.source = AxiStreamSource(AxiStreamBus.from_prefix(dut, "axis"), dut.clk, dut.rst) - self.sink = AxiStreamSink(AxiStreamBus.from_prefix(dut, "axis"), dut.clk, dut.rst) - self.monitor = AxiStreamMonitor(AxiStreamBus.from_prefix(dut, "axis"), dut.clk, dut.rst) + self.source = AxiStreamSource(AxiStreamBus.from_prefix(dut, "axis"), dut.clk, dut.rst, interleave=interleave) + self.sink = AxiStreamSink(AxiStreamBus.from_prefix(dut, "axis"), dut.clk, dut.rst, interleave=interleave) + self.monitor = AxiStreamMonitor(AxiStreamBus.from_prefix(dut, "axis"), dut.clk, dut.rst, interleave=interleave) def set_idle_generator(self, generator=None): if generator: @@ -71,9 +71,9 @@ async def reset(self): await RisingEdge(self.dut.clk) -async def run_test(dut, payload_lengths=None, payload_data=None, idle_inserter=None, backpressure_inserter=None): +async def run_test(dut, payload_lengths=None, payload_data=None, idle_inserter=None, backpressure_inserter=None, interleave=None): - tb = TB(dut) + tb = TB(dut,interleave) id_count = 2**len(tb.source.bus.tid) @@ -141,6 +141,7 @@ def incrementing_payload(length): factory.add_option("payload_lengths", [size_list]) factory.add_option("payload_data", [incrementing_payload]) factory.add_option("idle_inserter", [None, cycle_pause]) + factory.add_option("interleave", [None, "tid", "tdest", {"tid", "tdest"} ]) factory.add_option("backpressure_inserter", [None, cycle_pause]) factory.generate_tests() From c543da22f18e929c8ba88cd83723ebee6596a014 Mon Sep 17 00:00:00 2001 From: ollie <72926894+ollie-etl@users.noreply.github.com> Date: Thu, 16 Nov 2023 10:30:43 +0000 Subject: [PATCH 5/9] Revert simulator change --- tests/axis/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/axis/Makefile b/tests/axis/Makefile index 10fc915..7b4a37b 100644 --- a/tests/axis/Makefile +++ b/tests/axis/Makefile @@ -20,7 +20,7 @@ TOPLEVEL_LANG = verilog -SIM ?= verilator +SIM ?= icarus WAVES ?= 0 COCOTB_HDL_TIMEUNIT = 1ns From 85207df21a4b872ca80a524656dc46e6b0659b7d Mon Sep 17 00:00:00 2001 From: Oliver Bunting <72926894+ollie-etl@users.noreply.github.com> Date: Thu, 16 Nov 2023 10:41:47 +0000 Subject: [PATCH 6/9] Better default value --- cocotbext/axi/axis.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cocotbext/axi/axis.py b/cocotbext/axi/axis.py index 16ea3d4..b4f7a9d 100644 --- a/cocotbext/axi/axis.py +++ b/cocotbext/axi/axis.py @@ -267,7 +267,9 @@ def __init__(self, bus, clock, reset=None, reset_active_level=True, byte_size=None, byte_lanes=None, interleave=None, *args, **kwargs): self.bus = bus - self.interleave = interleave + self.interleave =interleave + if not self.interleave: + self.interleave = {} self.clock = clock self.reset = reset self.log = logging.getLogger(f"cocotb.{bus._entity._name}.{bus._name}") From 674bf70a4a40d40eed563e3be1125aff87caac95 Mon Sep 17 00:00:00 2001 From: Oliver Bunting <72926894+ollie-etl@users.noreply.github.com> Date: Thu, 16 Nov 2023 11:02:49 +0000 Subject: [PATCH 7/9] Fix typo --- cocotbext/axi/axis.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocotbext/axi/axis.py b/cocotbext/axi/axis.py index b4f7a9d..dd57cbf 100644 --- a/cocotbext/axi/axis.py +++ b/cocotbext/axi/axis.py @@ -790,7 +790,7 @@ def __init__(self, bus, clock, reset=None, reset_active_level=True, self.queue_occupancy_limit_bytes = -1 self.queue_occupancy_limit_frames = -1 - super().__init__(bus, clock, reset, reset_active_level, byte_size, byte_lanes, interleave *args, **kwargs) + super().__init__(bus, clock, reset, reset_active_level, byte_size, byte_lanes, interleave, *args, **kwargs) def full(self): if self.queue_occupancy_limit_bytes > 0 and self.queue_occupancy_bytes > self.queue_occupancy_limit_bytes: From 9dcc4c4e931887f4200367bbcc3ac2ab374261bc Mon Sep 17 00:00:00 2001 From: Oliver Bunting <72926894+ollie-etl@users.noreply.github.com> Date: Thu, 16 Nov 2023 11:13:58 +0000 Subject: [PATCH 8/9] Fix sampling --- cocotbext/axi/axis.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cocotbext/axi/axis.py b/cocotbext/axi/axis.py index dd57cbf..d0803b8 100644 --- a/cocotbext/axi/axis.py +++ b/cocotbext/axi/axis.py @@ -573,7 +573,8 @@ async def _run(self): k = None frame_offset = 0 if frames: - k, frame = choice(frames) + k = choice([frames.keys()]) + frame = frames[k] frame_offset = frame_offsets[k] if frame and not self.pause: From b00c88ae79e36b45bfe3e1a5d0c0686051ef1ebe Mon Sep 17 00:00:00 2001 From: Oliver Bunting <72926894+ollie-etl@users.noreply.github.com> Date: Thu, 16 Nov 2023 12:02:45 +0000 Subject: [PATCH 9/9] Fix type errors --- cocotbext/axi/axis.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cocotbext/axi/axis.py b/cocotbext/axi/axis.py index d0803b8..fd1f015 100644 --- a/cocotbext/axi/axis.py +++ b/cocotbext/axi/axis.py @@ -553,7 +553,7 @@ async def _run(self): # Schedule the previously popped frame if that doesn't exceed our limits if next_frame and (self.max_interleave_depth is None or len(frames) < self.max_interleave_depth): - k = (next_frame.tid if "tid" in self.interleave else None, next_frame.tdest if "tdest" in self.interleave else None) + k = (int(next_frame.tid) if "tid" in self.interleave else None, int(next_frame.tdest) if "tdest" in self.interleave else None) if frames.get(k) == None: frame = next_frame next_frame = None @@ -573,7 +573,7 @@ async def _run(self): k = None frame_offset = 0 if frames: - k = choice([frames.keys()]) + k = choice(list(frames.keys())) frame = frames[k] frame_offset = frame_offsets[k] @@ -736,8 +736,8 @@ async def _run(self): tvalid_sample = (not has_tvalid) or self.bus.tvalid.value if tready_sample and tvalid_sample: - k = (self.bus.tid.value if "tid" in self.interleave else None, self.bus.tdest.value if "tdest" in self.interleave else None) - frame = frames.pop(k) + k = (int(self.bus.tid.value) if "tid" in self.interleave else None, int(self.bus.tdest.value) if "tdest" in self.interleave else None) + frame = frames.pop(k, None) if not frame: if self.byte_size == 8: @@ -840,8 +840,8 @@ async def _run(self): tvalid_sample = (not has_tvalid) or self.bus.tvalid.value if tready_sample and tvalid_sample: - k = (self.bus.tid.value if "tid" in self.interleave else None, self.bus.tdest.value if "tdest" in self.interleave else None) - frame = frames.pop(k) + k = (int(self.bus.tid.value) if "tid" in self.interleave else None, int(self.bus.tdest.value) if "tdest" in self.interleave else None) + frame = frames.pop(k, None) if not frame: if self.byte_size == 8: