mirror of
https://github.com/verilator/verilator.git
synced 2026-10-06 10:03:44 +02:00
Optimize wide decoder case statements into decoder expressions (#7804)
Extend the decoder-pattern case optimization to selectors that are too
wide for a full 2^width lookup table. A decoder-pattern case (where
every case item assigns constants to a fixed set of LHSs) is lowered to
a new AstMachMasked expression. AstMachMasked is emitted as a run-time
VL_MATCHMASKEd_* function call. It contains a packed constant pool table,
'matchp', which is a list of '(mask, bits)' pairs. At runtime, the index of the
first matching entry is returned, and is used to index a value table. This single
(albeit complicated) expression can replace large if-else trees whole, resulting
in much more compact code with fewer static hard to predict branches. It
is worth about 10% speed and 30% code size in some designs.
Example:
```systemverilog
logic [39:0] sel;
always_comb
casez (sel)
40'b???????????????????????????????????????1: out = 8'h01;
40'b??????????????????????????????????????1?: out = 8'h02;
40'b?????????????????????????????????????1??: out = 8'h03;
default: out = 8'hff;
endcase
```
is compiled to:
```c++
out = TABLE_value[VL_MATCHMASKED_Q(sel, CONST_match)];
```
Where 'CONST_match' contains 4 entries, of a 40-bit mask and 40-bit bit
pattern each, and 'TABLE_value' contains 4 entries of the corresponding
8-bit results. (Entries are aligned to word boundaries to avoid runtime
bit swizzling)
This commit is contained in:
@@ -96,6 +96,11 @@ std::unique_ptr<DfgGraph> DfgGraph::clone() const {
|
||||
vtxp2clonep.emplace(&vtx, cp);
|
||||
break;
|
||||
} // LCOV_EXCL_STOP
|
||||
case VDfgType::MatchMasked: {
|
||||
DfgMatchMasked* const cp = new DfgMatchMasked{*clonep, vtx.fileline(), vtx.dtype()};
|
||||
vtxp2clonep.emplace(&vtx, cp);
|
||||
break;
|
||||
}
|
||||
case VDfgType::Sel: {
|
||||
DfgSel* const cp = new DfgSel{*clonep, vtx.fileline(), vtx.dtype()};
|
||||
cp->lsb(vtx.as<DfgSel>()->lsb());
|
||||
@@ -672,6 +677,15 @@ void DfgVertex::typeCheck(const DfgGraph& dfg) const {
|
||||
CHECK(v.dtype() == DfgDataType::select(v.srcp()->dtype(), v.lsb(), v.size()), "sel");
|
||||
return;
|
||||
}
|
||||
case VDfgType::MatchMasked: {
|
||||
const DfgMatchMasked& v = *as<DfgMatchMasked>();
|
||||
CHECK(v.isPacked(), "Should be Packed type");
|
||||
CHECK(v.size() == 32U, "Should yield a 32-bit result");
|
||||
CHECK(v.lhsp()->isPacked(), "Lhs should be packed");
|
||||
CHECK(v.matchp()->isPacked(), "Match should be Packed type");
|
||||
CHECK(v.matchp()->is<DfgVertexVar>(), "Match should be a variable");
|
||||
return;
|
||||
}
|
||||
case VDfgType::Mux: {
|
||||
const DfgMux& v = *as<DfgMux>();
|
||||
CHECK(v.isPacked(), "Should be Packed type");
|
||||
|
||||
Reference in New Issue
Block a user