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:
Geza Lore 2022-07-14 11:06:20 +01:00
parent 582da6df9a
commit ff1b9930fc
3 changed files with 45 additions and 33 deletions

View File

@ -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();

View File

@ -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

View File

@ -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");