---------------------------------------------------------------- -- Chapter 16 Files and Input/Output ---------------------------------------------------------------- ---------------------------------------------------------------- -- 16.1 Files ---------------------------------------------------------------- ---------------------------------------------------------------- -- 16.1.1 File Declarations ---------------------------------------------------------------- -- Page 499 type integer_file is file of integer; -- Page 500 file lookup_table_file : integer_file is "lookup-values"; type file_open_kind is (read_mode, write_mode, append_mode); ---------------------------------------------------------------- -- 16.1.2 Reading from Files ---------------------------------------------------------------- -- Page 501 type file_type is file of element_type; procedure read ( file f : file_type; value : out element_type ); function endfile ( file f : file_type ) return boolean; -- Example 16.1, Page 501 library ieee; use ieee.std_logic_1164.all; entity ROM is generic ( load_file_name : string ); port ( sel : in std_ulogic; address : in std_ulogic_vector; data : inout std_ulogic_vector ); end entity ROM; architecture behavioral of ROM is begin behavior : process is subtype word is std_ulogic_vector(0 to data'length - 1); type storage_array is array (natural range 0 to 2**address'length - 1) of word; variable storage : storage_array; variable index : natural; ... -- other declarations type load_file_type is file of word; file load_file : load_file_type open read_mode is load_file_name; begin -- load ROM contents from load_file index := 0; while not endfile(load_file) loop read(load_file, storage(index)); index := index + 1; end loop; -- respond to ROM accesses loop ... end loop; end process behavior; end architecture behavioral; -- Page 502 type bit_vector_file is file of bit_vector; procedure read ( file f : file_type; value : out element_type; length : out natural ); -- Page 503 file vectors : bit_vector_file open read_mode is "vectors.dat"; variable next_vector : bit_vector(63 downto 0); variable actual_len : natural; read(vectors, next_vector, actual_len); actual_len > next_vector'length -- Example 16.2, Page 503 stimulate_network : process is type packet_file is file of bit_vector; file stimulus_file : packet_file open read_mode is "test packets"; variable packet : bit_vector(1 to 2048); variable packet_length : natural; begin while not endfile(stimulus_file) loop read(stimulus_file, packet, packet_length); if packet_length > packet'length then report "stimulus packet too long - ignored" severity warning; else for bit_index in 1 to packet_length loop wait until stimulus_clock; stimulus_network <= not stimulus_network; wait until not stimulus_clock; stimulus_network <= stimulus_network xor packet(bit_index); end loop; end if; end loop; wait; -- end of stimulation: wait forever end process stimulate_network; ---------------------------------------------------------------- -- 16.1.3 Writing to Files ---------------------------------------------------------------- -- Page 504 procedure write ( file f : file_type; value : in element_type ); -- Example 16.3, Page 504 architecture instrumented of CPU is type count_file is file of natural; file instruction_counts : count_file open write_mode is "instructions"; begin interpreter : process is variable IR : word; alias opcode : byte is IR(0 to 7); variable opcode_number : natural; type counter_array is array (0 to 2**opcode'length - 1) of natural; variable counters : counter_array := (others => 0); ... begin ... -- initialize the instruction set interpreter instruction_loop : loop ... -- fetch the next instruction into IR -- decode the instruction opcode_number := convert_to_natural(opcode); counters(opcode_number) := counters(opcode_number) + 1; ... -- execute the decoded instruction case opcode is ... when halt_opcode => exit instruction_loop; ... end case; end loop instruction_loop; for index in counters'range loop write(instruction_counts, counters(index)); end loop; wait; -- program finished, wait forever end process interpreter; end architecture instrumented; -- Example 16.4, Page 506 cache_monitor : process is type measurement_record is record cache_size, block_size, associativity : positive; benchmark_name : string(1 to 10); miss_rate : real; ave_access_time : delay_length; end record; type measurement_file is file of measurement_record; file measurements : measurement_file open append_mode is "cache-measurements"; ... begin ... loop ... exit when halt; ... end loop; write ( measurements, measurement_record'( -- write values of generics for this run cache_size, block_size, associativity, benchmark_name, -- calculate performance metrics miss_rate => real(miss_count) / real(total_accesses), ave_access_time => total_delay / total_accesses ) ); wait; end process cache_monitor; -- Page 507 procedure flush ( file f : file_type ); ---------------------------------------------------------------- -- 16.1.4 Files Declared in Subprograms ---------------------------------------------------------------- -- Page 507 procedure write_to_file is file data_file : data_file_type open write_mode is "datafile"; begin ... end procedure write_to_file; -- Example 16.5, Page 508 type integer_vector is array (integer range <>) of integer; impure function read_array ( file_name : string; array_length : natural ) return integer_vector is type integer_file is file of integer; file data_file : integer_file open read_mode is file_name; variable result : integer_vector(1 to array_length) := (others => 0); variable index : integer := 1; begin while not endfile(data_file) and index <= array_length loop read(data_file, result(index)); index := index + 1; end loop; return result; end function read_array; constant coeffs : integer_vector := read_array("coeff-data", 16); -- Page 509 file log_info : log_file open write_mode is "logfile"; ---------------------------------------------------------------- -- 16.1.5 Explicit Open and Close Operations ---------------------------------------------------------------- -- Page 509 file lookup_table_file, result_file : integer_file; type file_type is file of element_type; procedure file_open ( file f : file_type; external_name : in string; open_kind : in file_open_kind := read_mode ); file lookup_table_file : integer_file open read_mode is "lookup-values"; file lookup_table_file : integer_file; ... -- Page 510 file_open ( lookup_table_file, external_name => "lookup-values", open_kind => read_mode ); procedure file_open ( status : out file_open_status; file f : file_type; external_name : in string; open_kind : in file_open_kind := read_mode ); type file_open_status is (open_ok, status_error, name_error, mode_error); procedure file_close ( file f : file_type ); -- Example 16.6, Page 511 stimulus_generator : process is type directory_file is file of string; file directory : directory_file open read_mode is "stimulus-directory"; variable file_name : string(1 to 50); variable file_name_length : natural; variable open_status : file_open_status; subtype stimulus_vector is std_ulogic_vector(0 to 9); type stimulus_file is file of stimulus_vector; file stimuli : stimulus_file; variable current_stimulus : stimulus_vector; ... begin file_loop : while not endfile(directory) loop read( directory, file_name, file_name_length ); if file_name_length > file_name'length then report "file name too long: " & file_name & "... - file skipped" severity warning; next file_loop; end if; file_open ( open_status, stimuli, file_name(1 to file_name_length), read_mode ); if open_status /= open_ok then report file_open_status'image(open_status) & " while opening file " & file_name(1 to file_name_length) & " - file skipped" severity warning; next file_loop; end if; stimulus_loop : while not endfile(stimuli) loop read(stimuli, current_stimulus); ... -- apply the stimulus end loop stimulus_loop; file_close(stimuli); end loop file_loop; wait; end process stimulus_generator; ---------------------------------------------------------------- -- 16.1.6 File Parameters in Subprograms ---------------------------------------------------------------- -- Example 16.7, Page 513 type transform_array is array (1 to 3, 1 to 3) of real; variable transform1, transform2 : transform_array; type transform_file is file of real; file initial_transforms : transform_file open read_mode is "transforms.ini"; procedure read_transform ( file f : transform_file; variable transform : out transform_array ) is begin for i in transform'range(1) loop for j in transform'range(2) loop if endfile(f) then report "unexpected end of file in read_transform - " & "some array elements not read" severity error; return; end if; read ( f, transform(i, j) ); end loop; end loop; end procedure read_transform; read_transform ( initial_transforms, transform1 ); read_transform ( initial_transforms, transform2 ); -- Page 514 procedure read_transform ( variable f : in transform_file; variable transform : out transform_array ) is ... ---------------------------------------------------------------- -- 16.1.7 Portability of Files ---------------------------------------------------------------- ---------------------------------------------------------------- -- 16.2 The Package Textio ---------------------------------------------------------------- -- Page 514 package textio is type line is access string; type text is file of string; type side is (right, left); subtype width is natural; file input : text open read_mode is "STD_INPUT"; file output : text open write_mode is "STD_OUTPUT"; procedure readline(file F: text; L: inout line); procedure read ( L : inout line; value: out bit; good : out boolean ); procedure read ( L : inout line; value: out bit ); procedure read ( L : inout line; value: out bit_vector; good : out boolean ); procedure read ( L : inout line; value: out bit_vector ); procedure read ( L : inout line; value: out boolean; good : out boolean ); procedure read ( L : inout line; value: out boolean ); procedure read ( L : inout line; value: out character; good : out boolean ); procedure read ( L : inout line; value: out character ); procedure read ( L : inout line; value: out integer; good : out boolean ); procedure read ( L : inout line; value: out integer ); procedure read ( L : inout line; value: out real; good : out boolean ); procedure read ( L : inout line; value: out real ); procedure read ( L : inout line; value: out string; good : out boolean ); procedure read ( L : inout line; value: out string ); procedure read ( L : inout line; value: out time; good : out boolean ); procedure read ( L : inout line; value: out time ); procedure sread ( L: inout line; value : out string; strlen: out natural); alias string_read is sread [line, string, natural]; alias bread is read [line, bit_vector, boolean]; alias bread is read [line, bit_vector]; alias binary_read is read [line, bit_vector, boolean]; alias binary_read is read [line, bit_vector]; procedure oread ( L: inout line; value: out bit_vector; good : out boolean ); procedure oread ( L: inout line; value: out bit_vector ); alias octal_read is oread [line, bit_vector, boolean]; alias octal_read is oread [line, bit_vector]; procedure hread ( L: inout line; value: out bit_vector; good : out boolean ); procedure hread ( L: inout line; value: out bit_vector ); alias hex_read is hread [line, bit_vector, boolean]; alias hex_read is hread [line, bit_vector]; procedure writeline ( file F : text; L : inout line ); procedure tee ( file F: text; L: inout line ); function justify ( value: string; justified: side := right; field: width := 0 ) return string; procedure write ( L : inout line; value : in bit; justified: in side := right; field: in width := 0 ); procedure write ( L : inout line; value : in bit_vector; justified: in side := right; field: in width := 0 ); procedure write ( L : inout line; value : in boolean; justified: in side := right; field: in width := 0 ); procedure write ( L : inout line; value : in character; justified: in side := right; field: in width := 0 ); procedure write ( L : inout line; value : in integer; justified: in side := right; field: in width := 0 ); procedure write ( L : inout line; value : in real; justified: in side := right; field: in width := 0; digits: in natural := 0 ); procedure write ( L: inout line; value: in real; format: in string); procedure write ( L : inout line; value : in string; justified: in side := right; field: in width := 0 ); procedure write ( L : inout line; value : in time; justified: in side := right; field: in width := 0; unit: in time := ns ); alias swrite is write [line, string, side, width]; alias string_write is write [line, string, side, width]; alias bwrite is write [line, bit_vector, side, width]; alias binary_write is write [line, bit_vector, side, width]; procedure owrite ( L: inout line; value: in bit_vector; justified: in side := right; field: in width := 0 ); alias octal_write is owrite [line, bit_vector, side, width]; procedure hwrite ( L: inout line; value: in bit_vector; justified: in side := right; field: in width := 0 ); alias hex_write is hwrite [line, bit_vector, side, width]; end package textio; ---------------------------------------------------------------- -- 16.2.1 Textio Read Operations ---------------------------------------------------------------- -- Page 518 sread(L, s, s_len); for i in 1 to s_len loop ... s(i) ... end loop; -- Example 16.8, Page 520 stimulus_interpreter : process is use std.textio.all; file control : text open read_mode is "control"; variable command : line; variable read_ok : boolean; variable next_time : time; variable whitespace : character; variable signal_id : string(1 to 4); variable temp_value, set_value : integer; variable on_value, fail_value : bit; begin command_loop : while not endfile(control) loop readline ( control, command ); -- read next stimulus time, and suspend until then read ( command, next_time, read_ok ); if not read_ok then report "error reading time from line: " & command.all severity warning; next command_loop; end if; wait for next_time - now; -- skip whitespace while command'length > 0 and ( command(command'left) = ' ' -- ordinary space or command(command'left) = ' ' -- non-breaking space or command(command'left) = HT ) loop read ( command, whitespace ); end loop; -- read signal identifier string read ( command, signal_id, read_ok ); if not read_ok then report "error reading signal id from line: " & command.all severity warning; next command_loop; end if; -- dispatch based on signal id case signal_id is when "temp" => read ( command, temp_value, read_ok ); if not read_ok then report "error reading temperature value from line: " & command.all severity warning; next command_loop; end if; temperature <= temp_value; when "set " => ... -- similar to "temp" when "on " => read ( command, on_value, read_ok ); if not read_ok then report "error reading on value from line: " & command.all severity warning; next command_loop; end if; enable <= on_value; when "fail" => ... -- similar to "on " when others => report "invalid signal id in line: " & signal_id severity warning; next command_loop; end case; end loop command_loop; wait; end process stimulus_interpreter; -- Page 522 if L'length < s'length then read(L, s(1 to L'length)); else read(L, s); end if; -- Page 523 function endline ( L : in line ) return boolean; ---------------------------------------------------------------- -- 16.2.2 Textio Write Operations ---------------------------------------------------------------- -- Page 523 write ( L, string'( "fred" ) ); write ( L, ' ' ); write ( L, bit_vector'( X"3A" ) ); -- Page 524 write ( L, "Trace message " ); write ( L, "0000" ); swrite ( L, "Trace message " ); swrite ( L, "0000" ); -- Example 16.9, Page 524 signal address : bit_vector(15 downto 0); signal data : resolve_bytes byte; signal rd, wr, io : bit; -- read, write, io/mem select signal ready : resolve_bits bit; bus_monitor : process is constant header : string(1 to 44) := FF & " Time R/W I/M Address Data"; use std.textio.all; file log : text open write_mode is "buslog"; variable trace_line : line; variable line_count : natural := 0; begin if line_count mod 60 = 0 then write ( trace_line, header ); writeline ( log, trace_line ); writeline ( log, trace_line ); -- empty line end if; wait until (rd or wr) and ready; write ( trace_line, now, justified => right, field => 10, unit => us ); write ( trace_line, string'(" ") ); if rd then write ( trace_line, 'R' ); else write ( trace_line, 'W' ); end if; write ( trace_line, string'(" ") ); if io then write ( trace_line, 'I' ); else write ( trace_line, 'M' ); end if; write ( trace_line, string'(" ") ); write ( trace_line, address ); write ( trace_line, ' '); write ( trace_line, data ); writeline ( log, trace_line ); line_count := line_count + 1; end process bus_monitor; -- Page 526 tee ( log, trace_line ); report "%%%TRACE:" & justify(to_string(now, ns), width => 10) & justify(to_hstring(out_vec), width => 6) & justify(to_string(count), width => 10); write(output, "%%%ERROR data value miscompare." & LF & " Actual value = " & to_hstring(data) & LF & " Expected value = " & to_hstring(expdata) & LF & " at time: " & to_string(now) ); ---------------------------------------------------------------- -- 16.2.3 Reading and Writing Other Types ---------------------------------------------------------------- -- Page 527 type speed_category is (stopped, slow, fast, maniacal); variable speed : speed_category; write ( L, speed_category'image(speed) ); write ( L, to_string(speed) ); readline( input, L ); sread(L, str, str_len); speed := speed_category'value(str(1 to str_len)); ---------------------------------------------------------------- -- Standard Package Read and Write Operations ---------------------------------------------------------------- -- Page 528 textio.write (L, to_string(value), justified, field); textio.write (L, to_ostring(value), justified, field); textio.write (L, to_hstring(value), justified, field); ---------------------------------------------------------------- -- Exercises ---------------------------------------------------------------- -- Exercise 4 readline(in_file, L); read(L, bit_value); -- read a value of type bit read(L, int_value); -- read a value of type integer read(L, real_value); -- read a value of type real read(L, str_value); -- read a value of type string(1 to 3) -- Exercise 6 write(L, 3.5 us, justified => right, field => 10, unit => ns); write(L, ' '); write(L, bit_vector'(X"3C")); write(L, ' '); swrite(L, "ok", justified => left, field => 5); writeline(output, L); -- Exercise 7 entity address_decoder is generic ( log_file_name : string ); port ( address : in natural; enable : in bit; ROM_sel, RAM_sel, IO_sel, int_sel : out bit ); end entity address_decoder; -- Exercise 8 subtype word is std_ulogic_vector(0 to 15); -- Exercise 9 subtype byte is bit_vector(7 downto 0); type mem_array is array (natural range <>) of byte; -- Exercise 12 type motor_state is (idle, forward, reverse); type motor_control is record state : motor_state; speed : natural; end record motor_control;