Library of reusable VHDL components
vhdl
osvvm
fpga
ghdl
testbenches
psl
coverage

StackP.vhd 3.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. library ieee;
  2. use ieee.std_logic_1164.all;
  3. package StackP is
  4. generic (
  5. type STACK_TYPE;
  6. MAX_LEN : natural := 64;
  7. function to_string(d : in STACK_TYPE) return string
  8. );
  9. -- linked list stack interface
  10. type t_stack is protected
  11. procedure push (data : in STACK_TYPE);
  12. procedure pop (data : inout STACK_TYPE);
  13. procedure init (logging : in boolean := false);
  14. impure function is_empty return boolean;
  15. impure function is_full return boolean;
  16. impure function fillstate return natural;
  17. end protected t_stack;
  18. end package StackP;
  19. package body StackP is
  20. -- linked list stack implementation
  21. type t_stack is protected body
  22. type t_entry;
  23. type t_entry_ptr is access t_entry;
  24. type t_data_ptr is access STACK_TYPE;
  25. type t_entry is record
  26. data : t_data_ptr;
  27. last_entry : t_entry_ptr;
  28. next_entry : t_entry_ptr;
  29. end record t_entry;
  30. variable v_head : t_entry_ptr := null;
  31. variable v_tail : t_entry_ptr := null;
  32. variable v_count : natural := 0;
  33. variable v_logging : boolean := false;
  34. -- write one entry into queue by
  35. -- creating new entry at head of list
  36. procedure push (data : in STACK_TYPE) is
  37. variable v_entry : t_entry_ptr;
  38. begin
  39. if (not(is_full)) then
  40. if (v_count /= 0) then
  41. v_entry := new t_entry;
  42. v_entry.data := new STACK_TYPE'(data);
  43. v_entry.last_entry := v_head;
  44. v_entry.next_entry := null;
  45. v_head := v_entry;
  46. v_head.last_entry.next_entry := v_head;
  47. else
  48. v_head := new t_entry;
  49. v_head.data := new STACK_TYPE'(data);
  50. v_head.last_entry := null;
  51. v_head.next_entry := null;
  52. v_tail := v_head;
  53. end if;
  54. v_count := v_count + 1;
  55. if v_logging then
  56. report t_stack'instance_name & " pushed 0x" & to_string(data) & " on stack";
  57. end if;
  58. else
  59. assert false
  60. report t_stack'instance_name & " push to full stack -> discared"
  61. severity warning;
  62. end if;
  63. end procedure push;
  64. -- read one entry from queue at tail of list and
  65. -- delete that entry from list after read
  66. procedure pop (data : inout STACK_TYPE) is
  67. variable v_entry : t_entry_ptr := v_head;
  68. begin
  69. assert not(is_empty)
  70. report "pop from empty queue -> discarded"
  71. severity failure;
  72. data := v_head.data.all;
  73. v_head := v_head.last_entry;
  74. deallocate(v_entry.data);
  75. deallocate(v_entry);
  76. v_count := v_count - 1;
  77. if v_logging then
  78. report t_stack'instance_name & " popped 0x" & to_string(data) & " from stack";
  79. end if;
  80. end procedure pop;
  81. procedure init (logging : in boolean := false) is
  82. begin
  83. v_logging := logging;
  84. end procedure init;
  85. -- returns true if queue is empty, false otherwise
  86. impure function is_empty return boolean is
  87. begin
  88. return v_head = null;
  89. end function is_empty;
  90. -- returns true if queue is full, false otherwise
  91. impure function is_full return boolean is
  92. begin
  93. return v_count = MAX_LEN;
  94. end function is_full;
  95. -- returns number of filled slots in queue
  96. impure function fillstate return natural is
  97. begin
  98. return v_count;
  99. end function fillstate;
  100. end protected body t_stack;
  101. end package body StackP;