Support string replication with variable (#4341)
This commit is contained in:
parent
294d78e0e2
commit
9aa90569bf
|
|
@ -729,19 +729,12 @@ private:
|
||||||
// width: value(LHS) * width(RHS)
|
// width: value(LHS) * width(RHS)
|
||||||
if (m_vup->prelim()) {
|
if (m_vup->prelim()) {
|
||||||
iterateCheckSizedSelf(nodep, "RHS", nodep->rhsp(), SELF, BOTH);
|
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);
|
const AstConst* const constp = VN_CAST(nodep->rhsp(), Const);
|
||||||
if (!constp) {
|
if (constp) times = constp->toUInt();
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
AstNodeDType* const vdtypep = m_vup->dtypeNullSkipRefp();
|
AstNodeDType* const vdtypep = m_vup->dtypeNullSkipRefp();
|
||||||
if (VN_IS(vdtypep, QueueDType) || VN_IS(vdtypep, DynArrayDType)
|
if (VN_IS(vdtypep, QueueDType) || VN_IS(vdtypep, DynArrayDType)
|
||||||
|
|
@ -775,7 +768,7 @@ private:
|
||||||
<< vdtypep->prettyDTypeNameQ() << " data type");
|
<< vdtypep->prettyDTypeNameQ() << " data type");
|
||||||
}
|
}
|
||||||
iterateCheckSizedSelf(nodep, "LHS", nodep->lhsp(), SELF, BOTH);
|
iterateCheckSizedSelf(nodep, "LHS", nodep->lhsp(), SELF, BOTH);
|
||||||
if (nodep->lhsp()->isString()) {
|
if ((vdtypep && vdtypep->isString()) || nodep->lhsp()->isString()) {
|
||||||
AstNode* const newp
|
AstNode* const newp
|
||||||
= new AstReplicateN{nodep->fileline(), nodep->lhsp()->unlinkFrBack(),
|
= new AstReplicateN{nodep->fileline(), nodep->lhsp()->unlinkFrBack(),
|
||||||
nodep->rhsp()->unlinkFrBack()};
|
nodep->rhsp()->unlinkFrBack()};
|
||||||
|
|
@ -783,6 +776,13 @@ private:
|
||||||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||||
return;
|
return;
|
||||||
} else {
|
} 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->dtypeSetLogicUnsized((nodep->lhsp()->width() * times),
|
||||||
(nodep->lhsp()->widthMin() * times),
|
(nodep->lhsp()->widthMin() * times),
|
||||||
VSigning::UNSIGNED);
|
VSigning::UNSIGNED);
|
||||||
|
|
@ -801,18 +801,7 @@ private:
|
||||||
if (m_vup->prelim()) {
|
if (m_vup->prelim()) {
|
||||||
iterateCheckString(nodep, "LHS", nodep->lhsp(), BOTH);
|
iterateCheckString(nodep, "LHS", nodep->lhsp(), BOTH);
|
||||||
iterateCheckSizedSelf(nodep, "RHS", nodep->rhsp(), SELF, BOTH);
|
iterateCheckSizedSelf(nodep, "RHS", nodep->rhsp(), SELF, BOTH);
|
||||||
V3Const::constifyParamsEdit(nodep->rhsp()); // rhsp may change
|
V3Const::constifyParamsNoWarnEdit(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)");
|
|
||||||
}
|
|
||||||
nodep->dtypeSetString();
|
nodep->dtypeSetString();
|
||||||
}
|
}
|
||||||
if (m_vup->final()) {
|
if (m_vup->final()) {
|
||||||
|
|
|
||||||
|
|
@ -8,15 +8,12 @@
|
||||||
| ^
|
| ^
|
||||||
... For warning description see https://verilator.org/warn/WIDTHEXPAND?v=latest
|
... 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.
|
... 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.
|
%Error: t/t_math_repl_bad.v:13:43: Replication value isn't a constant.
|
||||||
: ... In instance t
|
: ... In instance t
|
||||||
13 | o = {$test$plusargs("NON-CONSTANT") {1'b1}};
|
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
|
%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
|
: ... In instance t
|
||||||
13 | o = {$test$plusargs("NON-CONSTANT") {1'b1}};
|
13 | o = {$test$plusargs("NON-CONSTANT") {1'b1}};
|
||||||
| ^
|
| ^
|
||||||
|
%Error: Exiting due to
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
@ -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
|
||||||
Loading…
Reference in New Issue