Skip to content

Commit

Permalink
Merge pull request #180 from antmicro/rrozak/60210-add-zbb-tests
Browse files Browse the repository at this point in the history
Add tests of zbs and zbb instructions
  • Loading branch information
tmichalak authored Jun 7, 2024
2 parents 15041c9 + 9baad55 commit a8a87f3
Show file tree
Hide file tree
Showing 4 changed files with 230 additions and 47 deletions.
92 changes: 92 additions & 0 deletions verification/block/exu_alu/test_zbb.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# Copyright (c) 2023 Antmicro <www.antmicro.com>
# SPDX-License-Identifier: Apache-2.0
import random

import pyuvm
from cocotb.triggers import ClockCycles
from pyuvm import *
from testbench import BaseSequence, BaseTest

# =============================================================================


@pyuvm.test()
class TestClz(BaseTest):
def end_of_elaboration_phase(self):
super().end_of_elaboration_phase()
self.seq = BaseSequence("stimulus", ["clz"])

async def run(self):
await self.seq.start(self.env.alu_seqr)


@pyuvm.test()
class TestCtz(BaseTest):
def end_of_elaboration_phase(self):
super().end_of_elaboration_phase()
self.seq = BaseSequence("stimulus", ["ctz"])

async def run(self):
await self.seq.start(self.env.alu_seqr)


@pyuvm.test()
class TestCpop(BaseTest):
def end_of_elaboration_phase(self):
super().end_of_elaboration_phase()
self.seq = BaseSequence("stimulus", ["cpop"])

async def run(self):
await self.seq.start(self.env.alu_seqr)


@pyuvm.test()
class TestSextb(BaseTest):
def end_of_elaboration_phase(self):
super().end_of_elaboration_phase()
self.seq = BaseSequence("stimulus", ["sext_b"])

async def run(self):
await self.seq.start(self.env.alu_seqr)


@pyuvm.test()
class TestSexth(BaseTest):
def end_of_elaboration_phase(self):
super().end_of_elaboration_phase()
self.seq = BaseSequence("stimulus", ["sext_h"])

async def run(self):
await self.seq.start(self.env.alu_seqr)


@pyuvm.test()
class TestRol(BaseTest):
def end_of_elaboration_phase(self):
super().end_of_elaboration_phase()
self.seq = BaseSequence("stimulus", ["rol"])

async def run(self):
await self.seq.start(self.env.alu_seqr)


@pyuvm.test()
class TestRor(BaseTest):
def end_of_elaboration_phase(self):
super().end_of_elaboration_phase()
self.seq = BaseSequence("stimulus", ["ror"])

async def run(self):
await self.seq.start(self.env.alu_seqr)


@pyuvm.test()
class TestAll(BaseTest):
def end_of_elaboration_phase(self):
super().end_of_elaboration_phase()
self.seq = BaseSequence(
"stimulus", ["clz", "ctz", "cpop", "sext_b", "sext_h", "rol", "ror"]
)

async def run(self):
await self.seq.start(self.env.alu_seqr)
60 changes: 60 additions & 0 deletions verification/block/exu_alu/test_zbs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Copyright (c) 2023 Antmicro <www.antmicro.com>
# SPDX-License-Identifier: Apache-2.0
import random

import pyuvm
from cocotb.triggers import ClockCycles
from pyuvm import *
from testbench import BaseSequence, BaseTest

# =============================================================================


@pyuvm.test()
class TestBset(BaseTest):
def end_of_elaboration_phase(self):
super().end_of_elaboration_phase()
self.seq = BaseSequence("stimulus", ["bset"])

async def run(self):
await self.seq.start(self.env.alu_seqr)


@pyuvm.test()
class TestBclr(BaseTest):
def end_of_elaboration_phase(self):
super().end_of_elaboration_phase()
self.seq = BaseSequence("stimulus", ["bclr"])

async def run(self):
await self.seq.start(self.env.alu_seqr)


@pyuvm.test()
class TestBinv(BaseTest):
def end_of_elaboration_phase(self):
super().end_of_elaboration_phase()
self.seq = BaseSequence("stimulus", ["binv"])

async def run(self):
await self.seq.start(self.env.alu_seqr)


@pyuvm.test()
class TestBext(BaseTest):
def end_of_elaboration_phase(self):
super().end_of_elaboration_phase()
self.seq = BaseSequence("stimulus", ["bext"])

async def run(self):
await self.seq.start(self.env.alu_seqr)


@pyuvm.test()
class TestAll(BaseTest):
def end_of_elaboration_phase(self):
super().end_of_elaboration_phase()
self.seq = BaseSequence("stimulus", ["bset", "bclr", "binv", "bext"])

async def run(self):
await self.seq.start(self.env.alu_seqr)
123 changes: 76 additions & 47 deletions verification/block/exu_alu/testbench.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,28 +69,22 @@ async def run_phase(self):
self.dut.valid_in.value = 1

# Zbb
self.dut.ap_clz.value = 0
self.dut.ap_ctz.value = 0
self.dut.ap_cpop.value = 0
self.dut.ap_sext_b.value = 0
self.dut.ap_sext_h.value = 0
self.dut.ap_min.value = 0
self.dut.ap_max.value = 0
self.dut.ap_rol.value = 0
self.dut.ap_ror.value = 0
self.dut.ap_grev.value = 0
self.dut.ap_gorc.value = 0
self.dut.ap_zbb.value = 0
self.dut.ap_clz.value = it.op in ["clz"]
self.dut.ap_ctz.value = it.op in ["ctz"]
self.dut.ap_cpop.value = it.op in ["cpop"]
self.dut.ap_sext_b.value = it.op in ["sext_b"]
self.dut.ap_sext_h.value = it.op in ["sext_h"]
self.dut.ap_rol.value = it.op in ["rol"]
self.dut.ap_ror.value = it.op in ["ror"]

# Zbs
self.dut.ap_bset.value = 0
self.dut.ap_bclr.value = 0
self.dut.ap_binv.value = 0
self.dut.ap_bext.value = 0
self.dut.ap_bset.value = it.op in ["bset"]
self.dut.ap_bclr.value = it.op in ["bclr"]
self.dut.ap_binv.value = it.op in ["binv"]
self.dut.ap_bext.value = it.op in ["bext"]

# Zbp
self.dut.ap_pack.value = it.op in ["pack"]
self.dut.ap_packu.value = 0
self.dut.ap_packh.value = it.op in ["packh"]

# Zba
Expand Down Expand Up @@ -148,38 +142,48 @@ async def run_phase(self):
b = int(self.dut.b_in.value)

# Decode operation
ap_add = int(self.dut.ap_add.value)
ap_sub = int(self.dut.ap_sub.value)
ap_and = int(self.dut.ap_land.value)
ap_or = int(self.dut.ap_lor.value)
ap_xor = int(self.dut.ap_lxor.value)
ap_pack = int(self.dut.ap_pack.value)
ap_packh = int(self.dut.ap_packh.value)
ap_sh1add = int(self.dut.ap_sh1add.value)
ap_sh2add = int(self.dut.ap_sh2add.value)
ap_sh3add = int(self.dut.ap_sh3add.value)

op = None

if ap_add:
if int(self.dut.ap_add.value):
op = "add"
elif ap_sub:
elif int(self.dut.ap_sub.value):
op = "sub"
elif ap_and:
elif int(self.dut.ap_land.value):
op = "and"
elif ap_or:
elif int(self.dut.ap_lor.value):
op = "or"
elif ap_xor:
elif int(self.dut.ap_lxor.value):
op = "xor"
elif ap_pack:
elif int(self.dut.ap_clz.value):
op = "clz"
elif int(self.dut.ap_ctz.value):
op = "ctz"
elif int(self.dut.ap_cpop.value):
op = "cpop"
elif int(self.dut.ap_sext_b.value):
op = "sext_b"
elif int(self.dut.ap_sext_h.value):
op = "sext_h"
elif int(self.dut.ap_rol.value):
op = "rol"
elif int(self.dut.ap_ror.value):
op = "ror"
elif int(self.dut.ap_bset.value):
op = "bset"
elif int(self.dut.ap_bclr.value):
op = "bclr"
elif int(self.dut.ap_binv.value):
op = "binv"
elif int(self.dut.ap_bext.value):
op = "bext"
elif int(self.dut.ap_pack.value):
op = "pack"
elif ap_packh:
elif int(self.dut.ap_packh.value):
op = "packh"
elif ap_sh1add:
elif int(self.dut.ap_sh1add.value):
op = "sh1add"
elif ap_sh2add:
elif int(self.dut.ap_sh2add.value):
op = "sh2add"
elif ap_sh3add:
elif int(self.dut.ap_sh3add.value):
op = "sh3add"

# Write item
Expand Down Expand Up @@ -279,16 +283,41 @@ def check_phase(self):
result = item_inp.a | item_inp.b
elif item_inp.op == "xor":
result = item_inp.a ^ item_inp.b
elif item_inp.op == "clz":
result = next((i for i in range(32) if ((item_inp.a << i) & INT_MASK) >> 31), 32)
elif item_inp.op == "ctz":
result = next((i for i in range(32) if (item_inp.a >> i) & 1), 32)
elif item_inp.op == "cpop":
result = item_inp.a.bit_count()
elif item_inp.op == "sext_b":
last_byte = item_inp.a & 0xFF
sign = (item_inp.a & 0x00000080) >> 7
result = (0xFFFFFF00 * sign) | last_byte
elif item_inp.op == "sext_h":
last_2_bytes = item_inp.a & 0xFFFF
sign = (item_inp.a & 0x00008000) >> 15
result = (0xFFFF0000 * sign) | last_2_bytes
elif item_inp.op == "rol":
shamt = item_inp.b & 31
result = (item_inp.a << shamt) & INT_MASK | (item_inp.a >> ((32 - shamt) & 31))
elif item_inp.op == "ror":
shamt = item_inp.b & 31
result = (item_inp.a >> shamt) | (item_inp.a << ((32 - shamt) & 31)) & INT_MASK
elif item_inp.op == "bset":
result = item_inp.a | (1 << (item_inp.b & 31))
elif item_inp.op == "bclr":
result = item_inp.a & ~(1 << (item_inp.b & 31))
elif item_inp.op == "binv":
result = item_inp.a ^ (1 << (item_inp.b & 31))
elif item_inp.op == "bext":
result = 1 & (item_inp.a >> (item_inp.b & 31))
elif item_inp.op == "pack":
result = (((item_inp.a << 16) & INT_MASK) >> 16) | (item_inp.b << 16) & INT_MASK
elif item_inp.op == "packh":
result = (item_inp.a & 0xFF) | ((item_inp.b & 0xFF) << 8)
elif item_inp.op == "sh1add":
result = ((item_inp.a << 1) + item_inp.b) & INT_MASK
elif item_inp.op == "sh2add":
result = ((item_inp.a << 2) + item_inp.b) & INT_MASK
elif item_inp.op == "sh3add":
result = ((item_inp.a << 3) + item_inp.b) & INT_MASK
elif item_inp.op in ["sh1add", "sh2add", "sh3add"]:
shift = int(item_inp.op[2])
result = ((item_inp.a << shift) + item_inp.b) & INT_MASK
else:
self.logger.error("Unknown ALU operation '{}'".format(item_inp.op))
self.passed = False
Expand Down Expand Up @@ -339,8 +368,8 @@ async def body(self):
count = ConfigDB().get(None, "", "TEST_ITERATIONS")

for i in range(count):
a = random.randrange(1, 1 << 32)
b = random.randrange(1, 1 << 32)
a = random.randrange(-(1 << 31), 1 << 31)
b = random.randrange(-(1 << 31), 1 << 31)
op = random.choice(self.ops)

item = AluInputItem(op, a, b)
Expand Down
2 changes: 2 additions & 0 deletions verification/block/noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,8 @@ def ifu_compress_verify(session, blockName, testName, coverage):
[
"test_arith",
"test_logic",
"test_zbb",
"test_zbs",
"test_zbp",
"test_zba",
],
Expand Down

0 comments on commit a8a87f3

Please sign in to comment.