Skip to content

Commit

Permalink
Merge pull request chipsalliance#126 from antmicro/mczyz/lib-tests
Browse files Browse the repository at this point in the history
AXI to AHB converter tests
  • Loading branch information
mkurc-ant authored Oct 9, 2023
2 parents 446faa8 + a0d0af1 commit 3cd9d9d
Show file tree
Hide file tree
Showing 20 changed files with 1,663 additions and 0 deletions.
1 change: 1 addition & 0 deletions .github/workflows/test-uarch.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ jobs:
- "block/exu_div"
- "block/iccm"
- "block/dccm"
- "block/lib_axi4_to_ahb"
env:
CCACHE_DIR: "/opt/verification/.cache/"
VERILATOR_VERSION: v5.010
Expand Down
17 changes: 17 additions & 0 deletions verification/block/lib_axi4_to_ahb/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@

null :=
space := $(null) #
comma := ,

CURDIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST))))
SRCDIR := $(abspath $(CURDIR)../../../../design)

TEST_FILES = $(sort $(wildcard test_*.py))

MODULE ?= $(subst $(space),$(comma),$(subst .py,,$(TEST_FILES)))
TOPLEVEL = axi4_to_ahb

VERILOG_SOURCES = \
$(SRCDIR)/lib/axi4_to_ahb.sv

include $(CURDIR)/../common.mk
71 changes: 71 additions & 0 deletions verification/block/lib_axi4_to_ahb/ahb_lite_agent.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Copyright (c) 2023 Antmicro <www.antmicro.com>
# SPDX-License-Identifier: Apache-2.0

import cocotb
from ahb_lite_bfm import AHBLiteBFM
from cocotb.queue import QueueEmpty
from cocotb.triggers import RisingEdge
from common import BaseMonitor, get_int
from pyuvm import ConfigDB, uvm_agent, uvm_analysis_port, uvm_driver, uvm_sequencer


class AHBLiteAgent(uvm_agent):
"""
Seqr <---> Driver
Monitor <--^
"""

def build_phase(self):
self.seqr = uvm_sequencer("seqr", self)
ConfigDB().set(None, "*", "ahb_seqr", self.seqr)
self.monitor = AHBLiteMonitor("axi_w_agent", self)
self.driver = AHBLiteDriver("axi_w_driver", self)

def connect_phase(self):
self.driver.seq_item_port.connect(self.seqr.seq_item_export)


class AHBLiteDriver(uvm_driver):
def build_phase(self):
self.ap = uvm_analysis_port("ap", self)
self.rst_n = cocotb.top.rst_l
self.clk = cocotb.top.clk

def start_of_simulation_phase(self):
self.bfm = AHBLiteBFM()

async def run_phase(self):
self.bfm.start_bfm()
while True:
if get_int(self.rst_n) == 0:
await RisingEdge(self.rst_n)
self.logger.info("Agent: AHB Lite: Reset Posedge")

await RisingEdge(self.clk)
try:
response = self.bfm.rsp_driver_q.get_nowait()
self.seq_item_port.put_response(response)
# Expect two items per one response (hready is asserted for 2 cycles)
for _ in range(2):
item = await self.seq_item_port.get_next_item()
await self.drive(item)
self.logger.debug(f"Driven: {item}")
self.seq_item_port.item_done()
except QueueEmpty:
pass

async def drive(self, item):
await self.bfm.req_driver_q_put(
item.ahb_hrdata,
item.ahb_hready,
item.ahb_hresp,
)


class AHBLiteMonitor(BaseMonitor):
def __init__(self, name, parent):
super().__init__(name, parent)

def build_phase(self):
super().build_phase()
self.bfm = AHBLiteBFM()
98 changes: 98 additions & 0 deletions verification/block/lib_axi4_to_ahb/ahb_lite_bfm.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# Copyright (c) 2023 Antmicro <www.antmicro.com>
# SPDX-License-Identifier: Apache-2.0

import cocotb
from ahb_lite_pkg import (
AHB_LITE_NOTIFICATION,
AHB_LITE_RESPONSE_CODES,
AHB_LITE_TRANSFER_TYPE_ENCODING,
AHB_RSP_SIGNALS,
)
from cocotb.queue import QueueEmpty
from cocotb.triggers import RisingEdge
from common import get_int, get_signals
from pyuvm import UVMQueue, utility_classes


class AHBLiteBFM(metaclass=utility_classes.Singleton):
def __init__(self):
self.dut = cocotb.top
self.rst_n = cocotb.top.rst_l
self.clk = cocotb.top.clk
self.req_driver_q = UVMQueue(maxsize=1)
self.rsp_driver_q = UVMQueue()
self.req_monitor_q = UVMQueue()
self.rsp_monitor_q = UVMQueue()

async def req_driver_q_put(self, ahb_hrdata, ahb_hready, ahb_hresp):
item = (ahb_hrdata, ahb_hready, ahb_hresp)
await self.req_driver_q.put(item)

async def req_monitor_q_get(self):
item = await self.req_monitor_q.get()
return item

async def rsp_monitor_q_get(self):
result = await self.rsp_monitor_q.get()
return result

async def drive(self):
prev_htrans = AHB_LITE_TRANSFER_TYPE_ENCODING.IDLE
htrans = AHB_LITE_TRANSFER_TYPE_ENCODING.IDLE

while True:
if self.rst_n.value == 0:
self.dut.ahb_hrdata.value = 0
self.dut.ahb_hready.value = 0
self.dut.ahb_hresp.value = 0
await RisingEdge(self.rst_n)
await RisingEdge(self.clk)

prev_htrans = htrans
if get_int(self.dut.ahb_htrans) == AHB_LITE_TRANSFER_TYPE_ENCODING.IDLE:
htrans = AHB_LITE_TRANSFER_TYPE_ENCODING.IDLE
self.dut.ahb_hrdata.value = 0
self.dut.ahb_hready.value = 0
self.dut.ahb_hresp.value = AHB_LITE_RESPONSE_CODES.OKAY
elif get_int(self.dut.ahb_htrans) == AHB_LITE_TRANSFER_TYPE_ENCODING.NONSEQ:
htrans = AHB_LITE_TRANSFER_TYPE_ENCODING.NONSEQ
if get_int(self.dut.ahb_hwrite):
if htrans != prev_htrans:
self.rsp_driver_q.put_nowait(AHB_LITE_NOTIFICATION.AHB_LITE_WRITE)
else:
if htrans != prev_htrans:
self.rsp_driver_q.put_nowait(AHB_LITE_NOTIFICATION.AHB_LITE_READ)

try:
(ahb_hrdata, ahb_hready, ahb_hresp) = self.req_driver_q.get_nowait()
self.dut.ahb_hrdata.value = ahb_hrdata
self.dut.ahb_hready.value = ahb_hready
self.dut.ahb_hresp.value = ahb_hresp
except QueueEmpty:
self.dut.ahb_hrdata.value = 0
self.dut.ahb_hready.value = 0
self.dut.ahb_hresp.value = 0

async def req_monitor_q_bfm(self):
while True:
await RisingEdge(self.clk)
if get_int(self.dut.ahb_hready):
item = (
get_int(self.dut.ahb_hrdata),
get_int(self.dut.ahb_hready),
get_int(self.dut.ahb_hresp),
)
await self.req_monitor_q.put(item)

async def rsp_monitor_q_bfm(self):
while True:
await RisingEdge(self.clk)
if get_int(self.dut.ahb_hready):
sigs = get_signals(AHB_RSP_SIGNALS, self.dut)
values = tuple(sig.value for sig in sigs)
await self.rsp_monitor_q.put(values)

def start_bfm(self):
cocotb.start_soon(self.drive())
cocotb.start_soon(self.req_monitor_q_bfm())
cocotb.start_soon(self.rsp_monitor_q_bfm())
39 changes: 39 additions & 0 deletions verification/block/lib_axi4_to_ahb/ahb_lite_pkg.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Copyright (c) 2023 Antmicro <www.antmicro.com>
# SPDX-License-Identifier: Apache-2.0


from enum import IntEnum

AHB_DRV_SIGNALS = [
"ahb_hrdata",
"ahb_hready",
"ahb_hresp",
]

AHB_RSP_SIGNALS = [
"ahb_haddr",
"ahb_hburst",
"ahb_hmastlock",
"ahb_hprot",
"ahb_hsize",
"ahb_htrans",
"ahb_hwrite",
"ahb_hwdata",
]


class AHB_LITE_RESPONSE_CODES(IntEnum):
OKAY = 0


class AHB_LITE_TRANSFER_TYPE_ENCODING(IntEnum):
IDLE = 0
BUSY = 1
NONSEQ = 2
SEQ = 3


class AHB_LITE_NOTIFICATION(IntEnum):
AHB_LITE_WRITE = 1
AHB_LITE_READ = 2
AHB_LITE_IDLE = 3
72 changes: 72 additions & 0 deletions verification/block/lib_axi4_to_ahb/ahb_lite_seq.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Copyright (c) 2023 Antmicro <www.antmicro.com>
# SPDX-License-Identifier: Apache-2.0

import random

from ahb_lite_pkg import AHB_LITE_RESPONSE_CODES
from common import BaseSeq
from pyuvm import uvm_sequence_item


class AHBLiteBaseSeqItem(uvm_sequence_item):
def __init__(self, name):
super().__init__(name)
self.ahb_hrdata = 0
self.ahb_hready = 0
self.ahb_hresp = 0

def randomize(self):
pass

def __eq__(self, other):
pass

def __str__(self):
return self.__class__.__name__


class AHBLiteInactiveSeqItem(AHBLiteBaseSeqItem):
def __init__(self, name):
super().__init__(name)


class AHBLiteReadyReadSeqItem(AHBLiteBaseSeqItem):
def __init__(self, name):
super().__init__(name)
self.ahb_hready = 1
self.ahb_hresp = AHB_LITE_RESPONSE_CODES.OKAY

def randomize(self):
self.ahb_hrdata = random.randint(0, 255)


class AHBLiteReadyWriteSeqItem(AHBLiteBaseSeqItem):
def __init__(self, name):
super().__init__(name)
self.ahb_hready = 1
self.ahb_hresp = AHB_LITE_RESPONSE_CODES.OKAY


class AHBLiteReadyNoDataSeqItem(AHBLiteBaseSeqItem):
def __init__(self, name):
super().__init__(name)
self.ahb_hready = 1
self.ahb_hresp = AHB_LITE_RESPONSE_CODES.OKAY


class AHBLiteAcceptWriteSeq(BaseSeq):
async def body(self):
items = [
AHBLiteReadyNoDataSeqItem("AHBLiteReadyNoDataSeqItem"),
AHBLiteReadyWriteSeqItem("AHBLiteReadyWriteSeqItem"),
]
await self.run_items(items)


class AHBLiteAcceptReadSeq(BaseSeq):
async def body(self):
items = [
AHBLiteReadyNoDataSeqItem("AHBLiteReadyNoDataSeqItem"),
AHBLiteReadyReadSeqItem("AHBLiteReadyReadSeqItem"),
]
await self.run_items(items)
87 changes: 87 additions & 0 deletions verification/block/lib_axi4_to_ahb/axi_pkg.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# Copyright (c) 2023 Antmicro <www.antmicro.com>
# SPDX-License-Identifier: Apache-2.0

from enum import IntEnum

AXI_W_CHAN_DRV_SIGNALS = [
"axi_awvalid",
"axi_awid",
"axi_awaddr",
"axi_awsize",
"axi_awprot",
"axi_wvalid",
"axi_wdata",
"axi_wstrb",
"axi_wlast",
"axi_bready",
]

AXI_W_CHAN_RSP_SIGNALS = [
"axi_awready",
"axi_wready",
"axi_bvalid",
"axi_bresp",
"axi_bid",
]

AXI_W_CHAN_SIGNALS = AXI_W_CHAN_DRV_SIGNALS + AXI_W_CHAN_RSP_SIGNALS

AXI_R_CHAN_DRV_SIGNALS = [
"axi_arvalid",
"axi_arid",
"axi_araddr",
"axi_arsize",
"axi_arprot",
"axi_rready",
]

AXI_R_CHAN_RSP_SIGNALS = [
"axi_arready",
"axi_rvalid",
"axi_rid",
"axi_rdata",
"axi_rresp",
"axi_rlast",
]

AXI_R_CHAN_SIGNALS = AXI_R_CHAN_DRV_SIGNALS + AXI_R_CHAN_RSP_SIGNALS


class AXI_WRITE_RESPONSE_CODES(IntEnum):
OKAY = 0
EXOKAY = 1
SLVERR = 2
DECERR = 3
DEFER = 4
TRANSFAULT = 5
RESERVED = 6
UNSUPPORTED = 7


class AXI_READ_RESPONSE_CODES(IntEnum):
OKAY = 0
EXOKAY = 1
SLVERR = 2
DECERR = 3
PREFETCHED = 4
TRANSFAULT = 5
OKAYDIRTY = 6
RESERVED = 7


class AXI_AXSIZE_ENCODING(IntEnum):
MAX_1B_TRANSFER = 0
MAX_2B_TRANSFER = 1
MAX_4B_TRANSFER = 2
MAX_8B_TRANSFER = 3
MAX_16B_TRANSFER = 4
MAX_32B_TRANSFER = 5
MAX_64B_TRANSFER = 6
MAX_128B_TRANSFER = 7


class AXI_NOTIFICATION(IntEnum):
AXI_FREE = 1
AXI_BUSY = 2
AXI_AREAD_HANDSHAKE = 3
AXI_READ_HANDSHAKE = 4
Loading

0 comments on commit 3cd9d9d

Please sign in to comment.