I have a protected type in VHDL, which implements a initializer function or procedure.
Here is my code with an initializer procedure:
type T_SIM_STATUS is protected
procedure init;
procedure fail(Message : in STRING := "") ;
procedure simAssert(condition : BOOLEAN; Message : STRING := "") ;
procedure simReport;
end protected;
type T_SIM_STATUS is protected body
variable NotImplemented : BOOLEAN := TRUE;
variable Passed : BOOLEAN := TRUE;
procedure init is
begin
NotImplemented := FALSE;
end procedure;
procedure fail(Message : in STRING := "") is
begin
if (Message'length > 0) then
report Message severity error;
end if;
Passed := FALSE;
end procedure;
procedure simAssert(condition : BOOLEAN; Message : STRING := "") is
begin
if (condition = FALSE) then
fail(Message);
end if;
end procedure;
procedure simReport is
variable l : LINE;
begin
write(l, STRING'("SIMULATION RESULT = "));
if (NotImplemented = TRUE) then
write(l, STRING'("NOT IMPLEMENTED"));
elsif (Passed = TRUE) then
write(l, STRING'("PASSED"));
else
write(l, STRING'("FAILED"));
end if;
end procedure;
end protected body;
shared variable simStatus : T_SIM_STATUS;
Where should I call the init
procedure?
My current solution calls init
in a seperate process in the testbench's architecture body:
architecture rtl of test is
-- ...
begin
procInit : process
begin
simStatus.init;
wait;
end process;
procGenerator : process
begin
-- generate stimuli
wait;
end process;
procTester : process
begin
-- check results by using simStatus.simAssert
simStatus.simReport;
wait;
end process;
end architecture;
Are there better solutions?
Based on your code, and assuming effect of init
should be made before any use of other procedures (methods) in the protected type, it looks like init
procedure could be removed if NotImplemented
if given an initial value of FALSE
instead of TRUE
.
Otherwise, if init
is to be called first, just make sure that other uses of the shared variable are not called at time 0, in which case the call to init
can be made as concurrent, thus without the process
wrapper, but simply like:
simStatus.init;
If more complex setup must be done through a init
call, then it could be called automatically when instantiating the shared variable if init
is made as a function, that is then called from within the body of the shared variable, like:
type T_SIM_STATUS is protected
-- No init function is made public
procedure fail(Message : in STRING := "") ;
procedure simAssert(condition : BOOLEAN; Message : STRING := "") ;
procedure simReport;
end protected;
type T_SIM_STATUS is protected body
variable NotImplemented : BOOLEAN := TRUE;
variable Passed : BOOLEAN := TRUE;
... # Other code
impure function init return boolean is
begin
NotImplemented := FALSE;
... -- Or other more complex code
return TRUE;
end function;
variable dummy : boolean := init; -- Calling init with side effects
end protected body;