4
4
import random
5
5
6
6
from bus2csr import dword2int , int2dword
7
+ from cocotbext_i3c .i3c_controller import I3cController
8
+ from cocotbext_i3c .i3c_target import I3CTarget
7
9
from interface import I3CTopTestInterface
8
10
9
11
import cocotb
10
- from cocotb .triggers import ClockCycles , Combine , Event , RisingEdge , Timer
11
-
12
- STATIC_ADDR = 0x5A
13
- VIRT_STATIC_ADDR = 0x5B
14
- DYNAMIC_ADDR = 0x52
15
- VIRT_DYNAMIC_ADDR = 0x53
12
+ from cocotb .triggers import ClockCycles , Combine , Event , Join , RisingEdge , Timer
16
13
17
14
18
15
async def write_to_indirect_fifo (tb , data = None , format = "bytes" ):
@@ -180,7 +177,7 @@ async def get_fifo_ptrs():
180
177
assert (wrptr3 , rdptr3 ) == (0 , 0 )
181
178
182
179
# If top pointer is equal to 0, then FIFO should be full after write
183
- fifo_full_at_top = ( top_ptr == 0 )
180
+ fifo_full_at_top = top_ptr == 0
184
181
185
182
# Check empty/full progression
186
183
assert (full0 , empty0 ) == (False , True )
@@ -307,12 +304,18 @@ async def test_read(dut):
307
304
assert recovery_data == device_id
308
305
309
306
# Ensure there is access to rest of basic registers
310
- hw_status = dword2int (await tb .read_csr (tb .reg_map .I3C_EC .SECFWRECOVERYIF .HW_STATUS .base_addr , 4 ))
307
+ hw_status = dword2int (
308
+ await tb .read_csr (tb .reg_map .I3C_EC .SECFWRECOVERYIF .HW_STATUS .base_addr , 4 )
309
+ )
311
310
assert hw_status == 0x0
312
311
313
312
device_status = [
314
- dword2int (await tb .read_csr (tb .reg_map .I3C_EC .SECFWRECOVERYIF .DEVICE_STATUS_0 .base_addr , 4 )),
315
- dword2int (await tb .read_csr (tb .reg_map .I3C_EC .SECFWRECOVERYIF .DEVICE_STATUS_1 .base_addr , 4 )),
313
+ dword2int (
314
+ await tb .read_csr (tb .reg_map .I3C_EC .SECFWRECOVERYIF .DEVICE_STATUS_0 .base_addr , 4 )
315
+ ),
316
+ dword2int (
317
+ await tb .read_csr (tb .reg_map .I3C_EC .SECFWRECOVERYIF .DEVICE_STATUS_1 .base_addr , 4 )
318
+ ),
316
319
]
317
320
assert device_status == [0x3 , 0x0 ] # DEVICE_STATUS_0 was earlier set to 0x3
318
321
@@ -326,9 +329,12 @@ async def test_payload_available(dut):
326
329
# Initialize
327
330
tb = await initialize (dut , timeout = 50 )
328
331
329
- payload_size = dword2int (
330
- await tb .read_csr (tb .reg_map .I3C_EC .SECFWRECOVERYIF .INDIRECT_FIFO_STATUS_4 .base_addr , 4 )
331
- ) * 4 # Multiply by 4 to get bytes from dwords
332
+ payload_size = (
333
+ dword2int (
334
+ await tb .read_csr (tb .reg_map .I3C_EC .SECFWRECOVERYIF .INDIRECT_FIFO_STATUS_4 .base_addr , 4 )
335
+ )
336
+ * 4
337
+ ) # Multiply by 4 to get bytes from dwords
332
338
333
339
payload_available = dut .xi3c_wrapper .recovery_payload_available_o
334
340
@@ -418,6 +424,86 @@ async def test_image_activated(dut):
418
424
), "Upon writing 0xFF to RECOVERY_CTRL byte 2 image_activated should be deasserted"
419
425
420
426
427
+ @cocotb .test ()
428
+ async def test_i3c_bus_traffic_during_loopback (dut ):
429
+ tb = await initialize (dut , timeout = 500 )
430
+
431
+ rtl_target_addr = 0x5A
432
+ sim_target_addr = 0x23 # Arbitrary
433
+
434
+ fbus = 12.5
435
+ i3c_controller = I3cController (
436
+ sda_i = dut .bus_sda ,
437
+ sda_o = dut .sda_sim_ctrl_i ,
438
+ scl_i = dut .bus_scl ,
439
+ scl_o = dut .scl_sim_ctrl_i ,
440
+ debug_state_o = None ,
441
+ speed = fbus * 1e6 ,
442
+ )
443
+
444
+ i3c_target = I3CTarget ( # noqa
445
+ sda_i = dut .bus_sda ,
446
+ sda_o = dut .sda_sim_target_i ,
447
+ scl_i = dut .bus_scl ,
448
+ scl_o = dut .scl_sim_target_i ,
449
+ debug_state_o = None ,
450
+ speed = fbus * 1e6 ,
451
+ address = sim_target_addr ,
452
+ )
453
+
454
+ run_target_bus_traffic = Event ()
455
+
456
+ async def target_bus_traffic (addr , run_condition ):
457
+ await run_condition .wait ()
458
+ while run_condition .is_set ():
459
+ # Send data to simulated target
460
+ await i3c_controller .i3c_write (addr , [random .randint (0 , 255 )])
461
+
462
+ fifo_size = dword2int (
463
+ await tb .read_csr (tb .reg_map .I3C_EC .SECFWRECOVERYIF .INDIRECT_FIFO_STATUS_4 .base_addr , 4 )
464
+ )
465
+
466
+ for addr in [sim_target_addr , rtl_target_addr ]:
467
+ # Random delay to start transfer in the middle of I3C transaction
468
+
469
+ for _ in range (10 ): # Arbitrary number of repetitions
470
+ payload_data = [random .randint (0 , 2 ** 32 - 1 ) for _ in range (fifo_size )]
471
+ delay_cycles = random .randint (0 , 1000 )
472
+ dut ._log .info (f"Randomized delay is { delay_cycles } clock cycles" )
473
+
474
+ # Start I3C traffic
475
+ bus_traffic = cocotb .start_soon (target_bus_traffic (addr , run_target_bus_traffic ))
476
+ run_target_bus_traffic .set ()
477
+
478
+ # Wait for random number of cycles and start write to Indirect FIFO via bypass
479
+ await ClockCycles (tb .clk , delay_cycles )
480
+ write_fifo = cocotb .start_soon (
481
+ write_to_indirect_fifo (tb , payload_data , format = "dwords" )
482
+ )
483
+
484
+ # Wait for random number of cycles and start read from Indirect FIFO via bypass
485
+ await ClockCycles (tb .clk , delay_cycles )
486
+ payload_received = []
487
+ for _ in range (fifo_size ):
488
+ d = dword2int (
489
+ await tb .read_csr (
490
+ tb .reg_map .I3C_EC .SECFWRECOVERYIF .INDIRECT_FIFO_DATA .base_addr , 4
491
+ )
492
+ )
493
+ payload_received .append (d )
494
+
495
+ # Payload write/read to I3C Core finished so disable I3C bus traffic generator
496
+ await Join (write_fifo )
497
+ run_target_bus_traffic .clear ()
498
+ await Join (bus_traffic )
499
+
500
+ dut ._log .info ("Received data: " + " " .join ([hex (w ) for w in payload_received ]))
501
+ dut ._log .info ("Expected data: " + " " .join ([hex (w ) for w in payload_data ]))
502
+ assert (
503
+ payload_data == payload_received
504
+ ), "Reiceved payload data does not match sent data!"
505
+
506
+
421
507
@cocotb .test ()
422
508
async def test_recovery_flow (dut ):
423
509
"""
@@ -479,7 +565,7 @@ async def mcu_agent():
479
565
# Write image size to Indirect FIFO Control Image size field
480
566
await tb .write_csr_field (
481
567
tb .reg_map .I3C_EC .SECFWRECOVERYIF .INDIRECT_FIFO_CTRL_1 .base_addr ,
482
- tb .reg_map .I3C_EC .SECFWRECOVERYIF .INDIRECT_FIFO_CTRL_1 .IMAGE_SIZE_LSB ,
568
+ tb .reg_map .I3C_EC .SECFWRECOVERYIF .INDIRECT_FIFO_CTRL_1 .IMAGE_SIZE ,
483
569
image_size ,
484
570
)
485
571
# Clear Indirect FIFO Reset
0 commit comments