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
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
// 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
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
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);
senTreep->addSensesp(bp->sensesp()->cloneTree(true));
V3Const::constifyExpensiveEdit(senTreep); // Remove duplicates
@ -974,11 +976,10 @@ class OrderProcess final : VNDeleter {
// CONSTRUCTOR
OrderProcess(AstNetlist* netlistp, OrderGraph& graph,
const std::unordered_map<const AstSenItem*, const AstSenTree*>& trigToSen,
const string& tag, bool slow,
std::function<AstSenTree*(const AstVarScope*)> externalDomain)
const string& tag, bool slow, V3Order::ExternalDomainsProvider externalDomains)
: m_graph{graph}
, m_trigToSen{trigToSen}
, m_externalDomain{externalDomain}
, m_externalDomains{externalDomains}
, m_finder{netlistp}
, m_deleteDomainp{makeDeleteDomainSenTree(netlistp->fileline())}
, m_tag{tag}
@ -994,8 +995,8 @@ public:
main(AstNetlist* netlistp, OrderGraph& graph,
const std::unordered_map<const AstSenItem*, const AstSenTree*>& trigToSen,
const string& tag, bool parallel, bool slow,
std::function<AstSenTree*(const AstVarScope*)> externalDomain) {
OrderProcess visitor{netlistp, graph, trigToSen, tag, slow, externalDomain};
V3Order::ExternalDomainsProvider externalDomains) {
OrderProcess visitor{netlistp, graph, trigToSen, tag, slow, externalDomains};
visitor.process(parallel);
return std::move(visitor.m_result);
}
@ -1046,6 +1047,9 @@ void OrderProcess::processDomainsIterate(OrderEitherVertex* vertexp) {
if (OrderLogicVertex* const lvtxp = dynamic_cast<OrderLogicVertex*>(vertexp)) {
domainp = lvtxp->hybridp();
}
std::vector<AstSenTree*> externalDomainps;
for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep = edgep->inNextp()) {
OrderEitherVertex* const fromVertexp = static_cast<OrderEitherVertex*>(edgep->fromp());
if (edgep->weight() && fromVertexp->domainMatters()) {
@ -1054,12 +1058,13 @@ void OrderProcess::processDomainsIterate(OrderEitherVertex* vertexp) {
if (OrderVarVertex* const varVtxp = dynamic_cast<OrderVarVertex*>(fromVertexp)) {
AstVarScope* const vscp = varVtxp->vscp();
if (AstSenTree* const externalDomainp = m_externalDomain(vscp)) {
UASSERT(!externalDomainp->hasCombo(),
"There should be no need for combinational domains");
fromDomainp = fromDomainp == m_deleteDomainp
? externalDomainp
: combineDomains(fromDomainp, externalDomainp);
// Add in any external domains
externalDomainps.clear();
m_externalDomains(vscp, externalDomainps);
for (AstSenTree* const externalDomainp : externalDomainps) {
UASSERT_OBJ(!externalDomainp->hasCombo(), vscp,
"There should be no need for combinational domains");
fromDomainp = combineDomains(fromDomainp, externalDomainp);
}
}
@ -1538,12 +1543,12 @@ AstCFunc* order(AstNetlist* netlistp, //
const string& tag, //
bool parallel, //
bool slow, //
std::function<AstSenTree*(const AstVarScope*)> externalDomain) {
ExternalDomainsProvider externalDomains) {
// Order the code
const std::unique_ptr<OrderGraph> graph
= OrderBuildVisitor::process(netlistp, logic, trigToSen);
const auto& nodeps = OrderProcess::main(netlistp, *graph.get(), trigToSen, tag, parallel, slow,
externalDomain);
externalDomains);
// Create the result function
AstScope* const scopeTopp = netlistp->topScopep()->scopep();

View File

@ -38,13 +38,17 @@ struct LogicByScope;
namespace V3Order {
AstCFunc* order(AstNetlist* netlistp, //
const std::vector<V3Sched::LogicByScope*>& logic, //
const std::unordered_map<const AstSenItem*, const AstSenTree*>& trigToSen,
const string& tag, //
bool parallel, //
bool slow, //
std::function<AstSenTree*(const AstVarScope*)> externalDomain);
using ExternalDomainsProvider = std::function<void(const AstVarScope*, std::vector<AstSenTree*>&)>;
AstCFunc* order(
AstNetlist* netlistp, //
const std::vector<V3Sched::LogicByScope*>& logic, //
const std::unordered_map<const AstSenItem*, const AstSenTree*>& trigToSen,
const string& tag, //
bool parallel, //
bool slow, //
ExternalDomainsProvider externalDomains
= [](const AstVarScope*, std::vector<AstSenTree*>&) {});
}; // namespace V3Order

View File

@ -699,9 +699,9 @@ void createSettle(AstNetlist* netlistp, SenExprBuilder& senExprBulider,
AstSenTree* const inputChanged = trig.createTriggerSenTree(netlistp, firstIterationTrigger);
// Create and the body function
AstCFunc* const stlFuncp
= V3Order::order(netlistp, {&comb, &hybrid}, trigToSen, "stl", false, true,
[=](const AstVarScope*) { return inputChanged; });
AstCFunc* const stlFuncp = V3Order::order(
netlistp, {&comb, &hybrid}, trigToSen, "stl", false, true,
[=](const AstVarScope*, std::vector<AstSenTree*>& out) { out.push_back(inputChanged); });
splitCheck(stlFuncp);
// Create the eval loop
@ -763,10 +763,13 @@ AstNode* createInputCombLoop(AstNetlist* netlistp, SenExprBuilder& senExprBuilde
AstSenTree* const inputChanged = trig.createTriggerSenTree(netlistp, firstIterationTrigger);
// Create and Order the body function
AstCFunc* const icoFuncp = V3Order::order(
netlistp, {&logic}, trigToSen, "ico", false, false, [=](const AstVarScope* vscp) {
return vscp->scopep()->isTop() && vscp->varp()->isNonOutput() ? inputChanged : nullptr;
});
AstCFunc* const icoFuncp
= V3Order::order(netlistp, {&logic}, trigToSen, "ico", false, false,
[=](const AstVarScope* vscp, std::vector<AstSenTree*>& out) {
if (vscp->scopep()->isTop() && vscp->varp()->isNonOutput()) {
out.push_back(inputChanged);
}
});
splitCheck(icoFuncp);
// Create the eval loop
@ -1016,7 +1019,7 @@ void schedule(AstNetlist* netlistp) {
AstCFunc* const actFuncp = V3Order::order(
netlistp, {&logicRegions.m_pre, &logicRegions.m_act, &logicReplicas.m_act}, trigToSenAct,
"act", false, false, [](const AstVarScope*) { return nullptr; });
"act", false, false);
splitCheck(actFuncp);
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;
invertAndMergeSenTreeMap(trigToSenNba, nbaTrigMap);
AstCFunc* const nbaFuncp = V3Order::order(
netlistp, {&logicRegions.m_nba, &logicReplicas.m_nba}, trigToSenNba, "nba",
v3Global.opt.mtasks(), false, [](const AstVarScope*) { return nullptr; });
AstCFunc* const nbaFuncp
= V3Order::order(netlistp, {&logicRegions.m_nba, &logicReplicas.m_nba}, trigToSenNba,
"nba", v3Global.opt.mtasks(), false);
splitCheck(nbaFuncp);
netlistp->evalNbap(nbaFuncp); // Remember for V3LifePost
if (v3Global.opt.stats()) V3Stats::statsStage("sched-create-nba");