scanner: hoffentlich passen meinen annahmen ueber das ps/2 modul
[hwmod.git] / src / beh_scanner_tb.vhd
1 library ieee;
2 use ieee.std_logic_1164.all;
3 use ieee.numeric_std.all;
4 use work.gen_pkg.all;
5
6 entity beh_scanner_tb is
7 end entity beh_scanner_tb;
8
9 architecture sim of beh_scanner_tb is
10         -- system
11         signal sys_clk, sys_res_n : std_logic;
12         -- ps/2
13         signal new_data : std_logic;
14         signal data : std_logic_vector(7 downto 0);
15         -- history
16         signal s_char : hbyte;
17         signal s_take, s_done, s_backspace : std_logic;
18         -- parser
19         signal do_it : std_logic;
20         signal finished : std_logic;
21
22         signal stop : boolean := false;
23 begin
24         inst : entity work.scanner(beh)
25         port map
26         (
27                 sys_clk => sys_clk,
28                 sys_res_n => sys_res_n,
29                 -- ps/2
30                 new_data => new_data,
31                 data => data,
32                 -- history
33                 s_char => s_char,
34                 s_take => s_take,
35                 s_done => s_done,
36                 s_backspace => s_backspace,
37                 -- Parser
38                 do_it => do_it,
39                 finished => finished
40         );
41
42         process
43         begin
44                 sys_clk <= '0';
45                 wait for 15 ns;
46                 sys_clk <= '1';
47                 wait for 15 ns;
48                 if stop = true then
49                         wait;
50                 end if;
51         end process;
52
53         process
54                 function valid_char (x : std_logic_vector(7 downto 0); last : std_logic_vector(7 downto 0)) return boolean is
55                                 variable y : boolean;
56                 begin
57                         case x is
58                                 -- nur gueltig wenn davor ein numpad-mod byte gekommen ist
59                                 -- 0 - 4
60                                 when x"30" | x"31" | x"32" | x"33" | x"34" => y := last = x"e0";
61                                 -- 5 - 9
62                                 when x"35" | x"36" | x"37" | x"38" | x"39" => y := last = x"e0";
63                                 -- *, +, -, /
64                                 when x"2a" | x"2b" | x"2d" | x"2f" => y := last = x"e0";
65
66                                 -- immer gueltig
67                                 when x"20" => y := true; -- ' '
68                                 when x"1c" => y := true; -- enter
69                                 when x"0e" => y := true; -- backspace
70
71                                 -- alle anderen zeichen sind immer ungueltig
72                                 when others => y := false;
73                         end case;
74                         -- assert(false) report "x: " & integer'image(to_integer(unsigned(x))) & ", last: " & integer'image(to_integer(unsigned(last))) & ", result: " & boolean'image(y);
75                         return y;
76                 end function;
77
78                 -- textio stuff
79                 use std.textio.all;
80                 file f : text open read_mode is "../../src/scanner.test";
81                 variable l : line;
82
83                 variable input : hstring;
84                 variable expectedresult : hstring;
85                 variable realresult : hstring;
86
87                 variable checkall : boolean := true;
88                 variable run_tc, run_inner : boolean := true;
89                 variable i, j, k, y : natural;
90                 variable last : std_logic_vector(7 downto 0);
91         begin
92                 -- init & reset
93                 sys_res_n <= '0';
94                 new_data <= '0';
95                 data <= (others => '0');
96                 s_done <= '0';
97                 finished <= '0';
98
99                 icwait(sys_clk, 5);
100                 sys_res_n <= '1';
101
102                 i := 1;
103                 f_loop : while not endfile(f) loop
104                         data <= (others => '0');
105                         realresult := (others => nul);
106
107                         f1_loop : while not endfile(f) loop
108                                 readline (f, l);
109                                 input := (others => nul);
110                                 if (l'length <= 71) then
111                                         input(1 to l'length) := l.all;
112                                         if (input(1) = '#') then
113                                                 next f1_loop;
114                                         else
115                                                 exit f1_loop;
116                                         end if;
117                                 else
118                                         report "fehler in scanner.test: eingabe zu lange in testfall " & natural'image(i);
119                                         next f_loop;
120                                 end if;
121                         end loop f1_loop;
122
123                         f2_loop : while not endfile(f) loop
124                                 readline (f, l);
125                                 expectedresult := (others => nul);
126                                 if (l'length <= 71) then
127                                         expectedresult(1 to l'length) := l.all;
128                                         if (expectedresult(1) = '#') then
129                                                 next f2_loop;
130                                         else
131                                                 y := l'length;
132                                                 exit f2_loop;
133                                         end if;
134                                 else
135                                         report "fehler in scanner.test: eingabe zu lange in testfall " & natural'image(i);
136                                         next f_loop;
137                                 end if;
138                         end loop f2_loop;
139
140
141
142                         report "testcase(" & natural'image(i) & ").input: " & input;
143                         report "testcase(" & natural'image(i) & ").expectedresult: " & expectedresult;
144                         i := i + 1;
145
146                         icwait(sys_clk, 5);
147                         run_tc := true;
148                         j := 0; k := 1;
149
150                         mainl : while run_tc loop
151                                 last := data;
152                                 icwait(sys_clk, 1);
153                                 j := j + 1;
154
155                                 new_data <= '1';
156                                 case input(j) is
157                                         when '$' => data <= x"1c"; -- $ (enter)
158                                         when '!' => data <= x"0e"; -- ! (backspace)
159                                         when '.' => data <= x"e0"; -- . (modifier fuer Numpad)
160                                         when others => data <= std_logic_vector(to_unsigned(character'pos(input(j)),8));
161                                 end case;
162                                 icwait(sys_clk, 1);
163                                 new_data <= '0';
164
165                                 -- ack'en skippen, falls es ein "spezielles" zeichen ist (steht
166                                 -- in abhaengigkeit zum vorherigen zeichen)
167                                 if(not valid_char(data, last)) then
168                                         next mainl;
169                                 end if;
170
171                                 -- wuenschswert waere das hier:
172                                 -- > wait on s_backspace, s_take, do_it;
173                                 -- geht aber leider nicht, weil sich die signale vllt schon
174                                 -- geaendert haben
175                                 run_inner := true;
176                                 main_inner : while run_inner loop
177                                         icwait(sys_clk, 1);
178
179                                         run_inner := false;
180                                         if s_backspace = '1' then
181                                                 if k > 1 then
182                                                         realresult(k) := nul;
183                                                         k := k - 1;
184                                                         realresult(k) := nul;
185                                                 end if;
186                                                 icwait(sys_clk, 1);
187                                                 s_done <= '1';
188                                                 wait on s_take; -- = '0'
189                                                 icwait(sys_clk, 1);
190                                                 s_done <= '0';
191                                         elsif do_it = '1' then
192                                                 -- dauert normalweiser noch laenger (parser braucht
193                                                 -- relativ lange)
194                                                 icwait(sys_clk, 7);
195                                                 finished <= '1';
196                                                 wait on do_it; -- = '0'
197                                                 icwait(sys_clk, 1);
198                                                 finished <= '0';
199
200                                                 run_tc := false;
201                                         elsif s_take = '1' then
202                                                 realresult(k) := character'val(to_integer(unsigned(s_char)));
203                                                 k := k + 1;
204
205                                                 icwait(sys_clk, 1);
206                                                 s_done <= '1';
207                                                 wait on s_take; -- = '0'
208                                                 icwait(sys_clk, 1);
209                                                 s_done <= '0';
210                                         else
211                                                 -- assert(false) report "scanner_tb: kann passieren. wenn tb haengt, dann hier auskommentieren";
212                                                 run_inner := true;
213                                         end if;
214                                 end loop;
215                         end loop;
216
217                         report "realresult                : " & realresult;
218                         if realresult /= expectedresult then
219                                 checkall := false;
220                         end if;
221                         report "==================";
222                 end loop f_loop;
223
224                 if checkall then
225                         report "alle testfaelle des Scanners waren erfolgreich!";
226                 else
227                         report "nicht alle testfaelle des Scanners waren erfolgreich!";
228                 end if;
229                 stop <= true;
230                 wait;
231         end process;
232 end architecture sim;