Source code for xor_end_model
"""
Library for the XorEndModel class.
It contains the Python model used to verify the Xor End module.
@author: Timothée Charrier
"""
from __future__ import annotations
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from cocotb.handle import HierarchyObject
[docs]
class XorEndModel:
"""
Model for the XorEnd module.
This class defines the model used to verify the XorEnd module.
Attributes
----------
i_key : int
The input key.
o_state : list[int]
The output state.
Methods
-------
xor_key_end() -> None
Perform XOR operation at the end with the key.
xor_lsb_end() -> None
Perform XOR operation at the end with the least significant bit.
assert_output(dut: HierarchyObject, inputs: dict) -> None
Assert the output of the DUT and log the input and output values.
"""
def __init__(
self,
) -> None:
"""Initialize the model."""
# Output state
self.i_key: int = 0
self.o_state: list[int] = [0] * 5
[docs]
def xor_key_end(self) -> None:
"""Perform XOR operation at the end with the key."""
self.o_state[3] ^= self.i_key >> 64
self.o_state[4] ^= self.i_key & 0xFFFFFFFFFFFFFFFF
[docs]
def xor_lsb_end(self) -> None:
"""Perform XOR operation at the end with the least significant bit."""
self.o_state[4] ^= 0x0000000000000001
[docs]
def assert_output(
self,
dut: HierarchyObject,
inputs: dict | None = None,
) -> None:
"""
Assert the output of the DUT and log the input and output values.
Parameters
----------
dut : HierarchyObject
The device under test (DUT).
inputs : dict, optional
The input dictionary.
"""
# Set o_state to the input state
self.o_state = inputs["i_state"].copy()
self.i_key = inputs["i_key"]
# Compute the expected output
if inputs["i_enable_xor_key"]:
self.xor_key_end()
if inputs["i_enable_xor_lsb"]:
self.xor_lsb_end()
# Get the output state from the DUT
o_state: list[int] = [int(x) for x in dut.o_state.value]
# Convert the output to a list of integers
enable_str: str = (
f"Xor Key: {inputs['i_enable_xor_key']}, "
f"Xor LSB: {inputs['i_enable_xor_lsb']}"
)
input_str: str = "{:016X} {:016X} {:016X} {:016X} {:016X}".format(
*tuple(x & 0xFFFFFFFFFFFFFFFF for x in inputs["i_state"]),
)
expected_str: str = "{:016X} {:016X} {:016X} {:016X} {:016X}".format(
*tuple(x & 0xFFFFFFFFFFFFFFFF for x in self.o_state),
)
output_dut_str: str = "{:016X} {:016X} {:016X} {:016X} {:016X}".format(
*tuple(x & 0xFFFFFFFFFFFFFFFF for x in o_state),
)
# Log the input and output values
dut._log.info("Enable XOR : " + enable_str)
dut._log.info("Input state : " + input_str)
dut._log.info("Expected state : " + expected_str)
dut._log.info("Output state : " + output_dut_str)
dut._log.info("")
# Check if the output is correct
if expected_str != output_dut_str:
error_msg: str = f"Expected: {expected_str}\nReceived: {output_dut_str}"
raise ValueError(error_msg)