Support string replication with variable (#4341)

This commit is contained in:
Aleksander Kiryk 2023-07-07 10:05:06 +02:00 committed by GitHub
parent 294d78e0e2
commit 9aa90569bf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 83 additions and 31 deletions

View File

@ -729,19 +729,12 @@ private:
// width: value(LHS) * width(RHS)
if (m_vup->prelim()) {
iterateCheckSizedSelf(nodep, "RHS", nodep->rhsp(), SELF, BOTH);
V3Const::constifyParamsEdit(nodep->rhsp()); // rhsp may change
V3Const::constifyParamsNoWarnEdit(nodep->rhsp()); // rhsp may change
uint32_t times = 1;
const AstConst* const constp = VN_CAST(nodep->rhsp(), Const);
if (!constp) {
nodep->v3error("Replication value isn't a constant.");
return;
}
uint32_t times = constp->toUInt();
if (times == 0
&& !VN_IS(nodep->backp(), Concat)) { // Concat Visitor will clean it up.
nodep->v3error("Replication value of 0 is only legal under a concatenation"
" (IEEE 1800-2017 11.4.12.1)");
times = 1;
}
if (constp) times = constp->toUInt();
AstNodeDType* const vdtypep = m_vup->dtypeNullSkipRefp();
if (VN_IS(vdtypep, QueueDType) || VN_IS(vdtypep, DynArrayDType)
@ -775,7 +768,7 @@ private:
<< vdtypep->prettyDTypeNameQ() << " data type");
}
iterateCheckSizedSelf(nodep, "LHS", nodep->lhsp(), SELF, BOTH);
if (nodep->lhsp()->isString()) {
if ((vdtypep && vdtypep->isString()) || nodep->lhsp()->isString()) {
AstNode* const newp
= new AstReplicateN{nodep->fileline(), nodep->lhsp()->unlinkFrBack(),
nodep->rhsp()->unlinkFrBack()};
@ -783,6 +776,13 @@ private:
VL_DO_DANGLING(pushDeletep(nodep), nodep);
return;
} else {
if (!constp) nodep->v3error("Replication value isn't a constant.");
if (times == 0
&& !VN_IS(nodep->backp(), Concat)) { // Concat Visitor will clean it up.
nodep->v3error("Replication value of 0 is only legal under a concatenation"
" (IEEE 1800-2017 11.4.12.1)");
times = 1; // Set to 1, so we can continue looking for errors
}
nodep->dtypeSetLogicUnsized((nodep->lhsp()->width() * times),
(nodep->lhsp()->widthMin() * times),
VSigning::UNSIGNED);
@ -801,18 +801,7 @@ private:
if (m_vup->prelim()) {
iterateCheckString(nodep, "LHS", nodep->lhsp(), BOTH);
iterateCheckSizedSelf(nodep, "RHS", nodep->rhsp(), SELF, BOTH);
V3Const::constifyParamsEdit(nodep->rhsp()); // rhsp may change
const AstConst* const constp = VN_CAST(nodep->rhsp(), Const);
if (!constp) {
nodep->v3error("Replication value isn't a constant.");
return;
}
const uint32_t times = constp->toUInt();
if (times == 0
&& !VN_IS(nodep->backp(), Concat)) { // Concat Visitor will clean it up.
nodep->v3error("Replication value of 0 is only legal under a concatenation"
" (IEEE 1800-2017 11.4.12.1)");
}
V3Const::constifyParamsNoWarnEdit(nodep->rhsp()); // rhsp may change
nodep->dtypeSetString();
}
if (m_vup->final()) {

View File

@ -8,15 +8,12 @@
| ^
... For warning description see https://verilator.org/warn/WIDTHEXPAND?v=latest
... Use "/* verilator lint_off WIDTHEXPAND */" and lint_on around source to disable this message.
%Error: t/t_math_repl_bad.v:13:12: Expecting expression to be constant, but can't convert a TESTPLUSARGS to constant.
: ... In instance t
13 | o = {$test$plusargs("NON-CONSTANT") {1'b1}};
| ^~~~~~~~~~~~~~
%Error: t/t_math_repl_bad.v:13:43: Replication value isn't a constant.
: ... In instance t
13 | o = {$test$plusargs("NON-CONSTANT") {1'b1}};
| ^
%Error: Internal Error: t/t_math_repl_bad.v:13:9: ../V3Width.cpp:#: Node has no type
: ... In instance t
%Warning-WIDTHEXPAND: t/t_math_repl_bad.v:13:9: Operator ASSIGN expects 32 bits on the Assign RHS, but Assign RHS's REPLICATE generates 1 bits.
: ... In instance t
13 | o = {$test$plusargs("NON-CONSTANT") {1'b1}};
| ^
%Error: Exiting due to

21
test_regress/t/t_string_repl.pl Executable file
View File

@ -0,0 +1,21 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2022 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(
check_finished => 1,
);
ok(1);
1;

View File

@ -0,0 +1,45 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// Use this file as a template for submitting bugs, etc.
// This module takes a single clock input, and should either
// $write("*-* All Finished *-*\n");
// $finish;
// on success, or $stop.
//
// The code as shown applies a random vector to the Test
// module, then calculates a CRC on the Test module's outputs.
//
// **If you do not wish for your code to be released to the public
// please note it here, otherwise:**
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2023 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
module t(/*AUTOARG*/
// Inputs
clk
);
input clk;
integer cyc = 0;
string s;
// Test loop
always @ (posedge clk) begin
cyc <= cyc + 1;
s = {cyc{"*"}};
if (cyc != s.len()) $stop;
if (cyc == 0 && s != "") $stop;
if (cyc == 1 && s != "*") $stop;
if (cyc == 2 && s != "**") $stop;
if (cyc == 3 && s != "***") $stop;
if (cyc == 4 && s != "****") $stop;
if (cyc == 5 && s != "*****") $stop;
if (cyc == 5) begin
$write("*-* All Finished *-*\n");
$finish;
end
end
endmodule