From aa9784845096d6fae8fc5ef352dde099906dc715 Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Sun, 3 Jan 2021 23:28:33 -0800 Subject: [PATCH] Store SFD transfer sim time --- README.md | 2 ++ cocotbext/eth/gmii.py | 11 ++++++++++- cocotbext/eth/mii.py | 8 +++++++- cocotbext/eth/rgmii.py | 6 ++++++ cocotbext/eth/xgmii.py | 11 ++++++++++- 5 files changed, 35 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index d69a83c..93dcef6 100644 --- a/README.md +++ b/README.md @@ -120,6 +120,7 @@ Attributes: * `data`: bytearray * `error`: error field, optional; list, each entry qualifies the corresponding entry in `data`. * `sim_time_start`: simulation time of first transfer cycle of frame. +* `sim_time_sfd`: simulation time at which the SFD was transferred. * `sim_time_end`: simulation time of last transfer cycle of frame. * `start_lane`: byte lane in which the start control character was transferred. * `tx_complete`: event or callable triggered when frame is transmitted. @@ -387,6 +388,7 @@ Attributes: * `data`: bytearray * `ctrl`: control field, optional; list, each entry qualifies the corresponding entry in `data` as an XGMII control character. * `sim_time_start`: simulation time of first transfer cycle of frame. +* `sim_time_sfd`: simulation time at which the SFD was transferred. * `sim_time_end`: simulation time of last transfer cycle of frame. * `start_lane`: byte lane in which the start control character was transferred. * `tx_complete`: event or callable triggered when frame is transmitted. diff --git a/cocotbext/eth/gmii.py b/cocotbext/eth/gmii.py index 301f586..d3dab4a 100644 --- a/cocotbext/eth/gmii.py +++ b/cocotbext/eth/gmii.py @@ -41,6 +41,7 @@ class GmiiFrame: self.data = bytearray() self.error = None self.sim_time_start = None + self.sim_time_sfd = None self.sim_time_end = None self.tx_complete = None @@ -48,6 +49,7 @@ class GmiiFrame: self.data = bytearray(data.data) self.error = data.error self.sim_time_start = data.sim_time_start + self.sim_time_sfd = data.sim_time_sfd self.sim_time_end = data.sim_time_end self.tx_complete = data.tx_complete else: @@ -114,6 +116,7 @@ class GmiiFrame: f"{type(self).__name__}(data={self.data!r}, " f"error={self.error!r}, " f"sim_time_start={self.sim_time_start!r}, " + f"sim_time_sfd={self.sim_time_sfd!r}, " f"sim_time_end={self.sim_time_end!r})" ) @@ -253,7 +256,10 @@ class GmiiSource(Reset): self.active = True if frame is not None: - self.data <= frame.data.pop(0) + d = frame.data.pop(0) + if frame.sim_time_sfd is None and d in (EthPre.SFD, 0xD): + frame.sim_time_sfd = get_sim_time() + self.data <= d if self.er is not None: self.er <= frame.error.pop(0) self.dv <= 1 @@ -420,6 +426,9 @@ class GmiiSink(Reset): frame = None if frame is not None: + if frame.sim_time_sfd is None and d_val in (EthPre.SFD, 0xD): + frame.sim_time_sfd = get_sim_time() + frame.data.append(d_val) frame.error.append(er_val) diff --git a/cocotbext/eth/mii.py b/cocotbext/eth/mii.py index ac35eec..cfe3c4b 100644 --- a/cocotbext/eth/mii.py +++ b/cocotbext/eth/mii.py @@ -155,7 +155,10 @@ class MiiSource(Reset): self.active = True if frame is not None: - self.data <= frame.data.pop(0) + d = frame.data.pop(0) + if frame.sim_time_sfd is None and d == 0xD: + frame.sim_time_sfd = get_sim_time() + self.data <= d if self.er is not None: self.er <= frame.error.pop(0) self.dv <= 1 @@ -314,6 +317,9 @@ class MiiSink(Reset): frame = None if frame is not None: + if frame.sim_time_sfd is None and d_val == 0xD: + frame.sim_time_sfd = get_sim_time() + frame.data.append(d_val) frame.error.append(er_val) diff --git a/cocotbext/eth/rgmii.py b/cocotbext/eth/rgmii.py index 79ce798..07ad7e6 100644 --- a/cocotbext/eth/rgmii.py +++ b/cocotbext/eth/rgmii.py @@ -166,6 +166,9 @@ class RgmiiSource(Reset): er = frame.error.pop(0) en = 1 + if frame.sim_time_sfd is None and d in (EthPre.SFD, 0xD, 0xDD): + frame.sim_time_sfd = get_sim_time() + if not frame.data: ifg_cnt = max(self.ifg, 1) frame.sim_time_end = get_sim_time() @@ -339,6 +342,9 @@ class RgmiiSink(Reset): frame = None if frame is not None: + if frame.sim_time_sfd is None and d_val in (EthPre.SFD, 0xD, 0xDD): + frame.sim_time_sfd = get_sim_time() + frame.data.append(d_val) frame.error.append(er_val) diff --git a/cocotbext/eth/xgmii.py b/cocotbext/eth/xgmii.py index a196007..20466dc 100644 --- a/cocotbext/eth/xgmii.py +++ b/cocotbext/eth/xgmii.py @@ -41,6 +41,7 @@ class XgmiiFrame: self.data = bytearray() self.ctrl = None self.sim_time_start = None + self.sim_time_sfd = None self.sim_time_end = None self.start_lane = None self.tx_complete = None @@ -49,6 +50,7 @@ class XgmiiFrame: self.data = bytearray(data.data) self.ctrl = data.ctrl self.sim_time_start = data.sim_time_start + self.sim_time_sfd = data.sim_time_sfd self.sim_time_end = data.sim_time_end self.start_lane = data.start_lane self.tx_complete = data.tx_complete @@ -116,6 +118,7 @@ class XgmiiFrame: f"{type(self).__name__}(data={self.data!r}, " f"ctrl={self.ctrl!r}, " f"sim_time_start={self.sim_time_start!r}, " + f"sim_time_sfd={self.sim_time_sfd!r}, " f"sim_time_end={self.sim_time_end!r}, " f"start_lane={self.start_lane!r})" ) @@ -281,7 +284,10 @@ class XgmiiSource(Reset): for k in range(self.byte_width): if frame is not None: - d_val |= frame.data.pop(0) << k*8 + d = frame.data.pop(0) + if frame.sim_time_sfd is None and d == EthPre.SFD: + frame.sim_time_sfd = get_sim_time() + d_val |= d << k*8 c_val |= frame.ctrl.pop(0) << k if not frame.data: @@ -422,5 +428,8 @@ class XgmiiSink(Reset): frame = None else: + if frame.sim_time_sfd is None and d_val == EthPre.SFD: + frame.sim_time_sfd = get_sim_time() + frame.data.append(d_val) frame.ctrl.append(c_val)