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.
This commit is contained in:
parent
5c658f8cd5
commit
ef2776034e
|
|
@ -4265,9 +4265,7 @@ public:
|
||||||
bool same(const AstNode* samep) const override;
|
bool same(const AstNode* samep) const override;
|
||||||
inline bool same(const AstVarRef* samep) const;
|
inline bool same(const AstVarRef* samep) const;
|
||||||
inline bool sameNoLvalue(AstVarRef* samep) const;
|
inline bool sameNoLvalue(AstVarRef* samep) const;
|
||||||
int instrCount() const override {
|
int instrCount() const override;
|
||||||
return widthInstrs() * (access().isReadOrRW() ? INSTR_COUNT_LD : 1);
|
|
||||||
}
|
|
||||||
string emitVerilog() override { V3ERROR_NA_RETURN(""); }
|
string emitVerilog() override { V3ERROR_NA_RETURN(""); }
|
||||||
string emitC() override { V3ERROR_NA_RETURN(""); }
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
||||||
bool cleanOut() const override { return true; }
|
bool cleanOut() const override { return true; }
|
||||||
|
|
|
||||||
|
|
@ -2851,6 +2851,7 @@ public:
|
||||||
statement(true);
|
statement(true);
|
||||||
dtypeSetVoid();
|
dtypeSetVoid();
|
||||||
}
|
}
|
||||||
|
int instrCount() const override;
|
||||||
};
|
};
|
||||||
class AstCReset final : public AstNodeStmt {
|
class AstCReset final : public AstNodeStmt {
|
||||||
// Reset variable at startup
|
// Reset variable at startup
|
||||||
|
|
|
||||||
|
|
@ -2047,6 +2047,14 @@ void AstVarRef::dump(std::ostream& str) const {
|
||||||
bool AstVarRef::same(const AstNode* samep) const {
|
bool AstVarRef::same(const AstNode* samep) const {
|
||||||
return same(static_cast<const AstVarRef*>(samep));
|
return same(static_cast<const AstVarRef*>(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 {
|
void AstVar::dump(std::ostream& str) const {
|
||||||
this->AstNode::dump(str);
|
this->AstNode::dump(str);
|
||||||
if (isSc()) str << " [SC]";
|
if (isSc()) str << " [SC]";
|
||||||
|
|
@ -2247,6 +2255,18 @@ void AstCAwait::dump(std::ostream& str) const {
|
||||||
sensesp()->dump(str);
|
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 {
|
const char* AstCFunc::broken() const {
|
||||||
BROKEN_RTN((m_scopep && !m_scopep->brokeExists()));
|
BROKEN_RTN((m_scopep && !m_scopep->brokeExists()));
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue