示例代码预计会失败。请注意缺少过程file_close
调用。
在wait for 100 ns;
等待语句执行之后,进程语句的执行将在未来的模拟周期中恢复。进程中的语句按顺序执行,在最后一条语句(等待语句)之后是第一条语句
file_open(input, "input.txt");
将再次执行。
如果没有介入的 file_close 调用,后续的 file_open 调用将失败。
IEEE 标准 1076-2008
10.2 等待语句
timeout 子句指定进程将在此等待语句处保持挂起的最长时间。如果没有出现超时子句,则假定为 (STD.STANDARD.TIME'HIGH – STD.STANDARD.NOW) 的超时子句。如果 timeout 子句中的时间表达式的计算结果为负值,则会出错。
11.3 过程声明
流程语句的执行包括重复执行其语句序列。在执行流程语句的语句序列中的最后一条语句后,将立即继续执行语句序列中的第一条语句。
5.5.2 文件操作:
在第二种形式的 FILE_OPEN 中,通过 Status 参数返回的值表示过程调用的结果:
— OPEN_OK 值表示对 FILE_OPEN 的调用成功。如果对 FILE_OPEN 的调用指定了在调用开始时不存在的外部文件,并且如果传递给调用的文件对象的访问模式是只写的,则创建外部文件。
— STATUS_ERROR 的值表示文件对象已经有一个与之关联的外部文件。
— NAME_ERROR 的值表示外部文件不存在(在尝试从外部文件读取的情况下)或无法创建外部文件(在尝试写入或附加到外部文件的情况下)不存在)。如果外部文件因任何原因无法与文件对象关联,也会返回此值。
— MODE_ERROR 的值表示无法使用请求的 Open_Kind 打开外部文件。
如果在相同条件下调用第二种形式的 FILE_OPEN 时,会返回除 OPEN_OK 之外的状态值,则第一种形式的 FILE_OPEN 会导致错误发生。
file_open 过程调用的问题使用属于第一种形式。第二种形式将无法返回状态参数值 STATUS_ERROR,已经将外部文件与文件对象相关联input
。
解决方法是转换等待语句以防止进程继续执行:
wait; -- wait for 100 ns;
end process;
或提供显式的 file_close 调用,以便后续的 file_open 调用会成功。(这会导致大量主机活动而无用。)
修改后的代码可能如下所示:
-- 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。执行 endfile 调用将导致主机文件操作导致暂停和恢复 ghdl 模型执行。仅进行 endfile 过程调用的有效测试。
没有超时子句 ( ) 的等待语句 (10.2)for 100 ns
将等到 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
%%
主机文件操作可能会导致显着的执行时间损失。如果您要将读取的值分配给复合(数组或记录)类型对象的信号或变量,则可以重用它们而无需等待主机文件操作。