mirror of
https://github.com/verilator/verilator.git
synced 2025-01-01 04:07:34 +00:00
parent
f84592af49
commit
d9078df650
@ -2046,22 +2046,26 @@ bool VlReadMem::get(QData& addrr, std::string& valuer) {
|
||||
if (VL_UNLIKELY(!m_fp)) return false;
|
||||
valuer = "";
|
||||
// Prep for reading
|
||||
bool indata = false;
|
||||
bool ignore_to_eol = false;
|
||||
bool ignore_to_cmt = false;
|
||||
bool reading_addr = false;
|
||||
int lastc = ' ';
|
||||
bool inData = false;
|
||||
bool ignoreToEol = false;
|
||||
bool ignoreToComment = false;
|
||||
bool readingAddress = false;
|
||||
int lastCh = ' ';
|
||||
// Read the data
|
||||
// We process a character at a time, as then we don't need to deal
|
||||
// with changing buffer sizes dynamically, etc.
|
||||
while (true) {
|
||||
int c = std::fgetc(m_fp);
|
||||
if (VL_UNLIKELY(c == EOF)) break;
|
||||
const bool chIs4StateBin
|
||||
= c == '0' || c == '1' || c == 'x' || c == 'X' || c == 'z' || c == 'Z';
|
||||
const bool chIs2StateHex = std::isxdigit(c);
|
||||
const bool chIs4StateHex = std::isxdigit(c) || chIs4StateBin;
|
||||
// printf("%d: Got '%c' Addr%lx IN%d IgE%d IgC%d\n",
|
||||
// m_linenum, c, m_addr, indata, ignore_to_eol, ignore_to_cmt);
|
||||
// m_linenum, c, m_addr, inData, ignoreToEol, ignoreToComment);
|
||||
// See if previous data value has completed, and if so return
|
||||
if (c == '_') continue; // Ignore _ e.g. inside a number
|
||||
if (indata && !std::isxdigit(c) && c != 'x' && c != 'X') {
|
||||
if (inData && !chIs4StateHex) {
|
||||
// printf("Got data @%lx = %s\n", m_addr, valuer.c_str());
|
||||
ungetc(c, m_fp);
|
||||
addrr = m_addr;
|
||||
@ -2071,50 +2075,46 @@ bool VlReadMem::get(QData& addrr, std::string& valuer) {
|
||||
// Parse line
|
||||
if (c == '\n') {
|
||||
++m_linenum;
|
||||
ignore_to_eol = false;
|
||||
reading_addr = false;
|
||||
ignoreToEol = false;
|
||||
readingAddress = false;
|
||||
} else if (c == '\t' || c == ' ' || c == '\r' || c == '\f') {
|
||||
reading_addr = false;
|
||||
readingAddress = false;
|
||||
}
|
||||
// Skip // comments and detect /* comments
|
||||
else if (ignore_to_cmt && lastc == '*' && c == '/') {
|
||||
ignore_to_cmt = false;
|
||||
reading_addr = false;
|
||||
} else if (!ignore_to_eol && !ignore_to_cmt) {
|
||||
if (lastc == '/' && c == '*') {
|
||||
ignore_to_cmt = true;
|
||||
} else if (lastc == '/' && c == '/') {
|
||||
ignore_to_eol = true;
|
||||
else if (ignoreToComment && lastCh == '*' && c == '/') {
|
||||
ignoreToComment = false;
|
||||
readingAddress = false;
|
||||
} else if (!ignoreToEol && !ignoreToComment) {
|
||||
if (lastCh == '/' && c == '*') {
|
||||
ignoreToComment = true;
|
||||
} else if (lastCh == '/' && c == '/') {
|
||||
ignoreToEol = true;
|
||||
} else if (c == '/') { // Part of /* or //
|
||||
} else if (c == '#') {
|
||||
ignore_to_eol = true;
|
||||
ignoreToEol = true;
|
||||
} else if (c == '@') {
|
||||
reading_addr = true;
|
||||
readingAddress = true;
|
||||
m_anyAddr = true;
|
||||
m_addr = 0;
|
||||
}
|
||||
// Check for hex or binary digits as file format requests
|
||||
else if (std::isxdigit(c) || (!reading_addr && (c == 'x' || c == 'X'))) {
|
||||
} else if (readingAddress && chIs2StateHex) {
|
||||
c = std::tolower(c);
|
||||
const int value
|
||||
= (c >= 'a' ? (c == 'x' ? VL_RAND_RESET_I(4) : (c - 'a' + 10)) : (c - '0'));
|
||||
if (reading_addr) {
|
||||
// Decode @ addresses
|
||||
m_addr = (m_addr << 4) + value;
|
||||
} else {
|
||||
indata = true;
|
||||
valuer += static_cast<char>(c);
|
||||
// printf(" Value width=%d @%x = %c\n", width, m_addr, c);
|
||||
if (VL_UNLIKELY(value > 1 && !m_hex)) {
|
||||
VL_FATAL_MT(m_filename.c_str(), m_linenum, "",
|
||||
"$readmemb (binary) file contains hex characters");
|
||||
}
|
||||
const int addressValue = (c >= 'a') ? (c - 'a' + 10) : (c - '0');
|
||||
m_addr = (m_addr << 4) + addressValue;
|
||||
} else if (readingAddress && chIs4StateHex) {
|
||||
VL_FATAL_MT(m_filename.c_str(), m_linenum, "",
|
||||
"$readmem address contains 4-state characters");
|
||||
} else if (chIs4StateHex) {
|
||||
inData = true;
|
||||
valuer += static_cast<char>(c);
|
||||
if (VL_UNLIKELY(!m_hex && !chIs4StateBin)) {
|
||||
VL_FATAL_MT(m_filename.c_str(), m_linenum, "",
|
||||
"$readmemb (binary) file contains hex characters");
|
||||
}
|
||||
} else {
|
||||
VL_FATAL_MT(m_filename.c_str(), m_linenum, "", "$readmem file syntax error");
|
||||
}
|
||||
}
|
||||
lastc = c;
|
||||
lastCh = c;
|
||||
}
|
||||
|
||||
if (VL_UNLIKELY(m_end != ~0ULL && m_addr <= m_end && !m_anyAddr)) {
|
||||
@ -2123,7 +2123,7 @@ bool VlReadMem::get(QData& addrr, std::string& valuer) {
|
||||
}
|
||||
|
||||
addrr = m_addr;
|
||||
return indata; // EOF
|
||||
return inData; // EOF
|
||||
}
|
||||
void VlReadMem::setData(void* valuep, const std::string& rhs) {
|
||||
const QData shift = m_hex ? 4ULL : 1ULL;
|
||||
@ -2131,8 +2131,9 @@ void VlReadMem::setData(void* valuep, const std::string& rhs) {
|
||||
// Shift value in
|
||||
for (const auto& i : rhs) {
|
||||
const char c = std::tolower(i);
|
||||
const int value
|
||||
= (c >= 'a' ? (c == 'x' ? VL_RAND_RESET_I(4) : (c - 'a' + 10)) : (c - '0'));
|
||||
const int value = (c == 'x' || c == 'z') ? VL_RAND_RESET_I(m_hex ? 4 : 1)
|
||||
: (c >= 'a') ? (c - 'a' + 10)
|
||||
: (c - '0');
|
||||
if (m_bits <= 8) {
|
||||
CData* const datap = reinterpret_cast<CData*>(valuep);
|
||||
if (!innum) *datap = 0;
|
||||
|
14
test_regress/t/t_sys_readmem_4state.mem
Normal file
14
test_regress/t/t_sys_readmem_4state.mem
Normal file
@ -0,0 +1,14 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test data file
|
||||
//
|
||||
// Copyright 2024 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
0
|
||||
1
|
||||
x
|
||||
X
|
||||
z
|
||||
Z
|
26
test_regress/t/t_sys_readmem_4state.pl
Executable file
26
test_regress/t/t_sys_readmem_4state.pl
Executable file
@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2024 by Wilson Snyder. This program is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
scenarios(simulator => 1);
|
||||
|
||||
compile(
|
||||
verilator_flags2 => ["--x-initial unique"],
|
||||
);
|
||||
|
||||
execute(
|
||||
all_run_flags => ["+verilator+rand+reset+1"],
|
||||
check_finished => 1,
|
||||
);
|
||||
|
||||
files_identical("$Self->{obj_dir}/t_sys_readmem_4state_b.mem", "t/t_sys_readmem_4state_b.out");
|
||||
files_identical("$Self->{obj_dir}/t_sys_readmem_4state_h.mem", "t/t_sys_readmem_4state_h.out");
|
||||
|
||||
ok(1);
|
||||
1;
|
25
test_regress/t/t_sys_readmem_4state.v
Normal file
25
test_regress/t/t_sys_readmem_4state.v
Normal file
@ -0,0 +1,25 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2024 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
`define STRINGIFY(x) `"x`"
|
||||
|
||||
module t;
|
||||
reg [3:0] MEMB [6];
|
||||
reg [3:0] MEMH [6];
|
||||
|
||||
initial begin
|
||||
$readmemb("t/t_sys_readmem_4state.mem", MEMB);
|
||||
$display("MEMB=%p", MEMB);
|
||||
$writememh({`STRINGIFY(`TEST_OBJ_DIR),"/t_sys_readmem_4state_b.mem"}, MEMB);
|
||||
|
||||
$readmemh("t/t_sys_readmem_4state.mem", MEMH);
|
||||
$display("MEMH=%p", MEMH);
|
||||
$writememh({`STRINGIFY(`TEST_OBJ_DIR),"/t_sys_readmem_4state_h.mem"}, MEMH);
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
6
test_regress/t/t_sys_readmem_4state_b.out
Normal file
6
test_regress/t/t_sys_readmem_4state_b.out
Normal file
@ -0,0 +1,6 @@
|
||||
0
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
6
test_regress/t/t_sys_readmem_4state_h.out
Normal file
6
test_regress/t/t_sys_readmem_4state_h.out
Normal file
@ -0,0 +1,6 @@
|
||||
0
|
||||
1
|
||||
f
|
||||
f
|
||||
f
|
||||
f
|
9
test_regress/t/t_sys_readmem_bad_addr2.mem
Normal file
9
test_regress/t/t_sys_readmem_bad_addr2.mem
Normal file
@ -0,0 +1,9 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test data file
|
||||
//
|
||||
// Copyright 2024 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
@10x 10x
|
2
test_regress/t/t_sys_readmem_bad_addr2.out
Normal file
2
test_regress/t/t_sys_readmem_bad_addr2.out
Normal file
@ -0,0 +1,2 @@
|
||||
%Error: t/t_sys_readmem_bad_addr2.mem:8: $readmem address contains 4-state characters
|
||||
Aborting...
|
22
test_regress/t/t_sys_readmem_bad_addr2.pl
Executable file
22
test_regress/t/t_sys_readmem_bad_addr2.pl
Executable file
@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2024 by Wilson Snyder. This program is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
scenarios(simulator => 1);
|
||||
|
||||
compile(
|
||||
);
|
||||
|
||||
execute(
|
||||
fails => $Self->{vlt_all},
|
||||
expect_filename => $Self->{golden_filename},
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
15
test_regress/t/t_sys_readmem_bad_addr2.v
Normal file
15
test_regress/t/t_sys_readmem_bad_addr2.v
Normal file
@ -0,0 +1,15 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2024 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t;
|
||||
reg [175:0] hex [15:0];
|
||||
|
||||
initial begin
|
||||
$readmemh("t/t_sys_readmem_bad_addr2.mem", hex);
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
Loading…
Reference in New Issue
Block a user