mirror of
https://github.com/Silicon1602/srdl2sv.git
synced 2024-12-22 15:08:39 +00:00
Extend test_simple_rw_reg with 3 more tests
The following tests are now included: - Check access to registers over AHB bus - Check access to register over HW interface - Check access to register over HW interface if hw_wr-input is disabled. - Check if the slave responds with a correct error sequence if an illegal address is accessed.
This commit is contained in:
parent
ed08d4bd35
commit
4ba047dd2a
@ -3,8 +3,14 @@ import math
|
|||||||
import cocotb
|
import cocotb
|
||||||
from cocotb.triggers import Timer, RisingEdge
|
from cocotb.triggers import Timer, RisingEdge
|
||||||
|
|
||||||
# TODO: Does not yet implement HREADY_OUT == 0
|
class BusErrorResponse(Exception):
|
||||||
# TODO: Add support for HRESP (and throw error if HRESP occurs)
|
pass
|
||||||
|
|
||||||
|
class WrongErrorSequence(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class WrongHREADYOUTSequence(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
class HTRANS(Enum):
|
class HTRANS(Enum):
|
||||||
IDLE = 0
|
IDLE = 0
|
||||||
@ -59,8 +65,9 @@ class AMBA3AHBLiteDriver:
|
|||||||
await RisingEdge(self._dut.clk)
|
await RisingEdge(self._dut.clk)
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
|
if self._dut.HREADYOUT.value:
|
||||||
# Save address from previous phase
|
# Save address from previous phase
|
||||||
previous_address = hex(self._dut.HADDR.value)
|
previous_address = int(self._dut.HADDR.value)
|
||||||
|
|
||||||
# Set data for dataphase
|
# Set data for dataphase
|
||||||
self._dut.HWDATA <= (value >> (nbytes_cnt * 8))
|
self._dut.HWDATA <= (value >> (nbytes_cnt * 8))
|
||||||
@ -76,7 +83,29 @@ class AMBA3AHBLiteDriver:
|
|||||||
await RisingEdge(self._dut.clk)
|
await RisingEdge(self._dut.clk)
|
||||||
|
|
||||||
# Save into dictionary
|
# Save into dictionary
|
||||||
write_dict[previous_address] = hex(self._dut.HWDATA.value)
|
write_dict[previous_address] = int(self._dut.HWDATA.value)
|
||||||
|
|
||||||
|
# If HREADYOUT == 0 immediately after the first address phase
|
||||||
|
# this is illegal
|
||||||
|
elif nbytes_cnt == 0:
|
||||||
|
raise WrongHREADYOUTSequence
|
||||||
|
# If the slave is not yet ready, just wait
|
||||||
|
else:
|
||||||
|
await RisingEdge(self._dut.clk)
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Check for error condition
|
||||||
|
if self._dut.HRESP.value:
|
||||||
|
if self._dut.HREADYOUT.value:
|
||||||
|
raise WrongErrorSequence
|
||||||
|
|
||||||
|
await RisingEdge(self._dut.clk)
|
||||||
|
|
||||||
|
if self._dut.HREADYOUT.value:
|
||||||
|
raise BusErrorResponse
|
||||||
|
|
||||||
|
raise WrongErrorSequence
|
||||||
|
|
||||||
|
|
||||||
if nbytes_cnt >= nbytes:
|
if nbytes_cnt >= nbytes:
|
||||||
break
|
break
|
||||||
@ -113,8 +142,9 @@ class AMBA3AHBLiteDriver:
|
|||||||
await RisingEdge(self._dut.clk)
|
await RisingEdge(self._dut.clk)
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
|
if self._dut.HREADYOUT.value:
|
||||||
# Save address from previous phase
|
# Save address from previous phase
|
||||||
previous_address = hex(self._dut.HADDR.value)
|
previous_address = int(self._dut.HADDR.value)
|
||||||
|
|
||||||
# Check if we are done in next phase
|
# Check if we are done in next phase
|
||||||
if (nbytes_cnt := nbytes_cnt + step_size) >= nbytes:
|
if (nbytes_cnt := nbytes_cnt + step_size) >= nbytes:
|
||||||
@ -127,7 +157,27 @@ class AMBA3AHBLiteDriver:
|
|||||||
await RisingEdge(self._dut.clk)
|
await RisingEdge(self._dut.clk)
|
||||||
|
|
||||||
# Save into dictionary
|
# Save into dictionary
|
||||||
read_dict[previous_address] = hex(self._dut.HRDATA.value)
|
read_dict[previous_address] = int(self._dut.HRDATA.value)
|
||||||
|
# If HREADYOUT == 0 immediately after the first address phase
|
||||||
|
# this is illegal
|
||||||
|
elif nbytes_cnt == 0:
|
||||||
|
raise WrongHREADYOUTSequence
|
||||||
|
# If the slave is not yet ready, just wait
|
||||||
|
else:
|
||||||
|
await RisingEdge(self._dut.clk)
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Check for error condition
|
||||||
|
if self._dut.HRESP.value:
|
||||||
|
if self._dut.HREADYOUT.value:
|
||||||
|
raise WrongErrorSequence
|
||||||
|
|
||||||
|
await RisingEdge(self._dut.clk)
|
||||||
|
|
||||||
|
if self._dut.HREADYOUT.value:
|
||||||
|
raise BusErrorResponse
|
||||||
|
|
||||||
|
raise WrongErrorSequence
|
||||||
|
|
||||||
if nbytes_cnt >= nbytes:
|
if nbytes_cnt >= nbytes:
|
||||||
break
|
break
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
from enum import Enum
|
from enum import Enum
|
||||||
from cocotb.clock import Clock
|
from cocotb.clock import Clock
|
||||||
|
from cocotb.triggers import RisingEdge
|
||||||
import cocotb
|
import cocotb
|
||||||
import random
|
import random
|
||||||
|
|
||||||
from libs import AMBA3AHBLiteDriver
|
from libs import AMBA3AHBLiteDriver
|
||||||
|
|
||||||
@cocotb.test()
|
@cocotb.test()
|
||||||
async def test_simple_rw_reg(dut):
|
async def test_ahb_access(dut):
|
||||||
"""Test writing via the bus and reading back"""
|
"""Test writing via the bus and reading back"""
|
||||||
|
|
||||||
clock = Clock(dut.clk, 1, units="ns") # Create a 10us period clock on port clk
|
clock = Clock(dut.clk, 1, units="ns") # Create a 10us period clock on port clk
|
||||||
@ -47,5 +48,141 @@ async def test_simple_rw_reg(dut):
|
|||||||
|
|
||||||
assert write_dict == read_dict, "Read and write values differ!"
|
assert write_dict == read_dict, "Read and write values differ!"
|
||||||
|
|
||||||
|
@cocotb.test()
|
||||||
|
async def test_hw_access(dut):
|
||||||
|
"""Test writing via the hardware interface
|
||||||
|
and reading it back.
|
||||||
|
"""
|
||||||
|
|
||||||
|
clock = Clock(dut.clk, 1, units="ns") # Create a 10us period clock on port clk
|
||||||
|
cocotb.fork(clock.start()) # Start the clock
|
||||||
|
|
||||||
|
bus = AMBA3AHBLiteDriver.AMBA3AHBLiteDriver(dut=dut, nbytes=4)
|
||||||
|
|
||||||
|
await bus.reset()
|
||||||
|
|
||||||
|
write_dict = {}
|
||||||
|
read_dict = {}
|
||||||
|
|
||||||
|
# TODO: At this point, CocoTB has issues with single dimension unpacked but
|
||||||
|
# multidimensional packed arrays. Only check first dimension
|
||||||
|
dut.register_0__f1_hw_wr <= 1
|
||||||
|
dut.register_0__f2_hw_wr <= 1
|
||||||
|
|
||||||
|
rand_val = []
|
||||||
|
|
||||||
|
for addr in (0, 2):
|
||||||
|
# Save value that was written in dictionary
|
||||||
|
write_dict[addr] = random.randint(0, (1 << 16)-1)
|
||||||
|
|
||||||
|
dut.register_0__f2_in <= [write_dict[2], 0] #, write_dict[6]]
|
||||||
|
dut.register_0__f1_in <= [write_dict[0], 0] #, write_dict[4]]
|
||||||
|
|
||||||
|
await RisingEdge(dut.clk)
|
||||||
|
|
||||||
|
dut.register_0__f1_hw_wr <= 0
|
||||||
|
dut.register_0__f2_hw_wr <= 0
|
||||||
|
|
||||||
|
for addr in range(0, 4, 2):
|
||||||
|
read_dict.update(
|
||||||
|
await bus.read(
|
||||||
|
address=addr,
|
||||||
|
nbytes=2,
|
||||||
|
step_size=2))
|
||||||
|
|
||||||
|
dut._log.info(f"Wrote dictionary {write_dict}")
|
||||||
|
dut._log.info(f"Read back dictionary {read_dict}")
|
||||||
|
assert write_dict == read_dict, "Read and write values differ!"
|
||||||
|
|
||||||
|
@cocotb.test()
|
||||||
|
async def test_hw_access_hw_wr_inactive(dut):
|
||||||
|
"""Test writing via the hardware interface but
|
||||||
|
keeping the write-enable 0. The value that is
|
||||||
|
read back should *not* be the same as the value
|
||||||
|
that was fed by the testbench.
|
||||||
|
"""
|
||||||
|
|
||||||
|
clock = Clock(dut.clk, 1, units="ns") # Create a 10us period clock on port clk
|
||||||
|
cocotb.fork(clock.start()) # Start the clock
|
||||||
|
|
||||||
|
bus = AMBA3AHBLiteDriver.AMBA3AHBLiteDriver(dut=dut, nbytes=4)
|
||||||
|
|
||||||
|
await bus.reset()
|
||||||
|
|
||||||
|
write_dict = {}
|
||||||
|
read_dict = {}
|
||||||
|
|
||||||
|
# Force initial value
|
||||||
|
dut.register_0__f1_q <= [0, 0]
|
||||||
|
dut.register_0__f2_q <= [0, 0]
|
||||||
|
|
||||||
|
# Disable write
|
||||||
|
dut.register_0__f1_hw_wr <= 0
|
||||||
|
dut.register_0__f2_hw_wr <= 0
|
||||||
|
|
||||||
|
rand_val = []
|
||||||
|
|
||||||
|
for addr in (0, 2, 4, 6):
|
||||||
|
# Save value that was written in dictionary
|
||||||
|
write_dict[addr] = random.randint(0, (1 << 16)-1)
|
||||||
|
|
||||||
|
dut.register_0__f2_in <= [write_dict[2], write_dict[6]]
|
||||||
|
dut.register_0__f1_in <= [write_dict[0], write_dict[4]]
|
||||||
|
|
||||||
|
await RisingEdge(dut.clk)
|
||||||
|
|
||||||
|
dut.register_0__f1_hw_wr <= 0
|
||||||
|
dut.register_0__f2_hw_wr <= 0
|
||||||
|
|
||||||
|
for addr in range(0, 8, 2):
|
||||||
|
read_dict.update(
|
||||||
|
await bus.read(
|
||||||
|
address=addr,
|
||||||
|
nbytes=2,
|
||||||
|
step_size=2))
|
||||||
|
|
||||||
|
dut._log.info(f"Wrote dictionary {write_dict}")
|
||||||
|
dut._log.info(f"Read back dictionary {read_dict}")
|
||||||
|
assert write_dict != read_dict, "Read and write values differ!"
|
||||||
|
|
||||||
|
@cocotb.test()
|
||||||
|
async def test_illegal_address(dut):
|
||||||
|
"""Test reading and writing to an illegal address.
|
||||||
|
The logic should return a correct error sequence.
|
||||||
|
"""
|
||||||
|
|
||||||
|
clock = Clock(dut.clk, 1, units="ns") # Create a 10us period clock on port clk
|
||||||
|
cocotb.fork(clock.start()) # Start the clock
|
||||||
|
|
||||||
|
bus = AMBA3AHBLiteDriver.AMBA3AHBLiteDriver(dut=dut, nbytes=4)
|
||||||
|
await bus.reset()
|
||||||
|
|
||||||
|
rand_addr = random.randint(8, 1337)
|
||||||
|
rand_val = random.randint(0, (1 << 32)-1)
|
||||||
|
|
||||||
|
dut._log.info(f"Write value {rand_val} to illegal addres {rand_addr}.")
|
||||||
|
|
||||||
|
write_error = False
|
||||||
|
|
||||||
|
try:
|
||||||
|
await bus.write(
|
||||||
|
address=rand_addr,
|
||||||
|
value=rand_val,
|
||||||
|
nbytes=4,
|
||||||
|
step_size=4)
|
||||||
|
except AMBA3AHBLiteDriver.BusErrorResponse:
|
||||||
|
write_error = True
|
||||||
|
|
||||||
|
assert write_error == True, "Write to illegal address did not return an error!"
|
||||||
|
|
||||||
|
read_error = False
|
||||||
|
|
||||||
|
try:
|
||||||
|
await bus.read(
|
||||||
|
address=rand_addr,
|
||||||
|
nbytes=4,
|
||||||
|
step_size=4)
|
||||||
|
except AMBA3AHBLiteDriver.BusErrorResponse:
|
||||||
|
read_error = True
|
||||||
|
|
||||||
|
assert read_error == True, "Read from illegal address did not return an error!"
|
||||||
|
Loading…
Reference in New Issue
Block a user