读取 GHDL/VHDL 中的文件

Reading a file in GHDL/VHDL

我正在阅读 vhdl 格式的文本文件。有很多关于此的示例,但我很好奇为什么这个最小的展示示例 在 GHDL 中不起作用。它 在 ModelSim 中工作(由 Mentor 提供)

  1. 这是因为 GHDL 中缺少功能吗? (我没有在 docs/github 问题中找到任何内容)
  2. 难道是我在不知不觉中使用了错误的标准?
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use STD.textio.all;

entity test is
end test;

architecture behavioral of test is
    file input : text;
begin
    process
    variable line_in : line;
    begin
        file_open(input, "input.txt");
        while not endfile(input) loop
            readline(input, line_in); 
        end loop;
        wait for 100 ns;
    end process;

end behavioral;

我得到的输出是:

./test:error: cannot open file "input.txt"

这意味着,没有 file/cannot 可以打开,但文件存在并具有正确的访问权限(已在 Modelsim 中证明)。我也用完整的文件名试过了。

我在 Linux 上使用带有这些标志的 GHDL 0.37: --ieee=synopsys --std=08

如果

   file input : text;

替换为

    file input : text open read_mode is "input.txt";

        file_open(input, "input.txt");

已删除,它在 GHDL 中有效。

但是我还是不知道为什么之前的版本不行

示例代码预计会失败。注意缺少程序 file_close 调用。

执行完wait for 100 ns;wait语句后,process语句的执行将在以后的模拟循环中恢复。进程中的语句按顺序执行,在最后一条语句(等待语句)之后是第一条语句

        file_open(input, "input.txt");

将再次执行

如果没有干预 file_close 调用,后续 file_open 调用将失败。

IEEE 标准 1076-2008

10.2 等待语句

The timeout clause specifies the maximum amount of time the process will remain suspended at this wait statement. If no timeout clause appears, the timeout clause for (STD.STANDARD.TIME'HIGH – STD.STANDARD.NOW) is assumed. It is an error if the time expression in the timeout clause evaluates to a negative value.

11.3 流程声明

The execution of a process statement consists of the repetitive execution of its sequence of statements. After the last statement in the sequence of statements of a process statement is executed, execution will immediately continue with the first statement in the sequence of statements.

5.5.2 文件操作:

In the second form of FILE_OPEN, the value returned through the Status parameter indicates the results of the procedure call:

— A value of OPEN_OK indicates that the call to FILE_OPEN was successful. If the call to FILE_OPEN specifies an external file that does not exist at the beginning of the call, and if the access mode of the file object passed to the call is write-only, then the external file is created.
— A value of STATUS_ERROR indicates that the file object already has an external file associated with it.
— A value of NAME_ERROR indicates that the external file does not exist (in the case of an attempt to read from the external file) or the external file cannot be created (in the case of an attempt to write or append to an external file that does not exist). This value is also returned if the external file cannot be associated with the file object for any reason.
— A value of MODE_ERROR indicates that the external file cannot be opened with the requested Open_Kind.

如果在相同条件下调用 FILE_OPEN 的第二种形式时 return 的 Status 值不是 [=70],则 FILE_OPEN 的第一种形式会导致错误发生=].

file_open过程调用的问题使用是第一种形式。第二种形式将失败 returning Status 参数值 STATUS_ERROR,已经将外部文件与文件对象 input.

相关联

解决方法是转换等待语句以防止进程继续执行:

        wait; -- wait for 100 ns;
    end process;

或提供显式 file_close 调用,以便后续 file_open 调用成功。 (这会导致大量主机 activity 无用。)

修改后的代码可能如下所示:

-- library IEEE;
-- use IEEE.STD_LOGIC_1164.all;  -- NOT USED
use STD.textio.all;

entity test is
end test;

architecture behavioral of test is
    file input : text;
begin
    process
    variable line_in : line;
    begin
        file_open(input, "input.txt");
        while not endfile(input) loop
            readline(input, line_in);
            write (OUTPUT, line_in.all & LF);
        end loop;
        wait; -- wait for 100 ns;  -- EXECUTE ONCE
    end process;

end behavioral;

产量:

%% ghdl -a --ieee=synopsys  --std=08 test.vhdl
%% ghdl -e --ieee=synopsys  --std=08 test
%% ghdl -r --std=08 test
some text
more text
yet some more text
getting boring
%% 

其中对文件 OUTPUT(控制台)的写入回显了 input.txt 中找到的每一行的内容。请注意,行尾由 readline 过程调用删除,并重新引入到正在写入 OUTPUT 的字符串中。

那么为什么异文件声明成功了呢?

architecture file_declaration of test is
    -- file input : text;
    file input:     text open read_mode is "input.txt";
begin
    process
    variable line_in:   line;
    begin
        -- file_open(input, "input.txt");
        while not endfile(input) loop
            readline(input, line_in);
            write (OUTPUT, line_in.all & LF);
        end loop;
        wait for 100 ns;
    end process;

end architecture file_declaration;

只有一个对 file_open 的调用,一个在详细说明文件声明期间的隐式调用(6.4.2.5 文件声明)。该文件保持打开状态,但没有剩余行可读,由 endfile 调用确定。在这里,endfile 调用将每 100 ns 发生一次,这可能会导致您的 CPU 利用率随着测试执行而增加,直到达到 TIME'HIGH。执行结束文件调用将导致主机文件操作导致 ghdl 模型执行暂停和恢复。仅进行结束文件过程调用的有效测试。

没有超时子句 (for 100 ns) 的等待语句 (10.2) 将一直​​等到 TIME'HIGH 有效结束模拟,而无需任何干预信号事件或其他进程暂停和恢复或使 TIME'HIGH/100 ns - 1 endfile 过程调用,每个过程调用都涉及暂停和恢复显示的过程语句。

您还可以在 ghdl 的命令行上指定模拟停止时间,最有可能与 Modelsim 中的用法相匹配:

%% ghdl -a --ieee=synopsys  --std=08 test.vhdl
%% ghdl -e --ieee=synopsys  --std=08 test
%% ghdl -r --std=08 test --stop-time=300ns
some text
more text
yet some more text
getting boring
./test:info: simulation stopped by --stop-time @300ns
%% 

主机文件操作会导致严重的执行时间损失。如果您要将读取的值分配给复合(数组或记录)类型对象的信号或变量,则可以重复使用它们而无需等待主机文件操作。