I made a small effort to split the irqc_tb.vhd into use separate test using VUnit. I had some problem with test independence of the "Check irq acknowledge and re-enable test" depending on a variable value from the previous "Check autonomy for all interrupts" test case but I soon found and fixed it. I also ensured your _Alert.txt and _Log.txt files ended up in the test specific output folders. I did not need to use any of your hardcoded compile scripts since VUnit figured out the dependencies automatically. The non-verbose textual output when running looked like this. (The pass being in green color in a real terminal):
Starting irqc_lib.irqc_tb.Check defaults on output ports
pass (P=1 S=0 F=0 T=7) irqc_lib.irqc_tb.Check defaults on output ports (0.9 seconds)
Starting irqc_lib.irqc_tb.Check register defaults and access write read
pass (P=2 S=0 F=0 T=7) irqc_lib.irqc_tb.Check register defaults and access write read (0.3 seconds)
Starting irqc_lib.irqc_tb.Check register trigger clear mechanism
pass (P=3 S=0 F=0 T=7) irqc_lib.irqc_tb.Check register trigger clear mechanism (0.3 seconds)
Starting irqc_lib.irqc_tb.Check interrupt sources IER IPR and irq2cpu
pass (P=4 S=0 F=0 T=7) irqc_lib.irqc_tb.Check interrupt sources IER IPR and irq2cpu (0.3 seconds)
Starting irqc_lib.irqc_tb.Check autonomy for all interrupts
pass (P=5 S=0 F=0 T=7) irqc_lib.irqc_tb.Check autonomy for all interrupts (0.3 seconds)
Starting irqc_lib.irqc_tb.Check irq acknowledge and re-enable
pass (P=6 S=0 F=0 T=7) irqc_lib.irqc_tb.Check irq acknowledge and re-enable (0.3 seconds)
Starting irqc_lib.irqc_tb.Check Reset
pass (P=7 S=0 F=0 T=7) irqc_lib.irqc_tb.Check Reset (0.3 seconds)
==== Summary ==========================================================================
pass irqc_lib.irqc_tb.Check defaults on output ports (0.9 seconds)
pass irqc_lib.irqc_tb.Check register defaults and access write read (0.3 seconds)
pass irqc_lib.irqc_tb.Check register trigger clear mechanism (0.3 seconds)
pass irqc_lib.irqc_tb.Check interrupt sources IER IPR and irq2cpu (0.3 seconds)
pass irqc_lib.irqc_tb.Check autonomy for all interrupts (0.3 seconds)
pass irqc_lib.irqc_tb.Check irq acknowledge and re-enable (0.3 seconds)
pass irqc_lib.irqc_tb.Check Reset (0.3 seconds)
=======================================================================================
pass 7 of 7
=======================================================================================
Total time was 2.6 seconds
Elapsed time was 2.6 seconds
=======================================================================================
All passed!
The run.py file used to drive everything looked like this:
from os.path import dirname, join
from vunit import VUnit
root = dirname(__file__)
ui = VUnit.from_argv()
bvul_lib = ui.add_library("bitvis_util")
bvul_lib.add_source_files(join(root, "bitvis_util", "src2008", "*.vhd"))
bitvis_vip_spi_lib = ui.add_library("bitvis_vip_sbi")
bitvis_vip_spi_lib.add_source_files(join(root, "bitvis_vip_sbi", "src", "*.vhd"))
irqc_lib = ui.add_library("irqc_lib")
irqc_lib.add_source_files(join(root, "bitvis_irqc", "src", "*.vhd"))
irqc_lib.add_source_files(join(root, "bitvis_irqc", "tb", "*.vhd"))
ui.main()
The modified irqc_tb.vhd looked like this: (The name collision with your and our log method prevented me from using our VHDL-2008 context for the VUnit packages forcing me to use them individually to avoid exposing our log):
--========================================================================================================================
-- Copyright (c) 2015 by Bitvis AS. All rights reserved.
-- A free license is hereby granted, free of charge, to any person obtaining
-- a copy of this VHDL code and associated documentation files (for 'Bitvis Utility Library'),
-- to use, copy, modify, merge, publish and/or distribute - subject to the following conditions:
-- - This copyright notice shall be included as is in all copies or substantial portions of the code and documentation
-- - The files included in Bitvis Utility Library may only be used as a part of this library as a whole
-- - The License file may not be modified
-- - The calls in the code to the license file ('show_license') may not be removed or modified.
-- - No other conditions whatsoever may be added to those of this License
-- BITVIS UTILITY LIBRARY AND ANY PART THEREOF ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-- INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-- WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH BITVIS UTILITY LIBRARY.
--========================================================================================================================
------------------------------------------------------------------------------------------
-- VHDL unit : Bitvis IRQC Library : irqc_tb
--
-- Description : See dedicated powerpoint presentation and README-file(s)
------------------------------------------------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
library STD;
use std.textio.all;
-- library ieee_proposed;
-- use ieee_proposed.standard_additions.all;
-- use ieee_proposed.std_logic_1164_additions.all;
library vunit_lib;
use vunit_lib.run_types_pkg.all;
use vunit_lib.run_pkg.all;
use vunit_lib.run_base_pkg.all;
library bitvis_util;
use bitvis_util.types_pkg.all;
use bitvis_util.string_methods_pkg.all;
use bitvis_util.adaptations_pkg.all;
use bitvis_util.methods_pkg.all;
library bitvis_vip_sbi;
use bitvis_vip_sbi.sbi_bfm_pkg.all;
use work.irqc_pif_pkg.all;
-- Test case entity
entity irqc_tb is
generic (runner_cfg : runner_cfg_t);
end entity;
-- Test case architecture
architecture func of irqc_tb is
-- DSP interface and general control signals
signal clk : std_logic := '0';
signal arst : std_logic := '0';
-- CPU interface
signal cs : std_logic := '0';
signal addr : unsigned(2 downto 0) := (others => '0');
signal wr : std_logic := '0';
signal rd : std_logic := '0';
signal din : std_logic_vector(7 downto 0) := (others => '0');
signal dout : std_logic_vector(7 downto 0) := (others => '0');
signal rdy : std_logic := '1'; -- Always ready in the same clock cycle
-- Interrupt related signals
signal irq_source : std_logic_vector(C_NUM_SOURCES-1 downto 0) := (others => '0');
signal irq2cpu : std_logic := '0';
signal irq2cpu_ack : std_logic := '0';
signal clock_ena : boolean := false;
constant C_CLK_PERIOD : time := 10 ns;
procedure clock_gen(
signal clock_signal : inout std_logic;
signal clock_ena : in boolean;
constant clock_period : in time
) is
variable v_first_half_clk_period : time := C_CLK_PERIOD / 2;
begin
loop
if not clock_ena then
wait until clock_ena;
end if;
wait for v_first_half_clk_period;
clock_signal <= not clock_signal;
wait for (clock_period - v_first_half_clk_period);
clock_signal <= not clock_signal;
end loop;
end;
subtype t_irq_source is std_logic_vector(C_NUM_SOURCES-1 downto 0);
-- Trim (cut) a given vector to fit the number of irq sources (i.e. pot. reduce width)
function trim(
constant source : std_logic_vector;
constant num_bits : positive := C_NUM_SOURCES)
return t_irq_source is
variable v_result : std_logic_vector(source'length-1 downto 0) := source;
begin
return v_result(num_bits-1 downto 0);
end;
-- Fit a given vector to the number of irq sources by masking with zeros above irq width
function fit(
constant source : std_logic_vector;
constant num_bits : positive := C_NUM_SOURCES)
return std_logic_vector is
variable v_result : std_logic_vector(source'length-1 downto 0) := (others => '0');
variable v_source : std_logic_vector(source'length-1 downto 0) := source;
begin
v_result(num_bits-1 downto 0) := v_source(num_bits-1 downto 0);
return v_result;
end;
begin
-----------------------------------------------------------------------------
-- Instantiate DUT
-----------------------------------------------------------------------------
i_irqc: entity work.irqc
port map (
-- DSP interface and general control signals
clk => clk,
arst => arst,
-- CPU interface
cs => cs,
addr => addr,
wr => wr,
rd => rd,
din => din,
dout => dout,
-- Interrupt related signals
irq_source => irq_source,
irq2cpu => irq2cpu,
irq2cpu_ack => irq2cpu_ack
);
-- Set upt clock generator
clock_gen(clk, clock_ena, 10 ns);
------------------------------------------------
-- PROCESS: p_main
------------------------------------------------
p_main: process
constant C_SCOPE : string := C_TB_SCOPE_DEFAULT;
procedure pulse(
signal target : inout std_logic;
signal clock_signal : in std_logic;
constant num_periods : in natural;
constant msg : in string
) is
begin
if num_periods > 0 then
wait until falling_edge(clock_signal);
target <= '1';
for i in 1 to num_periods loop
wait until falling_edge(clock_signal);
end loop;
else
target <= '1';
wait for 0 ns; -- Delta cycle only
end if;
target <= '0';
log(ID_SEQUENCER_SUB, msg, C_SCOPE);
end;
procedure pulse(
signal target : inout std_logic_vector;
constant pulse_value : in std_logic_vector;
signal clock_signal : in std_logic;
constant num_periods : in natural;
constant msg : in string) is
begin
if num_periods > 0 then
wait until falling_edge(clock_signal);
target <= pulse_value;
for i in 1 to num_periods loop
wait until falling_edge(clock_signal);
end loop;
else
target <= pulse_value;
wait for 0 ns; -- Delta cycle only
end if;
target(target'range) <= (others => '0');
log(ID_SEQUENCER_SUB, "Pulsed to " & to_string(pulse_value, HEX, AS_IS, INCL_RADIX) & ". " & msg, C_SCOPE);
end;
-- Log overloads for simplification
procedure log(
msg : string) is
begin
log(ID_SEQUENCER, msg, C_SCOPE);
end;
-- Overloads for PIF BFMs for SBI (Simple Bus Interface)
procedure write(
constant addr_value : in natural;
constant data_value : in std_logic_vector;
constant msg : in string) is
begin
sbi_write(to_unsigned(addr_value, addr'length), data_value, msg,
clk, cs, addr, rd, wr, rdy, din, C_CLK_PERIOD, C_SCOPE);
end;
procedure check(
constant addr_value : in natural;
constant data_exp : in std_logic_vector;
constant alert_level : in t_alert_level;
constant msg : in string) is
begin
sbi_check(to_unsigned(addr_value, addr'length), data_exp, alert_level, msg,
clk, cs, addr, rd, wr, rdy, dout, C_CLK_PERIOD, C_SCOPE);
end;
procedure set_inputs_passive(
dummy : t_void) is
begin
cs <= '0';
addr <= (others => '0');
wr <= '0';
rd <= '0';
din <= (others => '0');
irq_source <= (others => '0');
irq2cpu_ack <= '0';
log(ID_SEQUENCER_SUB, "All inputs set passive", C_SCOPE);
end;
variable v_time_stamp : time := 0 ns;
variable v_irq_mask : std_logic_vector(7 downto 0);
variable v_irq_mask_inv : std_logic_vector(7 downto 0);
begin
test_runner_setup(runner, runner_cfg);
-- Use VUnit output path
set_log_file_name(output_path(runner_cfg) & "_Log.txt");
set_alert_file_name(output_path(runner_cfg) & "_Alert.txt");
-- Print the configuration to the log
report_global_ctrl(VOID);
report_msg_id_panel(VOID);
enable_log_msg(ALL_MESSAGES);
--disable_log_msg(ALL_MESSAGES);
--enable_log_msg(ID_LOG_HDR);
log(ID_LOG_HDR, "Start Simulation of TB for IRQC", C_SCOPE);
------------------------------------------------------------
set_inputs_passive(VOID);
clock_ena <= true; -- to start clock generator
pulse(arst, clk, 10, "Pulsed reset-signal - active for 10T");
v_time_stamp := now; -- time from which irq2cpu should be stable off until triggered
check_value(C_NUM_SOURCES > 0, FAILURE, "Must be at least 1 interrupt source", C_SCOPE);
check_value(C_NUM_SOURCES <= 8, TB_WARNING, "This TB is only checking IRQC with up to 8 interrupt sources", C_SCOPE);
while test_suite loop
if run("Check defaults on output ports") then
check_value(irq2cpu, '0', ERROR, "Interrupt to CPU must be default inactive", C_SCOPE);
check_value(dout, x"00", ERROR, "Register data bus output must be default passive");
elsif run("Check register defaults and access write read") then
log("\nChecking Register defaults");
check(C_ADDR_IRR, x"00", ERROR, "IRR default");
check(C_ADDR_IER, x"00", ERROR, "IER default");
check(C_ADDR_IPR, x"00", ERROR, "IPR default");
check(C_ADDR_IRQ2CPU_ALLOWED, x"00", ERROR, "IRQ2CPU_ALLOWED default");
log("\nChecking Register Write/Read");
write(C_ADDR_IER, fit(x"55"), "IER");
check(C_ADDR_IER, fit(x"55"), ERROR, "IER pure readback");
write(C_ADDR_IER, fit(x"AA"), "IER");
check(C_ADDR_IER, fit(x"AA"), ERROR, "IER pure readback");
write(C_ADDR_IER, fit(x"00"), "IER");
check(C_ADDR_IER, fit(x"00"), ERROR, "IER pure readback");
elsif run("Check register trigger clear mechanism") then
write(C_ADDR_ITR, fit(x"AA"), "ITR : Set interrupts");
check(C_ADDR_IRR, fit(x"AA"), ERROR, "IRR");
write(C_ADDR_ITR, fit(x"55"), "ITR : Set more interrupts");
check(C_ADDR_IRR, fit(x"FF"), ERROR, "IRR");
write(C_ADDR_ICR, fit(x"71"), "ICR : Clear interrupts");
check(C_ADDR_IRR, fit(x"8E"), ERROR, "IRR");
write(C_ADDR_ICR, fit(x"85"), "ICR : Clear interrupts");
check(C_ADDR_IRR, fit(x"0A"), ERROR, "IRR");
write(C_ADDR_ITR, fit(x"55"), "ITR : Set more interrupts");
check(C_ADDR_IRR, fit(x"5F"), ERROR, "IRR");
write(C_ADDR_ICR, fit(x"5F"), "ICR : Clear interrupts");
check(C_ADDR_IRR, fit(x"00"), ERROR, "IRR");
elsif run("Check interrupt sources IER IPR and irq2cpu") then
log("\nChecking interrupts and IRR");
write(C_ADDR_ICR, fit(x"FF"), "ICR : Clear all interrupts");
pulse(irq_source, trim(x"AA"), clk, 1, "Pulse irq_source 1T");
check(C_ADDR_IRR, fit(x"AA"), ERROR, "IRR after irq pulses");
pulse(irq_source, trim(x"01"), clk, 1, "Add more interrupts");
check(C_ADDR_IRR, fit(x"AB"), ERROR, "IRR after irq pulses");
pulse(irq_source, trim(x"A1"), clk, 1, "Repeat same interrupts");
check(C_ADDR_IRR, fit(x"AB"), ERROR, "IRR after irq pulses");
pulse(irq_source, trim(x"54"), clk, 1, "Add remaining interrupts");
check(C_ADDR_IRR, fit(x"FF"), ERROR, "IRR after irq pulses");
write(C_ADDR_ICR, fit(x"AA"), "ICR : Clear half the interrupts");
pulse(irq_source, trim(x"A0"), clk, 1, "Add more interrupts");
check(C_ADDR_IRR, fit(x"F5"), ERROR, "IRR after irq pulses");
write(C_ADDR_ICR, fit(x"FF"), "ICR : Clear all interrupts");
check(C_ADDR_IRR, fit(x"00"), ERROR, "IRR after clearing all");
log("Checking IER IPR and irq2cpu");
write(C_ADDR_ICR, fit(x"FF"), "ICR : Clear all interrupts");
write(C_ADDR_IER, fit(x"55"), "IER : Enable some interrupts");
write(C_ADDR_ITR, fit(x"AA"), "ITR : Trigger non-enable interrupts");
check(C_ADDR_IPR, fit(x"00"), ERROR, "IPR should not be active");
check(C_ADDR_IRQ2CPU_ALLOWED, x"00", ERROR, "IRQ2CPU_ALLOWED should not be active");
write(C_ADDR_IRQ2CPU_ENA, x"01", "IRQ2CPU_ENA : Enable main interrupt to CPU");
check(C_ADDR_IRQ2CPU_ALLOWED, x"01", ERROR, "IRQ2CPU_ALLOWED should now be active");
check_value(irq2cpu, '0', ERROR, "Interrupt to CPU must still be inactive", C_SCOPE);
check_stable(irq2cpu, (now - v_time_stamp), ERROR, "No spikes allowed on irq2cpu", C_SCOPE);
pulse(irq_source, trim(x"01"), clk, 1, "Add a single enabled interrupt");
await_value(irq2cpu, '1', 0 ns, C_CLK_PERIOD, ERROR, "Interrupt expected immediately", C_SCOPE);
v_time_stamp := now; -- from time of stable active irq2cpu
check(C_ADDR_IRR, fit(x"AB"), ERROR, "IRR should now be active");
check(C_ADDR_IPR, fit(x"01"), ERROR, "IPR should now be active");
log("\nMore details checked in the autonomy section below");
check_value(irq2cpu, '1', ERROR, "Interrupt to CPU must still be active", C_SCOPE);
check_stable(irq2cpu, (now - v_time_stamp), ERROR, "No spikes allowed on irq2cpu", C_SCOPE);
elsif run("Check autonomy for all interrupts") then
write(C_ADDR_ICR, fit(x"FF"), "ICR : Clear all interrupts");
write(C_ADDR_IER, fit(x"FF"), "IER : Disable all interrupts");
write(C_ADDR_IRQ2CPU_ENA, x"01", "IRQ2CPU_ENA : Allow interrupt to CPU");
for i in 0 to C_NUM_SOURCES-1 loop
log(" ");
log("- Checking irq_source(" & to_string(i) & ") and all corresponding functionality");
log("- - Check interrupt activation not affected by non related interrupts or registers");
v_time_stamp := now; -- from time of stable inactive irq2cpu
v_irq_mask := (i => '1', others => '0');
v_irq_mask_inv := (i => '0', others => '1');
write(C_ADDR_IER, v_irq_mask, "IER : Enable selected interrupt");
pulse(irq_source, trim(v_irq_mask_inv), clk, 1, "Pulse all non-enabled interrupts");
write(C_ADDR_ITR, v_irq_mask_inv, "ITR : Trigger all non-enabled interrupts");
check(C_ADDR_IRR, fit(v_irq_mask_inv), ERROR, "IRR not yet triggered");
check(C_ADDR_IPR, x"00", ERROR, "IPR not yet triggered");
check_value(irq2cpu, '0', ERROR, "Interrupt to CPU must still be inactive", C_SCOPE);
check_stable(irq2cpu, (now - v_time_stamp), ERROR, "No spikes allowed on irq2cpu", C_SCOPE);
pulse(irq_source, trim(v_irq_mask), clk, 1, "Pulse the enabled interrupt");
await_value(irq2cpu, '1', 0 ns, C_CLK_PERIOD, ERROR, "Interrupt expected immediately", C_SCOPE);
check(C_ADDR_IRR, fit(x"FF"), ERROR, "All IRR triggered");
check(C_ADDR_IPR, v_irq_mask, ERROR, "IPR triggered for selected");
log("\n- - Check interrupt deactivation not affected by non related interrupts or registers");
v_time_stamp := now; -- from time of stable active irq2cpu
write(C_ADDR_ICR, v_irq_mask_inv, "ICR : Clear all non-enabled interrupts");
write(C_ADDR_IER, fit(x"FF"), "IER : Enable all interrupts");
write(C_ADDR_IER, v_irq_mask, "IER : Disable non-selected interrupts");
pulse(irq_source, trim(x"FF"), clk, 1, "Pulse all interrupts");
write(C_ADDR_ITR, x"FF", "ITR : Trigger all interrupts");
check_stable(irq2cpu, (now - v_time_stamp), ERROR, "No spikes allowed on irq2cpu (='1')", C_SCOPE);
write(C_ADDR_IER, v_irq_mask_inv, "IER : Enable all interrupts but disable selected");
check_value(irq2cpu, '1', ERROR, "Interrupt to CPU still active", C_SCOPE);
check(C_ADDR_IRR, fit(x"FF"), ERROR, "IRR still active for all");
write(C_ADDR_ICR, v_irq_mask_inv, "ICR : Clear all non-enabled interrupts");
await_value(irq2cpu, '0', 0 ns, C_CLK_PERIOD, ERROR, "Interrupt deactivation expected immediately", C_SCOPE);
write(C_ADDR_IER, v_irq_mask, "IER : Re-enable selected interrupt");
await_value(irq2cpu, '1', 0 ns, C_CLK_PERIOD, ERROR, "Interrupt reactivation expected immediately", C_SCOPE);
check(C_ADDR_IPR, v_irq_mask, ERROR, "IPR still active for selected");
write(C_ADDR_ICR, v_irq_mask, "ICR : Clear selected interrupt");
check_value(irq2cpu, '0', ERROR, "Interrupt to CPU must go inactive", C_SCOPE);
check(C_ADDR_IRR, x"00", ERROR, "IRR all inactive");
check(C_ADDR_IPR, x"00", ERROR, "IPR all inactive");
write(C_ADDR_IER, x"00", "IER : Disable all interrupts");
end loop;
report_alert_counters(INTERMEDIATE); -- Report intermediate counters
elsif run("Check irq acknowledge and re-enable") then
log("- Activate interrupt");
write(C_ADDR_ITR, x"01", "ICR : Set single upper interrupt");
write(C_ADDR_IER, x"01", "IER : Enable single upper interrupts");
write(C_ADDR_IRQ2CPU_ENA, x"01", "IRQ2CPU_ENA : Allow interrupt to CPU");
await_value(irq2cpu, '1', 0 ns, C_CLK_PERIOD, ERROR, "Interrupt activation expected", C_SCOPE);
v_time_stamp := now; -- from time of stable active irq2cpu
log("\n- Try potential malfunction");
write(C_ADDR_IRQ2CPU_ENA, x"01", "IRQ2CPU_ENA : Allow interrupt to CPU again - should not affect anything");
write(C_ADDR_IRQ2CPU_ENA, x"00", "IRQ2CPU_ENA : Set to 0 - should not affect anything");
write(C_ADDR_IRQ2CPU_DISABLE, x"00", "IRQ2CPU_DISABLE : Set to 0 - should not affect anything");
check_stable(irq2cpu, (now - v_time_stamp), ERROR, "No spikes allowed on irq2cpu (='1')", C_SCOPE);
log("\n- Acknowledge and deactivate interrupt");
pulse(irq2cpu_ack, clk, 1, "Pulse irq2cpu_ack");
await_value(irq2cpu, '0', 0 ns, C_CLK_PERIOD, ERROR, "Interrupt deactivation expected", C_SCOPE);
v_time_stamp := now; -- from time of stable inactive irq2cpu
log("\n- Test for potential malfunction");
write(C_ADDR_IRQ2CPU_DISABLE, x"01", "IRQ2CPU_DISABLE : Disable interrupt to CPU again - should not affect anything");
write(C_ADDR_IRQ2CPU_DISABLE, x"00", "IRQ2CPU_DISABLE : Set to 0 - should not affect anything");
write(C_ADDR_IRQ2CPU_ENA, x"00", "IRQ2CPU_ENA : Set to 0 - should not affect anything");
write(C_ADDR_ITR, x"FF", "ICR : Trigger all interrupts");
write(C_ADDR_IER, x"FF", "IER : Enable all interrupts");
pulse(irq_source, trim(x"FF"), clk, 1, "Pulse all interrupts");
pulse(irq2cpu_ack, clk, 1, "Pulse irq2cpu_ack");
check_stable(irq2cpu, (now - v_time_stamp), ERROR, "No spikes allowed on irq2cpu (='0')", C_SCOPE);
log("\n- Re-/de-activation");
write(C_ADDR_IRQ2CPU_ENA, x"01", "IRQ2CPU_ENA : Reactivate interrupt to CPU");
await_value(irq2cpu, '1', 0 ns, C_CLK_PERIOD, ERROR, "Interrupt reactivation expected", C_SCOPE);
write(C_ADDR_IRQ2CPU_DISABLE, x"01", "IRQ2CPU_DISABLE : Deactivate interrupt to CPU");
await_value(irq2cpu, '0', 0 ns, C_CLK_PERIOD, ERROR, "Interrupt deactivation expected", C_SCOPE);
write(C_ADDR_IRQ2CPU_ENA, x"01", "IRQ2CPU_ENA : Reactivate interrupt to CPU");
await_value(irq2cpu, '1', 0 ns, C_CLK_PERIOD, ERROR, "Interrupt reactivation expected", C_SCOPE);
elsif run("Check Reset") then
log("- Activate all interrupts");
write(C_ADDR_ITR, x"FF", "ICR : Set all interrupts");
write(C_ADDR_IER, x"FF", "IER : Enable all interrupts");
write(C_ADDR_IRQ2CPU_ENA, x"01", "IRQ2CPU_ENA : Allow interrupt to CPU");
await_value(irq2cpu, '1', 0 ns, C_CLK_PERIOD, ERROR, "Interrupt activation expected", C_SCOPE);
pulse(arst, clk, 1, "Pulse reset");
await_value(irq2cpu, '0', 0 ns, C_CLK_PERIOD, ERROR, "Interrupt deactivation", C_SCOPE);
check(C_ADDR_IER, x"00", ERROR, "IER all inactive");
check(C_ADDR_IRR, x"00", ERROR, "IRR all inactive");
check(C_ADDR_IPR, x"00", ERROR, "IPR all inactive");
end if;
end loop;
--==================================================================================================
-- Ending the simulation
--------------------------------------------------------------------------------------
wait for 1000 ns; -- to allow some time for completion
report_alert_counters(FINAL); -- Report final counters and print conclusion for simulation (Success/Fail)
test_runner_cleanup(runner);
wait; -- to stop completely
end process p_main;
end func;