Source code for substitution_layer_model

"""
Library for the SubstitutionLayerModel class.

It contains the Python model used to verify the Substitution Layer module.

@author: Timothée Charrier
"""

from __future__ import annotations

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from cocotb.handle import HierarchyObject


[docs] class SubstitutionLayerModel: """ Model for the Substitution Layer module. This class defines the model used to verify the Substitution Layer module. Attributes ---------- o_state : list[int] The output state. Methods ------- _substitution_layer(state: list[int]) -> list[int] Apply the substitution layer (S-box). assert_output(dut: HierarchyObject, inputs: dict | None = None) -> None Assert the output of the DUT and log the input and output values. """ def __init__( self, ) -> None: """Initialize the model.""" # Output state self.o_state: list[int] = [0] * 5
[docs] def _substitution_layer(self, state: list[int]) -> list[int]: """ Apply the substitution layer (S-box). Parameters ---------- state : List[int] The current state. Returns ------- List[int] The updated state after the substitution layer. """ state[0] ^= state[4] state[4] ^= state[3] state[2] ^= state[1] temp = [(state[i] ^ 0xFFFFFFFFFFFFFFFF) & state[(i + 1) % 5] for i in range(5)] state = [state[i] ^ temp[(i + 1) % 5] for i in range(5)] state[1] ^= state[0] state[0] ^= state[4] state[3] ^= state[2] state[2] ^= 0xFFFFFFFFFFFFFFFF return state
[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. """ # Compute the expected output self.o_state = self._substitution_layer(state=inputs["i_state"]) # 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 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), ) 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)