From a589cc2133a2ca14222428af3267ce2f53d9a2f5 Mon Sep 17 00:00:00 2001 From: dam1n19 <dam1n19@soton.ac.uk> Date: Thu, 6 Jul 2023 12:34:04 +0100 Subject: [PATCH] Cocotb work continuation --- .gitignore | 6 +- flows/makefile.simulate | 3 + verif/cocotb/__init__.py | 1 + verif/cocotb/makefile | 37 +++++++- verif/cocotb/makefile.source | 25 ------ verif/cocotb/test_nanosoc_chip.py | 135 ++++++++++++++++++++++++++++++ 6 files changed, 177 insertions(+), 30 deletions(-) create mode 100644 verif/cocotb/__init__.py delete mode 100644 verif/cocotb/makefile.source create mode 100644 verif/cocotb/test_nanosoc_chip.py diff --git a/.gitignore b/.gitignore index d65cdde..b70865a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ # Exclude Simulation Files -verif/cocotb/modelsim.ini -verif/cocotb/transcript +verif/cocotb/* +!verif/cocotb/makefile +!verif/cocotb/*.py + # Exclude Compiled Binaries /software/*/*.elf diff --git a/flows/makefile.simulate b/flows/makefile.simulate index 8274c9e..1c77a12 100644 --- a/flows/makefile.simulate +++ b/flows/makefile.simulate @@ -45,6 +45,9 @@ endif # Cocotb GUI Variable GUI ?= 0 +# Cocotb Test Location +COCOTB_TEST_DIR := $(SOCLABS_NANOSOC_TECH_DIR)/verif/cocotb + # Cocotb Scratch Directory COCOTB_DIR := $(SIM_TOP_DIR)/cocotb COCOTB_SCRATCH_DIR := $(COCOTB_DIR)/scratch diff --git a/verif/cocotb/__init__.py b/verif/cocotb/__init__.py new file mode 100644 index 0000000..fc80254 --- /dev/null +++ b/verif/cocotb/__init__.py @@ -0,0 +1 @@ +pass \ No newline at end of file diff --git a/verif/cocotb/makefile b/verif/cocotb/makefile index b51957f..ff0f886 100644 --- a/verif/cocotb/makefile +++ b/verif/cocotb/makefile @@ -1,6 +1,37 @@ +#----------------------------------------------------------------------------- +# NanoSoC CocoTB Simulation Makefile +# A joint work commissioned on behalf of SoC Labs, under Arm Academic Access license. +# +# Contributors +# +# David Mapstone (d.a.mapstone@soton.ac.uk) +# +# Copyright (C) 2021-3, SoC Labs (www.soclabs.org) +#----------------------------------------------------------------------------- +# Copyright cocotb contributors +# Licensed under the Revised BSD License, see LICENSE for details. +# SPDX-License-Identifier: BSD-3-Clause -SIM = questa +# Simulator to Run +SIM ?= questa + +# Python Install to Use PYTHON_BIN = /usr/bin/python3.8 -include makefile.source -MODULE = test_nanosoc_chip +TOPLEVEL_LANG ?= verilog + +ifneq ($(TOPLEVEL_LANG),verilog) + +all: + @echo "Skipping test due to TOPLEVEL_LANG=$(TOPLEVEL_LANG) not being verilog" +clean:: + +else + +TOPLEVEL := nanosoc_tb + +include $(SOCLABS_PROJECT_DIR)/simulate/sim/cocotb/makefile.flist + +include $(shell cocotb-config --makefiles)/Makefile.sim + +endif diff --git a/verif/cocotb/makefile.source b/verif/cocotb/makefile.source deleted file mode 100644 index 17cd3a4..0000000 --- a/verif/cocotb/makefile.source +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright cocotb contributors -# Licensed under the Revised BSD License, see LICENSE for details. -# SPDX-License-Identifier: BSD-3-Clause - -TOPLEVEL_LANG ?= verilog - -ifneq ($(TOPLEVEL_LANG),verilog) - -all: - @echo "Skipping test due to TOPLEVEL_LANG=$(TOPLEVEL_LANG) not being verilog" -clean:: - -else - -TOPLEVEL := nanosoc_tb - -PWD=$(shell pwd) - -COCOTB?=$(PWD)/../../.. - -include $(SOCLABS_PROJECT_DIR)/simulate/sim/cocotb/makefile.flist - -include $(shell cocotb-config --makefiles)/Makefile.sim - -endif diff --git a/verif/cocotb/test_nanosoc_chip.py b/verif/cocotb/test_nanosoc_chip.py new file mode 100644 index 0000000..3f2211f --- /dev/null +++ b/verif/cocotb/test_nanosoc_chip.py @@ -0,0 +1,135 @@ +from random import randint, randrange, getrandbits, shuffle +from collections.abc import Iterable + +import logging +import cocotb +from cocotb.clock import Clock +from cocotb.regression import TestFactory +from cocotb.result import TestFailure +from cocotb.triggers import ClockCycles, Combine, Join, RisingEdge +# from cocotb_bus.drivers.amba import ( +# AXIBurst, AXI4Master, AXIProtocolError, AXIReadBurstLengthMismatch, +# AXIxRESP) +from systemrdltest.python.cmsdk_reg.lib import NormalCallbackSet +from systemrdltest.python.cmsdk_reg.reg_model import cmsdk_reg + +from cocotbext.axi import AxiBus, AxiMaster + +CLK_PERIOD = (10, "ns") +AXI_PREFIX = "S_AXI" + +async def setup_dut(dut): + cocotb.start_soon(Clock(dut.clk, *CLK_PERIOD).start()) + axi_bus = AxiBus.from_prefix(dut, AXI_PREFIX) + axi_driver = AxiMaster(axi_bus, dut.clk, dut.rstn, reset_active_level=False) + dut.rstn.value = 0 + await ClockCycles(dut.clk, 2) + dut.rstn.value = 1 + await ClockCycles(dut.clk, 2) + return axi_driver + +def binatodeci(binary): + return sum(val*(2**idx) for idx, val in enumerate(reversed(binary))) + +@cocotb.coroutine +async def reg_write(manager, register, data): + print("Writing address: "+str(register.address)) + await manager.write(register.address, data) + +@cocotb.coroutine +async def reg_read(manager, register, length = 1): + event = manager.init_read(register.address, length) + await event.wait() + return event.data.data + +@cocotb.coroutine +async def field_read(manager, register, field, length = 1): + reg_read_val = await reg_read(manager, register, length) + return getattr(register, field).decode_read_value(binatodeci(reg_read_val)) + +@cocotb.test() +async def test_read(dut): + """Test Software Readable CMSDK Registers can be read""" + + # Connect AXI4 driver into DUT AXI Signals + axim = AxiMaster(AxiBus.from_prefix(dut, AXI_PREFIX), dut.clk, dut.rstn, reset_active_level=False) + reg_address_map = cmsdk_reg.cmsdk_reg_cls(callbacks = NormalCallbackSet()) + + # Generate a Clock and Perform a Reset + await setup_dut(dut) + + # Select a readable register with known reset value + test_addr = reg_address_map.pid.PID_4 + expected_result = test_addr.ID.default + + #Read Register Field + read_result = await field_read(axim, test_addr, "ID") + + print(f"Address: {hex(test_addr.address)} | Read Value: {read_result}, Expected Value: {expected_result}") + assert read_result == expected_result + +@cocotb.test() +async def test_read(dut): + """Test 1 Software Readable CMSDK Register can be read""" + + # Connect AXI4 driver into DUT AXI Signals + + reg_address_map = cmsdk_reg.cmsdk_reg_cls(callbacks = NormalCallbackSet()) + + # Generate a Clock and Perform a Reset + axi_driver = await setup_dut(dut) + + # Select a readable register with known reset value + test_addr = reg_address_map.pid.PID_4 + expected_result = test_addr.ID.default + + #Read Register Field + read_result = await field_read(axi_driver, test_addr, "ID") + + log = logging.getLogger(f"cocotb.test") + log.info(f"Address: {hex(test_addr.address)} | Read Value: {read_result}, Expected Value: {expected_result}") + assert read_result == expected_result + +@cocotb.test() +async def test_readable_regs(dut): + """Test Software Readable CMSDK Registers can be read""" + + # Connect AXI4 driver into DUT AXI Signals + reg_address_map = cmsdk_reg.cmsdk_reg_cls(callbacks = NormalCallbackSet()) + + # Generate a Clock and Perform a Reset + axi_driver = await setup_dut(dut) + + # Setup Logger + log = logging.getLogger(f"cocotb.test") + + # Select a readable register with known reset values + sections = list(reg_address_map.get_sections()) + + # Get a list of readable registers + readable_reg_list = [] + for section in sections: + for reg in list(section.get_readable_registers()): + if isinstance(reg, Iterable): + for index in reg: + readable_reg_list.append(index) + else: + readable_reg_list.append(reg) + + # Randomly select registers in readable list and perform a read + shuffle(readable_reg_list) + for reg in readable_reg_list: + # Get a list of the fields in the register and randomise + readable_fields_list = list(reg.readable_fields) + shuffle(readable_fields_list) + + for field in readable_fields_list: + # Read each field + read_result = await field_read(axi_driver, reg, field.inst_name) + + # Get default (reset value) for each field + expected_result = field.default + + # Run an assertion against reset values + log.info(f"Field: {field.inst_name} @ Address: {hex(reg.address)} | Read Value: {read_result}, Expected Value: {expected_result}") + assert read_result == expected_result \ No newline at end of file -- GitLab