5 Commits

Author SHA1 Message Date
Alex Forencich
de18e62024 Release v0.1.14 2021-04-12 18:18:26 -07:00
Alex Forencich
14738c1dae Print model configuration 2021-04-12 18:18:01 -07:00
Alex Forencich
3d43812c7b Rename byte_width to byte_lanes 2021-04-12 15:17:02 -07:00
Alex Forencich
008d903bb9 Send data without using pop 2021-04-12 15:10:52 -07:00
Alex Forencich
0bd66da868 Bump to dev version 2021-04-01 15:29:03 -07:00
7 changed files with 97 additions and 55 deletions

View File

@@ -172,6 +172,10 @@ class EthMacTx(Reset):
self.log.info(" tuser width: %d bits", len(self.bus.tuser))
else:
self.log.info(" tuser: not present")
if self.ptp_time:
self.log.info(" ptp_time width: %d bits", len(self.ptp_time))
else:
self.log.info(" ptp_time: not present")
if self.bus.tready is None:
raise ValueError("tready is required")
@@ -378,6 +382,10 @@ class EthMacRx(Reset):
self.log.info(" tuser width: %d bits", len(self.bus.tuser))
else:
self.log.info(" tuser: not present")
if self.ptp_time:
self.log.info(" ptp_time width: %d bits", len(self.ptp_time))
else:
self.log.info(" ptp_time: not present")
if self.byte_size != 8:
raise ValueError("Byte size must be 8")
@@ -462,6 +470,7 @@ class EthMacRx(Reset):
async def _run(self):
frame = None
frame_offset = 0
tuser = 0
self.active = False
@@ -477,6 +486,7 @@ class EthMacRx(Reset):
frame.sim_time_sfd = None
frame.sim_time_end = None
self.log.info("TX frame: %s", frame)
frame_offset = 0
# wait for preamble time
await Timer(self.time_scale*8*8//self.speed, 'step')
@@ -499,11 +509,12 @@ class EthMacRx(Reset):
cycle.tuser = tuser
for offset in range(self.byte_lanes):
cycle.tdata |= (frame.data.pop(0) & self.byte_mask) << (offset * self.byte_size)
cycle.tdata |= (frame.data[frame_offset] & self.byte_mask) << (offset * self.byte_size)
cycle.tkeep |= 1 << offset
byte_count += 1
frame_offset += 1
if len(frame.data) == 0:
if frame_offset >= len(frame.data):
cycle.tlast = 1
frame.sim_time_end = get_sim_time()
frame.handle_tx_complete()

View File

@@ -258,6 +258,9 @@ class GmiiSource(Reset):
async def _run(self):
frame = None
frame_offset = 0
frame_data = None
frame_error = None
ifg_cnt = 0
self.active = False
@@ -286,28 +289,32 @@ class GmiiSource(Reset):
self.mii_mode = bool(self.mii_select.value.integer)
if self.mii_mode:
mii_data = []
mii_error = []
# convert to MII
frame_data = []
frame_error = []
for b, e in zip(frame.data, frame.error):
mii_data.append(b & 0x0F)
mii_data.append(b >> 4)
mii_error.append(e)
mii_error.append(e)
frame.data = mii_data
frame.error = mii_error
frame_data.append(b & 0x0F)
frame_data.append(b >> 4)
frame_error.append(e)
frame_error.append(e)
else:
frame_data = frame.data
frame_error = frame.error
self.active = True
frame_offset = 0
if frame is not None:
d = frame.data.pop(0)
d = frame_data[frame_offset]
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.er <= frame_error[frame_offset]
self.dv <= 1
frame_offset += 1
if not frame.data:
if frame_offset >= len(frame_data):
ifg_cnt = max(self.ifg, 1)
frame.sim_time_end = get_sim_time()
frame.handle_tx_complete()

View File

@@ -159,6 +159,9 @@ class MiiSource(Reset):
async def _run(self):
frame = None
frame_offset = 0
frame_data = None
frame_error = None
ifg_cnt = 0
self.active = False
@@ -183,28 +186,29 @@ class MiiSource(Reset):
self.log.info("TX frame: %s", frame)
frame.normalize()
mii_data = []
mii_error = []
# convert to MII
frame_data = []
frame_error = []
for b, e in zip(frame.data, frame.error):
mii_data.append(b & 0x0F)
mii_data.append(b >> 4)
mii_error.append(e)
mii_error.append(e)
frame.data = mii_data
frame.error = mii_error
frame_data.append(b & 0x0F)
frame_data.append(b >> 4)
frame_error.append(e)
frame_error.append(e)
self.active = True
frame_offset = 0
if frame is not None:
d = frame.data.pop(0)
d = frame_data[frame_offset]
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.er <= frame_error[frame_offset]
self.dv <= 1
frame_offset += 1
if not frame.data:
if frame_offset >= len(frame_data):
ifg_cnt = max(self.ifg, 1)
frame.sim_time_end = get_sim_time()
frame.handle_tx_complete()

View File

@@ -157,6 +157,9 @@ class RgmiiSource(Reset):
async def _run(self):
frame = None
frame_offset = 0
frame_data = None
frame_error = None
ifg_cnt = 0
self.active = False
d = 0
@@ -192,27 +195,31 @@ class RgmiiSource(Reset):
self.mii_mode = bool(self.mii_select.value.integer)
if self.mii_mode:
mii_data = []
mii_error = []
# convert to MII
frame_data = []
frame_error = []
for b, e in zip(frame.data, frame.error):
mii_data.append((b & 0x0F)*0x11)
mii_data.append((b >> 4)*0x11)
mii_error.append(e)
mii_error.append(e)
frame.data = mii_data
frame.error = mii_error
frame_data.append((b & 0x0F)*0x11)
frame_data.append((b >> 4)*0x11)
frame_error.append(e)
frame_error.append(e)
else:
frame_data = frame.data
frame_error = frame.error
self.active = True
frame_offset = 0
if frame is not None:
d = frame.data.pop(0)
er = frame.error.pop(0)
d = frame_data[frame_offset]
er = frame_error[frame_offset]
en = 1
frame_offset += 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:
if frame_offset >= len(frame_data):
ifg_cnt = max(self.ifg, 1)
frame.sim_time_end = get_sim_time()
frame.handle_tx_complete()

View File

@@ -1 +1 @@
__version__ = "0.1.12"
__version__ = "0.1.14"

View File

@@ -170,14 +170,19 @@ class XgmiiSource(Reset):
self.queue_occupancy_limit_frames = -1
self.width = len(self.data)
self.byte_width = len(self.ctrl)
self.byte_size = 8
self.byte_lanes = len(self.ctrl)
assert self.width == self.byte_width * 8
assert self.width == self.byte_lanes * self.byte_size
self.log.info("XGMII source model configuration")
self.log.info(" Byte size: %d bits", self.byte_size)
self.log.info(" Data width: %d bits (%d bytes)", self.width, self.byte_lanes)
self.idle_d = 0
self.idle_c = 0
for k in range(self.byte_width):
for k in range(self.byte_lanes):
self.idle_d |= XgmiiCtrl.IDLE << k*8
self.idle_c |= 1 << k
@@ -262,6 +267,7 @@ class XgmiiSource(Reset):
async def _run(self):
frame = None
frame_offset = 0
ifg_cnt = 0
deficit_idle_cnt = 0
self.active = False
@@ -270,9 +276,9 @@ class XgmiiSource(Reset):
await RisingEdge(self.clock)
if self.enable is None or self.enable.value:
if ifg_cnt + deficit_idle_cnt > self.byte_width-1 or (not self.enable_dic and ifg_cnt > 4):
if ifg_cnt + deficit_idle_cnt > self.byte_lanes-1 or (not self.enable_dic and ifg_cnt > 4):
# in IFG
ifg_cnt = ifg_cnt - self.byte_width
ifg_cnt = ifg_cnt - self.byte_lanes
if ifg_cnt < 0:
if self.enable_dic:
deficit_idle_cnt = max(deficit_idle_cnt+ifg_cnt, 0)
@@ -306,7 +312,7 @@ class XgmiiSource(Reset):
else:
min_ifg = 0
if self.byte_width > 4 and (ifg_cnt > min_ifg or self.force_offset_start):
if self.byte_lanes > 4 and (ifg_cnt > min_ifg or self.force_offset_start):
ifg_cnt = ifg_cnt-4
frame.start_lane = 4
frame.data = bytearray([XgmiiCtrl.IDLE]*4)+frame.data
@@ -316,6 +322,7 @@ class XgmiiSource(Reset):
deficit_idle_cnt = max(deficit_idle_cnt+ifg_cnt, 0)
ifg_cnt = 0
self.active = True
frame_offset = 0
else:
# clear counters
deficit_idle_cnt = 0
@@ -325,16 +332,17 @@ class XgmiiSource(Reset):
d_val = 0
c_val = 0
for k in range(self.byte_width):
for k in range(self.byte_lanes):
if frame is not None:
d = frame.data.pop(0)
d = frame.data[frame_offset]
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
c_val |= frame.ctrl[frame_offset] << k
frame_offset += 1
if not frame.data:
ifg_cnt = max(self.ifg - (self.byte_width-k), 0)
if frame_offset >= len(frame.data):
ifg_cnt = max(self.ifg - (self.byte_lanes-k), 0)
frame.sim_time_end = get_sim_time()
frame.handle_tx_complete()
frame = None
@@ -377,9 +385,14 @@ class XgmiiSink(Reset):
self.queue_occupancy_frames = 0
self.width = len(self.data)
self.byte_width = len(self.ctrl)
self.byte_size = 8
self.byte_lanes = len(self.ctrl)
assert self.width == self.byte_width * 8
assert self.width == self.byte_lanes * self.byte_size
self.log.info("XGMII sink model configuration")
self.log.info(" Byte size: %d bits", self.byte_size)
self.log.info(" Data width: %d bits (%d bytes)", self.width, self.byte_lanes)
self._run_cr = None
@@ -447,7 +460,7 @@ class XgmiiSink(Reset):
await RisingEdge(self.clock)
if self.enable is None or self.enable.value:
for offset in range(self.byte_width):
for offset in range(self.byte_lanes):
d_val = (self.data.value.integer >> (offset*8)) & 0xff
c_val = (self.ctrl.value.integer >> offset) & 1

View File

@@ -123,7 +123,7 @@ async def run_test_alignment(dut, payload_data=None, ifg=12, enable_dic=True,
tb = TB(dut)
byte_width = tb.source.width // 8
byte_lanes = tb.source.byte_lanes
tb.source.ifg = ifg
tb.source.enable_dic = enable_dic
@@ -164,23 +164,23 @@ async def run_test_alignment(dut, payload_data=None, ifg=12, enable_dic=True,
for test_data in test_frames:
if ifg == 0:
lane = 0
if force_offset_start and byte_width > 4:
if force_offset_start and byte_lanes > 4:
lane = 4
start_lane_ref.append(lane)
lane = (lane + len(test_data)+4+ifg) % byte_width
lane = (lane + len(test_data)+4+ifg) % byte_lanes
if enable_dic:
offset = lane % 4
if deficit_idle_count+offset >= 4:
offset += 4
lane = (lane - offset) % byte_width
lane = (lane - offset) % byte_lanes
deficit_idle_count = (deficit_idle_count + offset) % 4
else:
offset = lane % 4
if offset > 0:
offset += 4
lane = (lane - offset) % byte_width
lane = (lane - offset) % byte_lanes
tb.log.info("start_lane_ref: %s", start_lane_ref)