-- -- Copyright 1991 -- The VHDL Technology Group -- EDN -- All Rights Reserved -- -- File name : z80.parser.pkg_body.vhdl -- Title : Z80 Microprocessor -- Notes : This model, written by Bill Billowitch's organization -- parses the Sentry test patterns and prepares the data -- for the testbench model. This model will not operate -- without Billowitch's Std_DevelopersKit. -- -------------------------------------------------------------------- -- MODIFICATION HISTORY : -- -------------------------------------------------------------------- -- V0.100 | mkd | 10/05/91 | adding code to read input masks and data. -- -------------------------------------------------------------------- Package Body z80_parser is --+----------------------------------------------------------------------------- --| Function Name : Set_Masks_Statement --| --| Overloading : None --| --| Purpose : To set the Monitor masks and driver masks --| --| Parameters : --| line_buf - input , string to hold the text line --| index - input, integer, index of the character --| being read --| line_no - input, input_output, integer line number --| in the text file --| mask_no - output, integer --| masktype - output, Mask_Type, whether monitor mask or --| driver mask --| --| Result : --| --| NOTE : --| --| Use : --| VARIABLE --| VARIABLE --| --| --|----------------------------------------------------------------------------- Procedure Set_Masks_Statement ( VARIABLE line_buf : IN string; VARIABLE index : IN integer; VARIABLE line_no : IN integer; VARIABLE mask_no : OUT integer; VARIABLE masktype : OUT Mask_Type ) IS variable token : String(1 to 32); variable ch : character; variable lookahead : character; variable indx : integer := index; -- incomming index variable num_val : integer; BEGIN indx := get_NonBlank(line_buf, indx); ch := line_buf(indx); IF (indx < line_buf'LENGTH) THEN lookahead := line_buf(indx+1); ELSE lookahead := ' '; END IF; IF ((ch = 'M') AND (Is_Digit(lookahead))) THEN masktype := Monitor_Mask; indx := indx + 1; ch := line_buf(indx); num_val := 0; while (( Is_digit(ch)) AND (indx < line_buf'LENGTH)) LOOP num_val := num_val*10 + (character'pos(ch) - character'pos('0')); indx := indx + 1; ch := line_buf(indx); END LOOP; mask_no := num_val; ELSIF ((ch = 'D' ) AND (Is_Digit(lookahead))) THEN masktype := Driver_Mask; indx := indx + 1; ch := line_buf(indx); num_val := 0; while (( Is_digit(ch)) AND (indx < line_buf'LENGTH)) LOOP num_val := num_val*10 + (character'pos(ch) - character'pos('0')); indx := indx + 1; ch := line_buf(indx); END LOOP; mask_no := num_val; ELSE assert false report " Set_Mask_Statement Error: at line number " & To_String(line_no) severity error; END IF; return; END; --+----------------------------------------------------------------------------- --| Function Name : Set_F_Statement --| --| Overloading : None --| --| Purpose : To recognize the set F statement and set count --| --| Parameters : --| line_buf - input , string to hold the text line --| index - input, integer, index of the character --| being read --| line_no - input, input_output, integer line number --| in the text file --| count - output , integer --| --| Result : Integer --| --| NOTE : --| --| Use : --| VARIABLE --| VARIABLE --| --| --|----------------------------------------------------------------------------- Procedure Set_F_Statement ( VARIABLE line_buf : IN string; VARIABLE index : IN integer; VARIABLE line_no : IN integer; VARIABLE count : OUT integer ) IS variable token : String(1 to 32); variable ch : character; variable lookahead : character; variable indx : integer := index; -- incomming index variable idx : integer; variable counter : integer; BEGIN indx := get_NonBlank(line_buf, indx); ch := line_buf(indx); IF (indx < line_buf'LENGTH) THEN lookahead := line_buf(indx+1); ELSE lookahead := ' '; END IF; IF ((ch = 'F') AND (IS_Space(lookahead))) THEN counter := 1; ELSIF ((ch = 'F') AND (lookahead = NUL)) THEN counter := 1; ELSIF ((ch = 'F' ) AND (lookahead = 'C')) THEN idx := indx + 2; indx := get_NonBlank(line_buf, idx); ch := line_buf(indx); if (NOT Is_Digit(ch)) THEN assert false report " Set_F_Statement Error: at line number " & To_String(line_no) severity error; return; else counter := 0; while (Is_Digit(ch)) LOOP counter := counter * 10 + character'pos(ch) - character'pos('0'); indx := indx + 1; ch := line_buf(indx); end loop; end if; ELSE assert false report " Set_F_Statement Error: at line number " & To_String(line_no) severity error; return; END IF; count := counter; return; END; --+----------------------------------------------------------------------------- --| Function Name : Enable_Statement --| --| Overloading : None --| --| Purpose : To recognize the set F statement and set count --| --| Parameters : --| line_buf - input , string to hold the text line --| index - input, integer, index of the character --| being read --| line_no - input, input_output, integer line number --| in the text file --| mmasks - INPUT, Monitor_Masks_Table; --| dmasks - input, Driver_Masks_Table; --| enable_mmask - output, std_logic_vector; --| Enable_dmask -out put, std_logic_vector --| --| Result : --| --| NOTE : --| --| Use : --| VARIABLE --| VARIABLE --| --| --|----------------------------------------------------------------------------- Procedure Enable_Statement( VARIABLE line_buf : IN string; VARIABLE index : IN integer; VARIABLE line_no : IN integer; CONSTANT mmasks : IN Monitor_Masks_Table; CONSTANT dmasks : IN Driver_Masks_Table; VARIABLE enable_mmask : OUT std_logic_vector; VARIABLE enable_dmask : OUT std_logic_vector ) IS variable ch : character; variable mask_indx : integer := 0; variable num_val : integer; variable indx : integer := index; -- incomming index of string BEGIN -- get a non_blank character, the first nonblank character must be M -- indx := get_NonBlank(line_buf, indx); ch := line_buf(indx); -- M-mask IF (ch = 'M') THEN indx := indx + 1; ch := line_buf(indx); num_val := 0; while( Is_digit(ch) AND indx < line_buf'LENGTH) LOOP num_val := num_val*10 + character'pos(ch) - character'pos('0'); indx := indx + 1; ch := line_buf(indx); END LOOP; if (num_val > m_mask_size) THEN assert false report " Enable_Statement Error: at line number " & To_String(line_no) severity error; return; else enable_mmask := mmasks(num_val); end if; ELSE assert false report " Enable_Statement Error: at line number " & To_String(line_no) severity error; return; END IF; -- D mask D_LOOP : LOOP indx := indx + 1; ch := line_buf(indx); IF (ch = 'D') THEN indx := indx + 1; ch := line_buf(indx); num_val := 0; while( Is_digit(ch) AND indx < line_buf'LENGTH) LOOP num_val := num_val*10 + character'pos(ch) - character'pos('0'); indx := indx + 1; ch := line_buf(indx); END LOOP; if (num_val > d_mask_size) THEN assert false report " Enable_Statement Error: at line number " & To_String(line_no) severity error; return; else enable_dmask := dmasks(num_val); end if; exit D_LOOP; ELSIF (Is_Space(ch) OR (ch = ',')) THEN null; -- do nothing ELSE assert false report " Enable_Statement Error: at line number " & To_String(line_no) severity error; return; END IF; END LOOP; return; END; ----------------------------------------------------------------------------------------- procedure Build_Masks ( VARIABLE f_ptr : IN TEXT; VARIABLE l_num : INOUT INTEGER; VARIABLE M_Masks : OUT Monitor_Masks_Table; VARIABLE D_Masks : OUT Driver_Masks_Table ) IS variable line_buf : string (1 To 128); variable l : line; variable token : string(1 TO 32); variable index : Integer; variable idx : Integer; variable masknum, count : Integer; variable msktype : Mask_Type; variable ch : character; VARIABLE Data_Slices : std_logic_vector(1 TO 60); VARIABLE test_pat_start : BOOLEAN := false; VARIABLE sec_token : string(1 TO 32); BEGIN While (NOT ENDFILE(f_ptr)) LOOP fgetline(line_buf, f_ptr, l); line_buf := To_Upper(line_buf); l_num := l_num + 1; idx := 1; index := 1; index := get_NonBlank(line_buf, idx); get_word(line_buf, index, token); IF (StrNCmp(token, "REM", 3) = 0) THEN assert false report " z80_tester --- this is a REM line " & To_String(l_num) severity NOTE; ELSIF (StrNCmp(token, "SET", 3) = 0) THEN idx := index; ch := line_buf(idx); while (Is_Space(ch) AND (idx < line_buf'LENGTH)) LOOP idx := idx + 1; ch := line_buf(idx); END LOOP; get_word(line_buf, idx, sec_token); if (StrNCmp(sec_token, "MODULE", 6) = 0) THEN test_pat_start := TRUE; else Set_Masks_Statement(line_buf, index, l_num, masknum, msktype); case msktype IS when Monitor_Mask => get_channel_data(f_ptr, l_num, Data_Slices); M_Masks(masknum) := Data_Slices; when Driver_Mask => get_channel_data(f_ptr, l_num, Data_Slices); D_Masks(masknum) := Data_Slices; when OTHERS => assert false report " z80_tester --- error line number " & To_String(l_num) severity error; end case; end if; EXIT WHEN test_pat_start; END IF; END LOOP; end; --+----------------------------------------------------------------------------- --| Function Name : get_channel_data --| --| Overloading : None --| --| Purpose : To read the channels into variable channel_data --| --| Parameters : --| file_ptr - input, TEXT, --| line_no - input_output, integer line number --| in the text file --| channel_data - output , std_logic_vector --| --| Result : --| --| NOTE : --| --| Use : --| VARIABLE --| VARIABLE --| --| --|----------------------------------------------------------------------------- Procedure get_channel_data ( VARIABLE file_ptr : IN TEXT; VARIABLE line_no : INOUT integer; VARIABLE channel_data : OUT std_logic_vector ) IS variable line_buf : string (1 to 128); variable str_buf : string (1 to 128); variable ll : line; variable len : Natural := 0; variable result : std_logic_vector(1 TO channel_data'LENGTH); BEGIN -- IF (NOT ENDFILE(file_ptr)) THEN fgetline(line_buf, file_ptr, ll); line_no := line_no + 1; -- remove blanks for i IN 1 TO line_buf'LENGTH LOOP EXIT when ( line_buf(i) = ';'); IF ( line_buf(i) /= ' ') THEN len := len + 1; str_buf(len) := line_buf(i); END IF; END LOOP; result := From_String(str_buf); channel_data := result; ELSE null; END IF; return; END; --+----------------------------------------------------------------------------- --| Function Name : get_NonBlank --| --| Overloading : None --| --| Purpose : Find first non_blank character in a string --| --| Parameters : --| str_in - input , --| --| Result : Natural, index of non_blank character --| --| NOTE : --| --| Use : --| VARIABLE s_flag : String(1 TO 10) := " TRUE"; --| VARIABLE idx: Natural --| --| idx := Find_NonBlank (s_flag); --| --|----------------------------------------------------------------------------- FUNCTION get_NonBlank ( CONSTANT str_in : IN STRING; CONSTANT idx : IN integer ) RETURN INTEGER IS VARIABLE str_copy : STRING (1 TO str_in'LENGTH) := str_in; VARIABLE indx1 : INTEGER := idx; VARIABLE ch : character; BEGIN ch := str_copy(indx1); while ( ( indx1 < str_in'LENGTH) AND (Is_Space(ch) ) ) LOOP indx1 := indx1 + 1; ch := str_copy(indx1); end LOOP; return indx1; END; --+----------------------------------------------------------------------------- --| Function Name : get_word --| hidden --| Overloading : None --| --| Purpose : To get a token from a format string. --| used in fprint procedure. --| --| --| Parameters : --| format -- input, STRING, --| index -- input_output, INTEGER, --| at input it represents the beginning --| position of the word in the format --| string. When procedure terminates --| index represent the end of word. --| token -- output, STRING, holds the result. --| --| NOTE : --| --| --------------------------------------------------------------------------- PROCEDURE get_word ( CONSTANT format : IN STRING; VARIABLE index : INOUT INTEGER; VARIABLE token : OUT STRING ) IS VARIABLE fmt : STRING(1 TO format'LENGTH) := format; VARIABLE indx : INTEGER := index; VARIABLE res_str : STRING(1 TO max_token_len); VARIABLE j : Integer := 1; BEGIN fmt_Loop : LOOP res_str(j) := fmt(indx); EXIT fmt_loop WHEN ( (fmt(indx) = ' ') OR (fmt(indx) = HT ) OR (fmt(indx) = ',') OR (fmt(indx) = LF ) OR (indx >= format'LENGTH) OR (j >= max_token_len )); j := j + 1; indx := indx + 1; END LOOP; index := indx; token(1 TO j) := res_str(1 TO j); -- copy the slice RETURN; END; end Z80_parser;