Handle multiple external domains in V3Order
Make the external domains provider of ordering populate an output vector, which then allows us to add multiple external sensitivities to combinational logic.
This commit is contained in:
parent
582da6df9a
commit
ff1b9930fc
|
|
@ -895,10 +895,10 @@ class OrderProcess final : VNDeleter {
|
||||||
// Map from Trigger reference AstSenItem to the original AstSenTree
|
// Map from Trigger reference AstSenItem to the original AstSenTree
|
||||||
const std::unordered_map<const AstSenItem*, const AstSenTree*>& m_trigToSen;
|
const std::unordered_map<const AstSenItem*, const AstSenTree*>& m_trigToSen;
|
||||||
|
|
||||||
// This is a function provided by the invoker of the ordering that can and provide additional
|
// This is a function provided by the invoker of the ordering that can provide additional
|
||||||
// sensitivity expression that when triggered indicates the passed AstVarScope might have
|
// sensitivity expression that when triggered indicates the passed AstVarScope might have
|
||||||
// changed external to the code being ordered.
|
// changed external to the code being ordered.
|
||||||
const std::function<AstSenTree*(const AstVarScope*)> m_externalDomain;
|
const V3Order::ExternalDomainsProvider m_externalDomains;
|
||||||
|
|
||||||
SenTreeFinder m_finder; // Global AstSenTree manager
|
SenTreeFinder m_finder; // Global AstSenTree manager
|
||||||
AstSenTree* const m_deleteDomainp; // Dummy AstSenTree indicating needs deletion
|
AstSenTree* const m_deleteDomainp; // Dummy AstSenTree indicating needs deletion
|
||||||
|
|
@ -957,6 +957,8 @@ class OrderProcess final : VNDeleter {
|
||||||
|
|
||||||
// Make a domain that merges the two domains
|
// Make a domain that merges the two domains
|
||||||
AstSenTree* combineDomains(AstSenTree* ap, AstSenTree* bp) {
|
AstSenTree* combineDomains(AstSenTree* ap, AstSenTree* bp) {
|
||||||
|
if (ap == m_deleteDomainp) return bp;
|
||||||
|
UASSERT_OBJ(bp != m_deleteDomainp, bp, "Should not be delete domain");
|
||||||
AstSenTree* const senTreep = ap->cloneTree(false);
|
AstSenTree* const senTreep = ap->cloneTree(false);
|
||||||
senTreep->addSensesp(bp->sensesp()->cloneTree(true));
|
senTreep->addSensesp(bp->sensesp()->cloneTree(true));
|
||||||
V3Const::constifyExpensiveEdit(senTreep); // Remove duplicates
|
V3Const::constifyExpensiveEdit(senTreep); // Remove duplicates
|
||||||
|
|
@ -974,11 +976,10 @@ class OrderProcess final : VNDeleter {
|
||||||
// CONSTRUCTOR
|
// CONSTRUCTOR
|
||||||
OrderProcess(AstNetlist* netlistp, OrderGraph& graph,
|
OrderProcess(AstNetlist* netlistp, OrderGraph& graph,
|
||||||
const std::unordered_map<const AstSenItem*, const AstSenTree*>& trigToSen,
|
const std::unordered_map<const AstSenItem*, const AstSenTree*>& trigToSen,
|
||||||
const string& tag, bool slow,
|
const string& tag, bool slow, V3Order::ExternalDomainsProvider externalDomains)
|
||||||
std::function<AstSenTree*(const AstVarScope*)> externalDomain)
|
|
||||||
: m_graph{graph}
|
: m_graph{graph}
|
||||||
, m_trigToSen{trigToSen}
|
, m_trigToSen{trigToSen}
|
||||||
, m_externalDomain{externalDomain}
|
, m_externalDomains{externalDomains}
|
||||||
, m_finder{netlistp}
|
, m_finder{netlistp}
|
||||||
, m_deleteDomainp{makeDeleteDomainSenTree(netlistp->fileline())}
|
, m_deleteDomainp{makeDeleteDomainSenTree(netlistp->fileline())}
|
||||||
, m_tag{tag}
|
, m_tag{tag}
|
||||||
|
|
@ -994,8 +995,8 @@ public:
|
||||||
main(AstNetlist* netlistp, OrderGraph& graph,
|
main(AstNetlist* netlistp, OrderGraph& graph,
|
||||||
const std::unordered_map<const AstSenItem*, const AstSenTree*>& trigToSen,
|
const std::unordered_map<const AstSenItem*, const AstSenTree*>& trigToSen,
|
||||||
const string& tag, bool parallel, bool slow,
|
const string& tag, bool parallel, bool slow,
|
||||||
std::function<AstSenTree*(const AstVarScope*)> externalDomain) {
|
V3Order::ExternalDomainsProvider externalDomains) {
|
||||||
OrderProcess visitor{netlistp, graph, trigToSen, tag, slow, externalDomain};
|
OrderProcess visitor{netlistp, graph, trigToSen, tag, slow, externalDomains};
|
||||||
visitor.process(parallel);
|
visitor.process(parallel);
|
||||||
return std::move(visitor.m_result);
|
return std::move(visitor.m_result);
|
||||||
}
|
}
|
||||||
|
|
@ -1046,6 +1047,9 @@ void OrderProcess::processDomainsIterate(OrderEitherVertex* vertexp) {
|
||||||
if (OrderLogicVertex* const lvtxp = dynamic_cast<OrderLogicVertex*>(vertexp)) {
|
if (OrderLogicVertex* const lvtxp = dynamic_cast<OrderLogicVertex*>(vertexp)) {
|
||||||
domainp = lvtxp->hybridp();
|
domainp = lvtxp->hybridp();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<AstSenTree*> externalDomainps;
|
||||||
|
|
||||||
for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep = edgep->inNextp()) {
|
for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep = edgep->inNextp()) {
|
||||||
OrderEitherVertex* const fromVertexp = static_cast<OrderEitherVertex*>(edgep->fromp());
|
OrderEitherVertex* const fromVertexp = static_cast<OrderEitherVertex*>(edgep->fromp());
|
||||||
if (edgep->weight() && fromVertexp->domainMatters()) {
|
if (edgep->weight() && fromVertexp->domainMatters()) {
|
||||||
|
|
@ -1054,12 +1058,13 @@ void OrderProcess::processDomainsIterate(OrderEitherVertex* vertexp) {
|
||||||
|
|
||||||
if (OrderVarVertex* const varVtxp = dynamic_cast<OrderVarVertex*>(fromVertexp)) {
|
if (OrderVarVertex* const varVtxp = dynamic_cast<OrderVarVertex*>(fromVertexp)) {
|
||||||
AstVarScope* const vscp = varVtxp->vscp();
|
AstVarScope* const vscp = varVtxp->vscp();
|
||||||
if (AstSenTree* const externalDomainp = m_externalDomain(vscp)) {
|
// Add in any external domains
|
||||||
UASSERT(!externalDomainp->hasCombo(),
|
externalDomainps.clear();
|
||||||
"There should be no need for combinational domains");
|
m_externalDomains(vscp, externalDomainps);
|
||||||
fromDomainp = fromDomainp == m_deleteDomainp
|
for (AstSenTree* const externalDomainp : externalDomainps) {
|
||||||
? externalDomainp
|
UASSERT_OBJ(!externalDomainp->hasCombo(), vscp,
|
||||||
: combineDomains(fromDomainp, externalDomainp);
|
"There should be no need for combinational domains");
|
||||||
|
fromDomainp = combineDomains(fromDomainp, externalDomainp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1538,12 +1543,12 @@ AstCFunc* order(AstNetlist* netlistp, //
|
||||||
const string& tag, //
|
const string& tag, //
|
||||||
bool parallel, //
|
bool parallel, //
|
||||||
bool slow, //
|
bool slow, //
|
||||||
std::function<AstSenTree*(const AstVarScope*)> externalDomain) {
|
ExternalDomainsProvider externalDomains) {
|
||||||
// Order the code
|
// Order the code
|
||||||
const std::unique_ptr<OrderGraph> graph
|
const std::unique_ptr<OrderGraph> graph
|
||||||
= OrderBuildVisitor::process(netlistp, logic, trigToSen);
|
= OrderBuildVisitor::process(netlistp, logic, trigToSen);
|
||||||
const auto& nodeps = OrderProcess::main(netlistp, *graph.get(), trigToSen, tag, parallel, slow,
|
const auto& nodeps = OrderProcess::main(netlistp, *graph.get(), trigToSen, tag, parallel, slow,
|
||||||
externalDomain);
|
externalDomains);
|
||||||
|
|
||||||
// Create the result function
|
// Create the result function
|
||||||
AstScope* const scopeTopp = netlistp->topScopep()->scopep();
|
AstScope* const scopeTopp = netlistp->topScopep()->scopep();
|
||||||
|
|
|
||||||
|
|
@ -38,13 +38,17 @@ struct LogicByScope;
|
||||||
|
|
||||||
namespace V3Order {
|
namespace V3Order {
|
||||||
|
|
||||||
AstCFunc* order(AstNetlist* netlistp, //
|
using ExternalDomainsProvider = std::function<void(const AstVarScope*, std::vector<AstSenTree*>&)>;
|
||||||
const std::vector<V3Sched::LogicByScope*>& logic, //
|
|
||||||
const std::unordered_map<const AstSenItem*, const AstSenTree*>& trigToSen,
|
AstCFunc* order(
|
||||||
const string& tag, //
|
AstNetlist* netlistp, //
|
||||||
bool parallel, //
|
const std::vector<V3Sched::LogicByScope*>& logic, //
|
||||||
bool slow, //
|
const std::unordered_map<const AstSenItem*, const AstSenTree*>& trigToSen,
|
||||||
std::function<AstSenTree*(const AstVarScope*)> externalDomain);
|
const string& tag, //
|
||||||
|
bool parallel, //
|
||||||
|
bool slow, //
|
||||||
|
ExternalDomainsProvider externalDomains
|
||||||
|
= [](const AstVarScope*, std::vector<AstSenTree*>&) {});
|
||||||
|
|
||||||
}; // namespace V3Order
|
}; // namespace V3Order
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -699,9 +699,9 @@ void createSettle(AstNetlist* netlistp, SenExprBuilder& senExprBulider,
|
||||||
AstSenTree* const inputChanged = trig.createTriggerSenTree(netlistp, firstIterationTrigger);
|
AstSenTree* const inputChanged = trig.createTriggerSenTree(netlistp, firstIterationTrigger);
|
||||||
|
|
||||||
// Create and the body function
|
// Create and the body function
|
||||||
AstCFunc* const stlFuncp
|
AstCFunc* const stlFuncp = V3Order::order(
|
||||||
= V3Order::order(netlistp, {&comb, &hybrid}, trigToSen, "stl", false, true,
|
netlistp, {&comb, &hybrid}, trigToSen, "stl", false, true,
|
||||||
[=](const AstVarScope*) { return inputChanged; });
|
[=](const AstVarScope*, std::vector<AstSenTree*>& out) { out.push_back(inputChanged); });
|
||||||
splitCheck(stlFuncp);
|
splitCheck(stlFuncp);
|
||||||
|
|
||||||
// Create the eval loop
|
// Create the eval loop
|
||||||
|
|
@ -763,10 +763,13 @@ AstNode* createInputCombLoop(AstNetlist* netlistp, SenExprBuilder& senExprBuilde
|
||||||
AstSenTree* const inputChanged = trig.createTriggerSenTree(netlistp, firstIterationTrigger);
|
AstSenTree* const inputChanged = trig.createTriggerSenTree(netlistp, firstIterationTrigger);
|
||||||
|
|
||||||
// Create and Order the body function
|
// Create and Order the body function
|
||||||
AstCFunc* const icoFuncp = V3Order::order(
|
AstCFunc* const icoFuncp
|
||||||
netlistp, {&logic}, trigToSen, "ico", false, false, [=](const AstVarScope* vscp) {
|
= V3Order::order(netlistp, {&logic}, trigToSen, "ico", false, false,
|
||||||
return vscp->scopep()->isTop() && vscp->varp()->isNonOutput() ? inputChanged : nullptr;
|
[=](const AstVarScope* vscp, std::vector<AstSenTree*>& out) {
|
||||||
});
|
if (vscp->scopep()->isTop() && vscp->varp()->isNonOutput()) {
|
||||||
|
out.push_back(inputChanged);
|
||||||
|
}
|
||||||
|
});
|
||||||
splitCheck(icoFuncp);
|
splitCheck(icoFuncp);
|
||||||
|
|
||||||
// Create the eval loop
|
// Create the eval loop
|
||||||
|
|
@ -1016,7 +1019,7 @@ void schedule(AstNetlist* netlistp) {
|
||||||
|
|
||||||
AstCFunc* const actFuncp = V3Order::order(
|
AstCFunc* const actFuncp = V3Order::order(
|
||||||
netlistp, {&logicRegions.m_pre, &logicRegions.m_act, &logicReplicas.m_act}, trigToSenAct,
|
netlistp, {&logicRegions.m_pre, &logicRegions.m_act, &logicReplicas.m_act}, trigToSenAct,
|
||||||
"act", false, false, [](const AstVarScope*) { return nullptr; });
|
"act", false, false);
|
||||||
splitCheck(actFuncp);
|
splitCheck(actFuncp);
|
||||||
if (v3Global.opt.stats()) V3Stats::statsStage("sched-create-act");
|
if (v3Global.opt.stats()) V3Stats::statsStage("sched-create-act");
|
||||||
|
|
||||||
|
|
@ -1030,9 +1033,9 @@ void schedule(AstNetlist* netlistp) {
|
||||||
std::unordered_map<const AstSenItem*, const AstSenTree*> trigToSenNba;
|
std::unordered_map<const AstSenItem*, const AstSenTree*> trigToSenNba;
|
||||||
invertAndMergeSenTreeMap(trigToSenNba, nbaTrigMap);
|
invertAndMergeSenTreeMap(trigToSenNba, nbaTrigMap);
|
||||||
|
|
||||||
AstCFunc* const nbaFuncp = V3Order::order(
|
AstCFunc* const nbaFuncp
|
||||||
netlistp, {&logicRegions.m_nba, &logicReplicas.m_nba}, trigToSenNba, "nba",
|
= V3Order::order(netlistp, {&logicRegions.m_nba, &logicReplicas.m_nba}, trigToSenNba,
|
||||||
v3Global.opt.mtasks(), false, [](const AstVarScope*) { return nullptr; });
|
"nba", v3Global.opt.mtasks(), false);
|
||||||
splitCheck(nbaFuncp);
|
splitCheck(nbaFuncp);
|
||||||
netlistp->evalNbap(nbaFuncp); // Remember for V3LifePost
|
netlistp->evalNbap(nbaFuncp); // Remember for V3LifePost
|
||||||
if (v3Global.opt.stats()) V3Stats::statsStage("sched-create-nba");
|
if (v3Global.opt.stats()) V3Stats::statsStage("sched-create-nba");
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue