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

View File

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

View File

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

View File

@@ -157,6 +157,9 @@ class RgmiiSource(Reset):
async def _run(self): async def _run(self):
frame = None frame = None
frame_offset = 0
frame_data = None
frame_error = None
ifg_cnt = 0 ifg_cnt = 0
self.active = False self.active = False
d = 0 d = 0
@@ -192,27 +195,31 @@ class RgmiiSource(Reset):
self.mii_mode = bool(self.mii_select.value.integer) self.mii_mode = bool(self.mii_select.value.integer)
if self.mii_mode: if self.mii_mode:
mii_data = [] # convert to MII
mii_error = [] frame_data = []
frame_error = []
for b, e in zip(frame.data, frame.error): for b, e in zip(frame.data, frame.error):
mii_data.append((b & 0x0F)*0x11) frame_data.append((b & 0x0F)*0x11)
mii_data.append((b >> 4)*0x11) frame_data.append((b >> 4)*0x11)
mii_error.append(e) frame_error.append(e)
mii_error.append(e) frame_error.append(e)
frame.data = mii_data else:
frame.error = mii_error frame_data = frame.data
frame_error = frame.error
self.active = True self.active = True
frame_offset = 0
if frame is not None: if frame is not None:
d = frame.data.pop(0) d = frame_data[frame_offset]
er = frame.error.pop(0) er = frame_error[frame_offset]
en = 1 en = 1
frame_offset += 1
if frame.sim_time_sfd is None and d in (EthPre.SFD, 0xD, 0xDD): if frame.sim_time_sfd is None and d in (EthPre.SFD, 0xD, 0xDD):
frame.sim_time_sfd = get_sim_time() frame.sim_time_sfd = get_sim_time()
if not frame.data: if frame_offset >= len(frame_data):
ifg_cnt = max(self.ifg, 1) ifg_cnt = max(self.ifg, 1)
frame.sim_time_end = get_sim_time() frame.sim_time_end = get_sim_time()
frame.handle_tx_complete() 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.queue_occupancy_limit_frames = -1
self.width = len(self.data) 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_d = 0
self.idle_c = 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_d |= XgmiiCtrl.IDLE << k*8
self.idle_c |= 1 << k self.idle_c |= 1 << k
@@ -262,6 +267,7 @@ class XgmiiSource(Reset):
async def _run(self): async def _run(self):
frame = None frame = None
frame_offset = 0
ifg_cnt = 0 ifg_cnt = 0
deficit_idle_cnt = 0 deficit_idle_cnt = 0
self.active = False self.active = False
@@ -270,9 +276,9 @@ class XgmiiSource(Reset):
await RisingEdge(self.clock) await RisingEdge(self.clock)
if self.enable is None or self.enable.value: 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 # in IFG
ifg_cnt = ifg_cnt - self.byte_width ifg_cnt = ifg_cnt - self.byte_lanes
if ifg_cnt < 0: if ifg_cnt < 0:
if self.enable_dic: if self.enable_dic:
deficit_idle_cnt = max(deficit_idle_cnt+ifg_cnt, 0) deficit_idle_cnt = max(deficit_idle_cnt+ifg_cnt, 0)
@@ -306,7 +312,7 @@ class XgmiiSource(Reset):
else: else:
min_ifg = 0 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 ifg_cnt = ifg_cnt-4
frame.start_lane = 4 frame.start_lane = 4
frame.data = bytearray([XgmiiCtrl.IDLE]*4)+frame.data 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) deficit_idle_cnt = max(deficit_idle_cnt+ifg_cnt, 0)
ifg_cnt = 0 ifg_cnt = 0
self.active = True self.active = True
frame_offset = 0
else: else:
# clear counters # clear counters
deficit_idle_cnt = 0 deficit_idle_cnt = 0
@@ -325,16 +332,17 @@ class XgmiiSource(Reset):
d_val = 0 d_val = 0
c_val = 0 c_val = 0
for k in range(self.byte_width): for k in range(self.byte_lanes):
if frame is not None: 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: if frame.sim_time_sfd is None and d == EthPre.SFD:
frame.sim_time_sfd = get_sim_time() frame.sim_time_sfd = get_sim_time()
d_val |= d << k*8 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: if frame_offset >= len(frame.data):
ifg_cnt = max(self.ifg - (self.byte_width-k), 0) ifg_cnt = max(self.ifg - (self.byte_lanes-k), 0)
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
@@ -377,9 +385,14 @@ class XgmiiSink(Reset):
self.queue_occupancy_frames = 0 self.queue_occupancy_frames = 0
self.width = len(self.data) 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 self._run_cr = None
@@ -447,7 +460,7 @@ class XgmiiSink(Reset):
await RisingEdge(self.clock) await RisingEdge(self.clock)
if self.enable is None or self.enable.value: 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 d_val = (self.data.value.integer >> (offset*8)) & 0xff
c_val = (self.ctrl.value.integer >> offset) & 1 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) tb = TB(dut)
byte_width = tb.source.width // 8 byte_lanes = tb.source.byte_lanes
tb.source.ifg = ifg tb.source.ifg = ifg
tb.source.enable_dic = enable_dic 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: for test_data in test_frames:
if ifg == 0: if ifg == 0:
lane = 0 lane = 0
if force_offset_start and byte_width > 4: if force_offset_start and byte_lanes > 4:
lane = 4 lane = 4
start_lane_ref.append(lane) 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: if enable_dic:
offset = lane % 4 offset = lane % 4
if deficit_idle_count+offset >= 4: if deficit_idle_count+offset >= 4:
offset += 4 offset += 4
lane = (lane - offset) % byte_width lane = (lane - offset) % byte_lanes
deficit_idle_count = (deficit_idle_count + offset) % 4 deficit_idle_count = (deficit_idle_count + offset) % 4
else: else:
offset = lane % 4 offset = lane % 4
if offset > 0: if offset > 0:
offset += 4 offset += 4
lane = (lane - offset) % byte_width lane = (lane - offset) % byte_lanes
tb.log.info("start_lane_ref: %s", start_lane_ref) tb.log.info("start_lane_ref: %s", start_lane_ref)