mirror of
https://github.com/verilator/verilator.git
synced 2025-01-06 06:37:45 +00:00
Optimize $random concatenates/selects (#3114).
This commit is contained in:
parent
ffdc0afe5f
commit
692306ef44
1
Changes
1
Changes
@ -22,6 +22,7 @@ Verilator 4.215 devel
|
||||
* Improve --thread verilation-time performance.
|
||||
* Support task name in $display %m (#3211). [Julie Schwartz]
|
||||
* Make 'bit', 'logic' and 'time' types unsigned by default. [Geza Lore]
|
||||
* Optimize $random concatenates/selects (#3114).
|
||||
* Fix array method names with parenthesis (#3181) (#3183). [Teng Huang]
|
||||
* Fix split_var assign merging (#3177) (#3179). [Yutetsu TAKATSUKASA]
|
||||
* Fix wrong bit op tree optimization (#3185). [Yutetsu TAKATSUKASA]
|
||||
|
@ -308,16 +308,11 @@ vluint64_t vl_rand64() VL_MT_SAFE {
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifndef VL_NO_LEGACY
|
||||
// VL_RANDOM_W currently unused as $random always 32 bits, left for backwards compatibility
|
||||
// LCOV_EXCL_START
|
||||
WDataOutP VL_RANDOM_W(int obits, WDataOutP outwp) VL_MT_SAFE {
|
||||
for (int i = 0; i < VL_WORDS_I(obits); ++i) outwp[i] = vl_rand64();
|
||||
// Last word is unclean
|
||||
return outwp;
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
#endif
|
||||
|
||||
IData VL_RANDOM_SEEDED_II(IData seed) VL_MT_SAFE {
|
||||
Verilated::threadContextp()->randSeed(static_cast<int>(seed));
|
||||
|
@ -76,9 +76,7 @@ extern void VL_DBG_MSGF(const char* formatp, ...) VL_ATTR_PRINTF(1) VL_MT_SAFE;
|
||||
// EMIT_RULE: VL_RANDOM: oclean=dirty
|
||||
inline IData VL_RANDOM_I() VL_MT_SAFE { return vl_rand64(); }
|
||||
inline QData VL_RANDOM_Q() VL_MT_SAFE { return vl_rand64(); }
|
||||
#ifndef VL_NO_LEGACY
|
||||
extern WDataOutP VL_RANDOM_W(int obits, WDataOutP outwp);
|
||||
#endif
|
||||
extern IData VL_RANDOM_SEEDED_II(IData seed) VL_MT_SAFE;
|
||||
inline IData VL_URANDOM_RANGE_I(IData hi, IData lo) {
|
||||
const vluint64_t rnd = vl_rand64();
|
||||
|
@ -5481,6 +5481,10 @@ public:
|
||||
virtual bool isPredictOptimizable() const override { return false; }
|
||||
virtual int instrCount() const override { return INSTR_COUNT_PLI; }
|
||||
virtual bool same(const AstNode* samep) const override { return true; }
|
||||
bool combinable(const AstRand* samep) const {
|
||||
return !seedp() && !samep->seedp() && reset() == samep->reset()
|
||||
&& urandom() == samep->urandom();
|
||||
}
|
||||
AstNode* seedp() const { return op1p(); }
|
||||
bool reset() const { return m_reset; }
|
||||
bool urandom() const { return m_urandom; }
|
||||
|
@ -2229,6 +2229,29 @@ private:
|
||||
iterate(nodep); // Again?
|
||||
}
|
||||
|
||||
bool matchConcatRand(AstConcat* nodep) {
|
||||
// CONCAT(RAND, RAND) - created by Chisel code
|
||||
AstRand* const aRandp = VN_CAST(nodep->lhsp(), Rand);
|
||||
AstRand* const bRandp = VN_CAST(nodep->rhsp(), Rand);
|
||||
if (!aRandp || !bRandp) return false;
|
||||
if (!aRandp->combinable(bRandp)) return false;
|
||||
UINFO(4, "Concat(Rand,Rand) => Rand: " << nodep << endl);
|
||||
aRandp->dtypeFrom(nodep); // I.e. the total width
|
||||
nodep->replaceWith(aRandp->unlinkFrBack());
|
||||
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
||||
return true;
|
||||
}
|
||||
bool matchSelRand(AstSel* nodep) {
|
||||
// SEL(RAND) - created by Chisel code
|
||||
AstRand* const aRandp = VN_CAST(nodep->fromp(), Rand);
|
||||
if (!aRandp) return false;
|
||||
if (aRandp->seedp()) return false;
|
||||
UINFO(4, "Sel(Rand) => Rand: " << nodep << endl);
|
||||
aRandp->dtypeFrom(nodep); // I.e. the total width
|
||||
nodep->replaceWith(aRandp->unlinkFrBack());
|
||||
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
||||
return true;
|
||||
}
|
||||
int operandConcatMove(AstConcat* nodep) {
|
||||
// CONCAT under concat (See moveConcat)
|
||||
// Return value: true indicates to do it; 2 means move to LHS
|
||||
@ -3364,6 +3387,7 @@ private:
|
||||
TREEOPV("AstLogNot{$lhsp.width1, isTPure($lhsp)}", "AstNot{$lhsp}");
|
||||
// CONCAT(CONCAT({a},{b}),{c}) -> CONCAT({a},CONCAT({b},{c}))
|
||||
// CONCAT({const},CONCAT({const},{c})) -> CONCAT((constifiedCONC{const|const},{c}))
|
||||
TREEOPV("AstConcat{matchConcatRand(nodep)}", "DONE");
|
||||
TREEOPV("AstConcat{operandConcatMove(nodep)}", "moveConcat(nodep)");
|
||||
TREEOPV("AstConcat{$lhsp.isZero, $rhsp}", "replaceExtend(nodep, nodep->rhsp())");
|
||||
// CONCAT(a[1],a[0]) -> a[1:0]
|
||||
@ -3392,6 +3416,7 @@ private:
|
||||
TREEOPV("AstConcat{operandConcatSame(nodep)}", "DONE"); // {a,a}->{2{a}}, {a,2{a}}->{3{a}, etc
|
||||
// Next rule because AUTOINST puts the width of bits in
|
||||
// to pins, even when the widths are exactly the same across the hierarchy.
|
||||
TREEOPV("AstSel{matchSelRand(nodep)}", "DONE");
|
||||
TREEOPV("AstSel{operandSelExtend(nodep)}", "DONE");
|
||||
TREEOPV("AstSel{operandSelFull(nodep)}", "replaceWChild(nodep, nodep->fromp())");
|
||||
TREEOPV("AstSel{$fromp.castSel}", "replaceSelSel(nodep)");
|
||||
|
23
test_regress/t/t_sys_rand_concat.pl
Executable file
23
test_regress/t/t_sys_rand_concat.pl
Executable file
@ -0,0 +1,23 @@
|
||||
#!/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);
|
||||
|
||||
compile(
|
||||
);
|
||||
|
||||
execute(
|
||||
check_finished => 1,
|
||||
);
|
||||
|
||||
file_grep_not(glob_one("$Self->{obj_dir}/Vt_sys_rand_concat___024root__DepSet_*__0__Slow.cpp"), qr/(<<|>>)/x);
|
||||
|
||||
ok(1);
|
||||
1;
|
60
test_regress/t/t_sys_rand_concat.v
Normal file
60
test_regress/t/t_sys_rand_concat.v
Normal file
@ -0,0 +1,60 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2008 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
`define stop $stop
|
||||
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0)
|
||||
|
||||
module t;
|
||||
|
||||
`define TRIES 100
|
||||
|
||||
bit [6:0] b5a; // We use larger than [4:0] so make sure we truncate
|
||||
bit [6:0] b5b; // We use larger than [4:0] so make sure we truncate
|
||||
bit [6:0] b7c;
|
||||
bit [6:0] b7d;
|
||||
bit [59:0] b60c;
|
||||
bit [89:0] b90c;
|
||||
|
||||
bit [6:0] max_b5a;
|
||||
bit [6:0] max_b5b;
|
||||
bit [6:0] max_b7c;
|
||||
bit [6:0] max_b7d;
|
||||
bit [59:0] max_b60c;
|
||||
bit [89:0] max_b90c;
|
||||
|
||||
initial begin
|
||||
for (int i = 0; i < `TRIES; ++i) begin
|
||||
// verilator lint_off WIDTH
|
||||
// Optimize away extracts
|
||||
b5a = {$random}[4:0];
|
||||
b5b = {$random}[14:10];
|
||||
// Optimize away concats
|
||||
b7c = {$random, $random, $random, $random, $random, $random, $random};
|
||||
b7d = {{{$random}[0]}, {{$random}[0]}, {{$random}[0]}, {{$random}[0]}, {{$random}[0]}};
|
||||
b60c = {$random, $random, $random, $random, $random, $random, $random};
|
||||
b90c = {$random, $random, $random, $random, $random, $random, $random};
|
||||
// verilator lint_on WIDTH
|
||||
|
||||
max_b5a = max_b5a | b5a;
|
||||
max_b5b = max_b5b | b5b;
|
||||
max_b7c = max_b7c | b7c;
|
||||
max_b7d = max_b7d | b7d;
|
||||
max_b60c = max_b60c | b60c;
|
||||
max_b90c = max_b90c | b90c;
|
||||
end
|
||||
|
||||
`checkh(max_b5a, 7'h1f);
|
||||
`checkh(max_b5b, 7'h1f);
|
||||
`checkh(max_b7c, 7'h7f);
|
||||
`checkh(max_b7d, 7'h1f);
|
||||
`checkh(max_b60c, ~ 60'h0);
|
||||
`checkh(max_b90c, ~ 90'h0);
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule
|
Loading…
Reference in New Issue
Block a user