diff --git a/sim/StackP.vhd b/sim/StackP.vhd new file mode 100644 index 0000000..a518e69 --- /dev/null +++ b/sim/StackP.vhd @@ -0,0 +1,116 @@ +library ieee; + use ieee.std_logic_1164.all; + +--+ including vhdl 2008 libraries +--+ These lines can be commented out when using +--+ a simulator with built-in VHDL 2008 support +--library ieee_proposed; +-- use ieee_proposed.standard_additions.all; +-- use ieee_proposed.std_logic_1164_additions.all; + + +package StackP is + + + -- linked list stack interface + type t_stack is protected + + procedure push (data : in std_logic_vector); + procedure pop (data : inout std_logic_vector); + procedure init (logging : in boolean := false); + impure function is_empty return boolean; + impure function fillstate return natural; + + end protected t_stack; + + +end package StackP; + + + +package body StackP is + + + -- linked list stack implementation + type t_stack is protected body + + type t_entry; + type t_entry_ptr is access t_entry; + + type t_data_ptr is access std_logic_vector; + + type t_entry is record + data : t_data_ptr; + last_entry : t_entry_ptr; + next_entry : t_entry_ptr; + end record t_entry; + + variable v_head : t_entry_ptr := null; + variable v_tail : t_entry_ptr := null; + variable v_count : natural := 0; + variable v_logging : boolean := false; + + -- write one entry into queue by + -- creating new entry at head of list + procedure push (data : in std_logic_vector) is + variable v_entry : t_entry_ptr; + begin + if (v_count /= 0) then + v_entry := new t_entry; + v_entry.data := new std_logic_vector'(data); + v_entry.last_entry := v_head; + v_entry.next_entry := null; + v_head := v_entry; + v_head.last_entry.next_entry := v_head; + else + v_head := new t_entry; + v_head.data := new std_logic_vector'(data); + v_head.last_entry := null; + v_head.next_entry := null; + v_tail := v_head; + end if; + v_count := v_count + 1; + if v_logging then + report t_stack'instance_name & " pushed 0x" & to_hstring(data) & " on stack"; + end if; + end procedure push; + + -- read one entry from queue at tail of list and + -- delete that entry from list after read + procedure pop (data : inout std_logic_vector) is + variable v_entry : t_entry_ptr := v_head; + begin + assert not(is_empty) + report "pop from empty queue -> discarded" + severity failure; + data := v_head.data.all; + v_head := v_head.last_entry; + deallocate(v_entry.data); + deallocate(v_entry); + v_count := v_count - 1; + if v_logging then + report t_stack'instance_name & " popped 0x" & to_hstring(data) & " from stack"; + end if; + end procedure pop; + + procedure init (logging : in boolean := false) is + begin + v_logging := logging; + end procedure init; + + -- returns true if queue is empty, false otherwise + impure function is_empty return boolean is + begin + return v_head = null; + end function is_empty; + + -- returns number of filled slots in queue + impure function fillstate return natural is + begin + return v_count; + end function fillstate; + + end protected body t_stack; + + +end package body StackP; diff --git a/test/Makefile b/test/Makefile index 06278ca..71fee4c 100644 --- a/test/Makefile +++ b/test/Makefile @@ -6,7 +6,7 @@ VHD_STD := 08 .PHONY: all -all: queue dict sim wishbone +all: queue dict stack sim wishbone .PHONY: vhdl2008 @@ -41,6 +41,9 @@ dictt: RandomPkg.o DictP.o DictT.vhd ghdl -a --std=$(VHD_STD) DictT.vhd ghdl -e --std=$(VHD_STD) $@ +stackt: RandomPkg.o AssertP.o StackP.o StackT.vhd + ghdl -a --std=$(VHD_STD) StackT.vhd + ghdl -e --std=$(VHD_STD) $@ simt: RandomPkg.o UtilsP.o AssertP.o QueueP.o SimP.o SimT.vhd ghdl -a --std=$(VHD_STD) SimT.vhd @@ -79,6 +82,7 @@ clean: rm -f *.ghw rm -f queuet rm -f dictt + rm -f stackt rm -f stringt rm -f simt rm -f spit diff --git a/test/StackT.vhd b/test/StackT.vhd new file mode 100644 index 0000000..bf6acaa --- /dev/null +++ b/test/StackT.vhd @@ -0,0 +1,69 @@ +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + +--+ including vhdl 2008 libraries +--+ These lines can be commented out when using +--+ a simulator with built-in VHDL 2008 support +--library ieee_proposed; +-- use ieee_proposed.standard_additions.all; +-- use ieee_proposed.std_logic_1164_additions.all; +-- use ieee_proposed.numeric_std_additions.all; + +library osvvm; + use osvvm.RandomPkg.all; + +library libvhdl; + use libvhdl.AssertP.all; + use libvhdl.StackP.all; + + + +entity StackT is +end entity StackT; + + + +architecture sim of StackT is + + + constant C_STACK_DEPTH : natural := 64; + + type t_scoreboard is array (natural range <>) of std_logic_vector(7 downto 0); + + shared variable sv_stack : t_stack; + + +begin + + + StackInitP : process is + begin + sv_stack.init(false); + wait; + end process StackInitP; + + + StackTestP : process is + variable v_data : std_logic_vector(7 downto 0); + begin + -- check initial emptiness + assert_true(sv_stack.is_empty, "Stack should be empty!"); + for i in 0 to C_STACK_DEPTH-1 loop + sv_stack.push(std_logic_vector(to_unsigned(i, 8))); + end loop; + -- check that it's full + assert_equal(sv_stack.fillstate, C_STACK_DEPTH, "Stack should have" & integer'image(C_STACK_DEPTH) & "entries"); + -- empty the queue + for i in C_STACK_DEPTH-1 downto 0 loop + sv_stack.pop(v_data); + assert_equal(v_data, std_logic_vector(to_unsigned(i, 8))); + end loop; + -- check emptiness + assert_true(sv_stack.is_empty, "Stack should be empty!"); + report "INFO: t_stack test finished successfully"; + wait; + end process StackTestP; + + +end architecture sim; \ No newline at end of file