Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tests of zbs and zbb instructions #180

Merged
merged 3 commits into from
Jun 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading