From ef2776034eca1f6c41743c56b80764200bd89d5c Mon Sep 17 00:00:00 2001 From: Geza Lore Date: Thu, 27 Oct 2022 16:47:42 +0100 Subject: [PATCH] Adjust instruction count estimates for AstCMethodHard The cost of an AstCMethodHard right now is generally unknown. However, VlTriggerVec::at is used a lot in conditions, so we make an effort to estimate this correctly via 2 changes: - In general when an AstVarRef appears as the target of an AstCMethodHard, we cost it as a simple address computation (an add) - Check for VlTriggerVec::at explicitly when costing AstCMethodHard, which is essentially a load. This can have a significant effect when there are a lot of unique triggers in the design. --- src/V3AstNodeMath.h | 4 +--- src/V3AstNodeOther.h | 1 + src/V3AstNodes.cpp | 20 ++++++++++++++++++++ 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/V3AstNodeMath.h b/src/V3AstNodeMath.h index 398e57832..ef635a14a 100644 --- a/src/V3AstNodeMath.h +++ b/src/V3AstNodeMath.h @@ -4265,9 +4265,7 @@ public: bool same(const AstNode* samep) const override; inline bool same(const AstVarRef* samep) const; inline bool sameNoLvalue(AstVarRef* samep) const; - int instrCount() const override { - return widthInstrs() * (access().isReadOrRW() ? INSTR_COUNT_LD : 1); - } + int instrCount() const override; string emitVerilog() override { V3ERROR_NA_RETURN(""); } string emitC() override { V3ERROR_NA_RETURN(""); } bool cleanOut() const override { return true; } diff --git a/src/V3AstNodeOther.h b/src/V3AstNodeOther.h index 3e2fd6430..a0b3e991f 100644 --- a/src/V3AstNodeOther.h +++ b/src/V3AstNodeOther.h @@ -2851,6 +2851,7 @@ public: statement(true); dtypeSetVoid(); } + int instrCount() const override; }; class AstCReset final : public AstNodeStmt { // Reset variable at startup diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index 92e0b2fce..3487e1814 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -2047,6 +2047,14 @@ void AstVarRef::dump(std::ostream& str) const { bool AstVarRef::same(const AstNode* samep) const { return same(static_cast(samep)); } +int AstVarRef::instrCount() const { + // Account for the target of hard-coded method calls as just an address computation + if (const AstCMethodHard* const callp = VN_CAST(backp(), CMethodHard)) { + if (callp->fromp() == this) return 1; + } + // Otherwise as a load/store + return widthInstrs() * (access().isReadOrRW() ? INSTR_COUNT_LD : 1); +} void AstVar::dump(std::ostream& str) const { this->AstNode::dump(str); if (isSc()) str << " [SC]"; @@ -2247,6 +2255,18 @@ void AstCAwait::dump(std::ostream& str) const { sensesp()->dump(str); } } +int AstCMethodHard::instrCount() const { + if (AstBasicDType* const basicp = fromp()->dtypep()->basicp()) { + // TODO: add a more structured description of library methods, rather than using string + // matching. See #3715. + if (basicp->isTriggerVec() && m_name == "at") { + // This is an important special case for scheduling so we compute it precisely, + // it is simply a load. + return INSTR_COUNT_LD; + } + } + return AstNodeStmt::instrCount(); +} const char* AstCFunc::broken() const { BROKEN_RTN((m_scopep && !m_scopep->brokeExists())); return nullptr;