编译动态内存模块时 Icarus Verilog 崩溃
Icarus Verilog crash while compiling dynamic memory module
这是我在 Whosebug 上的第一个 post。
我是 Verilog 新手,但我在 Python、C 和 C++ 方面拥有丰富的经验。我在 Windows 10 上使用 Icarus Verilog 版本 10.1.1,并且正在尝试编写一个动态内存分配器。出于某种原因,当此命令为 运行:
iverilog dynmem.v dynmem_test.v -o dynmem_test.out
输出如下:
Assertion failed!
Program: c:\iverilog\lib\ivl\ivl.exe
File: ../verilog-10.1.1/pform.cc, Line 333
Expression: lexical_scope
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
我的代码有什么问题,我应该为此提交错误报告吗?
dynmem.v:
`define WORD_SIZE 32
`ifndef DYNMEM_SIZE // size of dynamic memory in words
`define DYNMEM_SIZE 16384*8/WORD_SIZE // 16 KB
`endif
`define __DYNMEM_BIT_SIZE WORD_SIZE*DYNMEM_SIZE-1 // size of dynamic memory in bits
reg [__DYNMEM_BIT_SIZE:0] dynmem; // dynamic memory
reg [DYNMEM_SIZE:0] allocated; // bitvector telling which words are allocated
reg mutex = 0;
module dynreg(address,
ioreg,
read_en,
write_en,
realloc_en);
output reg [WORD_SIZE-1:0] address;
output reg [WORD_SIZE-1:0] ioreg;
output reg read_en; // rising edge: put word stored at location address into ioreg
output reg write_en; // rising edge: put word stored in ioreg into location address
output reg realloc_en; // rising edge: if ioreg=0, free memory, otherwise reallocate memory into buffer of size ioreg.
task malloc; // allocate dynamic memory
output reg [WORD_SIZE-1:0] size;
output reg [WORD_SIZE-1:0] start;
unsigned integer size_int = size; // convert size to integer
reg flag1 = 1;
while (mutex) begin end // wait on mutex
mutex = 1; // acquire mutex
// loop through possible starting locations
for (index=size_int-1; (index < DYNMEM_SIZE) && flag1; index=index+1) begin
// check if unallocated
reg flag2 = 1;
for (offset=0; (offset < size_int) && flag2; offset=offset+1)
if (allocated[index-offset])
flag2 = 0;
if (flag2) begin // if memory block is free
start = index;
flag1 = 0; // exit loop
end
end
// mark as allocated
for (i=0; i<size; i=i+1)
allocated[start-offset] = 1;
mutex = 0; // release mutex
endtask
task freealloc;
output reg [WORD_SIZE-1:0] size;
output reg [WORD_SIZE-1:0] start;
while (mutex) begin end // wait on mutex
mutex = 1; // acquire mutex
// deallocate locations
for (index=start; index > 0; index=index-1)
allocated[index] = 0;
mutex = 0; // release mutex
endtask
// internal registers
unsigned integer start; // start address
unsigned integer size; // block size
unsigned integer address_int; // address register converted to int
initial begin
// allocate memory
size = ioreg;
malloc(size, start);
end
always @(posedge(read_en)) begin
// read memory into ioreg
address_int = address;
ioreg[WORD_SIZE-1:0] = dynmem[8*(start+address_int)-1 -:WORD_SIZE-1];
end
always @(posedge(write_en)) begin
// write memory from ioreg
address_int = address;
dynmem[8*(start+address_int)-1 -:WORD_SIZE-1] = ioreg[WORD_SIZE-1:0];
end
always @(posedge(realloc_en)) begin
unsigned integer ioreg_int = ioreg; // convert ioreg to integer
reg [WORD_SIZE-1:0] new_start; // new start address
if (ioreg_int != 0) begin // if memory is to be reallocated, not freed
malloc(ioreg, new_start); // allocated new memory
// copy memory
for (i=0; i<size; i=i+1)
dynmem[8*(new_start+i)-1 -:WORD_SIZE-1] = dynmem[8*(start+i)-1 -:WORD_SIZE-1];
end
freealloc(size, start); // free previous memory
// update registers
size = ioreg_int;
start = new_start;
end
endmodule
dynmem_test.v:
module testmodule();
$monitor ("%g ioreg1=%b ioreg2=%b",
$time, ioreg1, ioreg2);
reg [WORD_SIZE-1:0] address1, address2;
reg [WORD_SIZE-1:0] ioreg1=5, ioreg2=10;
reg read_en1, read_en2;
reg write_en1, write_en2;
reg realloc_en1, realloc_en2;
#1 dynreg dr1(address1, ioreg1, read_en1, write_en1, realloc_en1);
#1 dynreg dr2(address2, ioreg2, read_en2, write_en2, realloc_en2);
address1 = 0;
ioreg1 = 23;
#1 write_en1 = 1;
write_en1 = 0;
address1 = 2;
ioreg1 = 53;
#1 write_en1 = 1;
write_en1 = 0;
address1 = 0;
#1 read_en1 = 1;
read_en1 = 0;
address1 = 2;
#1 read_en1 = 1;
read_en1 = 0;
#1 $finish;
endmodule
更新: C:\iverilog\lib\verilog-10.1.1 不存在,事实上,我在 C:\iverilog 中搜索 pform.cc 和没有找到结果。奇怪。
#1 dynreg dr1(address1, ioreg1, read_en1, write_en1, realloc_en1);
在实例声明上使用延迟 (#1
) 可能让 Icarus 感到困惑,就像让我感到困惑一样。 (究竟应该延迟什么?一个模拟步骤是否不存在实例?)
消除这些延迟,并将测试台中的所有代码都放在这两个实例声明之后的 initial
块中。
就其价值而言,dynreg
可能无法像所写的那样综合。它没有时钟输入,并且包含几个无法在硬件中展开的循环。
UPDATE: C:\iverilog\lib\verilog-10.1.1 doesn't exist, and, in fact, I searched in C:\iverilog for pform.cc and found no results. Strange.
此路径可能指的是开发人员计算机上编译您的 Icarus 副本的代码位置。除非您打算自己尝试修复导致此崩溃的错误,否则您可以放心地忽略它。
这是我在 Whosebug 上的第一个 post。
我是 Verilog 新手,但我在 Python、C 和 C++ 方面拥有丰富的经验。我在 Windows 10 上使用 Icarus Verilog 版本 10.1.1,并且正在尝试编写一个动态内存分配器。出于某种原因,当此命令为 运行:
iverilog dynmem.v dynmem_test.v -o dynmem_test.out
输出如下:
Assertion failed!
Program: c:\iverilog\lib\ivl\ivl.exe
File: ../verilog-10.1.1/pform.cc, Line 333
Expression: lexical_scope
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
我的代码有什么问题,我应该为此提交错误报告吗?
dynmem.v:
`define WORD_SIZE 32
`ifndef DYNMEM_SIZE // size of dynamic memory in words
`define DYNMEM_SIZE 16384*8/WORD_SIZE // 16 KB
`endif
`define __DYNMEM_BIT_SIZE WORD_SIZE*DYNMEM_SIZE-1 // size of dynamic memory in bits
reg [__DYNMEM_BIT_SIZE:0] dynmem; // dynamic memory
reg [DYNMEM_SIZE:0] allocated; // bitvector telling which words are allocated
reg mutex = 0;
module dynreg(address,
ioreg,
read_en,
write_en,
realloc_en);
output reg [WORD_SIZE-1:0] address;
output reg [WORD_SIZE-1:0] ioreg;
output reg read_en; // rising edge: put word stored at location address into ioreg
output reg write_en; // rising edge: put word stored in ioreg into location address
output reg realloc_en; // rising edge: if ioreg=0, free memory, otherwise reallocate memory into buffer of size ioreg.
task malloc; // allocate dynamic memory
output reg [WORD_SIZE-1:0] size;
output reg [WORD_SIZE-1:0] start;
unsigned integer size_int = size; // convert size to integer
reg flag1 = 1;
while (mutex) begin end // wait on mutex
mutex = 1; // acquire mutex
// loop through possible starting locations
for (index=size_int-1; (index < DYNMEM_SIZE) && flag1; index=index+1) begin
// check if unallocated
reg flag2 = 1;
for (offset=0; (offset < size_int) && flag2; offset=offset+1)
if (allocated[index-offset])
flag2 = 0;
if (flag2) begin // if memory block is free
start = index;
flag1 = 0; // exit loop
end
end
// mark as allocated
for (i=0; i<size; i=i+1)
allocated[start-offset] = 1;
mutex = 0; // release mutex
endtask
task freealloc;
output reg [WORD_SIZE-1:0] size;
output reg [WORD_SIZE-1:0] start;
while (mutex) begin end // wait on mutex
mutex = 1; // acquire mutex
// deallocate locations
for (index=start; index > 0; index=index-1)
allocated[index] = 0;
mutex = 0; // release mutex
endtask
// internal registers
unsigned integer start; // start address
unsigned integer size; // block size
unsigned integer address_int; // address register converted to int
initial begin
// allocate memory
size = ioreg;
malloc(size, start);
end
always @(posedge(read_en)) begin
// read memory into ioreg
address_int = address;
ioreg[WORD_SIZE-1:0] = dynmem[8*(start+address_int)-1 -:WORD_SIZE-1];
end
always @(posedge(write_en)) begin
// write memory from ioreg
address_int = address;
dynmem[8*(start+address_int)-1 -:WORD_SIZE-1] = ioreg[WORD_SIZE-1:0];
end
always @(posedge(realloc_en)) begin
unsigned integer ioreg_int = ioreg; // convert ioreg to integer
reg [WORD_SIZE-1:0] new_start; // new start address
if (ioreg_int != 0) begin // if memory is to be reallocated, not freed
malloc(ioreg, new_start); // allocated new memory
// copy memory
for (i=0; i<size; i=i+1)
dynmem[8*(new_start+i)-1 -:WORD_SIZE-1] = dynmem[8*(start+i)-1 -:WORD_SIZE-1];
end
freealloc(size, start); // free previous memory
// update registers
size = ioreg_int;
start = new_start;
end
endmodule
dynmem_test.v:
module testmodule();
$monitor ("%g ioreg1=%b ioreg2=%b",
$time, ioreg1, ioreg2);
reg [WORD_SIZE-1:0] address1, address2;
reg [WORD_SIZE-1:0] ioreg1=5, ioreg2=10;
reg read_en1, read_en2;
reg write_en1, write_en2;
reg realloc_en1, realloc_en2;
#1 dynreg dr1(address1, ioreg1, read_en1, write_en1, realloc_en1);
#1 dynreg dr2(address2, ioreg2, read_en2, write_en2, realloc_en2);
address1 = 0;
ioreg1 = 23;
#1 write_en1 = 1;
write_en1 = 0;
address1 = 2;
ioreg1 = 53;
#1 write_en1 = 1;
write_en1 = 0;
address1 = 0;
#1 read_en1 = 1;
read_en1 = 0;
address1 = 2;
#1 read_en1 = 1;
read_en1 = 0;
#1 $finish;
endmodule
更新: C:\iverilog\lib\verilog-10.1.1 不存在,事实上,我在 C:\iverilog 中搜索 pform.cc 和没有找到结果。奇怪。
#1 dynreg dr1(address1, ioreg1, read_en1, write_en1, realloc_en1);
在实例声明上使用延迟 (#1
) 可能让 Icarus 感到困惑,就像让我感到困惑一样。 (究竟应该延迟什么?一个模拟步骤是否不存在实例?)
消除这些延迟,并将测试台中的所有代码都放在这两个实例声明之后的 initial
块中。
就其价值而言,dynreg
可能无法像所写的那样综合。它没有时钟输入,并且包含几个无法在硬件中展开的循环。
UPDATE: C:\iverilog\lib\verilog-10.1.1 doesn't exist, and, in fact, I searched in C:\iverilog for pform.cc and found no results. Strange.
此路径可能指的是开发人员计算机上编译您的 Icarus 副本的代码位置。除非您打算自己尝试修复导致此崩溃的错误,否则您可以放心地忽略它。