Put sources and sinks to sleep when idle

Signed-off-by: Alex Forencich <alex@alexforencich.com>
This commit is contained in:
Alex Forencich
2023-01-24 17:42:05 -08:00
parent dd35d734f9
commit 37b23c358b
4 changed files with 73 additions and 7 deletions

View File

@@ -157,6 +157,7 @@ class GmiiSource(Reset):
self.current_frame = None self.current_frame = None
self.idle_event = Event() self.idle_event = Event()
self.idle_event.set() self.idle_event.set()
self.active_event = Event()
self.ifg = 12 self.ifg = 12
self.mii_mode = False self.mii_mode = False
@@ -189,6 +190,7 @@ class GmiiSource(Reset):
frame = GmiiFrame(frame) frame = GmiiFrame(frame)
await self.queue.put(frame) await self.queue.put(frame)
self.idle_event.clear() self.idle_event.clear()
self.active_event.set()
self.queue_occupancy_bytes += len(frame) self.queue_occupancy_bytes += len(frame)
self.queue_occupancy_frames += 1 self.queue_occupancy_frames += 1
@@ -198,6 +200,7 @@ class GmiiSource(Reset):
frame = GmiiFrame(frame) frame = GmiiFrame(frame)
self.queue.put_nowait(frame) self.queue.put_nowait(frame)
self.idle_event.clear() self.idle_event.clear()
self.active_event.set()
self.queue_occupancy_bytes += len(frame) self.queue_occupancy_bytes += len(frame)
self.queue_occupancy_frames += 1 self.queue_occupancy_frames += 1
@@ -225,6 +228,7 @@ class GmiiSource(Reset):
frame.handle_tx_complete() frame.handle_tx_complete()
self.dequeue_event.set() self.dequeue_event.set()
self.idle_event.set() self.idle_event.set()
self.active_event.clear()
self.queue_occupancy_bytes = 0 self.queue_occupancy_bytes = 0
self.queue_occupancy_frames = 0 self.queue_occupancy_frames = 0
@@ -251,6 +255,7 @@ class GmiiSource(Reset):
if self.queue.empty(): if self.queue.empty():
self.idle_event.set() self.idle_event.set()
self.active_event.clear()
else: else:
self.log.info("Reset de-asserted") self.log.info("Reset de-asserted")
if self._run_cr is None: if self._run_cr is None:
@@ -332,7 +337,11 @@ class GmiiSource(Reset):
self.er.value = 0 self.er.value = 0
self.dv.value = 0 self.dv.value = 0
self.active = False self.active = False
self.idle_event.set()
if ifg_cnt == 0 and self.queue.empty():
self.idle_event.set()
self.active_event.clear()
await self.active_event.wait()
elif self.enable is not None and not self.enable.value: elif self.enable is not None and not self.enable.value:
await enable_event await enable_event
@@ -439,6 +448,8 @@ class GmiiSink(Reset):
clock_edge_event = RisingEdge(self.clock) clock_edge_event = RisingEdge(self.clock)
active_event = RisingEdge(self.dv)
enable_event = None enable_event = None
if self.enable is not None: if self.enable is not None:
enable_event = RisingEdge(self.enable) enable_event = RisingEdge(self.enable)
@@ -503,6 +514,9 @@ class GmiiSink(Reset):
frame.data.append(d_val) frame.data.append(d_val)
frame.error.append(er_val) frame.error.append(er_val)
if not dv_val:
await active_event
elif self.enable is not None and not self.enable.value: elif self.enable is not None and not self.enable.value:
await enable_event await enable_event

View File

@@ -59,6 +59,7 @@ class MiiSource(Reset):
self.current_frame = None self.current_frame = None
self.idle_event = Event() self.idle_event = Event()
self.idle_event.set() self.idle_event.set()
self.active_event = Event()
self.ifg = 12 self.ifg = 12
@@ -90,6 +91,7 @@ class MiiSource(Reset):
frame = GmiiFrame(frame) frame = GmiiFrame(frame)
await self.queue.put(frame) await self.queue.put(frame)
self.idle_event.clear() self.idle_event.clear()
self.active_event.set()
self.queue_occupancy_bytes += len(frame) self.queue_occupancy_bytes += len(frame)
self.queue_occupancy_frames += 1 self.queue_occupancy_frames += 1
@@ -99,6 +101,7 @@ class MiiSource(Reset):
frame = GmiiFrame(frame) frame = GmiiFrame(frame)
self.queue.put_nowait(frame) self.queue.put_nowait(frame)
self.idle_event.clear() self.idle_event.clear()
self.active_event.set()
self.queue_occupancy_bytes += len(frame) self.queue_occupancy_bytes += len(frame)
self.queue_occupancy_frames += 1 self.queue_occupancy_frames += 1
@@ -126,6 +129,7 @@ class MiiSource(Reset):
frame.handle_tx_complete() frame.handle_tx_complete()
self.dequeue_event.set() self.dequeue_event.set()
self.idle_event.set() self.idle_event.set()
self.active_event.clear()
self.queue_occupancy_bytes = 0 self.queue_occupancy_bytes = 0
self.queue_occupancy_frames = 0 self.queue_occupancy_frames = 0
@@ -152,6 +156,7 @@ class MiiSource(Reset):
if self.queue.empty(): if self.queue.empty():
self.idle_event.set() self.idle_event.set()
self.active_event.clear()
else: else:
self.log.info("Reset de-asserted") self.log.info("Reset de-asserted")
if self._run_cr is None: if self._run_cr is None:
@@ -226,7 +231,11 @@ class MiiSource(Reset):
self.er.value = 0 self.er.value = 0
self.dv.value = 0 self.dv.value = 0
self.active = False self.active = False
self.idle_event.set()
if ifg_cnt == 0 and self.queue.empty():
self.idle_event.set()
self.active_event.clear()
await self.active_event.wait()
elif self.enable is not None and not self.enable.value: elif self.enable is not None and not self.enable.value:
await enable_event await enable_event
@@ -330,6 +339,8 @@ class MiiSink(Reset):
clock_edge_event = RisingEdge(self.clock) clock_edge_event = RisingEdge(self.clock)
active_event = RisingEdge(self.dv)
enable_event = None enable_event = None
if self.enable is not None: if self.enable is not None:
enable_event = RisingEdge(self.enable) enable_event = RisingEdge(self.enable)
@@ -389,6 +400,9 @@ class MiiSink(Reset):
frame.data.append(d_val) frame.data.append(d_val)
frame.error.append(er_val) frame.error.append(er_val)
if not dv_val:
await active_event
elif self.enable is not None and not self.enable.value: elif self.enable is not None and not self.enable.value:
await enable_event await enable_event

View File

@@ -61,6 +61,7 @@ class RgmiiSource(Reset):
self.current_frame = None self.current_frame = None
self.idle_event = Event() self.idle_event = Event()
self.idle_event.set() self.idle_event.set()
self.active_event = Event()
self.ifg = 12 self.ifg = 12
self.mii_mode = False self.mii_mode = False
@@ -90,6 +91,7 @@ class RgmiiSource(Reset):
frame = GmiiFrame(frame) frame = GmiiFrame(frame)
await self.queue.put(frame) await self.queue.put(frame)
self.idle_event.clear() self.idle_event.clear()
self.active_event.set()
self.queue_occupancy_bytes += len(frame) self.queue_occupancy_bytes += len(frame)
self.queue_occupancy_frames += 1 self.queue_occupancy_frames += 1
@@ -99,6 +101,7 @@ class RgmiiSource(Reset):
frame = GmiiFrame(frame) frame = GmiiFrame(frame)
self.queue.put_nowait(frame) self.queue.put_nowait(frame)
self.idle_event.clear() self.idle_event.clear()
self.active_event.set()
self.queue_occupancy_bytes += len(frame) self.queue_occupancy_bytes += len(frame)
self.queue_occupancy_frames += 1 self.queue_occupancy_frames += 1
@@ -126,6 +129,7 @@ class RgmiiSource(Reset):
frame.handle_tx_complete() frame.handle_tx_complete()
self.dequeue_event.set() self.dequeue_event.set()
self.idle_event.set() self.idle_event.set()
self.active_event.clear()
self.queue_occupancy_bytes = 0 self.queue_occupancy_bytes = 0
self.queue_occupancy_frames = 0 self.queue_occupancy_frames = 0
@@ -150,6 +154,7 @@ class RgmiiSource(Reset):
if self.queue.empty(): if self.queue.empty():
self.idle_event.set() self.idle_event.set()
self.active_event.clear()
else: else:
self.log.info("Reset de-asserted") self.log.info("Reset de-asserted")
if self._run_cr is None: if self._run_cr is None:
@@ -161,6 +166,7 @@ class RgmiiSource(Reset):
frame_data = None frame_data = None
frame_error = None frame_error = None
ifg_cnt = 0 ifg_cnt = 0
in_ifg = False
self.active = False self.active = False
d = 0 d = 0
er = 0 er = 0
@@ -187,9 +193,12 @@ class RgmiiSource(Reset):
self.ctrl.value = en ^ er self.ctrl.value = en ^ er
if self.enable is None or self.enable.value: if self.enable is None or self.enable.value:
in_ifg = False
if ifg_cnt > 0: if ifg_cnt > 0:
# in IFG # in IFG
ifg_cnt -= 1 ifg_cnt -= 1
in_ifg = True
elif frame is None and not self.queue.empty(): elif frame is None and not self.queue.empty():
# send frame # send frame
@@ -234,6 +243,7 @@ class RgmiiSource(Reset):
if frame_offset >= len(frame_data): if frame_offset >= len(frame_data):
ifg_cnt = max(self.ifg, 1) ifg_cnt = max(self.ifg, 1)
in_ifg = True
frame.sim_time_end = get_sim_time() frame.sim_time_end = get_sim_time()
frame.handle_tx_complete() frame.handle_tx_complete()
frame = None frame = None
@@ -243,7 +253,11 @@ class RgmiiSource(Reset):
er = 0 er = 0
en = 0 en = 0
self.active = False self.active = False
self.idle_event.set()
if not in_ifg and self.queue.empty():
self.idle_event.set()
self.active_event.clear()
await self.active_event.wait()
elif self.enable is not None and not self.enable.value: elif self.enable is not None and not self.enable.value:
await enable_event await enable_event
@@ -352,6 +366,8 @@ class RgmiiSink(Reset):
clock_rising_edge_event = RisingEdge(self.clock) clock_rising_edge_event = RisingEdge(self.clock)
clock_falling_edge_event = FallingEdge(self.clock) clock_falling_edge_event = FallingEdge(self.clock)
active_event = RisingEdge(self.ctrl)
enable_event = None enable_event = None
if self.enable is not None: if self.enable is not None:
enable_event = RisingEdge(self.enable) enable_event = RisingEdge(self.enable)
@@ -423,6 +439,9 @@ class RgmiiSink(Reset):
frame.data.append(d_val) frame.data.append(d_val)
frame.error.append(er_val) frame.error.append(er_val)
if not dv_val:
await active_event
elif self.enable is not None and not self.enable.value: elif self.enable is not None and not self.enable.value:
await enable_event await enable_event

View File

@@ -28,7 +28,7 @@ import zlib
import cocotb import cocotb
from cocotb.queue import Queue, QueueFull from cocotb.queue import Queue, QueueFull
from cocotb.triggers import RisingEdge, Timer, First, Event from cocotb.triggers import Edge, RisingEdge, Timer, First, Event
from cocotb.utils import get_sim_time from cocotb.utils import get_sim_time
from .version import __version__ from .version import __version__
@@ -158,6 +158,7 @@ class XgmiiSource(Reset):
self.current_frame = None self.current_frame = None
self.idle_event = Event() self.idle_event = Event()
self.idle_event.set() self.idle_event.set()
self.active_event = Event()
self.enable_dic = True self.enable_dic = True
self.ifg = 12 self.ifg = 12
@@ -200,6 +201,7 @@ class XgmiiSource(Reset):
frame = XgmiiFrame(frame) frame = XgmiiFrame(frame)
await self.queue.put(frame) await self.queue.put(frame)
self.idle_event.clear() self.idle_event.clear()
self.active_event.set()
self.queue_occupancy_bytes += len(frame) self.queue_occupancy_bytes += len(frame)
self.queue_occupancy_frames += 1 self.queue_occupancy_frames += 1
@@ -209,6 +211,7 @@ class XgmiiSource(Reset):
frame = XgmiiFrame(frame) frame = XgmiiFrame(frame)
self.queue.put_nowait(frame) self.queue.put_nowait(frame)
self.idle_event.clear() self.idle_event.clear()
self.active_event.set()
self.queue_occupancy_bytes += len(frame) self.queue_occupancy_bytes += len(frame)
self.queue_occupancy_frames += 1 self.queue_occupancy_frames += 1
@@ -236,6 +239,7 @@ class XgmiiSource(Reset):
frame.handle_tx_complete() frame.handle_tx_complete()
self.dequeue_event.set() self.dequeue_event.set()
self.idle_event.set() self.idle_event.set()
self.active_event.clear()
self.queue_occupancy_bytes = 0 self.queue_occupancy_bytes = 0
self.queue_occupancy_frames = 0 self.queue_occupancy_frames = 0
@@ -260,6 +264,7 @@ class XgmiiSource(Reset):
if self.queue.empty(): if self.queue.empty():
self.idle_event.set() self.idle_event.set()
self.active_event.clear()
else: else:
self.log.info("Reset de-asserted") self.log.info("Reset de-asserted")
if self._run_cr is None: if self._run_cr is None:
@@ -363,7 +368,11 @@ class XgmiiSource(Reset):
self.data.value = self.idle_d self.data.value = self.idle_d
self.ctrl.value = self.idle_c self.ctrl.value = self.idle_c
self.active = False self.active = False
self.idle_event.set()
if ifg_cnt == 0 and self.queue.empty():
self.idle_event.set()
self.active_event.clear()
await self.active_event.wait()
elif self.enable is not None and not self.enable.value: elif self.enable is not None and not self.enable.value:
await enable_event await enable_event
@@ -467,17 +476,24 @@ class XgmiiSink(Reset):
clock_edge_event = RisingEdge(self.clock) clock_edge_event = RisingEdge(self.clock)
active_event = First(Edge(self.data), Edge(self.ctrl))
enable_event = None enable_event = None
if self.enable is not None: if self.enable is not None:
enable_event = RisingEdge(self.enable) enable_event = RisingEdge(self.enable)
idle_d = sum([XgmiiCtrl.IDLE << n*8 for n in range(self.byte_lanes)])
idle_c = 2**self.byte_lanes-1
while True: while True:
await clock_edge_event await clock_edge_event
if self.enable is None or self.enable.value: if self.enable is None or self.enable.value:
data_val = self.data.value.integer
ctrl_val = self.ctrl.value.integer
for offset in range(self.byte_lanes): for offset in range(self.byte_lanes):
d_val = (self.data.value.integer >> (offset*8)) & 0xff d_val = (data_val >> (offset*8)) & 0xff
c_val = (self.ctrl.value.integer >> offset) & 1 c_val = (ctrl_val >> offset) & 1
if frame is None: if frame is None:
if c_val and d_val == XgmiiCtrl.START: if c_val and d_val == XgmiiCtrl.START:
@@ -511,5 +527,8 @@ class XgmiiSink(Reset):
frame.data.append(d_val) frame.data.append(d_val)
frame.ctrl.append(c_val) frame.ctrl.append(c_val)
if data_val == idle_d and ctrl_val == idle_c:
await active_event
elif self.enable is not None and not self.enable.value: elif self.enable is not None and not self.enable.value:
await enable_event await enable_event