Optimize NFA delay-ring edge traversal, drop complexity to linear (#8145)
Signed-off-by: Artur Bieniek <abieniek@antmicro.com>
This commit is contained in:
parent
70b5ce802b
commit
8c2b7410f0
|
|
@ -33,6 +33,7 @@
|
||||||
#include "V3Assert.h"
|
#include "V3Assert.h"
|
||||||
#include "V3Const.h"
|
#include "V3Const.h"
|
||||||
#include "V3Graph.h"
|
#include "V3Graph.h"
|
||||||
|
#include "V3Stats.h"
|
||||||
#include "V3Task.h"
|
#include "V3Task.h"
|
||||||
#include "V3UniqueNames.h"
|
#include "V3UniqueNames.h"
|
||||||
|
|
||||||
|
|
@ -1706,6 +1707,7 @@ class SvaNfaLowering final {
|
||||||
AstNodeModule* const m_modp; // Module to add state vars and always blocks to
|
AstNodeModule* const m_modp; // Module to add state vars and always blocks to
|
||||||
AstNodeDType* const m_u32DTypep; // Shared unsigned counter dtype
|
AstNodeDType* const m_u32DTypep; // Shared unsigned counter dtype
|
||||||
V3UniqueNames m_names{"__Vnfa"};
|
V3UniqueNames m_names{"__Vnfa"};
|
||||||
|
size_t m_statDelayRingEdgeVisits = 0; // Delay-ring incoming edges visited
|
||||||
|
|
||||||
// Per-lowering shared context (passed to phase sub-functions)
|
// Per-lowering shared context (passed to phase sub-functions)
|
||||||
// Per-vertex lowering state is stored in SvaVertexData and accessed via
|
// Per-vertex lowering state is stored in SvaVertexData and accessed via
|
||||||
|
|
@ -1883,15 +1885,16 @@ class SvaNfaLowering final {
|
||||||
const uint32_t size = static_cast<uint32_t>(vtxp->m_delayRingSize);
|
const uint32_t size = static_cast<uint32_t>(vtxp->m_delayRingSize);
|
||||||
|
|
||||||
AstNodeExpr* incomingp = nullptr;
|
AstNodeExpr* incomingp = nullptr;
|
||||||
for (const SvaTransEdge* const tedgep : c.edges) {
|
for (const V3GraphEdge& edger : vtxp->inEdges()) {
|
||||||
if (static_cast<int>(tedgep->toVtxp()->color()) != ri) continue;
|
++m_statDelayRingEdgeVisits;
|
||||||
UASSERT_OBJ(tedgep->m_consumesCycle == vtxp->m_isFixedDelayRing, vtxp,
|
const SvaTransEdge& tedger = static_cast<const SvaTransEdge&>(edger);
|
||||||
|
UASSERT_OBJ(tedger.m_consumesCycle == vtxp->m_isFixedDelayRing, vtxp,
|
||||||
"Delay-ring incoming edge kind mismatch");
|
"Delay-ring incoming edge kind mismatch");
|
||||||
const int fi = tedgep->fromVtxp()->color();
|
const int fi = tedger.fromVtxp()->color();
|
||||||
UASSERT_OBJ(c.vtx[fi]->datap()->stateSigp, c.vtx[fi],
|
UASSERT_OBJ(c.vtx[fi]->datap()->stateSigp, c.vtx[fi],
|
||||||
"Delay-ring incoming source missing stateSig");
|
"Delay-ring incoming source missing stateSig");
|
||||||
AstNodeExpr* contribp = c.vtx[fi]->datap()->stateSigp->cloneTreePure(false);
|
AstNodeExpr* contribp = c.vtx[fi]->datap()->stateSigp->cloneTreePure(false);
|
||||||
contribp = andCond(c.flp, contribp, tedgep->m_condp);
|
contribp = andCond(c.flp, contribp, tedger.m_condp);
|
||||||
if (c.disableExprp) {
|
if (c.disableExprp) {
|
||||||
AstNodeExpr* const notDisp
|
AstNodeExpr* const notDisp
|
||||||
= new AstLogNot{c.flp, c.disableExprp->cloneTreePure(false)};
|
= new AstLogNot{c.flp, c.disableExprp->cloneTreePure(false)};
|
||||||
|
|
@ -2409,6 +2412,9 @@ public:
|
||||||
explicit SvaNfaLowering(AstNodeModule* modp)
|
explicit SvaNfaLowering(AstNodeModule* modp)
|
||||||
: m_modp{modp}
|
: m_modp{modp}
|
||||||
, m_u32DTypep{modp->findBasicDType(VBasicDTypeKwd::UINT32)} {}
|
, m_u32DTypep{modp->findBasicDType(VBasicDTypeKwd::UINT32)} {}
|
||||||
|
~SvaNfaLowering() {
|
||||||
|
V3Stats::addStatSum("Assertions, NFA delay ring edge visits", m_statDelayRingEdgeVisits);
|
||||||
|
}
|
||||||
|
|
||||||
// Lower NFA graph to synthesizable AstAlways blocks and raw result signals.
|
// Lower NFA graph to synthesizable AstAlways blocks and raw result signals.
|
||||||
// Links are combinational; Edges are registered (NBA).
|
// Links are combinational; Edges are registered (NBA).
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# 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-FileCopyrightText: 2026 Wilson Snyder
|
||||||
|
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
|
||||||
|
import vltest_bootstrap
|
||||||
|
|
||||||
|
test.scenarios('vlt')
|
||||||
|
|
||||||
|
test.lint(verilator_flags2=['--stats'])
|
||||||
|
|
||||||
|
test.file_grep(test.stats, r'Assertions, NFA delay ring edge visits\s+(\d+)', 15)
|
||||||
|
|
||||||
|
test.passes()
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain.
|
||||||
|
// SPDX-FileCopyrightText: 2026 Antmicro
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
`define S0 a
|
||||||
|
`define S1 (`S0 ##2 `S0)
|
||||||
|
`define S2 (`S1 ##2 `S1)
|
||||||
|
`define S3 (`S2 ##2 `S2)
|
||||||
|
`define S4 (`S3 ##2 `S3)
|
||||||
|
|
||||||
|
module t (
|
||||||
|
input clk,
|
||||||
|
input a
|
||||||
|
);
|
||||||
|
assert property (@(posedge clk) `S4);
|
||||||
|
endmodule
|
||||||
Loading…
Reference in New Issue