Skip to content

Commit

Permalink
Merge pull request #852 from larsclausen/vvp-string-vpi
Browse files Browse the repository at this point in the history
vvp: Handle null-bytes in a conistent way when reading through VPI
  • Loading branch information
steveicarus authored Jan 7, 2023
2 parents 97b897c + 71bb011 commit 08f2c88
Show file tree
Hide file tree
Showing 10 changed files with 138 additions and 12 deletions.
4 changes: 4 additions & 0 deletions ivtest/gold/br_gh827.gold
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Const Positive yes
Const Negative NO
Var Positive yes
Var Negative NO
2 changes: 1 addition & 1 deletion ivtest/gold/macro_with_args.gold
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
first..last first,last last..first
(a)..(c) (a,b,c) (c)..(a)
(a )..(c ) (a,b,c) (c )..(a )
sumsqr(3,4) = 25
sumsqr(5,12) = 169
9 changes: 9 additions & 0 deletions ivtest/ivltests/br_gh827.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module test;
reg expected = 1;
initial begin
$display("Const Positive %s", 1 ? "yes" : "NO");
$display("Const Negative %s", !1 ? "yes" : "NO");
$display("Var Positive %s", expected ? "yes" : "NO");
$display("Var Negative %s", !expected ? "yes" : "NO");
end
endmodule
58 changes: 58 additions & 0 deletions ivtest/ivltests/string13.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Check that null-bytes are handled consistently between string literals,
// number literals and signals of all kinds, especially when formatting as a
// string.

module test;

reg failed = 1'b0;

`define check(val, exp) \
if (val != exp) begin \
$display("FAILED(%0d): Expected '%0s', got '%0s'.", `__LINE__, exp, val); \
failed = 1'b1; \
end

reg [255:0] s;
reg [31:0] x;
reg [31:0] y[1:0];
wire [31:0] z;
wire [31:0] w;

assign z = "\000a\000b";
assign w = 32'h00610062;

initial begin
$sformat(s, ":%x:%0x:%s:%0s:", "\000a\000b", "\000a\000b", "\000a\000b", "\000a\000b");
`check(s, ":00610062:610062: a b:a b:")
$sformat(s, ":%x:%0x:%s:%0s:", 32'h00610062, 32'h00610062, 32'h00610062, 32'h00610062);
`check(s, ":00610062:610062: a b:a b:")

x = "\000a\000b";
$sformat(s, ":%x:%0x:%s:%0s:", x, x, x, x);
`check(s, ":00610062:610062: a b:a b:")

x = 32'h00610062;
$sformat(s, ":%x:%0x:%s:%0s:", x, x, x, x);
`check(s, ":00610062:610062: a b:a b:")

y[0] = "\000a\000b";
$sformat(s, ":%x:%0x:%s:%0s:", y[0], y[0], y[0], y[0]);
`check(s, ":00610062:610062: a b:a b:")

y[1] = 32'h00610062;
$sformat(s, ":%x:%0x:%s:%0s:", y[1], y[1], y[1], y[1]);
`check(s, ":00610062:610062: a b:a b:")

$sformat(s, ":%x:%0x:%s:%0s:", z, z, z, z);
`check(s, ":00610062:610062: a b:a b:")

$sformat(s, ":%x:%0x:%s:%0s:", w, w, w, w);
`check(s, ":00610062:610062: a b:a b:")


if (!failed) begin
$display("PASSED");
end
end

endmodule
38 changes: 38 additions & 0 deletions ivtest/ivltests/string14.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Check that the empty string "" is equivalent to 8'h00

module test;

reg failed = 1'b0;

`define check(val, exp) \
if (val != exp) begin \
$display("FAILED(%0d): Expected '%0s', got '%0s'.", `__LINE__, exp, val); \
failed = 1'b1; \
end

reg [47:0] s;
reg [7:0] x;
wire [7:0] y;

assign y = "";

initial begin
`check("", 8'h00);
`check($bits(""), 8);

$sformat(s, ":%s:%0s:", "", "");
`check(s, ": ::");

x = 8'h00;
$sformat(s, ":%s:%0s:", x, x);
`check(s, ": ::");

$sformat(s, ":%s:%0s:", y, y);
`check(s, ": ::");

if (!failed) begin
$display("PASSED");
end
end

endmodule
3 changes: 3 additions & 0 deletions ivtest/regress-vlg.list
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,7 @@ br_gh782e normal ivltests
br_gh782f normal ivltests
br_gh788 normal,-gno-io-range-error,-Wno-anachronisms ivltests gold=br_gh788.gold
br_gh793 normal ivltests
br_gh827 normal ivltests gold=br_gh827.gold
br_ml20150315 normal ivltests gold=br_ml_20150315.gold
br_ml20150321 CE ivltests
br_mw20171108 normal ivltests
Expand Down Expand Up @@ -1646,6 +1647,8 @@ string9 normal ivltests gold=string9.gold
string10 normal ivltests gold=string10.gold
string11 normal ivltests gold=string11.gold
string12 normal ivltests
string13 normal ivltests
string14 normal ivltests
supply1 normal ivltests
supply2 normal ivltests
switch_primitives normal ivltests gold=switch_primitives.gold
Expand Down
2 changes: 0 additions & 2 deletions tgt-vlog95/misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -512,8 +512,6 @@ static void emit_number_as_string(ivl_net_const_t net_const)
val |= (bits[idx-bit] == '1') ? 1 << (7-bit) : 0x00;
}

/* Skip any NULL bytes. */
if (val == 0) continue;
/* Print some values that can be escaped. */
if (val == '"') fprintf(vlog_out, "\\\"");
else if (val == '\\') fprintf(vlog_out, "\\\\");
Expand Down
8 changes: 2 additions & 6 deletions tgt-vlog95/numbers.c
Original file line number Diff line number Diff line change
Expand Up @@ -346,13 +346,9 @@ static void remove_two_chars(char* str)
void emit_string(const char* string)
{
char *buffer = strdup(string);
char *bptr = buffer;
char *cptr;
fprintf(vlog_out, "\"");
/* Prune any leading escaped NULL bytes. */
while ((bptr[0] == '\\') && (bptr[1] == '0') &&
(bptr[2] == '0') && (bptr[3] == '0')) bptr += 4;
for (cptr = bptr; *cptr; cptr += 1) {
for (cptr = buffer; *cptr; cptr += 1) {
if (*cptr == '\\') {
/* Replace any \011 with \t */
if ((cptr[1] == '0') && (cptr[2] == '1') &&
Expand Down Expand Up @@ -381,7 +377,7 @@ void emit_string(const char* string)
} else cptr += 3;
}
}
if (*bptr) fprintf(vlog_out, "%s", bptr);
if (*buffer) fprintf(vlog_out, "%s", buffer);
free(buffer);
fprintf(vlog_out, "\"");
}
19 changes: 16 additions & 3 deletions vvp/vpi_const.cc
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ int __vpiStringConst::vpi_get(int code)
{
switch (code) {
case vpiSize:
return strlen(value_)*8;
return value_len_ * 8;

case vpiSigned:
return 0;
Expand Down Expand Up @@ -121,7 +121,7 @@ void __vpiStringConst::vpi_get_value(p_vpi_value vp)
{
unsigned uint_value;
p_vpi_vecval vecp;
unsigned size = strlen(value_);
unsigned size = value_len_;
char*rbuf = 0;
char*cp;

Expand All @@ -131,9 +131,22 @@ void __vpiStringConst::vpi_get_value(p_vpi_value vp)
vp->format = vpiStringVal;
// fallthrough
case vpiStringVal:
cp = value_;
rbuf = (char *) need_result_buf(size + 1, RBUF_VAL);
strcpy(rbuf, value_);
vp->value.str = rbuf;

for (unsigned int i = 0; i < size; i++) {
// Ignore leading null-bytes and replace other null-bytes with space.
// The LRM is not entirely clear on how null bytes should be handled.
// This is the implementation chosen for iverilog.
if (*cp)
*rbuf++ = *cp;
else if (rbuf != vp->value.str)
*rbuf++ = ' ';

cp++;
}
*rbuf = '\0';
break;

case vpiDecStrVal:
Expand Down
7 changes: 7 additions & 0 deletions vvp/vpi_priv.cc
Original file line number Diff line number Diff line change
Expand Up @@ -635,6 +635,8 @@ static void vec4_get_value_string(const vvp_vector4_t&word_val, unsigned width,

if (char_val != 0)
*cp++ = char_val;
else if (cp != rbuf)
*cp++ = ' ';
}

for (unsigned idx = 0 ; idx < nchar ; idx += 1) {
Expand All @@ -645,8 +647,13 @@ static void vec4_get_value_string(const vvp_vector4_t&word_val, unsigned width,
if (val == BIT4_1)
char_val |= 1 << bdx;
}
// Ignore leading null-bytes and replace other null-bytes with space.
// The LRM is not entirely clear on how null bytes should be handled.
// This is the implementation chosen for iverilog.
if (char_val != 0)
*cp++ = char_val;
else if (cp != rbuf)
*cp++ = ' ';
}

*cp = 0;
Expand Down

0 comments on commit 08f2c88

Please sign in to comment.