mirror of
https://github.com/verilator/verilator.git
synced 2026-09-03 08:24:31 +02:00
AstMTaskBody is somewhat redundant and is problematic for #6280. We used to wrap all MTasks in a CFunc before emit anyway. Now we create that CFunc when we create the ExecMTask in V3OrderParallel, and subsequently use the CFunc to represent the contents of the MTask. Final output and optimizations are the same, but internals are simplified to move towards #6280. No functional change.
This commit is contained in:
+15
-15
@@ -1763,7 +1763,7 @@ class DpiThreadsVisitor final : public VNVisitorConst {
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit DpiThreadsVisitor(AstMTaskBody* nodep) { iterateConst(nodep); }
|
||||
explicit DpiThreadsVisitor(AstCFunc* nodep) { iterateConst(nodep); }
|
||||
int threads() const { return m_threads; }
|
||||
~DpiThreadsVisitor() override = default;
|
||||
|
||||
@@ -2431,8 +2431,9 @@ AstNodeStmt* V3Order::createParallel(OrderGraph& orderGraph, OrderMoveGraph& mov
|
||||
if (dumpGraphLevel() >= 9) moveGraph.dumpDotFilePrefixed(tag + "_ordermv_pruned");
|
||||
|
||||
// Create the AstExecGraph node which represents the execution of the MTask graph.
|
||||
FileLine* const rootFlp = v3Global.rootp()->fileline();
|
||||
AstExecGraph* const execGraphp = new AstExecGraph{rootFlp, tag};
|
||||
FileLine* const flp = v3Global.rootp()->fileline();
|
||||
AstScope* const scopep = v3Global.rootp()->topScopep()->scopep();
|
||||
AstExecGraph* const execGraphp = new AstExecGraph{flp, tag};
|
||||
V3Graph* const depGraphp = execGraphp->depGraphp();
|
||||
|
||||
// Translate the LogicMTask graph into the corresponding ExecMTask graph,
|
||||
@@ -2468,24 +2469,23 @@ AstNodeStmt* V3Order::createParallel(OrderGraph& orderGraph, OrderMoveGraph& mov
|
||||
VL_DO_DANGLING(mVtxp->unlinkDelete(&moveGraph), mVtxp);
|
||||
}
|
||||
|
||||
// We have 2 objects, because AstMTaskBody is an AstNode, and ExecMTask is a GraphVertex.
|
||||
// To combine them would involve multiple inheritance.
|
||||
|
||||
// Construct the actual MTaskBody
|
||||
AstMTaskBody* const bodyp = new AstMTaskBody{rootFlp};
|
||||
execGraphp->addMTaskBodiesp(bodyp);
|
||||
bodyp->addStmtsp(emitter.getStmts());
|
||||
UASSERT_OBJ(bodyp->stmtsp(), bodyp, "Should not try to create empty MTask");
|
||||
|
||||
// Create the ExecMTask
|
||||
ExecMTask* const execMTaskp = new ExecMTask{depGraphp, bodyp};
|
||||
if (!v3Global.opt.hierBlocks().empty())
|
||||
execMTaskp->threads(DpiThreadsVisitor{bodyp}.threads());
|
||||
ExecMTask* const execMTaskp = new ExecMTask{execGraphp, scopep, emitter.getStmts()};
|
||||
if (!v3Global.opt.hierBlocks().empty()) {
|
||||
execMTaskp->threads(DpiThreadsVisitor{execMTaskp->funcp()}.threads());
|
||||
}
|
||||
const bool newEntry = logicMTaskToExecMTask.emplace(mTaskp, execMTaskp).second;
|
||||
UASSERT_OBJ(newEntry, mTaskp, "LogicMTasks should be processed in dependencyorder");
|
||||
UINFO(3, "Final '" << tag << "' LogicMTask " << mTaskp->id() << " maps to ExecMTask"
|
||||
<< execMTaskp->id());
|
||||
|
||||
// For code analysis purposes, we can pretend the AstExecGraph runs the
|
||||
// MTasks sequentially, in some topological order that respects edges.
|
||||
// The order they are created here happens to be just such an order.
|
||||
AstCCall* const callp = new AstCCall{flp, execMTaskp->funcp()};
|
||||
callp->dtypeSetVoid();
|
||||
execGraphp->addStmtsp(callp->makeStmt());
|
||||
|
||||
// Add the dependency edges between ExecMTasks
|
||||
for (const V3GraphEdge& edge : mTaskp->inEdges()) {
|
||||
const V3GraphVertex* fromVxp = edge.fromp();
|
||||
|
||||
Reference in New Issue
Block a user