Add $writememb support (#2450)

This commit is contained in:
Fan Shupei 2020-07-02 05:32:15 +08:00 committed by GitHub
parent e7bd44561c
commit 04c96694e6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 192 additions and 34 deletions

View File

@ -12,6 +12,7 @@ David Horton
David Stanford
Driss Hafdi
Eric Rippey
Fan Shupei
Garrett Smith
Geza Lore
Gianfranco Costamagna

View File

@ -1707,7 +1707,7 @@ const char* vl_dumpctl_filenamep(bool setit, const std::string& filename) VL_MT_
static const char* memhFormat(int nBits) {
assert((nBits >= 1) && (nBits <= 32));
static char buf[32];
static VL_THREAD_LOCAL char buf[32];
switch ((nBits - 1) / 4) {
case 0: VL_SNPRINTF(buf, 32, "%%01x"); break;
case 1: VL_SNPRINTF(buf, 32, "%%02x"); break;
@ -1722,6 +1722,18 @@ static const char* memhFormat(int nBits) {
return buf;
}
static const char* formatBinary(int nBits, vluint32_t bits) {
assert((nBits >= 1) && (nBits <= 32));
static VL_THREAD_LOCAL char buf[64];
for (int i = 0; i < nBits; i++) {
bool isOne = bits & (1 << (nBits - 1 - i));
buf[i] = (isOne ? '1' : '0');
}
buf[nBits] = '\0';
return buf;
}
VlReadMem::VlReadMem(bool hex, int bits, const std::string& filename, QData start, QData end)
: m_hex(hex)
, m_bits(bits)
@ -1859,14 +1871,9 @@ void VlReadMem::setData(void* valuep, const std::string& rhs) {
}
VlWriteMem::VlWriteMem(bool hex, int bits, const std::string& filename, QData start, QData end)
: m_bits(bits)
: m_hex(hex)
, m_bits(bits)
, m_addr(0) {
if (VL_UNLIKELY(!hex)) {
VL_FATAL_MT(filename.c_str(), 0, "",
"Unsupported: $writemem binary format (suggest hex format)");
return;
}
if (VL_UNLIKELY(start > end)) {
VL_FATAL_MT(filename.c_str(), 0, "", "$writemem invalid address range");
return;
@ -1893,23 +1900,40 @@ void VlWriteMem::print(QData addr, bool addrstamp, const void* valuep) {
m_addr = addr + 1;
if (m_bits <= 8) {
const CData* datap = reinterpret_cast<const CData*>(valuep);
fprintf(m_fp, memhFormat(m_bits), VL_MASK_I(m_bits) & *datap);
fprintf(m_fp, "\n");
if (m_hex) {
fprintf(m_fp, memhFormat(m_bits), VL_MASK_I(m_bits) & *datap);
fprintf(m_fp, "\n");
} else {
fprintf(m_fp, "%s\n", formatBinary(m_bits, *datap));
}
} else if (m_bits <= 16) {
const SData* datap = reinterpret_cast<const SData*>(valuep);
fprintf(m_fp, memhFormat(m_bits), VL_MASK_I(m_bits) & *datap);
fprintf(m_fp, "\n");
if (m_hex) {
fprintf(m_fp, memhFormat(m_bits), VL_MASK_I(m_bits) & *datap);
fprintf(m_fp, "\n");
} else {
fprintf(m_fp, "%s\n", formatBinary(m_bits, *datap));
}
} else if (m_bits <= 32) {
const IData* datap = reinterpret_cast<const IData*>(valuep);
fprintf(m_fp, memhFormat(m_bits), VL_MASK_I(m_bits) & *datap);
fprintf(m_fp, "\n");
if (m_hex) {
fprintf(m_fp, memhFormat(m_bits), VL_MASK_I(m_bits) & *datap);
fprintf(m_fp, "\n");
} else {
fprintf(m_fp, "%s\n", formatBinary(m_bits, *datap));
}
} else if (m_bits <= 64) {
const QData* datap = reinterpret_cast<const QData*>(valuep);
vluint64_t value = VL_MASK_Q(m_bits) & *datap;
vluint32_t lo = value & 0xffffffff;
vluint32_t hi = value >> 32;
fprintf(m_fp, memhFormat(m_bits - 32), hi);
fprintf(m_fp, "%08x\n", lo);
if (m_hex) {
fprintf(m_fp, memhFormat(m_bits - 32), hi);
fprintf(m_fp, "%08x\n", lo);
} else {
fprintf(m_fp, "%s", formatBinary(m_bits - 32, hi));
fprintf(m_fp, "%s\n", formatBinary(32, lo));
}
} else {
WDataInP datap = reinterpret_cast<WDataInP>(valuep);
// output as a sequence of VL_EDATASIZE'd words
@ -1922,9 +1946,17 @@ void VlWriteMem::print(QData addr, bool addrstamp, const void* valuep) {
if (first) {
data &= VL_MASK_E(m_bits);
int top_word_nbits = VL_BITBIT_E(m_bits - 1) + 1;
fprintf(m_fp, memhFormat(top_word_nbits), data);
if (m_hex) {
fprintf(m_fp, memhFormat(top_word_nbits), data);
} else {
fprintf(m_fp, "%s", formatBinary(top_word_nbits, data));
}
} else {
fprintf(m_fp, "%08x", data);
if (m_hex) {
fprintf(m_fp, "%08x", data);
} else {
fprintf(m_fp, "%s", formatBinary(32, data));
}
}
word_idx--;
first = false;

View File

@ -62,6 +62,7 @@ public:
};
class VlWriteMem {
bool m_hex; // Hex format
int m_bits; // Bit width of values
FILE* m_fp; // File handle for filename
QData m_addr; // Next address to write

View File

@ -4153,8 +4153,9 @@ public:
class AstWriteMem : public AstNodeReadWriteMem {
public:
AstWriteMem(FileLine* fl, AstNode* filenamep, AstNode* memp, AstNode* lsbp, AstNode* msbp)
: ASTGEN_SUPER(fl, true, filenamep, memp, lsbp, msbp) {}
AstWriteMem(FileLine* fl, bool hex, AstNode* filenamep, AstNode* memp, AstNode* lsbp,
AstNode* msbp)
: ASTGEN_SUPER(fl, hex, filenamep, memp, lsbp, msbp) {}
ASTNODE_NODE_FUNCS(WriteMem)
virtual string verilogKwd() const { return (isHex() ? "$writememh" : "$writememb"); }
virtual const char* cFuncPrefixp() const { return "VL_WRITEMEM_"; }

View File

@ -265,6 +265,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
"$writeb" { FL; return yD_WRITEB; }
"$writeh" { FL; return yD_WRITEH; }
"$writeo" { FL; return yD_WRITEO; }
"$writememb" { FL; return yD_WRITEMEMB; }
"$writememh" { FL; return yD_WRITEMEMH; }
/* Keywords */
"always" { FL; return yALWAYS; }

View File

@ -801,6 +801,7 @@ class AstSenTree;
%token<fl> yD_WRITE "$write"
%token<fl> yD_WRITEB "$writeb"
%token<fl> yD_WRITEH "$writeh"
%token<fl> yD_WRITEMEMB "$writememb"
%token<fl> yD_WRITEMEMH "$writememh"
%token<fl> yD_WRITEO "$writeo"
@ -3554,9 +3555,12 @@ system_t_call<nodep>: // IEEE: system_tf_call (as task)
| yD_READMEMH '(' expr ',' idClassSel ',' expr ')' { $$ = new AstReadMem($1,true, $3,$5,$7,NULL); }
| yD_READMEMH '(' expr ',' idClassSel ',' expr ',' expr ')' { $$ = new AstReadMem($1,true, $3,$5,$7,$9); }
//
| yD_WRITEMEMH '(' expr ',' idClassSel ')' { $$ = new AstWriteMem($1,$3,$5,NULL,NULL); }
| yD_WRITEMEMH '(' expr ',' idClassSel ',' expr ')' { $$ = new AstWriteMem($1,$3,$5,$7,NULL); }
| yD_WRITEMEMH '(' expr ',' idClassSel ',' expr ',' expr ')' { $$ = new AstWriteMem($1,$3,$5,$7,$9); }
| yD_WRITEMEMB '(' expr ',' idClassSel ')' { $$ = new AstWriteMem($1, false, $3, $5, NULL, NULL); }
| yD_WRITEMEMB '(' expr ',' idClassSel ',' expr ')' { $$ = new AstWriteMem($1, false, $3, $5, $7, NULL); }
| yD_WRITEMEMB '(' expr ',' idClassSel ',' expr ',' expr ')' { $$ = new AstWriteMem($1, false, $3, $5, $7, $9); }
| yD_WRITEMEMH '(' expr ',' idClassSel ')' { $$ = new AstWriteMem($1, true, $3, $5, NULL, NULL); }
| yD_WRITEMEMH '(' expr ',' idClassSel ',' expr ')' { $$ = new AstWriteMem($1, true, $3, $5, $7, NULL); }
| yD_WRITEMEMH '(' expr ',' idClassSel ',' expr ',' expr ')' { $$ = new AstWriteMem($1, true, $3, $5, $7, $9); }
//
// Any system function as a task
| system_f_call_or_t { $$ = new AstSysFuncAsTask($<fl>1, $1); }

View File

@ -4,6 +4,14 @@
// any use, without warranty, 2003 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
`ifdef WRITEMEM_BIN
`define READMEMX $readmemb
`define WRITEMEMX $writememb
`else
`define READMEMX $readmemh
`define WRITEMEMX $writememh
`endif
module t;
// verilator lint_off LITENDIAN
@ -53,14 +61,16 @@ module t;
begin
`ifdef WRITEMEM_READ_BACK
$readmemb("t/t_sys_readmem_b.mem", binary_nostart_tmp);
// Do a round-trip $writememh and $readmemh cycle.
// Do a round-trip $writememh(b) and $readmemh(b) cycle.
// This covers $writememh and ensures we can read our
// own memh output file.
// If WRITEMEM_BIN is also defined, use $writememb and
// $readmemb, otherwise use $writememh and $readmemh.
`ifdef TEST_VERBOSE
$display("-Writing %s", `OUT_TMP1);
`endif
$writememh(`OUT_TMP1, binary_nostart_tmp);
$readmemh(`OUT_TMP1, binary_nostart);
`WRITEMEMX(`OUT_TMP1, binary_nostart_tmp);
`READMEMX(`OUT_TMP1, binary_nostart);
`else
$readmemb("t/t_sys_readmem_b.mem", binary_nostart);
`endif
@ -86,8 +96,8 @@ module t;
`ifdef TEST_VERBOSE
$display("-Writing %s", `OUT_TMP2);
`endif
$writememh(`OUT_TMP2, binary_start_tmp, 4, 4+7);
$readmemh(`OUT_TMP2, binary_start, 4, 4+7);
`WRITEMEMX(`OUT_TMP2, binary_start_tmp, 4, 4+7);
`READMEMX(`OUT_TMP2, binary_start, 4, 4+7);
`else
$readmemb("t/t_sys_readmem_b_8.mem", binary_start, 4, 4+7); // 4-11
`endif
@ -114,8 +124,8 @@ module t;
`ifdef TEST_VERBOSE
$display("-Writing %s", `OUT_TMP3);
`endif
$writememh(`OUT_TMP3, hex_tmp, 0);
$readmemh(`OUT_TMP3, hex, 0);
`WRITEMEMX(`OUT_TMP3, hex_tmp, 0);
`READMEMX(`OUT_TMP3, hex, 0);
`else
$readmemh("t/t_sys_readmem_h.mem", hex, 0);
`endif
@ -136,8 +146,8 @@ module t;
`ifdef TEST_VERBOSE
$display("-Writing %s", `OUT_TMP4);
`endif
$writememh(`OUT_TMP4, hex_align_tmp, 0);
$readmemh(`OUT_TMP4, hex_align, 0);
`WRITEMEMX(`OUT_TMP4, hex_align_tmp, 0);
`READMEMX(`OUT_TMP4, hex_align, 0);
`else
$readmemh("t/t_sys_readmem_align_h.mem", hex_align, 0);
`endif
@ -158,8 +168,8 @@ module t;
`ifdef TEST_VERBOSE
$display("-Writing %s", `OUT_TMP5);
`endif
$writememh(fns_tmp, binary_string_tmp);
$readmemh(fns_tmp, binary_string);
`WRITEMEMX(fns_tmp, binary_string_tmp);
`READMEMX(fns_tmp, binary_string);
`else
$readmemb(fns, binary_string);
`endif

View File

@ -0,0 +1,14 @@
000010
000011
000100
000101
000110
000111
010000
000000
000000
000000
010100
010101
000000
000000

View File

@ -0,0 +1,8 @@
010000
010001
010010
010011
010100
010101
010110
010111

View File

@ -0,0 +1,16 @@
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
01000000000001000011011101100101010000110010000100100111011001010100001100100001000101110110010101000011001000010000011101100101010000110010000110101011110011011110111100010000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
01000000000010100011011101100101010000110010000100100111011001010100001100100001000101110110010101000011001000010000011101100101010000110010000110101011110011011110111100010001
01000000000010110011011101100101010000110010000100100111011001010100001100100001000101110110010101000011001000010000011101100101010000110010000110101011110011011110111100010010
01000000000011000011011101100101010000110010000100100111011001010100001100100001000101110110010101000011001000010000011101100101010000110010000110101011110011011110111100010011
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

View File

@ -0,0 +1,16 @@
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
011101110101010101000000000001000011011101100101010000110010000100100111011001010100001100100001000101110110010101000011001000010000011101100101010000110010000110101011110011011110111100010000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
011101110101010101000000000010100011011101100101010000110010000100100111011001010100001100100001000101110110010101000011001000010000011101100101010000110010000110101011110011011110111100010001
011101110101010101000000000010110011011101100101010000110010000100100111011001010100001100100001000101110110010101000011001000010000011101100101010000110010000110101011110011011110111100010010
011101110101010101000000000011000011011101100101010000110010000100100111011001010100001100100001000101110110010101000011001000010000011101100101010000110010000110101011110011011110111100010011
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

View File

@ -0,0 +1,14 @@
000010
000011
000100
000101
000110
000111
010000
000000
000000
000000
010100
010101
000000
000000

View File

@ -0,0 +1,40 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 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);
top_filename("t/t_sys_readmem.v");
# Use random reset to ensure we're fully initializing arrays before
# $writememh, to avoid miscompares with X's on 4-state simulators.
$Self->{verilated_randReset} = 2; # 2 == truly random
compile(v_flags2 => [
"+define+WRITEMEM_READ_BACK=1",
"+define+WRITEMEM_BIN=1",
"+define+OUT_TMP1=\\\"$Self->{obj_dir}/tmp1.mem\\\"",
"+define+OUT_TMP2=\\\"$Self->{obj_dir}/tmp2.mem\\\"",
"+define+OUT_TMP3=\\\"$Self->{obj_dir}/tmp3.mem\\\"",
"+define+OUT_TMP4=\\\"$Self->{obj_dir}/tmp4.mem\\\"",
"+define+OUT_TMP5=\\\"$Self->{obj_dir}/tmp5.mem\\\"",
]);
execute(
check_finished => 1,
);
for (my $i = 1; $i <= 5; $i++) {
my $gold = "$Self->{t_dir}/t_sys_writemem_b.gold${i}.mem";
my $out = "$Self->{obj_dir}/tmp${i}.mem";
files_identical($out, $gold);
}
ok(1);
1;