mirror of
https://github.com/verilator/verilator.git
synced 2025-04-16 01:26:54 +00:00
Merge branch 'master' into develop-v5
This commit is contained in:
commit
582da6df9a
@ -116,6 +116,7 @@ Unai Martinez-Corral
|
||||
Vassilis Papaefstathiou
|
||||
Veripool API Bot
|
||||
Victor Besyakov
|
||||
William D. Jones
|
||||
Wilson Snyder
|
||||
Xi Zhang
|
||||
Yoda Lee
|
||||
|
@ -281,13 +281,13 @@ void AstNode::addNextHere(AstNode* newp) {
|
||||
// This could be at head, tail, or both (single)
|
||||
// New could be head of single node, or list
|
||||
UASSERT(newp, "Null item passed to addNext");
|
||||
UASSERT(!newp->backp(), "New node (back) already assigned?");
|
||||
UASSERT_OBJ(!newp->backp(), newp, "New node (back) already assigned?");
|
||||
debugTreeChange(this, "-addHereThs: ", __LINE__, false);
|
||||
debugTreeChange(newp, "-addHereNew: ", __LINE__, true);
|
||||
newp->editCountInc();
|
||||
|
||||
AstNode* const addlastp = newp->m_headtailp; // Last node in list to be added
|
||||
UASSERT(!addlastp->m_nextp, "Headtailp tail isn't at the tail");
|
||||
UASSERT_OBJ(!addlastp->m_nextp, addlastp, "Headtailp tail isn't at the tail");
|
||||
|
||||
// Forward links
|
||||
AstNode* const oldnextp = this->m_nextp;
|
||||
@ -437,7 +437,7 @@ void VNRelinker::dump(std::ostream& str) const {
|
||||
AstNode* AstNode::unlinkFrBackWithNext(VNRelinker* linkerp) {
|
||||
debugTreeChange(this, "-unlinkWNextThs: ", __LINE__, true);
|
||||
AstNode* const oldp = this;
|
||||
UASSERT(oldp->m_backp, "Node has no back, already unlinked?");
|
||||
UASSERT_OBJ(oldp->m_backp, oldp, "Node has no back, already unlinked?");
|
||||
oldp->editCountInc();
|
||||
AstNode* const backp = oldp->m_backp;
|
||||
if (linkerp) {
|
||||
@ -497,7 +497,7 @@ AstNode* AstNode::unlinkFrBackWithNext(VNRelinker* linkerp) {
|
||||
AstNode* AstNode::unlinkFrBack(VNRelinker* linkerp) {
|
||||
debugTreeChange(this, "-unlinkFrBkThs: ", __LINE__, true);
|
||||
AstNode* const oldp = this;
|
||||
UASSERT(oldp->m_backp, "Node has no back, already unlinked?");
|
||||
UASSERT_OBJ(oldp->m_backp, oldp, "Node has no back, already unlinked?");
|
||||
oldp->editCountInc();
|
||||
AstNode* const backp = oldp->m_backp;
|
||||
if (linkerp) {
|
||||
@ -565,7 +565,7 @@ void AstNode::relink(VNRelinker* linkerp) {
|
||||
}
|
||||
AstNode* const newp = this;
|
||||
UASSERT(linkerp && linkerp->m_backp, "Need non-empty linker");
|
||||
UASSERT(!newp->backp(), "New node already linked?");
|
||||
UASSERT_OBJ(!newp->m_backp, newp, "New node already linked?");
|
||||
newp->editCountInc();
|
||||
|
||||
if (debug() > 8) {
|
||||
@ -631,11 +631,56 @@ void AstNode::relinkOneLink(AstNode*& pointpr, // Ref to pointer that gets set
|
||||
}
|
||||
|
||||
void AstNode::addHereThisAsNext(AstNode* newp) {
|
||||
// {old}->this->{next} becomes {old}->new->this->{next}
|
||||
VNRelinker handle;
|
||||
this->unlinkFrBackWithNext(&handle);
|
||||
newp->addNext(this);
|
||||
handle.relink(newp);
|
||||
// {back}->this->{next} becomes {back}->new->this->{next}
|
||||
UASSERT_OBJ(!newp->backp(), newp, "New node already linked?");
|
||||
UASSERT_OBJ(this->m_backp, this, "'this' node has no back, already unlinked?");
|
||||
UASSERT_OBJ(newp->m_headtailp, newp, "m_headtailp not set on new node");
|
||||
//
|
||||
AstNode* const backp = this->m_backp;
|
||||
AstNode* const newLastp = newp->m_headtailp;
|
||||
//
|
||||
this->editCountInc();
|
||||
// Common linkage
|
||||
newLastp->m_nextp = this;
|
||||
this->m_backp = newLastp;
|
||||
newp->m_backp = backp;
|
||||
// newLastp will not be the last node in the list as 'this' will follow it.
|
||||
// If newLastp == newp, then below handles newp becoming head
|
||||
newLastp->m_headtailp = nullptr;
|
||||
// Linkage dependent on position
|
||||
if (backp && backp->m_nextp == this) {
|
||||
// If 'this' is not at the head of a list, then the new node will also not be at the head
|
||||
// of a list, so we can just link in the new node in the middle.
|
||||
backp->m_nextp = newp;
|
||||
newp->m_headtailp = nullptr;
|
||||
} else {
|
||||
// If 'this' is at the head of a list, then the new node becomes the head of that list.
|
||||
if (backp) {
|
||||
if (backp->m_op1p == this) {
|
||||
backp->m_op1p = newp;
|
||||
} else if (backp->m_op2p == this) {
|
||||
backp->m_op2p = newp;
|
||||
} else if (backp->m_op3p == this) {
|
||||
backp->m_op3p = newp;
|
||||
} else {
|
||||
UASSERT_OBJ(backp->m_op4p == this, this, "Don't know where newp should go");
|
||||
backp->m_op4p = newp;
|
||||
}
|
||||
}
|
||||
// We also need to update m_headtailp.
|
||||
AstNode* const tailp = this->m_headtailp;
|
||||
this->m_headtailp = nullptr;
|
||||
newp->m_headtailp = tailp;
|
||||
tailp->m_headtailp = newp;
|
||||
}
|
||||
// Iterator fixup
|
||||
if (newLastp->m_iterpp) {
|
||||
*(newLastp->m_iterpp) = this;
|
||||
} else if (this->m_iterpp) {
|
||||
*(this->m_iterpp) = newp;
|
||||
}
|
||||
//
|
||||
debugTreeChange(this, "-addHereThisAsNext: ", __LINE__, true);
|
||||
}
|
||||
|
||||
void AstNode::swapWith(AstNode* bp) {
|
||||
|
@ -1800,7 +1800,6 @@ public:
|
||||
void deleteTree(); // Always deletes the next link
|
||||
void checkTree(); // User Interface version
|
||||
void checkIter() const;
|
||||
void clearIter() { m_iterpp = nullptr; }
|
||||
void dumpPtrs(std::ostream& os = std::cout) const;
|
||||
void dumpTree(std::ostream& os = std::cout, const string& indent = " ",
|
||||
int maxDepth = 0) const;
|
||||
|
@ -68,10 +68,7 @@ private:
|
||||
// Put assignment before the referencing statement
|
||||
AstAssign* const assp = new AstAssign{
|
||||
nodep->fileline(), new AstVarRef{nodep->fileline(), varp, VAccess::WRITE}, nodep};
|
||||
VNRelinker linker2;
|
||||
m_stmtp->unlinkFrBack(&linker2);
|
||||
assp->addNext(m_stmtp);
|
||||
linker2.relink(assp);
|
||||
m_stmtp->addHereThisAsNext(assp);
|
||||
}
|
||||
|
||||
// VISITORS
|
||||
|
@ -248,8 +248,8 @@ private:
|
||||
VL_RESTORER(m_funcp);
|
||||
if (!nodep->user1()) {
|
||||
// Static functions should have been moved under the corresponding AstClassPackage
|
||||
UASSERT(!(nodep->isStatic() && VN_IS(m_modp, Class)),
|
||||
"Static function under AstClass");
|
||||
UASSERT_OBJ(!(nodep->isStatic() && VN_IS(m_modp, Class)), nodep,
|
||||
"Static function under AstClass");
|
||||
m_funcp = nodep;
|
||||
iterateChildren(nodep);
|
||||
nodep->user1(true);
|
||||
|
@ -169,30 +169,8 @@ void EmitCFunc::emitOpName(AstNode* nodep, const string& format, AstNode* lhsp,
|
||||
}
|
||||
}
|
||||
|
||||
// We only do one display at once, so can just use static state
|
||||
static struct EmitDispState {
|
||||
string m_format; // "%s" and text from user
|
||||
std::vector<char> m_argsChar; // Format of each argument to be printed
|
||||
std::vector<AstNode*> m_argsp; // Each argument to be printed
|
||||
std::vector<string> m_argsFunc; // Function before each argument to be printed
|
||||
EmitDispState() { clear(); }
|
||||
void clear() {
|
||||
m_format = "";
|
||||
m_argsChar.clear();
|
||||
m_argsp.clear();
|
||||
m_argsFunc.clear();
|
||||
}
|
||||
void pushFormat(const string& fmt) { m_format += fmt; }
|
||||
void pushFormat(char fmt) { m_format += fmt; }
|
||||
void pushArg(char fmtChar, AstNode* nodep, const string& func) {
|
||||
m_argsChar.push_back(fmtChar);
|
||||
m_argsp.push_back(nodep);
|
||||
m_argsFunc.push_back(func);
|
||||
}
|
||||
} emitDispState;
|
||||
|
||||
void EmitCFunc::displayEmit(AstNode* nodep, bool isScan) {
|
||||
if (emitDispState.m_format == ""
|
||||
if (m_emitDispState.m_format == ""
|
||||
&& VN_IS(nodep, Display)) { // not fscanf etc, as they need to return value
|
||||
// NOP
|
||||
} else {
|
||||
@ -235,12 +213,12 @@ void EmitCFunc::displayEmit(AstNode* nodep, bool isScan) {
|
||||
} else {
|
||||
nodep->v3fatalSrc("Unknown displayEmit node type");
|
||||
}
|
||||
ofp()->putsQuoted(emitDispState.m_format);
|
||||
ofp()->putsQuoted(m_emitDispState.m_format);
|
||||
// Arguments
|
||||
for (unsigned i = 0; i < emitDispState.m_argsp.size(); i++) {
|
||||
const char fmt = emitDispState.m_argsChar[i];
|
||||
AstNode* const argp = emitDispState.m_argsp[i];
|
||||
const string func = emitDispState.m_argsFunc[i];
|
||||
for (unsigned i = 0; i < m_emitDispState.m_argsp.size(); i++) {
|
||||
const char fmt = m_emitDispState.m_argsChar[i];
|
||||
AstNode* const argp = m_emitDispState.m_argsp[i];
|
||||
const string func = m_emitDispState.m_argsFunc[i];
|
||||
if (func != "" || argp) {
|
||||
puts(",");
|
||||
ofp()->indentInc();
|
||||
@ -265,7 +243,7 @@ void EmitCFunc::displayEmit(AstNode* nodep, bool isScan) {
|
||||
puts(" ");
|
||||
}
|
||||
// Prep for next
|
||||
emitDispState.clear();
|
||||
m_emitDispState.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@ -306,16 +284,16 @@ void EmitCFunc::displayArg(AstNode* dispp, AstNode** elistp, bool isScan, const
|
||||
} else {
|
||||
pfmt = string("%") + vfmt + fmtLetter;
|
||||
}
|
||||
emitDispState.pushFormat(pfmt);
|
||||
m_emitDispState.pushFormat(pfmt);
|
||||
if (!ignore) {
|
||||
if (argp->dtypep()->basicp()
|
||||
&& argp->dtypep()->basicp()->keyword() == VBasicDTypeKwd::STRING) {
|
||||
// string in SystemVerilog is std::string in C++ which is not POD
|
||||
emitDispState.pushArg(' ', nullptr, "-1");
|
||||
m_emitDispState.pushArg(' ', nullptr, "-1");
|
||||
} else {
|
||||
emitDispState.pushArg(' ', nullptr, cvtToStr(argp->widthMin()));
|
||||
m_emitDispState.pushArg(' ', nullptr, cvtToStr(argp->widthMin()));
|
||||
}
|
||||
emitDispState.pushArg(fmtLetter, argp, "");
|
||||
m_emitDispState.pushArg(fmtLetter, argp, "");
|
||||
if (fmtLetter == 't' || fmtLetter == '^') {
|
||||
const AstSFormatF* fmtp = nullptr;
|
||||
if (const AstDisplay* const nodep = VN_CAST(dispp, Display)) {
|
||||
@ -328,10 +306,10 @@ void EmitCFunc::displayArg(AstNode* dispp, AstNode** elistp, bool isScan, const
|
||||
UASSERT_OBJ(fmtp, dispp,
|
||||
"Use of %t must be under AstDisplay, AstSFormat, or AstSFormatF");
|
||||
UASSERT_OBJ(!fmtp->timeunit().isNone(), fmtp, "timenunit must be set");
|
||||
emitDispState.pushArg(' ', nullptr, cvtToStr((int)fmtp->timeunit().powerOfTen()));
|
||||
m_emitDispState.pushArg(' ', nullptr, cvtToStr((int)fmtp->timeunit().powerOfTen()));
|
||||
}
|
||||
} else {
|
||||
emitDispState.pushArg(fmtLetter, nullptr, "");
|
||||
m_emitDispState.pushArg(fmtLetter, nullptr, "");
|
||||
}
|
||||
}
|
||||
|
||||
@ -341,7 +319,7 @@ void EmitCFunc::displayNode(AstNode* nodep, AstScopeName* scopenamep, const stri
|
||||
|
||||
// Convert Verilog display to C printf formats
|
||||
// "%0t" becomes "%d"
|
||||
emitDispState.clear();
|
||||
m_emitDispState.clear();
|
||||
string vfmt;
|
||||
string::const_iterator pos = vformat.begin();
|
||||
bool inPct = false;
|
||||
@ -353,7 +331,7 @@ void EmitCFunc::displayNode(AstNode* nodep, AstScopeName* scopenamep, const stri
|
||||
ignore = false;
|
||||
vfmt = "";
|
||||
} else if (!inPct) { // Normal text
|
||||
emitDispState.pushFormat(*pos);
|
||||
m_emitDispState.pushFormat(*pos);
|
||||
} else { // Format character
|
||||
inPct = false;
|
||||
switch (tolower(pos[0])) {
|
||||
@ -374,7 +352,7 @@ void EmitCFunc::displayNode(AstNode* nodep, AstScopeName* scopenamep, const stri
|
||||
inPct = true; // Get more digits
|
||||
break;
|
||||
case '%':
|
||||
emitDispState.pushFormat("%%"); // We're printf'ing it, so need to quote the %
|
||||
m_emitDispState.pushFormat("%%"); // We're printf'ing it, so need to quote the %
|
||||
break;
|
||||
case '*':
|
||||
vfmt += pos[0];
|
||||
@ -410,17 +388,17 @@ void EmitCFunc::displayNode(AstNode* nodep, AstScopeName* scopenamep, const stri
|
||||
UASSERT_OBJ(scopenamep, nodep, "Display with %m but no AstScopeName");
|
||||
const string suffix = scopenamep->scopePrettySymName();
|
||||
if (suffix == "") {
|
||||
emitDispState.pushFormat("%S");
|
||||
m_emitDispState.pushFormat("%S");
|
||||
} else {
|
||||
emitDispState.pushFormat("%N"); // Add a . when needed
|
||||
m_emitDispState.pushFormat("%N"); // Add a . when needed
|
||||
}
|
||||
emitDispState.pushArg(' ', nullptr, "vlSymsp->name()");
|
||||
emitDispState.pushFormat(suffix);
|
||||
m_emitDispState.pushArg(' ', nullptr, "vlSymsp->name()");
|
||||
m_emitDispState.pushFormat(suffix);
|
||||
break;
|
||||
}
|
||||
case 'l': {
|
||||
// Better than not compiling
|
||||
emitDispState.pushFormat("----");
|
||||
m_emitDispState.pushFormat("----");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -121,6 +121,28 @@ private:
|
||||
bool m_inUC = false; // Inside an AstUCStmt or AstUCMath
|
||||
bool m_emitConstInit = false; // Emitting constant initializer
|
||||
|
||||
// State associated with processing $display style string formatting
|
||||
struct EmitDispState {
|
||||
string m_format; // "%s" and text from user
|
||||
std::vector<char> m_argsChar; // Format of each argument to be printed
|
||||
std::vector<AstNode*> m_argsp; // Each argument to be printed
|
||||
std::vector<string> m_argsFunc; // Function before each argument to be printed
|
||||
EmitDispState() { clear(); }
|
||||
void clear() {
|
||||
m_format = "";
|
||||
m_argsChar.clear();
|
||||
m_argsp.clear();
|
||||
m_argsFunc.clear();
|
||||
}
|
||||
void pushFormat(const string& fmt) { m_format += fmt; }
|
||||
void pushFormat(char fmt) { m_format += fmt; }
|
||||
void pushArg(char fmtChar, AstNode* nodep, const string& func) {
|
||||
m_argsChar.push_back(fmtChar);
|
||||
m_argsp.push_back(nodep);
|
||||
m_argsFunc.push_back(func);
|
||||
}
|
||||
} m_emitDispState;
|
||||
|
||||
protected:
|
||||
EmitCLazyDecls m_lazyDecls; // Visitor for emitting lazy declarations
|
||||
bool m_useSelfForThis = false; // Replace "this" with "vlSelf"
|
||||
|
@ -82,10 +82,7 @@ private:
|
||||
|
||||
static void insertBefore(AstNode* placep, AstNode* newp) {
|
||||
newp->user1(1); // Already processed, don't need to re-iterate
|
||||
VNRelinker linker;
|
||||
placep->unlinkFrBack(&linker);
|
||||
newp->addNext(placep);
|
||||
linker.relink(newp);
|
||||
placep->addHereThisAsNext(newp);
|
||||
}
|
||||
static void replaceWithDelete(AstNode* nodep, AstNode* newp) {
|
||||
newp->user1(1); // Already processed, don't need to re-iterate
|
||||
|
@ -489,8 +489,8 @@ private:
|
||||
#ifdef INFILTER_PIPE
|
||||
int fd_stdin[2];
|
||||
int fd_stdout[2];
|
||||
static const int P_RD = 0;
|
||||
static const int P_WR = 1;
|
||||
constexpr int P_RD = 0;
|
||||
constexpr int P_WR = 1;
|
||||
|
||||
if (pipe(fd_stdin) != 0 || pipe(fd_stdout) != 0) {
|
||||
v3fatal("--pipe-filter: Can't pipe: " << strerror(errno));
|
||||
@ -623,17 +623,9 @@ V3OutFormatter::V3OutFormatter(const string& filename, V3OutFormatter::Language
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
string V3OutFormatter::indentSpaces(int num) {
|
||||
// Indent the specified number of spaces. Use spaces.
|
||||
static char str[MAXSPACE + 20];
|
||||
char* cp = str;
|
||||
if (num > MAXSPACE) num = MAXSPACE;
|
||||
while (num > 0) {
|
||||
*cp++ = ' ';
|
||||
--num;
|
||||
}
|
||||
*cp++ = '\0';
|
||||
string st{str}; // No const, move optimization
|
||||
return st;
|
||||
// Indent the specified number of spaces.
|
||||
if (num <= 0) return std::string{};
|
||||
return std::string(std::min<size_t>(num, MAXSPACE), ' ');
|
||||
}
|
||||
|
||||
bool V3OutFormatter::tokenMatch(const char* cp, const char* cmp) {
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
|
||||
//============================================================================
|
||||
// V3File: Create streams, recording dependency information
|
||||
|
@ -27,9 +27,12 @@
|
||||
#include "V3Stats.h"
|
||||
|
||||
//######################################################################
|
||||
// V3 Class -- top level
|
||||
// V3Global
|
||||
|
||||
AstNetlist* V3Global::makeNetlist() { return new AstNetlist(); }
|
||||
void V3Global::boot() {
|
||||
UASSERT(!m_rootp, "call once");
|
||||
m_rootp = new AstNetlist();
|
||||
}
|
||||
|
||||
void V3Global::clear() {
|
||||
#ifdef VL_LEAK_CHECK
|
||||
|
@ -120,11 +120,7 @@ public:
|
||||
|
||||
// CONSTRUCTORS
|
||||
V3Global() {}
|
||||
AstNetlist* makeNetlist();
|
||||
void boot() {
|
||||
UASSERT(!m_rootp, "call once");
|
||||
m_rootp = makeNetlist();
|
||||
}
|
||||
void boot();
|
||||
void clear();
|
||||
void shutdown(); // Release allocated resorces
|
||||
// ACCESSORS (general)
|
||||
|
@ -442,7 +442,7 @@ private:
|
||||
int expr_i = i;
|
||||
if (const AstSliceSel* const slicep = VN_CAST(newp->exprp(), SliceSel)) {
|
||||
varrefp = VN_AS(slicep->fromp(), VarRef);
|
||||
UASSERT(VN_IS(slicep->rhsp(), Const), "Slices should be constant");
|
||||
UASSERT_OBJ(VN_IS(slicep->rhsp(), Const), slicep, "Slices should be constant");
|
||||
const int slice_index
|
||||
= slicep->declRange().left() + in * slicep->declRange().leftToRightInc();
|
||||
const auto* const exprArrp = VN_AS(varrefp->dtypep(), UnpackArrayDType);
|
||||
|
@ -73,11 +73,7 @@ void V3LinkLevel::modSortByLevel() {
|
||||
// Reorder the netlist's modules to have modules in level sorted order
|
||||
stable_sort(mods.begin(), mods.end(), CmpLevel()); // Sort the vector
|
||||
UINFO(9, "modSortByLevel() sorted\n"); // Comment required for gcc4.6.3 / bug666
|
||||
for (AstNodeModule* nodep : mods) {
|
||||
nodep->clearIter(); // Because we didn't iterate to find the node
|
||||
// pointers, may have a stale m_iterp() needing cleanup
|
||||
nodep->unlinkFrBack();
|
||||
}
|
||||
for (AstNodeModule* nodep : mods) nodep->unlinkFrBack();
|
||||
UASSERT_OBJ(!v3Global.rootp()->modulesp(), v3Global.rootp(), "Unlink didn't work");
|
||||
for (AstNodeModule* nodep : mods) v3Global.rootp()->addModulep(nodep);
|
||||
UINFO(9, "modSortByLevel() done\n"); // Comment required for gcc4.6.3 / bug666
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "V3Stats.h"
|
||||
#include "V3UniqueNames.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <unordered_set>
|
||||
@ -1529,20 +1530,6 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
static const GraphWay* s_shortestWaywardCpInclusiveWay;
|
||||
static int shortestWaywardCpInclusive(const void* vap, const void* vbp) {
|
||||
const GraphWay* const wp = s_shortestWaywardCpInclusiveWay;
|
||||
const LogicMTask* const ap = *reinterpret_cast<const LogicMTask* const*>(vap);
|
||||
const LogicMTask* const bp = *reinterpret_cast<const LogicMTask* const*>(vbp);
|
||||
const uint32_t aCp = ap->critPathCost(*wp) + ap->stepCost();
|
||||
const uint32_t bCp = bp->critPathCost(*wp) + bp->stepCost();
|
||||
if (aCp < bCp) return -1;
|
||||
if (aCp > bCp) return 1;
|
||||
if (ap->id() < bp->id()) return -1;
|
||||
if (ap->id() > bp->id()) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void siblingPairFromRelatives(GraphWay way, V3GraphVertex* mtaskp, bool exhaustive) {
|
||||
std::vector<LogicMTask*> shortestPrereqs;
|
||||
|
||||
@ -1554,22 +1541,32 @@ private:
|
||||
if (shortestPrereqs.size() > PART_SIBLING_EDGE_LIMIT) break;
|
||||
}
|
||||
|
||||
if (shortestPrereqs.empty()) return;
|
||||
if (shortestPrereqs.size() <= 1) return;
|
||||
|
||||
// qsort_r would be nice here, but it isn't portable
|
||||
s_shortestWaywardCpInclusiveWay = &way;
|
||||
qsort(&shortestPrereqs[0], shortestPrereqs.size(), sizeof(LogicMTask*),
|
||||
&shortestWaywardCpInclusive);
|
||||
const auto cmp = [way](const LogicMTask* ap, const LogicMTask* bp) {
|
||||
const uint32_t aCp = ap->critPathCost(way) + ap->stepCost();
|
||||
const uint32_t bCp = bp->critPathCost(way) + bp->stepCost();
|
||||
if (aCp != bCp) return aCp < bCp;
|
||||
return ap->id() < bp->id();
|
||||
};
|
||||
|
||||
// Don't make all NxN/2 possible pairs of prereqs, that's a lot
|
||||
// to cart around. Just make a few pairs.
|
||||
auto it = shortestPrereqs.cbegin();
|
||||
for (unsigned i = 0; exhaustive || (i < 3); ++i) {
|
||||
if (it == shortestPrereqs.cend()) break;
|
||||
LogicMTask* const ap = *(it++);
|
||||
if (it == shortestPrereqs.cend()) break;
|
||||
LogicMTask* const bp = *(it++);
|
||||
makeSiblingMC(ap, bp);
|
||||
// Don't make all possible pairs of prereqs when not requested (non-exhaustive).
|
||||
// Just make a few pairs.
|
||||
constexpr size_t MAX_NONEXHAUSTIVE_PAIRS = 3;
|
||||
|
||||
size_t end; // End index of pairs to add to candidates (exclusive)
|
||||
|
||||
if (exhaustive || (shortestPrereqs.size() <= 2 * MAX_NONEXHAUSTIVE_PAIRS)) {
|
||||
end = shortestPrereqs.size() & ~static_cast<size_t>(1); // Round down to even
|
||||
std::sort(shortestPrereqs.begin(), shortestPrereqs.end(), cmp);
|
||||
} else {
|
||||
end = 2 * MAX_NONEXHAUSTIVE_PAIRS;
|
||||
std::partial_sort(shortestPrereqs.begin(), shortestPrereqs.begin() + end,
|
||||
shortestPrereqs.end(), cmp);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < end; i += 2) {
|
||||
makeSiblingMC(shortestPrereqs[i], shortestPrereqs[i + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1691,8 +1688,6 @@ private:
|
||||
VL_UNCOPYABLE(PartContraction);
|
||||
};
|
||||
|
||||
const GraphWay* PartContraction::s_shortestWaywardCpInclusiveWay = nullptr;
|
||||
|
||||
//######################################################################
|
||||
// DpiImportCallVisitor
|
||||
|
||||
|
@ -49,9 +49,8 @@ protected:
|
||||
return level;
|
||||
}
|
||||
|
||||
void boot(char** env) {
|
||||
void boot() {
|
||||
// Create the implementation pointer
|
||||
if (env) {}
|
||||
if (!s_preprocp) {
|
||||
FileLine* const cmdfl = new FileLine(FileLine::commandLineFilename());
|
||||
s_preprocp = V3PreProc::createPreProc(cmdfl);
|
||||
@ -162,7 +161,7 @@ VInFilter* V3PreShellImp::s_filterp = nullptr;
|
||||
//######################################################################
|
||||
// V3PreShell
|
||||
|
||||
void V3PreShell::boot(char** env) { V3PreShellImp::s_preImp.boot(env); }
|
||||
void V3PreShell::boot() { V3PreShellImp::s_preImp.boot(); }
|
||||
bool V3PreShell::preproc(FileLine* fl, const string& modname, VInFilter* filterp,
|
||||
V3ParseImp* parsep, const string& errmsg) {
|
||||
return V3PreShellImp::s_preImp.preproc(fl, modname, filterp, parsep, errmsg);
|
||||
|
@ -32,7 +32,7 @@ class VSpellCheck;
|
||||
class V3PreShell final {
|
||||
// Static class for calling preprocessor
|
||||
public:
|
||||
static void boot(char** env);
|
||||
static void boot();
|
||||
static bool preproc(FileLine* fl, const string& modname, VInFilter* filterp,
|
||||
V3ParseImp* parsep, const string& errmsg);
|
||||
static void preprocInclude(FileLine* fl, const string& modname);
|
||||
|
@ -109,10 +109,7 @@ private:
|
||||
} else if (m_inTracep) {
|
||||
m_inTracep->addPrecondsp(newp);
|
||||
} else if (m_stmtp) {
|
||||
VNRelinker linker;
|
||||
m_stmtp->unlinkFrBack(&linker);
|
||||
newp->addNext(m_stmtp);
|
||||
linker.relink(newp);
|
||||
m_stmtp->addHereThisAsNext(newp);
|
||||
} else {
|
||||
newp->v3fatalSrc("No statement insertion point.");
|
||||
}
|
||||
|
@ -709,7 +709,7 @@ int main(int argc, char** argv, char** env) {
|
||||
|
||||
// Preprocessor
|
||||
// Before command parsing so we can handle -Ds on command line.
|
||||
V3PreShell::boot(env);
|
||||
V3PreShell::boot();
|
||||
|
||||
// Command option parsing
|
||||
v3Global.opt.bin(argv[0]);
|
||||
|
Loading…
Reference in New Issue
Block a user