From 49e2b233f3d8ae48594d67f51ed883c4df90cb96 Mon Sep 17 00:00:00 2001 From: Aleksander Kiryk Date: Wed, 13 Sep 2023 19:13:57 +0200 Subject: [PATCH 1/9] Add configs --- verification/block/ifu/Makefile | 16 ++++++++++++++++ verification/block/ifu/test_compress.py | 0 verification/block/noxfile.py | 9 +++++++++ 3 files changed, 25 insertions(+) create mode 100644 verification/block/ifu/Makefile create mode 100644 verification/block/ifu/test_compress.py diff --git a/verification/block/ifu/Makefile b/verification/block/ifu/Makefile new file mode 100644 index 00000000000..d2e37a9683c --- /dev/null +++ b/verification/block/ifu/Makefile @@ -0,0 +1,16 @@ +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 = el2_ifu_compress_ctl + +VERILOG_SOURCES = \ + $(SRCDIR)/ifu/el2_ifu_compress_ctl.sv + +include $(CURDIR)/../common.mk diff --git a/verification/block/ifu/test_compress.py b/verification/block/ifu/test_compress.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/verification/block/noxfile.py b/verification/block/noxfile.py index 777d531e35b..9749d0cefc2 100644 --- a/verification/block/noxfile.py +++ b/verification/block/noxfile.py @@ -148,6 +148,7 @@ def pic_verify(session, blockName, testName, coverage): def pic_gw_verify(session, blockName, testName, coverage): verify_block(session, blockName, testName, coverage) + @nox.session(tags=["tests"]) @nox.parametrize("blockName", ["dma"]) @nox.parametrize( @@ -167,6 +168,14 @@ def pic_gw_verify(session, blockName, testName, coverage): def dma_verify(session, blockName, testName, coverage): verify_block(session, blockName, testName, coverage) + +@nox.parametrize("blockName", ["ifu"]) +@nox.parametrize("testName", ["test_compress"]) +@nox.parametrize("coverage", coverageTypes) +def ifu_verify(session, blockName, testName, coverage): + verify_block(session, blockName, testName, coverage) + + @nox.session() def isort(session: nox.Session) -> None: """Options are defined in pyproject.toml file""" From a978d70857f5e942b71028e51b65cde29bd607a7 Mon Sep 17 00:00:00 2001 From: Aleksander Kiryk Date: Wed, 27 Sep 2023 12:16:36 +0200 Subject: [PATCH 2/9] Fix session name --- verification/block/noxfile.py | 1 + 1 file changed, 1 insertion(+) diff --git a/verification/block/noxfile.py b/verification/block/noxfile.py index 9749d0cefc2..6df17cbd8b1 100644 --- a/verification/block/noxfile.py +++ b/verification/block/noxfile.py @@ -169,6 +169,7 @@ def dma_verify(session, blockName, testName, coverage): verify_block(session, blockName, testName, coverage) +@nox.session(tags=["tests"]) @nox.parametrize("blockName", ["ifu"]) @nox.parametrize("testName", ["test_compress"]) @nox.parametrize("coverage", coverageTypes) From 05f2c59d14d826c4a1b481fabfcae1ff4136cc94 Mon Sep 17 00:00:00 2001 From: Aleksander Kiryk Date: Thu, 14 Sep 2023 18:40:47 +0200 Subject: [PATCH 3/9] Add basic test classes --- verification/block/ifu/test_compress.py | 37 ++++ verification/block/ifu/testbench.py | 233 ++++++++++++++++++++++++ 2 files changed, 270 insertions(+) create mode 100644 verification/block/ifu/testbench.py diff --git a/verification/block/ifu/test_compress.py b/verification/block/ifu/test_compress.py index e69de29bb2d..38111d88549 100644 --- a/verification/block/ifu/test_compress.py +++ b/verification/block/ifu/test_compress.py @@ -0,0 +1,37 @@ +import pyuvm +from pyuvm import * + +from testbench import BaseEnv, BaseTest +from testbench import CompressedSequence + + +class TestEnv(BaseEnv): + def build_phase(self): + super().build_phase() + + # Add scoreboard + # self.scoreboard = Scoreboard("scoreboard", self) + + def connect_phase(self): + super().connect_phase() + + # Connect monitors + # self.dcm_mon.ap.connect(self.scoreboard.fifo.analysis_export) + + +@pyuvm.test() +class TestDecompressor(BaseTest): + """ + Decompression test + """ + + def __init__(self, name, parent): + super().__init__(name, parent, TestEnv) + + def end_of_elaboration_phase(self): + super().end_of_elaboration_phase() + self.seq = CompressedSequence.create("stimulus") + + async def run(self): + await self.seq.start(self.env.dcm_seqr) + diff --git a/verification/block/ifu/testbench.py b/verification/block/ifu/testbench.py new file mode 100644 index 00000000000..29d04234cfb --- /dev/null +++ b/verification/block/ifu/testbench.py @@ -0,0 +1,233 @@ +import os + +from cocotb.triggers import Timer +from cocotb.binary import BinaryValue + +import pyuvm +from pyuvm import * + + +def decompress(nop): + # TODO: Actually decompress instructions into BinaryValue type + return BinaryValue(value="00000000000000000000000000010011") + + +def collect_signals(signals, uut, obj, uut_prefix="", obj_prefix=""): + """ + Collects signal objects from UUT and attaches them to the given object. + Optionally UUT signals can be prefixed with the uut_prefix and object + signals with the obj_prefix + """ + + for sig in signals: + uut_sig = uut_prefix + sig + obj_sig = obj_prefix + sig + if hasattr(uut, uut_sig): + s = getattr(uut, uut_sig) + + else: + s = None + logging.error( + "Module {} does not have a signal '{}'".format(str(uut), sig) + ) + + setattr(obj, obj_sig, s) + + +class DecompressorItem(uvm_sequence_item): + """ + A generic instruction-input stimulus + """ + def __init__(self, din, dout): + super().__init__("InstructionItem") + """ + Records a state of decompressor's pins + """ + + self.din = din + self.dout = dout + + +class CompressedInstructionItem(uvm_sequence_item): + """ + A generic compressed instruction-input stimulus + """ + def __init__(self): + super().__init__("CompressedInstructionItem") + """ + Creates a 16-bit instruction + """ + + # TODO: Create a random compressed instruction + self.instr = int(("0" * 15) + "1") + + +class CompressedSequence(uvm_sequence): + """ + A sequencer that generates random RISC-V compressed instructions + """ + + def __init__(self, name): + super().__init__(name) + + async def body(self): + for j in range(50): + # Create a compressed instruction + item = CompressedInstructionItem() + await self.start_item(item) + await self.finish_item(item) + + +class DecompressorDriver(uvm_driver): + """ + A driver for the IFU instruction decompressor + """ + + SIGNALS = ["din", "dout"] + + def __init__(self, *args, **kwargs): + uut = kwargs["uut"] + del kwargs["uut"] + super().__init__(*args, **kwargs) + + # Collect signals + collect_signals(self.SIGNALS, uut, self) + + async def write(self, instr): + """ + Pushes instruction to the decompressor + """ + + self.din.value = instr + await Timer(10, "us") + + async def run_phase(self): + + while True: + it = await self.seq_item_port.get_next_item() + if isinstance(it, CompressedInstructionItem): + await self.write(it.instr) + else: + raise RuntimeError("Unknown item '{}'".format(type(it))) + self.seq_item_port.item_done() + + +class DecompressorMonitor(uvm_component): + """ + A monitor for the IFU instruction decompressor + """ + + SIGNALS = ["din", "dout"] + + def __init__(self, *args, **kwargs): + uut = kwargs["uut"] + del kwargs["uut"] + + super().__init__(*args, **kwargs) + + collect_signals(self.SIGNALS, uut, self) + + def build_phase(self): + self.ap = uvm_analysis_port("ap", self) + + async def run_phase(self): + while True: + await Timer(10, "us") + it = DecompressorItem(self.din, self.dout) + self.ap.write(it) + + +class Scoreboard(uvm_component): + """ + Checks if all decompressed instructions have the expected value + """ + + def __init__(self, name, parent): + super().__init__(name, parent) + + self.passed = None + + def build_phase(self): + self.fifo = uvm_tlm_analysis_fifo("fifo", self) + self.port = uvm_get_port("port", self) + + def connect_phase(self): + self.port.connect(self.fifo.get_export) + + def check_phase(self): + + # Process items + while self.port.can_get(): + + # Get an item + got_item, item = self.port.try_get() + assert got_item + + # Initially pass + if self.passed is None: + self.passed = True + + # Got a decompressed instruction which is incorrect + if isinstance(item, DecompressorItem): + if item.dout != decompress(item.din): + self.logger.debug( + "Instruction decompressed incorrectly: 0x%v -> 0x%v".format( + item.din, + item.dout + )) + self.passed = False + + + def final_phase(self): + if not self.passed: + self.logger.critical("{} reports a failure".format(type(self))) + assert False + + +class BaseEnv(uvm_env): + """ + Base PyUVM test environment + """ + + def build_phase(self): + + # Add scoreboard + self.scoreboard = Scoreboard("scoreboard", self) + + # Sequencers + self.dcm_seqr = uvm_sequencer("dcm_seqr", self) + + self.dcm_drv = DecompressorDriver("dcm_drv", self, uut=cocotb.top) + + self.dcm_mon = DecompressorMonitor("dcm_mon", self, uut=cocotb.top) + + def connect_phase(self): + self.dcm_drv.seq_item_port.connect(self.dcm_seqr.seq_item_export) + self.dcm_mon.ap.connect(self.scoreboard.fifo.analysis_export) + + +class BaseTest(uvm_test): + """ + Base test for the module + """ + + def __init__(self, name, parent, env_class=BaseEnv): + super().__init__(name, parent) + self.env_class = env_class + + # Synchronize pyuvm logging level with cocotb logging level. Unclear + # why it does not happen automatically. + level = logging.getLevelName(os.environ.get("COCOTB_LOG_LEVEL", "INFO")) + uvm_report_object.set_default_logging_level(level) + + def build_phase(self): + self.env = self.env_class("env", self) + + async def run_phase(self): + self.raise_objection() + await self.run() + self.drop_objection() + + async def run(self): + raise NotImplementedError() + From 0febdf8ebe5492904883eb7fe4e7ee7450e7cf9a Mon Sep 17 00:00:00 2001 From: Aleksander Kiryk Date: Tue, 19 Sep 2023 19:04:46 +0200 Subject: [PATCH 4/9] Add instruction pair generator --- verification/block/ifu/testbench.py | 87 ++++++++++++++++++++++++++--- 1 file changed, 78 insertions(+), 9 deletions(-) diff --git a/verification/block/ifu/testbench.py b/verification/block/ifu/testbench.py index 29d04234cfb..9715f629f21 100644 --- a/verification/block/ifu/testbench.py +++ b/verification/block/ifu/testbench.py @@ -1,4 +1,7 @@ import os +import random +import subprocess +from queue import Queue from cocotb.triggers import Timer from cocotb.binary import BinaryValue @@ -7,11 +10,6 @@ from pyuvm import * -def decompress(nop): - # TODO: Actually decompress instructions into BinaryValue type - return BinaryValue(value="00000000000000000000000000010011") - - def collect_signals(signals, uut, obj, uut_prefix="", obj_prefix=""): """ Collects signal objects from UUT and attaches them to the given object. @@ -34,6 +32,77 @@ def collect_signals(signals, uut, obj, uut_prefix="", obj_prefix=""): setattr(obj, obj_sig, s) +def get_opcode(asm_line, ext="rv32i", size=32): + """ + Generates binary opcode string based on a line of assembly + """ + + import textwrap + + cmd = f"echo '{asm_line}' | riscv64-unknown-elf-as -march={ext} -o /dev/null -al | tail -n 1" + out = subprocess.check_output([cmd], shell=True).decode().split()[2] + out = "".join(textwrap.wrap(out, 2)[::-1]) + + opcode = f"{int(out, 16):0{size}b}" + + return opcode + + +def generate_assembly_pair(): + """ + Generates random assembly instruction that can be compressed + """ + + # x8--x15 are the allowed registers for compressed instructions + dreg = random.randrange(8, 16) + sreg = random.randrange(8, 16) + + imm = random.randrange(2**5) + + return random.choice([ + (f"c.add x{dreg}, x{sreg}", f"add x{dreg}, x{dreg}, x{sreg}"), + (f"c.or x{dreg}, x{sreg}", f"or x{dreg}, x{dreg}, x{sreg}"), + (f"c.xor x{dreg}, x{sreg}", f"xor x{dreg}, x{dreg}, x{sreg}"), + (f"c.sub x{dreg}, x{sreg}", f"sub x{dreg}, x{dreg}, x{sreg}"), + (f"c.mv x{dreg}, x{sreg}", f"add x{dreg}, x0, x{sreg}"), + (f"c.andi x{dreg}, {imm}", f"andi x{dreg}, x{dreg}, {imm}"), + ]) + + +class CompressedGenerator: + """ + Generates compressed instruction and caches their expected + decompressed counterpart, allowing for a fast lookup + """ + + lookup = {} + + @classmethod + def get(self): + """ + Generates compressed/decompressed instruction pair + """ + + com, dec = generate_assembly_pair() + + com = get_opcode(com, ext="rv32ic", size=16) + dec = get_opcode(dec, ext="rv32i", size=32) + + self.lookup[com] = dec + + return com + + @classmethod + def check(self, com, dec): + """ + Checks if a previously generated instruction corresponds to the + decompressed one given + """ + + assert com in self.lookup, f"instruction '{com}' not generated before" + return self.lookup[com] == dec + + class DecompressorItem(uvm_sequence_item): """ A generic instruction-input stimulus @@ -58,8 +127,8 @@ def __init__(self): Creates a 16-bit instruction """ - # TODO: Create a random compressed instruction - self.instr = int(("0" * 15) + "1") + instr = CompressedGenerator.get() + self.instr = BinaryValue(value=instr, bigEndian=False) class CompressedSequence(uvm_sequence): @@ -71,7 +140,7 @@ def __init__(self, name): super().__init__(name) async def body(self): - for j in range(50): + for j in range(200): # Create a compressed instruction item = CompressedInstructionItem() await self.start_item(item) @@ -169,7 +238,7 @@ def check_phase(self): # Got a decompressed instruction which is incorrect if isinstance(item, DecompressorItem): - if item.dout != decompress(item.din): + if not CompressedGenerator.check(str(item.din.value), str(item.dout.value)): self.logger.debug( "Instruction decompressed incorrectly: 0x%v -> 0x%v".format( item.din, From 6e4175616efd65e4ee4fe3a5dad8891f47643622 Mon Sep 17 00:00:00 2001 From: Aleksander Kiryk Date: Mon, 25 Sep 2023 13:38:56 +0200 Subject: [PATCH 5/9] Adjust style to that of other tests --- verification/block/ifu/test_compress.py | 37 ------- .../block/{ifu => ifu_compress}/Makefile | 0 .../block/ifu_compress/test_compress.py | 20 ++++ .../block/{ifu => ifu_compress}/testbench.py | 100 ++++++++++-------- verification/block/noxfile.py | 2 +- 5 files changed, 79 insertions(+), 80 deletions(-) delete mode 100644 verification/block/ifu/test_compress.py rename verification/block/{ifu => ifu_compress}/Makefile (100%) create mode 100644 verification/block/ifu_compress/test_compress.py rename verification/block/{ifu => ifu_compress}/testbench.py (73%) diff --git a/verification/block/ifu/test_compress.py b/verification/block/ifu/test_compress.py deleted file mode 100644 index 38111d88549..00000000000 --- a/verification/block/ifu/test_compress.py +++ /dev/null @@ -1,37 +0,0 @@ -import pyuvm -from pyuvm import * - -from testbench import BaseEnv, BaseTest -from testbench import CompressedSequence - - -class TestEnv(BaseEnv): - def build_phase(self): - super().build_phase() - - # Add scoreboard - # self.scoreboard = Scoreboard("scoreboard", self) - - def connect_phase(self): - super().connect_phase() - - # Connect monitors - # self.dcm_mon.ap.connect(self.scoreboard.fifo.analysis_export) - - -@pyuvm.test() -class TestDecompressor(BaseTest): - """ - Decompression test - """ - - def __init__(self, name, parent): - super().__init__(name, parent, TestEnv) - - def end_of_elaboration_phase(self): - super().end_of_elaboration_phase() - self.seq = CompressedSequence.create("stimulus") - - async def run(self): - await self.seq.start(self.env.dcm_seqr) - diff --git a/verification/block/ifu/Makefile b/verification/block/ifu_compress/Makefile similarity index 100% rename from verification/block/ifu/Makefile rename to verification/block/ifu_compress/Makefile diff --git a/verification/block/ifu_compress/test_compress.py b/verification/block/ifu_compress/test_compress.py new file mode 100644 index 00000000000..28fd74624eb --- /dev/null +++ b/verification/block/ifu_compress/test_compress.py @@ -0,0 +1,20 @@ +import pyuvm +from pyuvm import * +from testbench import BaseEnv, BaseTest, CompressedSequence + + +@pyuvm.test() +class TestDecompressor(BaseTest): + """ + Decompression test + """ + + def __init__(self, name, parent): + super().__init__(name, parent, BaseEnv) + + def end_of_elaboration_phase(self): + super().end_of_elaboration_phase() + self.seq = CompressedSequence.create("stimulus") + + async def run(self): + await self.seq.start(self.env.dcm_seqr) diff --git a/verification/block/ifu/testbench.py b/verification/block/ifu_compress/testbench.py similarity index 73% rename from verification/block/ifu/testbench.py rename to verification/block/ifu_compress/testbench.py index 9715f629f21..d218c1acaea 100644 --- a/verification/block/ifu/testbench.py +++ b/verification/block/ifu_compress/testbench.py @@ -1,12 +1,12 @@ import os import random import subprocess +import textwrap from queue import Queue -from cocotb.triggers import Timer -from cocotb.binary import BinaryValue - import pyuvm +from cocotb.binary import BinaryValue +from cocotb.triggers import Timer from pyuvm import * @@ -25,9 +25,7 @@ def collect_signals(signals, uut, obj, uut_prefix="", obj_prefix=""): else: s = None - logging.error( - "Module {} does not have a signal '{}'".format(str(uut), sig) - ) + logging.error("Module {} does not have a signal '{}'".format(str(uut), sig)) setattr(obj, obj_sig, s) @@ -37,12 +35,15 @@ def get_opcode(asm_line, ext="rv32i", size=32): Generates binary opcode string based on a line of assembly """ - import textwrap - cmd = f"echo '{asm_line}' | riscv64-unknown-elf-as -march={ext} -o /dev/null -al | tail -n 1" + + # Take instruction hex (3rd column) and change its endianess out = subprocess.check_output([cmd], shell=True).decode().split()[2] out = "".join(textwrap.wrap(out, 2)[::-1]) + assert len(out) == size // 4, f"instruction '{asm_line}' assembled to unexpected width" + + # Convert hex to bin opcode = f"{int(out, 16):0{size}b}" return opcode @@ -53,26 +54,38 @@ def generate_assembly_pair(): Generates random assembly instruction that can be compressed """ - # x8--x15 are the allowed registers for compressed instructions + # For most compressed instructions only x8--x15 are allowed dreg = random.randrange(8, 16) sreg = random.randrange(8, 16) - imm = random.randrange(2**5) - - return random.choice([ - (f"c.add x{dreg}, x{sreg}", f"add x{dreg}, x{dreg}, x{sreg}"), - (f"c.or x{dreg}, x{sreg}", f"or x{dreg}, x{dreg}, x{sreg}"), - (f"c.xor x{dreg}, x{sreg}", f"xor x{dreg}, x{dreg}, x{sreg}"), - (f"c.sub x{dreg}, x{sreg}", f"sub x{dreg}, x{dreg}, x{sreg}"), - (f"c.mv x{dreg}, x{sreg}", f"add x{dreg}, x0, x{sreg}"), - (f"c.andi x{dreg}, {imm}", f"andi x{dreg}, x{dreg}, {imm}"), - ]) + imm = random.randrange(2**11) + sgn = random.choice(["-", ""]) + + # In f-strings below: + # {imm%width} -- when the immediate's magnitude has a limited width + # {imm or 1} -- when the immediate cannot be 0 + # {sgn}{imm} -- when the immediate is signed + return random.choice( + [ + (f"c.add x{dreg}, x{sreg}", f"add x{dreg}, x{dreg}, x{sreg}"), + (f"c.or x{dreg}, x{sreg}", f"or x{dreg}, x{dreg}, x{sreg}"), + (f"c.xor x{dreg}, x{sreg}", f"xor x{dreg}, x{dreg}, x{sreg}"), + (f"c.sub x{dreg}, x{sreg}", f"sub x{dreg}, x{dreg}, x{sreg}"), + (f"c.mv x{dreg}, x{sreg}", f"add x{dreg}, x0, x{sreg}"), + (f"c.andi x{dreg}, {sgn}{imm%5}", f"andi x{dreg}, x{dreg}, {sgn}{imm%5}"), + (f"c.addi x{dreg}, {sgn}{imm%5}", f"addi x{dreg}, x{dreg}, {sgn}{imm%5}"), + (f"c.srli x{dreg}, {imm%5 or 1}", f"srli x{dreg}, x{dreg}, {imm%5 or 1}"), + (f"c.srai x{dreg}, {imm%5 or 1}", f"srai x{dreg}, x{dreg}, {imm%5 or 1}"), + (f"c.slli x{dreg}, {imm%5 or 1}", f"slli x{dreg}, x{dreg}, {imm%5 or 1}"), + ("c.ebreak", "ebreak"), + ] + ) class CompressedGenerator: """ - Generates compressed instruction and caches their expected - decompressed counterpart, allowing for a fast lookup + Generates compressed instructions and caches their expected + decompressed counterpart to allow fast checks """ lookup = {} @@ -83,10 +96,10 @@ def get(self): Generates compressed/decompressed instruction pair """ - com, dec = generate_assembly_pair() + asm_com, asm_dec = generate_assembly_pair() - com = get_opcode(com, ext="rv32ic", size=16) - dec = get_opcode(dec, ext="rv32i", size=32) + com = get_opcode(asm_com, ext="rv32ic", size=16) + dec = get_opcode(asm_dec, ext="rv32i", size=32) self.lookup[com] = dec @@ -99,14 +112,15 @@ def check(self, com, dec): decompressed one given """ - assert com in self.lookup, f"instruction '{com}' not generated before" + assert com in self.lookup, f"instruction 0b{com} not generated before" return self.lookup[com] == dec -class DecompressorItem(uvm_sequence_item): +class InstructionPairItem(uvm_sequence_item): """ A generic instruction-input stimulus """ + def __init__(self, din, dout): super().__init__("InstructionItem") """ @@ -121,6 +135,7 @@ class CompressedInstructionItem(uvm_sequence_item): """ A generic compressed instruction-input stimulus """ + def __init__(self): super().__init__("CompressedInstructionItem") """ @@ -140,7 +155,9 @@ def __init__(self, name): super().__init__(name) async def body(self): - for j in range(200): + count = ConfigDB().get(None, "", "TEST_ITERATIONS") + + for j in range(count): # Create a compressed instruction item = CompressedInstructionItem() await self.start_item(item) @@ -158,7 +175,7 @@ def __init__(self, *args, **kwargs): uut = kwargs["uut"] del kwargs["uut"] super().__init__(*args, **kwargs) - + # Collect signals collect_signals(self.SIGNALS, uut, self) @@ -171,7 +188,6 @@ async def write(self, instr): await Timer(10, "us") async def run_phase(self): - while True: it = await self.seq_item_port.get_next_item() if isinstance(it, CompressedInstructionItem): @@ -202,7 +218,7 @@ def build_phase(self): async def run_phase(self): while True: await Timer(10, "us") - it = DecompressorItem(self.din, self.dout) + it = InstructionPairItem(self.din, self.dout) self.ap.write(it) @@ -224,10 +240,8 @@ def connect_phase(self): self.port.connect(self.fifo.get_export) def check_phase(self): - # Process items while self.port.can_get(): - # Get an item got_item, item = self.port.try_get() assert got_item @@ -237,16 +251,15 @@ def check_phase(self): self.passed = True # Got a decompressed instruction which is incorrect - if isinstance(item, DecompressorItem): + if isinstance(item, InstructionPairItem): if not CompressedGenerator.check(str(item.din.value), str(item.dout.value)): self.logger.debug( - "Instruction decompressed incorrectly: 0x%v -> 0x%v".format( - item.din, - item.dout - )) + "Instruction decompressed incorrectly: 0b{} -> 0b{}".format( + item.din, item.dout + ) + ) self.passed = False - def final_phase(self): if not self.passed: self.logger.critical("{} reports a failure".format(type(self))) @@ -259,17 +272,21 @@ class BaseEnv(uvm_env): """ def build_phase(self): - - # Add scoreboard - self.scoreboard = Scoreboard("scoreboard", self) + # Config + ConfigDB().set(None, "*", "TEST_ITERATIONS", 500) # Sequencers self.dcm_seqr = uvm_sequencer("dcm_seqr", self) + # Driver self.dcm_drv = DecompressorDriver("dcm_drv", self, uut=cocotb.top) + # Monitor self.dcm_mon = DecompressorMonitor("dcm_mon", self, uut=cocotb.top) + # Scoreboard + self.scoreboard = Scoreboard("scoreboard", self) + def connect_phase(self): self.dcm_drv.seq_item_port.connect(self.dcm_seqr.seq_item_export) self.dcm_mon.ap.connect(self.scoreboard.fifo.analysis_export) @@ -299,4 +316,3 @@ async def run_phase(self): async def run(self): raise NotImplementedError() - diff --git a/verification/block/noxfile.py b/verification/block/noxfile.py index 6df17cbd8b1..93597b0007f 100644 --- a/verification/block/noxfile.py +++ b/verification/block/noxfile.py @@ -170,7 +170,7 @@ def dma_verify(session, blockName, testName, coverage): @nox.session(tags=["tests"]) -@nox.parametrize("blockName", ["ifu"]) +@nox.parametrize("blockName", ["ifu_compress"]) @nox.parametrize("testName", ["test_compress"]) @nox.parametrize("coverage", coverageTypes) def ifu_verify(session, blockName, testName, coverage): From 4162e1cf833ce0ddcf26a348e9c8e879c9fd55bc Mon Sep 17 00:00:00 2001 From: Aleksander Kiryk Date: Tue, 26 Sep 2023 14:03:50 +0200 Subject: [PATCH 6/9] Fix session name --- verification/block/noxfile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/verification/block/noxfile.py b/verification/block/noxfile.py index 93597b0007f..d258f9194a4 100644 --- a/verification/block/noxfile.py +++ b/verification/block/noxfile.py @@ -173,7 +173,7 @@ def dma_verify(session, blockName, testName, coverage): @nox.parametrize("blockName", ["ifu_compress"]) @nox.parametrize("testName", ["test_compress"]) @nox.parametrize("coverage", coverageTypes) -def ifu_verify(session, blockName, testName, coverage): +def ifu_compress_verify(session, blockName, testName, coverage): verify_block(session, blockName, testName, coverage) From 218094969267c2448b9e242c2be1dfbc0eb36b37 Mon Sep 17 00:00:00 2001 From: Aleksander Kiryk Date: Tue, 26 Sep 2023 16:50:38 +0200 Subject: [PATCH 7/9] Disable branch coverage for IFU's decompressor --- verification/block/noxfile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/verification/block/noxfile.py b/verification/block/noxfile.py index d258f9194a4..81194681180 100644 --- a/verification/block/noxfile.py +++ b/verification/block/noxfile.py @@ -172,7 +172,7 @@ def dma_verify(session, blockName, testName, coverage): @nox.session(tags=["tests"]) @nox.parametrize("blockName", ["ifu_compress"]) @nox.parametrize("testName", ["test_compress"]) -@nox.parametrize("coverage", coverageTypes) +@nox.parametrize("coverage", "toggle") # No branches in the decompressor def ifu_compress_verify(session, blockName, testName, coverage): verify_block(session, blockName, testName, coverage) From 46a8075090a32672ad6da1e8d0865161ffa47983 Mon Sep 17 00:00:00 2001 From: Aleksander Kiryk Date: Wed, 27 Sep 2023 12:52:11 +0200 Subject: [PATCH 8/9] Enable IFU tests in CI --- .github/workflows/test-uarch.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-uarch.yml b/.github/workflows/test-uarch.yml index 386f24cf828..57e3e9ad1b9 100644 --- a/.github/workflows/test-uarch.yml +++ b/.github/workflows/test-uarch.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - test: ["block/pic", "block/pic_gw", "block/dma"] + test: ["block/pic", "block/pic_gw", "block/dma", "block/ifu_compress"] env: CCACHE_DIR: "/opt/verification/.cache/" VERILATOR_VERSION: v5.010 From f507e41e6437c7e0c8e575cfe22b0539d5c457a4 Mon Sep 17 00:00:00 2001 From: Aleksander Kiryk Date: Thu, 28 Sep 2023 11:30:07 +0200 Subject: [PATCH 9/9] Reformat test list --- .github/workflows/test-uarch.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test-uarch.yml b/.github/workflows/test-uarch.yml index 57e3e9ad1b9..eccdc24efb7 100644 --- a/.github/workflows/test-uarch.yml +++ b/.github/workflows/test-uarch.yml @@ -12,7 +12,11 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - test: ["block/pic", "block/pic_gw", "block/dma", "block/ifu_compress"] + test: + - "block/pic" + - "block/pic_gw" + - "block/dma" + - "block/ifu_compress" env: CCACHE_DIR: "/opt/verification/.cache/" VERILATOR_VERSION: v5.010