Skip to content

Commit 86c038d

Browse files
committed
umi2apb bug fix
1 parent 525a2eb commit 86c038d

11 files changed

Lines changed: 283 additions & 246 deletions

File tree

‎pyproject.toml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ test = [
3737
"cocotb-bus==0.3.0",
3838
"cocotbext-axi==0.1.28",
3939
"cocotbext-umi==0.0.3",
40-
"cocotbext-apb==0.7.4"
40+
"cocotbext-apb==0.11.0"
4141
]
4242

4343
[tool.check-wheel-contents]

‎tests/adapters/umi2apb/__init__.py‎

Lines changed: 0 additions & 6 deletions
This file was deleted.

‎tests/adapters/umi2apb/env.py‎

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,40 @@
22
# and provides common functionality for the tests.
33

44
from cocotb.clock import Clock
5-
from cocotb.triggers import ClockCycles
5+
from cocotb.triggers import ClockCycles, Timer
66

77
from cocotb_bus.scoreboard import Scoreboard
88
from cocotbext.apb import ApbBus, ApbSlave, MemoryRegion
99

10-
from cocotblib.umi.drivers.sumi_driver import SumiDriver
11-
from cocotblib.umi.monitors.sumi_monitor import SumiMonitor
12-
from cocotblib.umi.sumi import SumiTransaction, SumiCmdType, SumiCmd
13-
from cocotblib.common import drive_reset
10+
from cocotbext.umi.drivers.sumi_driver import SumiDriver
11+
from cocotbext.umi.monitors.sumi_monitor import SumiMonitor
12+
from cocotbext.umi.sumi import SumiTransaction, SumiCmdType, SumiCmd
13+
14+
15+
async def do_reset(reset, time_ns: int, active_level: bool = False):
16+
"""Drive an asynchronous reset pulse on *reset*."""
17+
reset.value = not active_level
18+
await Timer(1, unit="step")
19+
reset.value = active_level
20+
await Timer(time_ns, "ns")
21+
reset.value = not active_level
22+
await Timer(1, unit="step")
1423

1524

1625
# Creates the umi2apb test environment
1726
class UMI2APBEnv:
18-
def __init__(self, dut, clk_period_ns=10, mem_size=2**16):
27+
def __init__(
28+
self,
29+
dut,
30+
clk_period_ns=10,
31+
mem_size=2**16,
32+
umi_valid_gen=None,
33+
backpressure_on_apb=True
34+
):
1935
self.dut = dut
2036
self.clk_period_ns = clk_period_ns
2137
self.mem_size = mem_size
38+
self.umi_valid_gen = umi_valid_gen
2239

2340
self.data_width = int(dut.RW.value) # default of 64
2441
self.addr_width = int(dut.AW.value) # default of 64
@@ -29,22 +46,20 @@ def __init__(self, dut, clk_period_ns=10, mem_size=2**16):
2946
self.clk = dut.apb_pclk
3047
self.nreset = dut.apb_nreset
3148

32-
self._build()
33-
34-
def _build(self):
35-
dut = self.dut
36-
3749
# Instantiates UMI driver
3850
self.sumi_driver = SumiDriver(
3951
entity=dut,
4052
name="udev_req",
4153
clock=self.clk,
42-
bus_separator="_"
54+
bus_separator="_",
55+
valid_generator=self.umi_valid_gen,
4356
)
4457

4558
# Instantiates APB slave and memory region
4659
apb_bus = ApbBus.from_prefix(dut, "apb")
4760
self.apb_slave = ApbSlave(apb_bus, self.clk, self.nreset)
61+
if backpressure_on_apb:
62+
self.apb_slave.enable_backpressure()
4863
self.region = MemoryRegion(self.mem_size)
4964
self.apb_slave.target = self.region
5065

@@ -62,21 +77,9 @@ def _build(self):
6277

6378
# Prerequisites for starting tests
6479
async def start(self):
80+
await do_reset(self.nreset, self.clk_period_ns)
6581
Clock(self.clk, self.clk_period_ns, unit="ns").start()
66-
await drive_reset(self.nreset, self.clk_period_ns)
67-
self.dut.udev_resp_ready.value = 1
68-
69-
# Waits for umi responses
70-
async def wait_for_responses(self, max_cycles):
71-
cycles = 0
72-
while self.expected_responses:
73-
await ClockCycles(self.clk, 1)
74-
cycles += 1
75-
if cycles > max_cycles:
76-
raise TimeoutError(
77-
f"Timeout waiting for responses "
78-
f"({len(self.expected_responses)} remaining)"
79-
)
82+
await ClockCycles(self.clk, 10)
8083

8184

8285
# Creates an ideal umi write response

‎tests/adapters/umi2apb/test_backpressure.py‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@
44
from cocotb.handle import SimHandleBase
55
from cocotb.triggers import ClockCycles
66

7-
from cocotblib.umi.sumi import SumiTransaction, SumiCmdType, SumiCmd
8-
from adapters.umi2apb.env import UMI2APBEnv, create_expected_write_response
7+
from cocotbext.umi.sumi import SumiTransaction, SumiCmdType, SumiCmd
8+
from env import UMI2APBEnv, create_expected_write_response
99

1010

11-
@cocotb.test(timeout_time=50, timeout_unit="ms")
11+
@cocotb.test(timeout_time=1, timeout_unit="ms")
1212
async def test_backpressure(dut: SimHandleBase):
1313
"""
1414
Test response backpressure handling:
@@ -54,7 +54,7 @@ async def test_backpressure(dut: SimHandleBase):
5454
env.sumi_driver.append(write_txn)
5555
print(f"Sent write: addr=0x{test_addr:x}, data=0x{test_data:08x}")
5656

57-
await ClockCycles(env.clk, 20)
57+
await ClockCycles(env.clk, 200)
5858

5959
# Verify response is being held
6060
assert dut.udev_resp_valid.value == 1, "Response should be valid"
@@ -65,7 +65,7 @@ async def test_backpressure(dut: SimHandleBase):
6565
dut.udev_resp_ready.value = 1
6666
print("Re-enabled udev_resp_ready")
6767

68-
await env.wait_for_responses(max_cycles=10)
68+
await ClockCycles(env.clk, 100)
6969

7070
# Verify mem was written correctly
7171
mem_data = await env.region.read(test_addr, env.data_size)

‎tests/adapters/umi2apb/test_basic_WR.py‎

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@
22
import cocotb
33

44
from cocotb.handle import SimHandleBase
5+
from cocotb.triggers import ClockCycles
6+
from cocotb_bus.drivers import BitDriver
57

6-
from cocotblib.umi.sumi import SumiTransaction, SumiCmdType, SumiCmd
7-
from adapters.umi2apb.env import UMI2APBEnv, create_expected_write_response
8+
from cocotbext.umi.sumi import SumiTransaction, SumiCmdType, SumiCmd
9+
from cocotbext.umi.utils.generators import random_toggle_generator
10+
from env import UMI2APBEnv, create_expected_write_response
811

912

1013
@cocotb.test(timeout_time=50, timeout_unit="ms")
@@ -21,6 +24,10 @@ async def test_basic_WR(dut: SimHandleBase):
2124
env = UMI2APBEnv(dut)
2225
await env.start()
2326

27+
BitDriver(signal=dut.udev_resp_ready, clk=env.clk).start(
28+
generator=random_toggle_generator()
29+
)
30+
2431
umi_size = int(math.log2(env.data_size))
2532
test_addr = 0x100
2633
test_data = 0xDEADBEEF
@@ -47,10 +54,8 @@ async def test_basic_WR(dut: SimHandleBase):
4754
)
4855
)
4956

50-
env.sumi_driver.append(write_txn)
51-
52-
# Wait for write response
53-
await env.wait_for_responses(max_cycles=100)
57+
await env.sumi_driver.send(write_txn)
58+
await ClockCycles(env.clk, 20)
5459

5560
# Verify APB memory contents
5661
mem_data = await env.region.read(test_addr, env.data_size)
@@ -89,10 +94,13 @@ async def test_basic_WR(dut: SimHandleBase):
8994
)
9095

9196
env.expected_responses.append(expected_read_resp)
92-
env.sumi_driver.append(read_txn)
97+
await env.sumi_driver.send(read_txn)
98+
99+
# Wait for scoreboard to consume all expected outputs
100+
while len(env.expected_responses) != 0:
101+
await ClockCycles(env.clk, 1)
93102

94-
# Wait for read response
95-
await env.wait_for_responses(max_cycles=100)
103+
await ClockCycles(env.clk, 10)
96104

97105
print("Read response verified by scoreboard")
98106

‎tests/adapters/umi2apb/test_full_throughput.py‎

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import math
22
import cocotb
33

4-
from adapters.umi2apb.env import UMI2APBEnv
5-
from cocotblib.umi.sumi import SumiTransaction, SumiCmdType, SumiCmd
4+
from cocotb.triggers import Event, Combine, ClockCycles
5+
6+
from env import UMI2APBEnv
7+
from cocotbext.umi.sumi import SumiTransaction, SumiCmdType, SumiCmd
68

79

810
@cocotb.test(timeout_time=50, timeout_unit="ms")
@@ -16,6 +18,9 @@ async def test_full_throughput(dut):
1618
env = UMI2APBEnv(dut)
1719
await env.start()
1820

21+
# Always ready to accept responses
22+
dut.udev_resp_ready.value = 1
23+
1924
data_size = env.data_size
2025
addr_width = env.addr_width
2126
umi_size = int(math.log2(data_size))
@@ -24,6 +29,7 @@ async def test_full_throughput(dut):
2429

2530
print("=== Back-to-Back Full Throughput Test ===")
2631

32+
send_events = []
2733
for i in range(num_transactions):
2834
txn_size = i % (umi_size + 1)
2935
txn_bytes = 1 << txn_size
@@ -81,10 +87,15 @@ async def test_full_throughput(dut):
8187
)
8288

8389
env.expected_responses.append(expected_resp)
84-
env.sumi_driver.append(txn)
90+
evt = Event()
91+
env.sumi_driver.append(txn, event=evt)
92+
send_events.append(evt)
8593

8694
# Wait for all responses
87-
await env.wait_for_responses(max_cycles=num_transactions * 50)
95+
await Combine(*(e.wait() for e in send_events))
96+
97+
await ClockCycles(env.clk, 100)
8898

8999
print(f" All {num_transactions} back-to-back transactions completed successfully!")
100+
90101
raise env.scoreboard.result

‎tests/adapters/umi2apb/test_posted_write.py‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22
import cocotb
33

44
from cocotb.handle import SimHandleBase
5+
from cocotb_bus.drivers import BitDriver
56
from cocotb.triggers import ClockCycles
67

7-
from cocotblib.umi.sumi import SumiTransaction, SumiCmdType, SumiCmd
8-
from adapters.umi2apb.env import UMI2APBEnv
8+
from cocotbext.umi.sumi import SumiTransaction, SumiCmdType, SumiCmd
9+
from cocotbext.umi.utils.generators import random_toggle_generator
10+
from env import UMI2APBEnv
911

1012

1113
@cocotb.test(timeout_time=50, timeout_unit="ms")
@@ -19,6 +21,10 @@ async def test_posted_write(dut: SimHandleBase):
1921
env = UMI2APBEnv(dut)
2022
await env.start()
2123

24+
BitDriver(signal=dut.udev_resp_ready, clk=env.clk).start(
25+
generator=random_toggle_generator()
26+
)
27+
2228
umi_size = int(math.log2(env.data_size))
2329

2430
print("=== Posted Write Test ===")

0 commit comments

Comments
 (0)