removed aliases in V3UndrivenCapture, updated comments per feedback

This commit is contained in:
em2machine 2025-12-22 17:58:11 +01:00
parent 74c7d598cb
commit d8d46b8fce
3 changed files with 36 additions and 45 deletions

View File

@ -52,8 +52,8 @@ class UndrivenVarEntry final {
const FileLine* m_nodeFileLinep = nullptr; // File line of varref if driven, else nullptr const FileLine* m_nodeFileLinep = nullptr; // File line of varref if driven, else nullptr
bool m_underGen = false; // Under a generate bool m_underGen = false; // Under a generate
const AstNode* m_callNodep = nullptr; // call node if driven via writeSummary, else nullptr const AstNode* m_callNodep = nullptr; // Call node if driven via writeSummary, else nullptr
const FileLine* m_callFileLinep = nullptr; // file line of call node if driven via summary const FileLine* m_callFileLinep = nullptr; // File line of call node if driven via summary
enum : uint8_t { FLAG_USED = 0, FLAG_DRIVEN = 1, FLAG_DRIVEN_ALWCOMB = 2, FLAGS_PER_BIT = 3 }; enum : uint8_t { FLAG_USED = 0, FLAG_DRIVEN = 1, FLAG_DRIVEN_ALWCOMB = 2, FLAGS_PER_BIT = 3 };
@ -318,8 +318,8 @@ class UndrivenVisitor final : public VNVisitorConst {
const AstAlways* m_alwaysp = nullptr; // Current always of either type const AstAlways* m_alwaysp = nullptr; // Current always of either type
const AstAlways* m_alwaysCombp = nullptr; // Current always if combo, otherwise nullptr const AstAlways* m_alwaysCombp = nullptr; // Current always if combo, otherwise nullptr
V3UndrivenCapture* const m_capturep = nullptr; V3UndrivenCapture* const m_capturep = nullptr; // Capture object. 'nullptr' if disabled.
const bool m_enableWriteSummary = false; const bool m_enableWriteSummary = false; // Enable writeSummary computation plumbing
// METHODS // METHODS
@ -565,19 +565,15 @@ class UndrivenVisitor final : public VNVisitorConst {
// If writeSummary is enabled, task/function definitions are treated as non-executed. // If writeSummary is enabled, task/function definitions are treated as non-executed.
// Do not apply writeSummary at calls inside a task definition, or they will look like // Do not apply writeSummary at calls inside a task definition, or they will look like
// independent drivers (phantom MULTIDRIVEN). did the lambda on purpose - lessen chance of // independent drivers (phantom MULTIDRIVEN). Did the lambda on purpose - lessen chance of
// screwup in future edits. // screwup in future edits.
//const auto inExecutedContext = [this]() const {
// return !(m_taskp && !m_alwaysp && !m_inContAssign && !m_inInitialStatic &&
// !m_inBBox);
//};
const auto inExecutedContext = [this]() { const auto inExecutedContext = [this]() {
return !(m_taskp && !m_alwaysp && !m_inContAssign && !m_inInitialStatic && !m_inBBox return !(m_taskp && !m_alwaysp && !m_inContAssign && !m_inInitialStatic && !m_inBBox
&& !m_taskp->dpiExport()); && !m_taskp->dpiExport());
}; };
if (!inExecutedContext()) { return; } if (!inExecutedContext()) return;
AstNodeFTask* const calleep = nodep->taskp(); AstNodeFTask* const calleep = nodep->taskp();
if (!calleep) return; if (!calleep) return;

View File

@ -96,14 +96,12 @@ private:
bool V3UndrivenCapture::enableWriteSummary = true; bool V3UndrivenCapture::enableWriteSummary = true;
// static void V3UndrivenCapture::sortUniqueVars(std::vector<AstVar*>& vec) {
void V3UndrivenCapture::sortUniqueVars(std::vector<Var>& vec) {
std::sort(vec.begin(), vec.end()); std::sort(vec.begin(), vec.end());
vec.erase(std::unique(vec.begin(), vec.end()), vec.end()); vec.erase(std::unique(vec.begin(), vec.end()), vec.end());
} }
// static void V3UndrivenCapture::sortUniqueFTasks(std::vector<const AstNodeFTask*>& vec) {
void V3UndrivenCapture::sortUniqueFTasks(std::vector<FTask>& vec) {
std::sort(vec.begin(), vec.end()); std::sort(vec.begin(), vec.end());
vec.erase(std::unique(vec.begin(), vec.end()), vec.end()); vec.erase(std::unique(vec.begin(), vec.end()), vec.end());
} }
@ -130,19 +128,19 @@ void V3UndrivenCapture::gather(AstNetlist* netlistp) {
CaptureVisitor{*this, netlistp}; CaptureVisitor{*this, netlistp};
} }
const V3UndrivenCapture::FTaskInfo* V3UndrivenCapture::find(FTask taskp) const { const V3UndrivenCapture::FTaskInfo* V3UndrivenCapture::find(const AstNodeFTask* taskp) const {
const auto it = m_info.find(taskp); const auto it = m_info.find(taskp);
if (it == m_info.end()) return nullptr; if (it == m_info.end()) return nullptr;
return &it->second; return &it->second;
} }
const std::vector<V3UndrivenCapture::Var>& V3UndrivenCapture::writeSummary(FTask taskp) { const std::vector<AstVar*>& V3UndrivenCapture::writeSummary(const AstNodeFTask* taskp) {
// Ensure entry exists even if empty // Ensure entry exists even if empty
(void)m_info[taskp]; (void)m_info[taskp];
return computeWriteSummary(taskp); return computeWriteSummary(taskp);
} }
const std::vector<V3UndrivenCapture::Var>& V3UndrivenCapture::computeWriteSummary(FTask taskp) { const std::vector<AstVar*>& V3UndrivenCapture::computeWriteSummary(const AstNodeFTask* taskp) {
FTaskInfo& info = m_info[taskp]; FTaskInfo& info = m_info[taskp];
if (info.state == State::DONE) { if (info.state == State::DONE) {
@ -166,9 +164,9 @@ const std::vector<V3UndrivenCapture::Var>& V3UndrivenCapture::computeWriteSummar
info.writeSummary = info.directWrites; info.writeSummary = info.directWrites;
// Need callees // Need callees
for (FTask calleep : info.callees) { for (const AstNodeFTask* calleep : info.callees) {
if (m_info.find(calleep) == m_info.end()) continue; if (m_info.find(calleep) == m_info.end()) continue;
const std::vector<Var>& sub = computeWriteSummary(calleep); const std::vector<AstVar*>& sub = computeWriteSummary(calleep);
info.writeSummary.insert(info.writeSummary.end(), sub.begin(), sub.end()); info.writeSummary.insert(info.writeSummary.end(), sub.begin(), sub.end());
} }
@ -183,9 +181,9 @@ const std::vector<V3UndrivenCapture::Var>& V3UndrivenCapture::computeWriteSummar
return info.writeSummary; return info.writeSummary;
} }
void V3UndrivenCapture::noteTask(FTask taskp) { (void)m_info[taskp]; } void V3UndrivenCapture::noteTask(const AstNodeFTask* taskp) { (void)m_info[taskp]; }
void V3UndrivenCapture::noteDirectWrite(FTask taskp, Var varp) { void V3UndrivenCapture::noteDirectWrite(const AstNodeFTask* taskp, AstVar* varp) {
FTaskInfo& info = m_info[taskp]; FTaskInfo& info = m_info[taskp];
// Exclude function return variable (not an externally visible side-effect) // Exclude function return variable (not an externally visible side-effect)
@ -195,12 +193,12 @@ void V3UndrivenCapture::noteDirectWrite(FTask taskp, Var varp) {
info.directWrites.push_back(varp); info.directWrites.push_back(varp);
} }
void V3UndrivenCapture::noteCallEdge(FTask callerp, FTask calleep) { void V3UndrivenCapture::noteCallEdge(const AstNodeFTask* callerp, const AstNodeFTask* calleep) {
m_info[callerp].callees.push_back(calleep); m_info[callerp].callees.push_back(calleep);
(void)m_info[calleep]; // ensure callee entry exists (void)m_info[calleep]; // ensure callee entry exists
} }
void V3UndrivenCapture::debugDumpTask(FTask taskp, int level) const { void V3UndrivenCapture::debugDumpTask(const AstNodeFTask* taskp, int level) const {
const auto* const infop = find(taskp); const auto* const infop = find(taskp);
if (!infop) { if (!infop) {
UINFO(level, "undriven capture no entry for task " << taskp); UINFO(level, "undriven capture no entry for task " << taskp);

View File

@ -28,9 +28,6 @@ class AstNetlist;
class V3UndrivenCapture final { class V3UndrivenCapture final {
public: public:
using FTask = const AstNodeFTask*;
using Var = AstVar*;
// DFS computation state for writeSummary propagation. // DFS computation state for writeSummary propagation.
// UNVISITED: write summary not computed yet // UNVISITED: write summary not computed yet
// VISITING: currently computing on the call stack - used to detect cycles // VISITING: currently computing on the call stack - used to detect cycles
@ -39,13 +36,13 @@ public:
struct FTaskInfo final { struct FTaskInfo final {
// Variables written directly in this task/function body. // Variables written directly in this task/function body.
std::vector<Var> directWrites; std::vector<AstVar*> directWrites;
// Direct resolved callees from this task/function body. // Direct resolved callees from this task/function body.
std::vector<FTask> callees; std::vector<const AstNodeFTask*> callees;
// 'write through write' writeSummary for the given task/function. Meaning ultimately // 'Write through write' writeSummary for the given task/function. Meaning ultimately
// everything that this function/task writes to. // everything that this function/task writes to.
std::vector<Var> writeSummary; std::vector<AstVar*> writeSummary;
// state for writeSummary computation. // State for writeSummary computation.
State state = State::UNVISITED; State state = State::UNVISITED;
}; };
@ -58,21 +55,21 @@ private:
// task). This is our 'graph' of tasks/functions. Each node has a list of direct callees and // task). This is our 'graph' of tasks/functions. Each node has a list of direct callees and
// a list of variables written in the function body. There are methods to remove duplicates // a list of variables written in the function body. There are methods to remove duplicates
// otherwise this could explode. // otherwise this could explode.
std::unordered_map<FTask, FTaskInfo> m_info; std::unordered_map<const AstNodeFTask*, FTaskInfo> m_info;
// Sort and remove duplicates from a vector of variables. This is called after a task/function // Sort and remove duplicates from a vector of variables. This is called after a task/function
// write summary is computed. writeSummary can accumulate duplicates if a variable is written // write summary is computed. writeSummary can accumulate duplicates if a variable is written
// in multiple tasks/functions. // in multiple tasks/functions.
static void sortUniqueVars(std::vector<Var>& vec); static void sortUniqueVars(std::vector<AstVar*>& vec);
// Sort and remove duplicates from a vector of callees. The visitor can record the same callee // Sort and remove duplicates from a vector of callees. The visitor can record the same callee
// multiple times (multiple call sites, branches, etc). // multiple times (multiple call sites, branches, etc).
static void sortUniqueFTasks(std::vector<FTask>& vec); static void sortUniqueFTasks(std::vector<const AstNodeFTask*>& vec);
// Collect direct writes and call edges for all tasks/functions. Run one time when // Collect direct writes and call edges for all tasks/functions. Run one time when
// UndrivenCapture is created. This runs the visitor over the tree. // UndrivenCapture is created. This runs the visitor over the tree.
void gather(AstNetlist* netlistp); void gather(AstNetlist* netlistp);
// Compute (and cache) 'write through write' writeSummary for the given task/function. // Compute (and cache) 'write through write' writeSummary for the given task/function.
const std::vector<Var>& computeWriteSummary(FTask taskp); const std::vector<AstVar*>& computeWriteSummary(const AstNodeFTask* taskp);
public: public:
// Build capture database and precompute writeSummary for all discovered tasks/functions. // Build capture database and precompute writeSummary for all discovered tasks/functions.
@ -80,26 +77,26 @@ public:
// Lookup task/function capture info (nullptr if unknown). This is currently only used for the // Lookup task/function capture info (nullptr if unknown). This is currently only used for the
// debug helper. // debug helper.
const FTaskInfo* find(FTask taskp) const; const FTaskInfo* find(const AstNodeFTask* taskp) const;
// Get write through write through write, etc (call chain) writeSummary for a task/function // Get write through write through write, etc (call chain) writeSummary for a task/function
// (creates empty entry if needed). This returns a vector of variables that a particular // (creates empty entry if needed). This returns a vector of variables that a particular
// task/function writes to, including all variables written by functions called by this // task/function writes to, including all variables written by functions called by this
// task/function, and so on. // task/function, and so on.
const std::vector<Var>& writeSummary(FTask taskp); const std::vector<AstVar*>& writeSummary(const AstNodeFTask* taskp);
// used by the capture visitor to record information about tasks/functions and their statements // Used by the capture visitor to record information about tasks/functions and their statements
// and callees. noteTask() makes sure there is an entry for the given taskp. // and callees. noteTask() makes sure there is an entry for the given taskp.
void noteTask(FTask taskp); void noteTask(const AstNodeFTask* taskp);
// inside the body of taskp there is a write to variable varp // Inside the body of taskp there is a write to variable varp
void noteDirectWrite(FTask taskp, Var varp); void noteDirectWrite(const AstNodeFTask* taskp, AstVar* varp);
// inside the body of callerp there is a call to calleep, this is needed so we can create a // Inside the body of callerp there is a call to calleep, this is needed so we can create a
// summary that includes all variables written by functions called by this task/function, and // summary that includes all variables written by functions called by this task/function, and
// so on. // so on.
void noteCallEdge(FTask callerp, FTask calleep); void noteCallEdge(const AstNodeFTask* callerp, const AstNodeFTask* calleep);
// dump one task's summary for debugging. leaving this in, in case need to debug future // Dump one task's summary for debugging. leaving this in, in case need to debug future
// functionality. // functionality.
void debugDumpTask(FTask taskp, int level = 9) const; void debugDumpTask(const AstNodeFTask* taskp, int level = 9) const;
}; };
#endif // VERILATOR_V3UNDRIVENCAPTURE_H_ #endif // VERILATOR_V3UNDRIVENCAPTURE_H_