Internals: Refactor AstNodeBlock representation (#6280) AstNodeBlock now has 2 child lists: 'declsp' to hold declarations within the block, and 'stmtsp' to hold the procedural statements. AstBegin is then just a simple subtype of AstNodeBlock. AstFork is a proper superset of AstNodeBlock (and also AstBegin), and adds 'forksp' which hold the parallel statements. Having the sequential 'stmtsp' in AstFork is required to properly implement variable initializers in fork blocks (IEEE 1800-2023 9.3.2), this makes that clear, while also separating the non AstNodeStmt declarations (for #6280). The actual fork branches in 'AstFork::forkps()' are all AstBegin nodes. This is required as lowering stages will introduce additional statements in each parallel branch. (We used to wrap AstFork statements into AstBegin in 3 different places, now they always are AstBegin and this is enforced via the type checker/V3Broken). Also fixes incorrect disabling of forked processes from within the `fork`.
This commit is contained in:
parent
65c5071246
commit
d864057a60
|
|
@ -298,10 +298,10 @@ class AssertVisitor final : public VNVisitor {
|
||||||
AstNode* const precondps = pExpr->precondp();
|
AstNode* const precondps = pExpr->precondp();
|
||||||
UASSERT_OBJ(precondps, pExpr, "Should have precondition");
|
UASSERT_OBJ(precondps, pExpr, "Should have precondition");
|
||||||
precondps->unlinkFrBackWithNext()->addNext(ifp);
|
precondps->unlinkFrBackWithNext()->addNext(ifp);
|
||||||
AstNodeStmt* const assertOnp
|
AstNodeStmt* const aonp = newIfAssertOn(precondps, nodep->directive(), nodep->type());
|
||||||
= newIfAssertOn(precondps, nodep->directive(), nodep->type());
|
FileLine* const flp = precondps->fileline();
|
||||||
AstFork* const forkp = new AstFork{precondps->fileline(), "", assertOnp};
|
AstFork* const forkp = new AstFork{flp, VJoinType::JOIN_NONE};
|
||||||
forkp->joinType(VJoinType::JOIN_NONE);
|
forkp->addForksp(new AstBegin{flp, "", aonp, true});
|
||||||
return forkp;
|
return forkp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -247,8 +247,8 @@ private:
|
||||||
// Create a fork so that this AlwaysObserved can be retriggered before the
|
// Create a fork so that this AlwaysObserved can be retriggered before the
|
||||||
// assignment happens. Also then it can be combo, avoiding the need for creating
|
// assignment happens. Also then it can be combo, avoiding the need for creating
|
||||||
// new triggers.
|
// new triggers.
|
||||||
AstFork* const forkp = new AstFork{flp, "", ifp};
|
AstFork* const forkp = new AstFork{flp, VJoinType::JOIN_NONE};
|
||||||
forkp->joinType(VJoinType::JOIN_NONE);
|
forkp->addForksp(new AstBegin{flp, "", ifp, true});
|
||||||
// Use Observed for this to make sure we do not miss the event
|
// Use Observed for this to make sure we do not miss the event
|
||||||
m_clockingp->addNextHere(new AstAlwaysObserved{
|
m_clockingp->addNextHere(new AstAlwaysObserved{
|
||||||
flp, new AstSenTree{flp, m_clockingp->sensesp()->cloneTree(false)}, forkp});
|
flp, new AstSenTree{flp, m_clockingp->sensesp()->cloneTree(false)}, forkp});
|
||||||
|
|
|
||||||
|
|
@ -1300,6 +1300,7 @@ public:
|
||||||
: m_e{_e} {}
|
: m_e{_e} {}
|
||||||
explicit VJoinType(int _e)
|
explicit VJoinType(int _e)
|
||||||
: m_e(static_cast<en>(_e)) {} // Need () or GCC 4.8 false warning
|
: m_e(static_cast<en>(_e)) {} // Need () or GCC 4.8 false warning
|
||||||
|
constexpr operator en() const { return m_e; }
|
||||||
const char* ascii() const {
|
const char* ascii() const {
|
||||||
static const char* const names[] = {"JOIN", "JOIN_ANY", "JOIN_NONE"};
|
static const char* const names[] = {"JOIN", "JOIN_ANY", "JOIN_NONE"};
|
||||||
return names[m_e];
|
return names[m_e];
|
||||||
|
|
|
||||||
|
|
@ -69,17 +69,16 @@ public:
|
||||||
};
|
};
|
||||||
class AstNodeBlock VL_NOT_FINAL : public AstNodeStmt {
|
class AstNodeBlock VL_NOT_FINAL : public AstNodeStmt {
|
||||||
// A Begin/fork block
|
// A Begin/fork block
|
||||||
// @astgen op2 := stmtsp : List[AstNode]
|
|
||||||
// Parents: statement
|
// Parents: statement
|
||||||
|
// @astgen op1 := declsp : List[AstNode] // Declarations inside block
|
||||||
|
// @astgen op2 := stmtsp : List[AstNode] // Sequential statements inside block
|
||||||
string m_name; // Name of block
|
string m_name; // Name of block
|
||||||
bool m_unnamed; // Originally unnamed (name change does not affect this)
|
bool m_unnamed; // Originally unnamed (name change does not affect this)
|
||||||
protected:
|
protected:
|
||||||
AstNodeBlock(VNType t, FileLine* fl, const string& name, AstNode* stmtsp)
|
AstNodeBlock(VNType t, FileLine* fl, const string& name)
|
||||||
: AstNodeStmt{t, fl}
|
: AstNodeStmt{t, fl}
|
||||||
, m_name{name} {
|
, m_name{name}
|
||||||
addStmtsp(stmtsp);
|
, m_unnamed{name == ""} {}
|
||||||
m_unnamed = (name == "");
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ASTGEN_MEMBERS_AstNodeBlock;
|
ASTGEN_MEMBERS_AstNodeBlock;
|
||||||
|
|
@ -1351,17 +1350,16 @@ public:
|
||||||
|
|
||||||
// === AstNodeBlock ===
|
// === AstNodeBlock ===
|
||||||
class AstBegin final : public AstNodeBlock {
|
class AstBegin final : public AstNodeBlock {
|
||||||
// A Begin/end named block, only exists shortly after parsing until linking
|
// A 'begin'/'end' named block.
|
||||||
// Parents: statement
|
|
||||||
|
|
||||||
bool m_needProcess : 1; // Uses VlProcess
|
bool m_needProcess : 1; // Uses VlProcess
|
||||||
const bool m_implied : 1; // Not inserted by user
|
const bool m_implied : 1; // Not inserted by user
|
||||||
public:
|
public:
|
||||||
// Node that puts name into the output stream
|
|
||||||
AstBegin(FileLine* fl, const string& name, AstNode* stmtsp, bool implied)
|
AstBegin(FileLine* fl, const string& name, AstNode* stmtsp, bool implied)
|
||||||
: ASTGEN_SUPER_Begin(fl, name, stmtsp)
|
: ASTGEN_SUPER_Begin(fl, name)
|
||||||
, m_needProcess{false}
|
, m_needProcess{false}
|
||||||
, m_implied{implied} {}
|
, m_implied{implied} {
|
||||||
|
addStmtsp(stmtsp);
|
||||||
|
}
|
||||||
ASTGEN_MEMBERS_AstBegin;
|
ASTGEN_MEMBERS_AstBegin;
|
||||||
void dump(std::ostream& str) const override;
|
void dump(std::ostream& str) const override;
|
||||||
void dumpJson(std::ostream& str) const override;
|
void dumpJson(std::ostream& str) const override;
|
||||||
|
|
@ -1370,21 +1368,25 @@ public:
|
||||||
bool implied() const { return m_implied; }
|
bool implied() const { return m_implied; }
|
||||||
};
|
};
|
||||||
class AstFork final : public AstNodeBlock {
|
class AstFork final : public AstNodeBlock {
|
||||||
// A fork named block
|
// A 'fork'/'join*' named block. Note that this is a strict superset of
|
||||||
// @astgen op1 := initsp : List[AstNode]
|
// AstBegin, and it does contain AstNodeBlock::stmtsp(), which are
|
||||||
// Parents: statement
|
// statements that execute sequentially before the parallel statements are
|
||||||
// Children: statements
|
// spawned. This is necessary to implement things like local variable
|
||||||
VJoinType m_joinType; // Join keyword type
|
// initializers properly. The parallel statements inside the fork must all
|
||||||
|
// be AstBegin, as lowering stages will introduce additional statements to
|
||||||
|
// be executed sequentially within eaach fork branch.
|
||||||
|
//
|
||||||
|
// @astgen op3 := forksp : List[AstBegin]
|
||||||
|
const VJoinType m_joinType; // Join keyword type
|
||||||
public:
|
public:
|
||||||
// Node that puts name into the output stream
|
AstFork(FileLine* fl, VJoinType joinType, const string& name = "")
|
||||||
AstFork(FileLine* fl, const string& name, AstNode* stmtsp)
|
: ASTGEN_SUPER_Fork(fl, name)
|
||||||
: ASTGEN_SUPER_Fork(fl, name, stmtsp) {}
|
, m_joinType{joinType} {}
|
||||||
ASTGEN_MEMBERS_AstFork;
|
ASTGEN_MEMBERS_AstFork;
|
||||||
bool isTimingControl() const override { return !joinType().joinNone(); }
|
bool isTimingControl() const override { return !joinType().joinNone(); }
|
||||||
void dump(std::ostream& str) const override;
|
void dump(std::ostream& str) const override;
|
||||||
void dumpJson(std::ostream& str) const override;
|
void dumpJson(std::ostream& str) const override;
|
||||||
VJoinType joinType() const { return m_joinType; }
|
VJoinType joinType() const { return m_joinType; }
|
||||||
void joinType(const VJoinType& flag) { m_joinType = flag; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// === AstNodeCoverOrAssert ===
|
// === AstNodeCoverOrAssert ===
|
||||||
|
|
|
||||||
|
|
@ -3039,7 +3039,7 @@ void AstCoverInc::dump(std::ostream& str) const {
|
||||||
void AstCoverInc::dumpJson(std::ostream& str) const { dumpJsonGen(str); }
|
void AstCoverInc::dumpJson(std::ostream& str) const { dumpJsonGen(str); }
|
||||||
void AstFork::dump(std::ostream& str) const {
|
void AstFork::dump(std::ostream& str) const {
|
||||||
this->AstNodeBlock::dump(str);
|
this->AstNodeBlock::dump(str);
|
||||||
if (!joinType().join()) str << " [" << joinType() << "]";
|
str << " [" << joinType() << "]";
|
||||||
}
|
}
|
||||||
void AstFork::dumpJson(std::ostream& str) const {
|
void AstFork::dumpJson(std::ostream& str) const {
|
||||||
dumpJsonStr(str, "joinType", joinType().ascii());
|
dumpJsonStr(str, "joinType", joinType().ascii());
|
||||||
|
|
|
||||||
|
|
@ -80,15 +80,16 @@ class BeginVisitor final : public VNVisitor {
|
||||||
|
|
||||||
string dot(const string& a, const string& b) { return VString::dot(a, "__DOT__", b); }
|
string dot(const string& a, const string& b) { return VString::dot(a, "__DOT__", b); }
|
||||||
|
|
||||||
void dotNames(const std::string& name, FileLine* const flp, AstNode* stmtsp,
|
void dotNames(const std::string& name, FileLine* const flp, const char* const blockName) {
|
||||||
const char* const blockName) {
|
|
||||||
UINFO(8, "nname " << m_namedScope);
|
UINFO(8, "nname " << m_namedScope);
|
||||||
if (name != "") { // Else unneeded unnamed block
|
// If unneeded unnamed block, whatever that means :)
|
||||||
|
if (name == "") return;
|
||||||
|
|
||||||
// Create data for dotted variable resolution
|
// Create data for dotted variable resolution
|
||||||
string dottedname = name + "__DOT__"; // So always found
|
std::string dottedname = name + "__DOT__"; // So always found
|
||||||
string::size_type pos;
|
std::string::size_type pos;
|
||||||
while ((pos = dottedname.find("__DOT__")) != string::npos) {
|
while ((pos = dottedname.find("__DOT__")) != std::string::npos) {
|
||||||
const string ident = dottedname.substr(0, pos);
|
const std::string ident = dottedname.substr(0, pos);
|
||||||
dottedname = dottedname.substr(pos + std::strlen("__DOT__"));
|
dottedname = dottedname.substr(pos + std::strlen("__DOT__"));
|
||||||
if (name != "") {
|
if (name != "") {
|
||||||
m_displayScope = dot(m_displayScope, ident);
|
m_displayScope = dot(m_displayScope, ident);
|
||||||
|
|
@ -97,17 +98,12 @@ class BeginVisitor final : public VNVisitor {
|
||||||
m_unnamedScope = dot(m_unnamedScope, ident);
|
m_unnamedScope = dot(m_unnamedScope, ident);
|
||||||
// Create CellInline for dotted var resolution
|
// Create CellInline for dotted var resolution
|
||||||
if (!m_ftaskp) {
|
if (!m_ftaskp) {
|
||||||
AstCellInline* const inlinep
|
AstCellInline* const inlinep = new AstCellInline{flp, m_unnamedScope, blockName};
|
||||||
= new AstCellInline{flp, m_unnamedScope, blockName};
|
|
||||||
m_modp->addInlinesp(inlinep); // Must be parsed before any AstCells
|
m_modp->addInlinesp(inlinep); // Must be parsed before any AstCells
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remap var names and replace lower Begins
|
|
||||||
iterateAndNextNull(stmtsp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void liftNode(AstNode* nodep) {
|
void liftNode(AstNode* nodep) {
|
||||||
nodep->unlinkFrBack();
|
nodep->unlinkFrBack();
|
||||||
if (m_ftaskp) {
|
if (m_ftaskp) {
|
||||||
|
|
@ -125,21 +121,14 @@ class BeginVisitor final : public VNVisitor {
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
void visit(AstFork* nodep) override {
|
void visit(AstFork* nodep) override {
|
||||||
|
dotNames(nodep->name(), nodep->fileline(), "__FORK__");
|
||||||
|
iterateAndNextNull(nodep->stmtsp());
|
||||||
|
{
|
||||||
// Keep begins in forks to group their statements together
|
// Keep begins in forks to group their statements together
|
||||||
VL_RESTORER(m_keepBegins);
|
VL_RESTORER(m_keepBegins);
|
||||||
m_keepBegins = true;
|
m_keepBegins = true;
|
||||||
// If a statement is not a begin, wrap it in a begin. This fixes an issue when the
|
iterateAndNextNull(nodep->forksp());
|
||||||
// statement is a task call that gets inlined later (or any other statement that gets
|
|
||||||
// replaced with multiple statements)
|
|
||||||
for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp = stmtp->nextp()) {
|
|
||||||
if (!VN_IS(stmtp, Begin)) {
|
|
||||||
AstBegin* const beginp = new AstBegin{stmtp->fileline(), "", nullptr, false};
|
|
||||||
stmtp->replaceWith(beginp);
|
|
||||||
beginp->addStmtsp(stmtp);
|
|
||||||
stmtp = beginp;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
dotNames(nodep->name(), nodep->fileline(), nodep->stmtsp(), "__FORK__");
|
|
||||||
nodep->name("");
|
nodep->name("");
|
||||||
}
|
}
|
||||||
void visit(AstForeach* nodep) override {
|
void visit(AstForeach* nodep) override {
|
||||||
|
|
@ -215,7 +204,8 @@ class BeginVisitor final : public VNVisitor {
|
||||||
VL_RESTORER(m_namedScope);
|
VL_RESTORER(m_namedScope);
|
||||||
VL_RESTORER(m_unnamedScope);
|
VL_RESTORER(m_unnamedScope);
|
||||||
UASSERT_OBJ(!m_keepBegins, nodep, "Should be able to eliminate all AstGenBlock");
|
UASSERT_OBJ(!m_keepBegins, nodep, "Should be able to eliminate all AstGenBlock");
|
||||||
dotNames(nodep->name(), nodep->fileline(), nodep->itemsp(), "__BEGIN__");
|
dotNames(nodep->name(), nodep->fileline(), "__BEGIN__");
|
||||||
|
iterateAndNextNull(nodep->itemsp());
|
||||||
// Repalce node with body then delete
|
// Repalce node with body then delete
|
||||||
if (AstNode* const itemsp = nodep->itemsp()) {
|
if (AstNode* const itemsp = nodep->itemsp()) {
|
||||||
nodep->addNextHere(itemsp->unlinkFrBackWithNext());
|
nodep->addNextHere(itemsp->unlinkFrBackWithNext());
|
||||||
|
|
@ -231,7 +221,8 @@ class BeginVisitor final : public VNVisitor {
|
||||||
{
|
{
|
||||||
VL_RESTORER(m_keepBegins);
|
VL_RESTORER(m_keepBegins);
|
||||||
m_keepBegins = false;
|
m_keepBegins = false;
|
||||||
dotNames(nodep->name(), nodep->fileline(), nodep->stmtsp(), "__BEGIN__");
|
dotNames(nodep->name(), nodep->fileline(), "__BEGIN__");
|
||||||
|
iterateChildren(nodep);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cleanup
|
// Cleanup
|
||||||
|
|
@ -240,6 +231,10 @@ class BeginVisitor final : public VNVisitor {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
AstNode* addsp = nullptr;
|
AstNode* addsp = nullptr;
|
||||||
|
if (AstNode* const declsp = nodep->declsp()) {
|
||||||
|
declsp->unlinkFrBackWithNext();
|
||||||
|
addsp = AstNode::addNext(addsp, declsp);
|
||||||
|
}
|
||||||
if (AstNode* const stmtsp = nodep->stmtsp()) {
|
if (AstNode* const stmtsp = nodep->stmtsp()) {
|
||||||
stmtsp->unlinkFrBackWithNext();
|
stmtsp->unlinkFrBackWithNext();
|
||||||
addsp = AstNode::addNext(addsp, stmtsp);
|
addsp = AstNode::addNext(addsp, stmtsp);
|
||||||
|
|
|
||||||
112
src/V3Fork.cpp
112
src/V3Fork.cpp
|
|
@ -137,8 +137,8 @@ public:
|
||||||
UASSERT_OBJ(m_instance.initialized(), m_procp, "No dynamic scope prototype");
|
UASSERT_OBJ(m_instance.initialized(), m_procp, "No dynamic scope prototype");
|
||||||
UASSERT_OBJ(!linked(), m_instance.m_handlep, "Handle already linked");
|
UASSERT_OBJ(!linked(), m_instance.m_handlep, "Handle already linked");
|
||||||
|
|
||||||
if (VN_IS(m_procp, Fork)) {
|
if (AstFork* const forkp = VN_CAST(m_procp, Fork)) {
|
||||||
linkNodesOfFork(memberMap);
|
linkNodesOfFork(memberMap, forkp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -221,32 +221,20 @@ private:
|
||||||
new AstVarRef{m_procp->fileline(), m_instance.m_handlep, VAccess::WRITE}, newp};
|
new AstVarRef{m_procp->fileline(), m_instance.m_handlep, VAccess::WRITE}, newp};
|
||||||
}
|
}
|
||||||
|
|
||||||
void linkNodesOfFork(VMemberMap& memberMap) {
|
// Wrap Fork in Begin
|
||||||
// Special case
|
void linkNodesOfFork(VMemberMap& memberMap, AstFork* forkp) {
|
||||||
|
// Replace the Fork with a Begin
|
||||||
AstFork* const forkp = VN_AS(m_procp, Fork);
|
const std::string name = "_Vwrapped_" //
|
||||||
VNRelinker forkHandle;
|
+ (forkp->name().empty() ? "" : forkp->name() + "_") //
|
||||||
forkp->unlinkFrBack(&forkHandle);
|
+ std::to_string(m_id);
|
||||||
|
AstBegin* const beginp = new AstBegin{forkp->fileline(), name, m_instance.m_handlep, true};
|
||||||
AstBegin* const beginp = new AstBegin{
|
forkp->replaceWith(beginp);
|
||||||
forkp->fileline(),
|
// Create the dynamic scope in the Begin
|
||||||
"_Vwrapped_" + (forkp->name().empty() ? "" : forkp->name() + "_") + cvtToStr(m_id),
|
beginp->addStmtsp(instantiateDynScope(memberMap));
|
||||||
m_instance.m_handlep, true};
|
// Move all sequential statements there
|
||||||
forkHandle.relink(beginp);
|
if (forkp->stmtsp()) beginp->addStmtsp(forkp->stmtsp()->unlinkFrBackWithNext());
|
||||||
|
// Put the Fork back at the end of the Begin
|
||||||
AstNode* const instAsgnp = instantiateDynScope(memberMap);
|
beginp->addStmtsp(forkp);
|
||||||
|
|
||||||
beginp->stmtsp()->addNext(instAsgnp);
|
|
||||||
beginp->stmtsp()->addNext(forkp);
|
|
||||||
|
|
||||||
if (forkp->initsp()) {
|
|
||||||
forkp->initsp()->foreach([forkp](AstAssign* asgnp) {
|
|
||||||
asgnp->unlinkFrBack();
|
|
||||||
forkp->addHereThisAsNext(asgnp);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
UASSERT_OBJ(!forkp->initsp(), forkp, "Leftover nodes in block_item_declaration");
|
|
||||||
|
|
||||||
m_modp->addStmtsp(m_instance.m_classp);
|
m_modp->addStmtsp(m_instance.m_classp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -386,25 +374,24 @@ class DynScopeVisitor final : public VNVisitor {
|
||||||
const bool oldAfterTimingControl = m_afterTimingControl;
|
const bool oldAfterTimingControl = m_afterTimingControl;
|
||||||
|
|
||||||
ForkDynScopeFrame* framep = nullptr;
|
ForkDynScopeFrame* framep = nullptr;
|
||||||
if (nodep->initsp()) framep = pushDynScopeFrame(nodep);
|
if (nodep->declsp() || nodep->stmtsp()) framep = pushDynScopeFrame(nodep);
|
||||||
|
|
||||||
for (AstNode* stmtp = nodep->initsp(); stmtp; stmtp = stmtp->nextp()) {
|
// This can be probably optimized to detect cases in which dynscopes could be avoided
|
||||||
if (AstVar* const varp = VN_CAST(stmtp, Var)) {
|
for (AstNode* declp = nodep->declsp(); declp; declp = declp->nextp()) {
|
||||||
// This can be probably optimized to detect cases in which dynscopes
|
AstVar* const varp = VN_CAST(declp, Var);
|
||||||
// could be avoided
|
UASSERT_OBJ(varp, declp, "Invalid node under block item initialization part of fork");
|
||||||
if (!framep->instance().initialized()) framep->createInstancePrototype();
|
if (!framep->instance().initialized()) framep->createInstancePrototype();
|
||||||
framep->captureVarInsert(varp);
|
framep->captureVarInsert(varp);
|
||||||
bindNodeToDynScope(varp, framep);
|
bindNodeToDynScope(varp, framep);
|
||||||
} else {
|
}
|
||||||
|
for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp = stmtp->nextp()) {
|
||||||
AstAssign* const asgnp = VN_CAST(stmtp, Assign);
|
AstAssign* const asgnp = VN_CAST(stmtp, Assign);
|
||||||
UASSERT_OBJ(asgnp, stmtp,
|
UASSERT_OBJ(asgnp, stmtp, "Invalid node under block item initialization part of fork");
|
||||||
"Invalid node under block item initialization part of fork");
|
|
||||||
bindNodeToDynScope(asgnp->lhsp(), framep);
|
bindNodeToDynScope(asgnp->lhsp(), framep);
|
||||||
iterate(asgnp->rhsp());
|
iterate(asgnp->rhsp());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp = stmtp->nextp()) {
|
for (AstNode* stmtp = nodep->forksp(); stmtp; stmtp = stmtp->nextp()) {
|
||||||
m_afterTimingControl = false;
|
m_afterTimingControl = false;
|
||||||
iterate(stmtp);
|
iterate(stmtp);
|
||||||
}
|
}
|
||||||
|
|
@ -470,11 +457,10 @@ class DynScopeVisitor final : public VNVisitor {
|
||||||
})) {
|
})) {
|
||||||
nodep->user2(true);
|
nodep->user2(true);
|
||||||
// Put it in a fork to prevent lifetime issues with the local
|
// Put it in a fork to prevent lifetime issues with the local
|
||||||
AstBegin* const beginp = new AstBegin{nodep->fileline(), "", nullptr, false};
|
FileLine* const flp = nodep->fileline();
|
||||||
AstFork* const forkp = new AstFork{nodep->fileline(), "", beginp};
|
AstFork* const forkp = new AstFork{flp, VJoinType::JOIN_NONE};
|
||||||
forkp->joinType(VJoinType::JOIN_NONE);
|
|
||||||
nodep->replaceWith(forkp);
|
nodep->replaceWith(forkp);
|
||||||
beginp->addStmtsp(nodep);
|
forkp->addForksp(new AstBegin{flp, "", nodep, false});
|
||||||
UINFO(9, "assign new fork " << forkp);
|
UINFO(9, "assign new fork " << forkp);
|
||||||
} else {
|
} else {
|
||||||
visit(static_cast<AstNodeStmt*>(nodep));
|
visit(static_cast<AstNodeStmt*>(nodep));
|
||||||
|
|
@ -559,7 +545,9 @@ class ForkVisitor final : public VNVisitor {
|
||||||
return varp;
|
return varp;
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNodeStmt* taskify(AstNode* stmtp) {
|
// Wrap body of the given Begin (an AstFork branch), in an AstTask, and
|
||||||
|
// replace body with a call to that task. Returns true iff wrapped.
|
||||||
|
bool taskify(AstBegin* beginp) {
|
||||||
// Visit statement to gather variables (And recursively process)
|
// Visit statement to gather variables (And recursively process)
|
||||||
VL_RESTORER(m_forkLocalsp);
|
VL_RESTORER(m_forkLocalsp);
|
||||||
VL_RESTORER(m_capturedVarsp);
|
VL_RESTORER(m_capturedVarsp);
|
||||||
|
|
@ -567,33 +555,26 @@ class ForkVisitor final : public VNVisitor {
|
||||||
m_forkLocalsp.clear();
|
m_forkLocalsp.clear();
|
||||||
m_capturedVarsp = nullptr;
|
m_capturedVarsp = nullptr;
|
||||||
m_capturedArgsp = nullptr;
|
m_capturedArgsp = nullptr;
|
||||||
iterate(stmtp);
|
iterate(beginp);
|
||||||
|
|
||||||
// No need to do it if no variabels are captured
|
// No need to do it if no variabels are captured
|
||||||
if (m_forkLocalsp.empty() && !m_capturedVarsp && !v3Global.opt.fTaskifyAll()) {
|
if (m_forkLocalsp.empty() && !m_capturedVarsp && !v3Global.opt.fTaskifyAll()) return false;
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create task holding the statement and repalce statement with call to that task
|
// Create task holding the statement and repalce statement with call to that task
|
||||||
FileLine* const flp = stmtp->fileline();
|
FileLine* const flp = beginp->fileline();
|
||||||
const std::string name = "__VforkTask_" + std::to_string(m_nForkTasks++);
|
const std::string name = "__VforkTask_" + std::to_string(m_nForkTasks++);
|
||||||
AstTask* const taskp = new AstTask{flp, name, m_capturedVarsp};
|
AstTask* const taskp = new AstTask{flp, name, m_capturedVarsp};
|
||||||
m_tasksp = AstNode::addNext(m_tasksp, taskp);
|
m_tasksp = AstNode::addNext(m_tasksp, taskp);
|
||||||
|
if (beginp->declsp()) taskp->addStmtsp(beginp->declsp()->unlinkFrBackWithNext());
|
||||||
|
if (beginp->stmtsp()) taskp->addStmtsp(beginp->stmtsp()->unlinkFrBackWithNext());
|
||||||
AstTaskRef* const callp = new AstTaskRef{flp, taskp, m_capturedArgsp};
|
AstTaskRef* const callp = new AstTaskRef{flp, taskp, m_capturedArgsp};
|
||||||
AstNodeStmt* const replacementp = callp->makeStmt();
|
beginp->addStmtsp(callp->makeStmt());
|
||||||
stmtp->replaceWith(replacementp);
|
|
||||||
if (AstBegin* const beginp = VN_CAST(stmtp, Begin)) {
|
|
||||||
taskp->addStmtsp(beginp->stmtsp()->unlinkFrBackWithNext());
|
|
||||||
VL_DO_DANGLING(pushDeletep(beginp), beginp);
|
|
||||||
} else {
|
|
||||||
taskp->addStmtsp(stmtp);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Variables were moved under the task, so make sure they are marked as funcLocal
|
// Variables were moved under the task, so make sure they are marked as funcLocal
|
||||||
for (AstVar* const localp : m_forkLocalsp) localp->funcLocal(true);
|
for (AstVar* const localp : m_forkLocalsp) localp->funcLocal(true);
|
||||||
|
|
||||||
// Return the replacement
|
// We did wrap the body
|
||||||
return replacementp;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
|
|
@ -615,21 +596,18 @@ class ForkVisitor final : public VNVisitor {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
iterateAndNextNull(nodep->initsp());
|
iterateAndNextNull(nodep->declsp());
|
||||||
std::vector<AstNodeStmt*> newps;
|
iterateAndNextNull(nodep->stmtsp());
|
||||||
|
std::vector<AstBegin*> wrappedp;
|
||||||
{
|
{
|
||||||
VL_RESTORER(m_inFork);
|
VL_RESTORER(m_inFork);
|
||||||
m_inFork = true;
|
m_inFork = true;
|
||||||
for (AstNode *itemp = nodep->stmtsp(), *nextp; itemp; itemp = nextp) {
|
for (AstBegin* itemp = nodep->forksp(); itemp; itemp = VN_AS(itemp->nextp(), Begin)) {
|
||||||
nextp = itemp->nextp();
|
if (taskify(itemp)) wrappedp.push_back(itemp);
|
||||||
AstNodeStmt* const stmtp = VN_CAST(itemp, NodeStmt);
|
|
||||||
if (!stmtp) continue;
|
|
||||||
AstNodeStmt* const newp = taskify(stmtp);
|
|
||||||
if (newp) newps.push_back(newp);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Analyze replacements in context of enclosing fork
|
// Analyze replacements in context of enclosing fork
|
||||||
for (AstNodeStmt* const stmtp : newps) iterate(stmtp);
|
for (AstBegin* const beginp : wrappedp) iterateAndNextNull(beginp);
|
||||||
}
|
}
|
||||||
void visit(AstVar* nodep) override {
|
void visit(AstVar* nodep) override {
|
||||||
if (m_inFork) m_forkLocalsp.insert(nodep);
|
if (m_inFork) m_forkLocalsp.insert(nodep);
|
||||||
|
|
|
||||||
|
|
@ -519,11 +519,17 @@ class HasherVisitor final : public VNVisitorConst {
|
||||||
void visit(AstNodeProcedure* nodep) override {
|
void visit(AstNodeProcedure* nodep) override {
|
||||||
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, []() {});
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, []() {});
|
||||||
}
|
}
|
||||||
void visit(AstNodeBlock* nodep) override {
|
void visit(AstBegin* nodep) override {
|
||||||
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [this, nodep]() { //
|
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [this, nodep]() { //
|
||||||
m_hash += nodep->name();
|
m_hash += nodep->name();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
void visit(AstFork* nodep) override {
|
||||||
|
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [this, nodep]() { //
|
||||||
|
m_hash += nodep->name();
|
||||||
|
m_hash += nodep->joinType();
|
||||||
|
});
|
||||||
|
}
|
||||||
void visit(AstPin* nodep) override {
|
void visit(AstPin* nodep) override {
|
||||||
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [this, nodep]() {
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [this, nodep]() {
|
||||||
m_hash += nodep->name();
|
m_hash += nodep->name();
|
||||||
|
|
|
||||||
|
|
@ -224,9 +224,10 @@ private:
|
||||||
void visit(AstFork* nodep) override {
|
void visit(AstFork* nodep) override {
|
||||||
if (m_ignoreRemaining) return;
|
if (m_ignoreRemaining) return;
|
||||||
const VisitBase vb{this, nodep};
|
const VisitBase vb{this, nodep};
|
||||||
|
iterateAndNextConstNull(nodep->stmtsp());
|
||||||
uint32_t totalCount = m_instrCount;
|
uint32_t totalCount = m_instrCount;
|
||||||
// Sum counts in each statement until the first await
|
// Sum counts in each statement until the first await
|
||||||
for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp = stmtp->nextp()) {
|
for (AstNode* stmtp = nodep->forksp(); stmtp; stmtp = stmtp->nextp()) {
|
||||||
reset();
|
reset();
|
||||||
iterateConst(stmtp);
|
iterateConst(stmtp);
|
||||||
totalCount += m_instrCount;
|
totalCount += m_instrCount;
|
||||||
|
|
|
||||||
|
|
@ -1258,20 +1258,26 @@ class LinkDotFindVisitor final : public VNVisitor {
|
||||||
// unnamed#'s would just confuse tracing variables in
|
// unnamed#'s would just confuse tracing variables in
|
||||||
// places such as tasks, where "task ...; begin ... end"
|
// places such as tasks, where "task ...; begin ... end"
|
||||||
// are common.
|
// are common.
|
||||||
for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp = stmtp->nextp()) {
|
const auto containsDecl = [](const AstNode* nodesp) -> bool {
|
||||||
if (VN_IS(stmtp, Var) || VN_IS(stmtp, Foreach)) {
|
for (const AstNode* np = nodesp; np; np = np->nextp()) {
|
||||||
|
if (VN_IS(np, Var) || VN_IS(np, Foreach)) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
bool needName = nodep->declsp() || containsDecl(nodep->stmtsp());
|
||||||
|
if (const AstFork* const forkp = VN_CAST(nodep, Fork)) {
|
||||||
|
needName = needName || containsDecl(forkp->forksp());
|
||||||
|
}
|
||||||
|
if (needName) {
|
||||||
|
const std::string stepStr
|
||||||
|
= m_statep->forPrimary() ? "" : std::to_string(m_statep->stepNumber()) + "_";
|
||||||
std::string name;
|
std::string name;
|
||||||
const std::string stepStr = m_statep->forPrimary()
|
|
||||||
? ""
|
|
||||||
: std::to_string(m_statep->stepNumber()) + "_";
|
|
||||||
do {
|
do {
|
||||||
++m_modBlockNum;
|
++m_modBlockNum;
|
||||||
name = "unnamedblk" + stepStr + cvtToStr(m_modBlockNum);
|
name = "unnamedblk" + stepStr + cvtToStr(m_modBlockNum);
|
||||||
// Increment again if earlier pass of V3LinkDot claimed this name
|
// Increment again if earlier pass of V3LinkDot claimed this name
|
||||||
} while (m_curSymp->findIdFlat(name));
|
} while (m_curSymp->findIdFlat(name));
|
||||||
nodep->name(name);
|
nodep->name(name);
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (nodep->name() == "") {
|
if (nodep->name() == "") {
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ class LinkJumpVisitor final : public VNVisitor {
|
||||||
// AstBegin/etc::user1() -> AstJumpBlock*, for body of this loop
|
// AstBegin/etc::user1() -> AstJumpBlock*, for body of this loop
|
||||||
// AstFinish::user1() -> bool, processed
|
// AstFinish::user1() -> bool, processed
|
||||||
// AstNode::user2() -> AstJumpBlock*, for this block
|
// AstNode::user2() -> AstJumpBlock*, for this block
|
||||||
// AstNodeBlock::user3() -> bool, true if contains a fork
|
// AstNodeBegin::user3() -> bool, true if contains a fork
|
||||||
const VNUser1InUse m_user1InUse;
|
const VNUser1InUse m_user1InUse;
|
||||||
const VNUser2InUse m_user2InUse;
|
const VNUser2InUse m_user2InUse;
|
||||||
const VNUser3InUse m_user3InUse;
|
const VNUser3InUse m_user3InUse;
|
||||||
|
|
@ -80,9 +80,11 @@ class LinkJumpVisitor final : public VNVisitor {
|
||||||
|
|
||||||
AstNode* underp = nullptr;
|
AstNode* underp = nullptr;
|
||||||
bool under_and_next = true;
|
bool under_and_next = true;
|
||||||
if (AstNodeBlock* const blockp = VN_CAST(nodep, NodeBlock)) {
|
if (AstBegin* const blockp = VN_CAST(nodep, Begin)) {
|
||||||
|
UASSERT_OBJ(!endOfIter, nodep, "No endOfIter for Begin");
|
||||||
underp = blockp->stmtsp();
|
underp = blockp->stmtsp();
|
||||||
} else if (AstNodeFTask* const fTaskp = VN_CAST(nodep, NodeFTask)) {
|
} else if (AstNodeFTask* const fTaskp = VN_CAST(nodep, NodeFTask)) {
|
||||||
|
UASSERT_OBJ(!endOfIter, nodep, "No endOfIter for FTask");
|
||||||
underp = fTaskp->stmtsp();
|
underp = fTaskp->stmtsp();
|
||||||
} else if (AstForeach* const foreachp = VN_CAST(nodep, Foreach)) {
|
} else if (AstForeach* const foreachp = VN_CAST(nodep, Foreach)) {
|
||||||
if (endOfIter) {
|
if (endOfIter) {
|
||||||
|
|
@ -180,10 +182,10 @@ class LinkJumpVisitor final : public VNVisitor {
|
||||||
// handle is pushed to the queue. `disable` statement is replaced with calling `kill()`
|
// handle is pushed to the queue. `disable` statement is replaced with calling `kill()`
|
||||||
// method on each element of the queue.
|
// method on each element of the queue.
|
||||||
FileLine* const fl = nodep->fileline();
|
FileLine* const fl = nodep->fileline();
|
||||||
const std::string targetName = nodep->targetp()->name();
|
AstNode* const targetp = nodep->targetp();
|
||||||
if (m_ftaskp) {
|
if (m_ftaskp) {
|
||||||
if (!m_ftaskp->exists([targetp = nodep->targetp()](const AstNodeBlock* blockp)
|
if (!m_ftaskp->exists(
|
||||||
-> bool { return blockp == targetp; })) {
|
[targetp](const AstNodeBlock* blockp) -> bool { return blockp == targetp; })) {
|
||||||
// Disabling a fork, which is within the same task, is not a problem
|
// Disabling a fork, which is within the same task, is not a problem
|
||||||
nodep->v3warn(E_UNSUPPORTED, "Unsupported: disabling fork from task / function");
|
nodep->v3warn(E_UNSUPPORTED, "Unsupported: disabling fork from task / function");
|
||||||
}
|
}
|
||||||
|
|
@ -193,7 +195,7 @@ class LinkJumpVisitor final : public VNVisitor {
|
||||||
= VN_AS(getMemberp(v3Global.rootp()->stdPackagep(), "process"), Class);
|
= VN_AS(getMemberp(v3Global.rootp()->stdPackagep(), "process"), Class);
|
||||||
// Declare queue of processes (as a global variable for simplicity)
|
// Declare queue of processes (as a global variable for simplicity)
|
||||||
AstVar* const processQueuep = new AstVar{
|
AstVar* const processQueuep = new AstVar{
|
||||||
fl, VVarType::VAR, m_queueNames.get(targetName), VFlagChildDType{},
|
fl, VVarType::VAR, m_queueNames.get(targetp->name()), VFlagChildDType{},
|
||||||
new AstQueueDType{fl, VFlagChildDType{},
|
new AstQueueDType{fl, VFlagChildDType{},
|
||||||
new AstClassRefDType{fl, processClassp, nullptr}, nullptr}};
|
new AstClassRefDType{fl, processClassp, nullptr}, nullptr}};
|
||||||
processQueuep->lifetime(VLifetime::STATIC_EXPLICIT);
|
processQueuep->lifetime(VLifetime::STATIC_EXPLICIT);
|
||||||
|
|
@ -219,12 +221,21 @@ class LinkJumpVisitor final : public VNVisitor {
|
||||||
killQueueCall->classOrPackagep(processClassp);
|
killQueueCall->classOrPackagep(processClassp);
|
||||||
AstStmtExpr* const killStmtp = new AstStmtExpr{fl, killQueueCall};
|
AstStmtExpr* const killStmtp = new AstStmtExpr{fl, killQueueCall};
|
||||||
nodep->addNextHere(killStmtp);
|
nodep->addNextHere(killStmtp);
|
||||||
if (existsBlockAbove(targetName)) {
|
|
||||||
// process::kill doesn't kill the current process immediately, because it is in the
|
// 'process::kill' does not immediately kill the current process
|
||||||
// running state. Since the current process has to be terminated immediately, we jump
|
// executing the disable statement (because it's in the running state).
|
||||||
// at the end of the fork that is being disabled
|
// If the disable statement is indeed executed by a process under the
|
||||||
AstJumpBlock* const jumpBlockp = getJumpBlock(nodep->targetp(), false);
|
// target AstFork, then jump to the end of that fork branch.
|
||||||
killStmtp->addNextHere(new AstJumpGo{fl, jumpBlockp});
|
if (VN_IS(targetp, Fork)) {
|
||||||
|
AstNodeBlock* forkBranchp = nullptr;
|
||||||
|
for (AstNodeBlock* const blockp : vlstd::reverse_view(m_blockStack)) {
|
||||||
|
if (blockp == targetp) {
|
||||||
|
AstJumpBlock* const jmpBlockp = getJumpBlock(VN_AS(forkBranchp, Begin), false);
|
||||||
|
killStmtp->addNextHere(new AstJumpGo{fl, jmpBlockp});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
forkBranchp = blockp;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static bool directlyUnderFork(const AstNode* const nodep) {
|
static bool directlyUnderFork(const AstNode* const nodep) {
|
||||||
|
|
@ -247,24 +258,24 @@ class LinkJumpVisitor final : public VNVisitor {
|
||||||
m_ftaskp = nodep;
|
m_ftaskp = nodep;
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
}
|
}
|
||||||
void visit(AstNodeBlock* nodep) override {
|
void visit(AstBegin* nodep) override {
|
||||||
UINFO(8, " " << nodep);
|
UINFO(8, " " << nodep);
|
||||||
VL_RESTORER(m_inFork);
|
|
||||||
VL_RESTORER(m_unrollFull);
|
VL_RESTORER(m_unrollFull);
|
||||||
m_blockStack.push_back(nodep);
|
m_blockStack.push_back(nodep);
|
||||||
{
|
|
||||||
if (VN_IS(nodep, Fork)) {
|
|
||||||
m_inFork = true; // And remains set for children
|
|
||||||
// Mark all upper blocks also, can stop once see
|
|
||||||
// one set to avoid O(n^2)
|
|
||||||
for (auto itr : vlstd::reverse_view(m_blockStack)) {
|
|
||||||
if (itr->user3()) break;
|
|
||||||
itr->user3(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nodep->user3(m_inFork);
|
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
|
m_blockStack.pop_back();
|
||||||
}
|
}
|
||||||
|
void visit(AstFork* nodep) override {
|
||||||
|
UINFO(8, " " << nodep);
|
||||||
|
VL_RESTORER(m_unrollFull);
|
||||||
|
VL_RESTORER(m_inFork);
|
||||||
|
m_inFork = true;
|
||||||
|
// Mark all upper blocks, can stop once see one set to avoid O(n^2)
|
||||||
|
for (AstNodeBlock* const blockp : vlstd::reverse_view(m_blockStack)) {
|
||||||
|
if (blockp->user3SetOnce()) break;
|
||||||
|
}
|
||||||
|
m_blockStack.push_back(nodep);
|
||||||
|
iterateChildren(nodep);
|
||||||
m_blockStack.pop_back();
|
m_blockStack.pop_back();
|
||||||
}
|
}
|
||||||
void visit(AstStmtPragma* nodep) override {
|
void visit(AstStmtPragma* nodep) override {
|
||||||
|
|
@ -392,32 +403,17 @@ class LinkJumpVisitor final : public VNVisitor {
|
||||||
void visit(AstDisable* nodep) override {
|
void visit(AstDisable* nodep) override {
|
||||||
UINFO(8, " DISABLE " << nodep);
|
UINFO(8, " DISABLE " << nodep);
|
||||||
AstNode* const targetp = nodep->targetp();
|
AstNode* const targetp = nodep->targetp();
|
||||||
FileLine* const fl = nodep->fileline();
|
|
||||||
UASSERT_OBJ(targetp, nodep, "Unlinked disable statement");
|
UASSERT_OBJ(targetp, nodep, "Unlinked disable statement");
|
||||||
if (VN_IS(targetp, Task)) {
|
if (VN_IS(targetp, Task)) {
|
||||||
nodep->v3warn(E_UNSUPPORTED, "Unsupported: disabling task by name");
|
nodep->v3warn(E_UNSUPPORTED, "Unsupported: disabling task by name");
|
||||||
} else if (AstFork* const forkp = VN_CAST(targetp, Fork)) {
|
} else if (AstFork* const forkp = VN_CAST(targetp, Fork)) {
|
||||||
std::vector<AstBegin*> forks;
|
std::vector<AstBegin*> forks;
|
||||||
for (AstNode* forkItemp = forkp->stmtsp(); forkItemp; forkItemp = forkItemp->nextp()) {
|
for (AstBegin* itemp = forkp->forksp(); itemp; itemp = VN_AS(itemp->nextp(), Begin)) {
|
||||||
// Further handling of disable stmt requires all forks to be begin blocks
|
forks.push_back(itemp);
|
||||||
AstBegin* beginp = VN_CAST(forkItemp, Begin);
|
|
||||||
if (!beginp) {
|
|
||||||
beginp = new AstBegin{fl, "", nullptr, false};
|
|
||||||
forkItemp->replaceWith(beginp);
|
|
||||||
beginp->addStmtsp(forkItemp);
|
|
||||||
// In order to continue the iteration
|
|
||||||
forkItemp = beginp;
|
|
||||||
}
|
|
||||||
forks.push_back(beginp);
|
|
||||||
}
|
}
|
||||||
handleDisableOnFork(nodep, forks);
|
handleDisableOnFork(nodep, forks);
|
||||||
} else if (AstBegin* const beginp = VN_CAST(targetp, Begin)) {
|
} else if (AstBegin* const beginp = VN_CAST(targetp, Begin)) {
|
||||||
if (directlyUnderFork(beginp)) {
|
if (existsBlockAbove(beginp->name())) {
|
||||||
std::vector<AstBegin*> forks{beginp};
|
|
||||||
handleDisableOnFork(nodep, forks);
|
|
||||||
} else {
|
|
||||||
const std::string targetName = beginp->name();
|
|
||||||
if (existsBlockAbove(targetName)) {
|
|
||||||
if (beginp->user3()) {
|
if (beginp->user3()) {
|
||||||
nodep->v3warn(E_UNSUPPORTED,
|
nodep->v3warn(E_UNSUPPORTED,
|
||||||
"Unsupported: disabling block that contains a fork");
|
"Unsupported: disabling block that contains a fork");
|
||||||
|
|
@ -426,9 +422,13 @@ class LinkJumpVisitor final : public VNVisitor {
|
||||||
AstJumpBlock* const blockp = getJumpBlock(beginp, false);
|
AstJumpBlock* const blockp = getJumpBlock(beginp, false);
|
||||||
nodep->addNextHere(new AstJumpGo{nodep->fileline(), blockp});
|
nodep->addNextHere(new AstJumpGo{nodep->fileline(), blockp});
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (directlyUnderFork(beginp)) {
|
||||||
|
std::vector<AstBegin*> forks{beginp};
|
||||||
|
handleDisableOnFork(nodep, forks);
|
||||||
} else {
|
} else {
|
||||||
nodep->v3warn(E_UNSUPPORTED, "disable isn't underneath a begin with name: '"
|
nodep->v3warn(E_UNSUPPORTED, "disable isn't underneath a begin with name: '"
|
||||||
<< targetName << "'");
|
<< beginp->name() << "'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,7 @@ class LinkParseVisitor final : public VNVisitor {
|
||||||
AstNodeModule* m_modp = nullptr; // Current module
|
AstNodeModule* m_modp = nullptr; // Current module
|
||||||
AstNodeProcedure* m_procedurep = nullptr; // Current procedure
|
AstNodeProcedure* m_procedurep = nullptr; // Current procedure
|
||||||
AstNodeFTask* m_ftaskp = nullptr; // Current task
|
AstNodeFTask* m_ftaskp = nullptr; // Current task
|
||||||
|
AstNodeBlock* m_blockp = nullptr; // Current AstNodeBlock
|
||||||
AstNodeDType* m_dtypep = nullptr; // Current data type
|
AstNodeDType* m_dtypep = nullptr; // Current data type
|
||||||
AstNodeExpr* m_defaultInSkewp = nullptr; // Current default input skew
|
AstNodeExpr* m_defaultInSkewp = nullptr; // Current default input skew
|
||||||
AstNodeExpr* m_defaultOutSkewp = nullptr; // Current default output skew
|
AstNodeExpr* m_defaultOutSkewp = nullptr; // Current default output skew
|
||||||
|
|
@ -377,20 +378,27 @@ class LinkParseVisitor final : public VNVisitor {
|
||||||
if (m_procedurep && VN_IS(m_procedurep, Always))
|
if (m_procedurep && VN_IS(m_procedurep, Always))
|
||||||
nodep->fileline()->modifyWarnOff(V3ErrorCode::BLKSEQ, true);
|
nodep->fileline()->modifyWarnOff(V3ErrorCode::BLKSEQ, true);
|
||||||
if (nodep->valuep()) {
|
if (nodep->valuep()) {
|
||||||
// A variable with an = value can be three things:
|
|
||||||
FileLine* const fl = nodep->valuep()->fileline();
|
FileLine* const fl = nodep->valuep()->fileline();
|
||||||
|
// A variable with an = value can be 4 things:
|
||||||
if (nodep->isParam() || (m_ftaskp && nodep->isNonOutput())) {
|
if (nodep->isParam() || (m_ftaskp && nodep->isNonOutput())) {
|
||||||
// 1. Parameters and function inputs: It's a default to use if not overridden
|
// 1. Parameters and function inputs: It's a default to use if not overridden
|
||||||
} else if (!m_ftaskp && !VN_IS(m_modp, Class) && nodep->isNonOutput()
|
} else if (!m_ftaskp && !VN_IS(m_modp, Class) && nodep->isNonOutput()
|
||||||
&& !nodep->isInput()) {
|
&& !nodep->isInput()) {
|
||||||
// Module inout/ref/constref: const default to use
|
// 2. Module inout/ref/constref: const default to use
|
||||||
nodep->v3warn(E_UNSUPPORTED,
|
nodep->v3warn(E_UNSUPPORTED,
|
||||||
"Unsupported: Default value on module inout/ref/constref: "
|
"Unsupported: Default value on module inout/ref/constref: "
|
||||||
<< nodep->prettyNameQ());
|
<< nodep->prettyNameQ());
|
||||||
nodep->valuep()->unlinkFrBack()->deleteTree();
|
nodep->valuep()->unlinkFrBack()->deleteTree();
|
||||||
} // 2. Under modules/class, it's an initial value to be loaded at time 0 via an
|
} else if (m_blockp) {
|
||||||
// AstInitial
|
// 3. Under blocks, it's an initial value to be under an assign
|
||||||
else if (m_valueModp) {
|
// TODO: This is wrong if it's a static variable right?
|
||||||
|
FileLine* const newfl = new FileLine{fl};
|
||||||
|
newfl->warnOff(V3ErrorCode::E_CONSTWRITTEN, true);
|
||||||
|
m_blockp->addStmtsp(
|
||||||
|
new AstAssign{newfl, new AstVarRef{newfl, nodep, VAccess::WRITE},
|
||||||
|
VN_AS(nodep->valuep()->unlinkFrBack(), NodeExpr)});
|
||||||
|
} else if (m_valueModp) {
|
||||||
|
// 4. Under modules/class, it's the time 0 initialziation value
|
||||||
// Making an AstAssign (vs AstAssignW) to a wire is an error, suppress it
|
// Making an AstAssign (vs AstAssignW) to a wire is an error, suppress it
|
||||||
FileLine* const newfl = new FileLine{fl};
|
FileLine* const newfl = new FileLine{fl};
|
||||||
newfl->warnOff(V3ErrorCode::PROCASSWIRE, true);
|
newfl->warnOff(V3ErrorCode::PROCASSWIRE, true);
|
||||||
|
|
@ -405,13 +413,8 @@ class LinkParseVisitor final : public VNVisitor {
|
||||||
} else {
|
} else {
|
||||||
nodep->addNextHere(new AstInitialStatic{newfl, assp});
|
nodep->addNextHere(new AstInitialStatic{newfl, assp});
|
||||||
}
|
}
|
||||||
} // 4. Under blocks, it's an initial value to be under an assign
|
} else {
|
||||||
else {
|
nodep->v3fatalSrc("Variable with initializer in unexpected position");
|
||||||
FileLine* const newfl = new FileLine{fl};
|
|
||||||
newfl->warnOff(V3ErrorCode::E_CONSTWRITTEN, true);
|
|
||||||
nodep->addNextHere(
|
|
||||||
new AstAssign{newfl, new AstVarRef{newfl, nodep, VAccess::WRITE},
|
|
||||||
VN_AS(nodep->valuep()->unlinkFrBack(), NodeExpr)});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -762,10 +765,23 @@ class LinkParseVisitor final : public VNVisitor {
|
||||||
}
|
}
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
}
|
}
|
||||||
void visit(AstBegin* nodep) override {
|
void visit(AstNodeBlock* nodep) override {
|
||||||
V3Control::applyCoverageBlock(m_modp, nodep);
|
{
|
||||||
|
VL_RESTORER(m_blockp);
|
||||||
|
m_blockp = nodep;
|
||||||
|
// Temporarily unlink the statements so variable initializers can be inserted in order
|
||||||
|
AstNode* const stmtsp = nodep->stmtsp();
|
||||||
|
if (stmtsp) stmtsp->unlinkFrBackWithNext();
|
||||||
|
iterateAndNextNull(nodep->declsp());
|
||||||
|
nodep->addStmtsp(stmtsp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AstBegin* const beginp = VN_CAST(nodep, Begin)) {
|
||||||
|
V3Control::applyCoverageBlock(m_modp, beginp);
|
||||||
|
}
|
||||||
cleanFileline(nodep);
|
cleanFileline(nodep);
|
||||||
iterateChildren(nodep);
|
iterateAndNextNull(nodep->stmtsp());
|
||||||
|
if (AstFork* const forkp = VN_CAST(nodep, Fork)) iterateAndNextNull(forkp->forksp());
|
||||||
}
|
}
|
||||||
void visit(AstCase* nodep) override {
|
void visit(AstCase* nodep) override {
|
||||||
V3Control::applyCase(nodep);
|
V3Control::applyCase(nodep);
|
||||||
|
|
|
||||||
|
|
@ -304,16 +304,6 @@ public:
|
||||||
return m_scopedSigAttr ? m_scopedSigAttr->cloneTree(true) : nullptr;
|
return m_scopedSigAttr ? m_scopedSigAttr->cloneTree(true) : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void addForkStmtsp(AstFork* forkp, AstNode* stmtsp) {
|
|
||||||
forkp->addStmtsp(stmtsp);
|
|
||||||
for (AstNode* stmtp = stmtsp; stmtp; stmtp = stmtp->nextp()) {
|
|
||||||
AstVar* const varp = VN_CAST(stmtp, Var);
|
|
||||||
if (!varp) break;
|
|
||||||
varp->unlinkFrBack();
|
|
||||||
forkp->addInitsp(varp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void createGenericIface(AstNode* const nodep, AstNodeRange* const rangep,
|
void createGenericIface(AstNode* const nodep, AstNodeRange* const rangep,
|
||||||
AstNode* sigAttrListp, FileLine* const modportFileline = nullptr,
|
AstNode* sigAttrListp, FileLine* const modportFileline = nullptr,
|
||||||
const string& modportstrp = "") {
|
const string& modportstrp = "") {
|
||||||
|
|
@ -334,4 +324,17 @@ public:
|
||||||
createVariable(nodep->fileline(), nodep->name(), rangep, sigAttrListp));
|
createVariable(nodep->fileline(), nodep->name(), rangep, sigAttrListp));
|
||||||
m_varDecl = VVarType::VAR;
|
m_varDecl = VVarType::VAR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Wrap all statements in the given list in an AstBegin (except those already an AstBegin)
|
||||||
|
static AstBegin* wrapInBegin(AstNodeStmt* stmtsp) {
|
||||||
|
AstBegin* resp = nullptr;
|
||||||
|
for (AstNodeStmt *nodep = stmtsp, *nextp; nodep; nodep = nextp) {
|
||||||
|
nextp = VN_AS(nodep->nextp(), NodeStmt);
|
||||||
|
if (nextp) nextp->unlinkFrBackWithNext();
|
||||||
|
AstBegin* beginp = VN_CAST(nodep, Begin);
|
||||||
|
if (!beginp) beginp = new AstBegin{nodep->fileline(), "", nodep, true};
|
||||||
|
resp = AstNode::addNext(resp, beginp);
|
||||||
|
}
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -360,8 +360,8 @@ void transformForks(AstNetlist* const netlistp) {
|
||||||
// Replace self with the function calls (no co_await, as we don't want the main
|
// Replace self with the function calls (no co_await, as we don't want the main
|
||||||
// process to suspend whenever any of the children do)
|
// process to suspend whenever any of the children do)
|
||||||
// V3Dead could have removed all statements from the fork, so guard against it
|
// V3Dead could have removed all statements from the fork, so guard against it
|
||||||
AstNode* const stmtsp = nodep->stmtsp();
|
if (nodep->forksp()) nodep->addNextHere(nodep->forksp()->unlinkFrBackWithNext());
|
||||||
if (stmtsp) nodep->addNextHere(stmtsp->unlinkFrBackWithNext());
|
if (nodep->stmtsp()) nodep->addNextHere(nodep->stmtsp()->unlinkFrBackWithNext());
|
||||||
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
|
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
|
||||||
}
|
}
|
||||||
void visit(AstBegin* nodep) override {
|
void visit(AstBegin* nodep) override {
|
||||||
|
|
|
||||||
|
|
@ -142,10 +142,11 @@ private:
|
||||||
void visit(AstFork* nodep) override {
|
void visit(AstFork* nodep) override {
|
||||||
if (m_ignoreRemaining) return;
|
if (m_ignoreRemaining) return;
|
||||||
const VisitBase vb{this, nodep};
|
const VisitBase vb{this, nodep};
|
||||||
|
iterateAndNextConstNull(nodep->stmtsp());
|
||||||
uint32_t totalCount = m_stackSize;
|
uint32_t totalCount = m_stackSize;
|
||||||
VL_RESTORER(m_ignoreRemaining);
|
VL_RESTORER(m_ignoreRemaining);
|
||||||
// Sum counts in each statement
|
// Sum counts in each statement
|
||||||
for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp = stmtp->nextp()) {
|
for (AstNode* stmtp = nodep->forksp(); stmtp; stmtp = stmtp->nextp()) {
|
||||||
reset();
|
reset();
|
||||||
iterateConst(stmtp);
|
iterateConst(stmtp);
|
||||||
totalCount += m_stackSize;
|
totalCount += m_stackSize;
|
||||||
|
|
|
||||||
|
|
@ -731,7 +731,7 @@ class TimingControlVisitor final : public VNVisitor {
|
||||||
= createTemp(flp, forkp->name() + "__sync", getCreateForkSyncDTypep(), insertBeforep);
|
= createTemp(flp, forkp->name() + "__sync", getCreateForkSyncDTypep(), insertBeforep);
|
||||||
unsigned joinCount = 0; // Needed for join counter
|
unsigned joinCount = 0; // Needed for join counter
|
||||||
// Add a <fork sync>.done() to each begin
|
// Add a <fork sync>.done() to each begin
|
||||||
for (AstNode* beginp = forkp->stmtsp(); beginp; beginp = beginp->nextp()) {
|
for (AstNode* beginp = forkp->forksp(); beginp; beginp = beginp->nextp()) {
|
||||||
addForkDone(VN_AS(beginp, Begin), forkVscp);
|
addForkDone(VN_AS(beginp, Begin), forkVscp);
|
||||||
joinCount++;
|
joinCount++;
|
||||||
}
|
}
|
||||||
|
|
@ -1025,10 +1025,7 @@ class TimingControlVisitor final : public VNVisitor {
|
||||||
// Put it in a fork so it doesn't block
|
// Put it in a fork so it doesn't block
|
||||||
// Could already be the only thing directly under a fork, reuse that if possible
|
// Could already be the only thing directly under a fork, reuse that if possible
|
||||||
AstFork* forkp = !nodep->nextp() ? VN_CAST(nodep->firstAbovep(), Fork) : nullptr;
|
AstFork* forkp = !nodep->nextp() ? VN_CAST(nodep->firstAbovep(), Fork) : nullptr;
|
||||||
if (!forkp) {
|
if (!forkp) forkp = new AstFork{flp, VJoinType::JOIN_NONE};
|
||||||
forkp = new AstFork{flp, "", nullptr};
|
|
||||||
forkp->joinType(VJoinType::JOIN_NONE);
|
|
||||||
}
|
|
||||||
if (!m_underProcedure) {
|
if (!m_underProcedure) {
|
||||||
// If it's in a function, it won't be handled by V3Delayed
|
// If it's in a function, it won't be handled by V3Delayed
|
||||||
// Put it behind an additional named event that gets triggered in the NBA region
|
// Put it behind an additional named event that gets triggered in the NBA region
|
||||||
|
|
@ -1043,7 +1040,7 @@ class TimingControlVisitor final : public VNVisitor {
|
||||||
controlp->replaceWith(forkp);
|
controlp->replaceWith(forkp);
|
||||||
AstBegin* beginp = VN_CAST(controlp, Begin);
|
AstBegin* beginp = VN_CAST(controlp, Begin);
|
||||||
if (!beginp) beginp = new AstBegin{nodep->fileline(), "", controlp, false};
|
if (!beginp) beginp = new AstBegin{nodep->fileline(), "", controlp, false};
|
||||||
forkp->addStmtsp(beginp);
|
forkp->addForksp(beginp);
|
||||||
controlp = forkp;
|
controlp = forkp;
|
||||||
}
|
}
|
||||||
UASSERT_OBJ(nodep, controlp, "Assignment should have timing control");
|
UASSERT_OBJ(nodep, controlp, "Assignment should have timing control");
|
||||||
|
|
@ -1115,11 +1112,11 @@ class TimingControlVisitor final : public VNVisitor {
|
||||||
AstNode* const controlp = nodep->timingControlp()->unlinkFrBack();
|
AstNode* const controlp = nodep->timingControlp()->unlinkFrBack();
|
||||||
AstAssign* const assignp = new AstAssign{nodep->fileline(), lhs1p, rhs1p, controlp};
|
AstAssign* const assignp = new AstAssign{nodep->fileline(), lhs1p, rhs1p, controlp};
|
||||||
// Put the assignment in a fork..join_none.
|
// Put the assignment in a fork..join_none.
|
||||||
AstBegin* const beginp = new AstBegin{flp, "", assignp, false};
|
AstFork* const forkp = new AstFork{flp, VJoinType::JOIN_NONE};
|
||||||
AstFork* const forkp = new AstFork{flp, "", beginp};
|
|
||||||
forkp->joinType(VJoinType::JOIN_NONE);
|
|
||||||
nodep->replaceWith(forkp);
|
nodep->replaceWith(forkp);
|
||||||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||||
|
AstBegin* const beginp = new AstBegin{flp, "", assignp, false};
|
||||||
|
forkp->addForksp(beginp);
|
||||||
visit(forkp); // Visit now as we need to do some post-processing
|
visit(forkp); // Visit now as we need to do some post-processing
|
||||||
// IEEE 1800-2023 10.3.3 - if the RHS value differs from the currently scheduled value to
|
// IEEE 1800-2023 10.3.3 - if the RHS value differs from the currently scheduled value to
|
||||||
// be assigned, the currently scheduled assignment is descheduled. To keep track if an
|
// be assigned, the currently scheduled assignment is descheduled. To keep track if an
|
||||||
|
|
@ -1239,21 +1236,23 @@ class TimingControlVisitor final : public VNVisitor {
|
||||||
void visit(AstFork* nodep) override {
|
void visit(AstFork* nodep) override {
|
||||||
if (nodep->user1SetOnce()) return;
|
if (nodep->user1SetOnce()) return;
|
||||||
v3Global.setUsesTiming();
|
v3Global.setUsesTiming();
|
||||||
|
|
||||||
// Create a unique name for this fork
|
// Create a unique name for this fork
|
||||||
nodep->name("__Vfork_" + cvtToStr(++m_forkCnt));
|
nodep->name("__Vfork_" + std::to_string(++m_forkCnt));
|
||||||
unsigned idx = 0; // Index for naming begins
|
|
||||||
AstNode* stmtp = nodep->stmtsp();
|
// TODO: Should process nodep->stmtsp() in case an earlier pass
|
||||||
// Put each statement in a begin
|
// inserted something there, but as of today we don't need to.
|
||||||
while (stmtp) {
|
|
||||||
UASSERT_OBJ(VN_IS(stmtp, Begin), nodep,
|
// Process and name each fork
|
||||||
"All statements under forks must be begins at this point");
|
size_t idx = 0; // Index for naming begins
|
||||||
AstBegin* const beginp = VN_AS(stmtp, Begin);
|
for (AstBegin *itemp = nodep->forksp(), *nextp; itemp; itemp = nextp) {
|
||||||
stmtp = beginp->nextp();
|
nextp = VN_AS(itemp->nextp(), Begin);
|
||||||
iterate(beginp);
|
iterate(itemp);
|
||||||
// Even if we do not find any awaits, we cannot simply inline the process here, as new
|
// Note: Even if we do not find any awaits, we cannot simply inline
|
||||||
// awaits could be added later.
|
// the process here, as new awaits could be added later.
|
||||||
|
|
||||||
// Name the begin (later the name will be used for a new function)
|
// Name the begin (later the name will be used for a new function)
|
||||||
beginp->name(nodep->name() + "__" + cvtToStr(idx++));
|
itemp->name(nodep->name() + "__" + std::to_string(idx++));
|
||||||
}
|
}
|
||||||
if (!nodep->joinType().joinNone()) makeForkJoin(nodep);
|
if (!nodep->joinType().joinNone()) makeForkJoin(nodep);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -741,16 +741,17 @@ class WidthVisitor final : public VNVisitor {
|
||||||
}
|
}
|
||||||
if (!nodep->fileline()->timingOn()
|
if (!nodep->fileline()->timingOn()
|
||||||
// With no statements, begin is identical
|
// With no statements, begin is identical
|
||||||
|| !nodep->stmtsp()
|
|| !nodep->forksp()
|
||||||
|| (!v3Global.opt.timing().isSetTrue() // If no --timing
|
|| (!v3Global.opt.timing().isSetTrue() // If no --timing
|
||||||
&& (v3Global.opt.bboxUnsup()
|
&& (v3Global.opt.bboxUnsup()
|
||||||
// With one statement and no timing, a begin block does as good as a
|
// With one statement and no timing, a begin block does as good as a
|
||||||
// fork/join or join_any
|
// fork/join or join_any
|
||||||
|| (!nodep->stmtsp()->nextp() && !nodep->joinType().joinNone())))) {
|
|| (!nodep->forksp()->nextp() && !nodep->joinType().joinNone())))) {
|
||||||
AstNode* stmtsp = nullptr;
|
AstBegin* const newp = new AstBegin{nodep->fileline(), nodep->name(), nullptr, false};
|
||||||
if (nodep->stmtsp()) stmtsp = nodep->stmtsp()->unlinkFrBack();
|
|
||||||
AstBegin* const newp = new AstBegin{nodep->fileline(), nodep->name(), stmtsp, false};
|
|
||||||
nodep->replaceWith(newp);
|
nodep->replaceWith(newp);
|
||||||
|
if (nodep->declsp()) newp->addDeclsp(nodep->declsp()->unlinkFrBackWithNext());
|
||||||
|
if (nodep->stmtsp()) newp->addStmtsp(nodep->stmtsp()->unlinkFrBackWithNext());
|
||||||
|
if (nodep->forksp()) newp->addStmtsp(nodep->forksp()->unlinkFrBackWithNext());
|
||||||
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
||||||
} else if (v3Global.opt.timing().isSetTrue()) {
|
} else if (v3Global.opt.timing().isSetTrue()) {
|
||||||
VL_RESTORER(m_underFork);
|
VL_RESTORER(m_underFork);
|
||||||
|
|
|
||||||
|
|
@ -3360,15 +3360,23 @@ senitemEdge<senItemp>: // IEEE: part of event_expression
|
||||||
seq_block<beginp>: // ==IEEE: seq_block
|
seq_block<beginp>: // ==IEEE: seq_block
|
||||||
// // IEEE doesn't allow declarations in unnamed blocks, but several simulators do.
|
// // IEEE doesn't allow declarations in unnamed blocks, but several simulators do.
|
||||||
// // So need AstBegin's even if unnamed to scope variables down
|
// // So need AstBegin's even if unnamed to scope variables down
|
||||||
seq_blockFront blockDeclStmtListE yEND endLabelE
|
yBEGIN startLabelE blockDeclListE stmtListE yEND endLabelE
|
||||||
{ $$ = $1; $1->addStmtsp($2);
|
{
|
||||||
GRAMMARP->endLabel($<fl>4, $1, $4); }
|
$$ = new AstBegin{$1, $2 ? *$2 : "", nullptr, false};
|
||||||
|
GRAMMARP->endLabel($<fl>6, $$, $6);
|
||||||
|
$$->addDeclsp($3);
|
||||||
|
$$->addStmtsp($4);
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
seq_blockPreId<beginp>: // IEEE: seq_block, but called with leading ID
|
seq_blockPreId<beginp>: // IEEE: seq_block, but called with leading ID
|
||||||
seq_blockFrontPreId blockDeclStmtListE yEND endLabelE
|
id yP_COLON__BEGIN yBEGIN blockDeclListE stmtListE yEND endLabelE
|
||||||
{ $$ = $1; $1->addStmtsp($2);
|
{
|
||||||
GRAMMARP->endLabel($<fl>4, $1, $4); }
|
$$ = new AstBegin{$3, *$1, nullptr, false};
|
||||||
|
GRAMMARP->endLabel($<fl>7, $$, $7);
|
||||||
|
$$->addDeclsp($4);
|
||||||
|
$$->addStmtsp($5);
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
par_blockJoin<joinType>:
|
par_blockJoin<joinType>:
|
||||||
|
|
@ -3378,61 +3386,28 @@ par_blockJoin<joinType>:
|
||||||
;
|
;
|
||||||
|
|
||||||
par_block<forkp>: // ==IEEE: par_block
|
par_block<forkp>: // ==IEEE: par_block
|
||||||
par_blockFront blockDeclStmtListE par_blockJoin endLabelE
|
yFORK startLabelE blockDeclListE stmtListE par_blockJoin endLabelE
|
||||||
{ $$ = $1; $1->joinType($3);
|
{
|
||||||
V3ParseGrammar::addForkStmtsp($1, $2);
|
$$ = new AstFork{$1, $5, $2 ? *$2 : ""};
|
||||||
GRAMMARP->endLabel($<fl>4, $1, $4); }
|
GRAMMARP->endLabel($<fl>6, $$, $6);
|
||||||
|
$$->addDeclsp($3);
|
||||||
|
$$->addForksp(V3ParseGrammar::wrapInBegin($4));
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
par_blockPreId<forkp>: // ==IEEE: par_block but called with leading ID
|
par_blockPreId<forkp>: // ==IEEE: par_block but called with leading ID
|
||||||
par_blockFrontPreId blockDeclStmtListE par_blockJoin endLabelE
|
id yP_COLON__FORK yFORK blockDeclListE stmtListE par_blockJoin endLabelE
|
||||||
{ $$ = $1; $1->joinType($3);
|
{
|
||||||
V3ParseGrammar::addForkStmtsp($1, $2);
|
$$ = new AstFork{$3, $6, *$1};
|
||||||
GRAMMARP->endLabel($<fl>4, $1, $4); }
|
GRAMMARP->endLabel($<fl>7, $$, $7);
|
||||||
|
$$->addDeclsp($4);
|
||||||
|
$$->addForksp(V3ParseGrammar::wrapInBegin($5));
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
seq_blockFront<beginp>: // IEEE: part of seq_block
|
blockDeclListE<nodep>: // IEEE: [ block_item_declaration ]
|
||||||
yBEGIN
|
|
||||||
{ $$ = new AstBegin{$1, "", nullptr, false}; }
|
|
||||||
| yBEGIN ':' idAny/*new-block_identifier*/
|
|
||||||
{ $$ = new AstBegin{$<fl>3, *$3, nullptr, false}; }
|
|
||||||
;
|
|
||||||
|
|
||||||
par_blockFront<forkp>: // IEEE: part of par_block
|
|
||||||
yFORK
|
|
||||||
{ $$ = new AstFork{$1, "", nullptr}; }
|
|
||||||
| yFORK ':' idAny/*new-block_identifier*/
|
|
||||||
{ $$ = new AstFork{$<fl>3, *$3, nullptr}; }
|
|
||||||
;
|
|
||||||
|
|
||||||
seq_blockFrontPreId<beginp>: // IEEE: part of seq_block/stmt with leading id
|
|
||||||
id/*block_identifier*/ yP_COLON__BEGIN yBEGIN
|
|
||||||
{ $$ = new AstBegin{$3, *$1, nullptr, false}; }
|
|
||||||
;
|
|
||||||
|
|
||||||
par_blockFrontPreId<forkp>: // IEEE: part of par_block/stmt with leading id
|
|
||||||
id/*block_identifier*/ yP_COLON__FORK yFORK
|
|
||||||
{ $$ = new AstFork{$3, *$1, nullptr}; }
|
|
||||||
;
|
|
||||||
|
|
||||||
|
|
||||||
blockDeclStmtList<nodep>: // IEEE: { block_item_declaration } { statement or null }
|
|
||||||
// // The spec seems to suggest a empty declaration isn't ok, but most simulators take it
|
|
||||||
block_item_declarationList { $$ = $1; }
|
|
||||||
| block_item_declarationList stmtList { $$ = addNextNull($1, $2); }
|
|
||||||
| stmtList { $$ = $1; }
|
|
||||||
;
|
|
||||||
|
|
||||||
blockDeclStmtListE<nodep>: // IEEE: [ { block_item_declaration } { statement or null } ]
|
|
||||||
/*empty*/ { $$ = nullptr; }
|
/*empty*/ { $$ = nullptr; }
|
||||||
| blockDeclStmtList { $$ = $1; }
|
| blockDeclListE block_item_declaration { $$ = addNextNull($1, $2); }
|
||||||
;
|
|
||||||
|
|
||||||
block_item_declarationList<nodep>: // IEEE: [ block_item_declaration ]
|
|
||||||
block_item_declaration { $$ = $1; }
|
|
||||||
| block_item_declarationList block_item_declaration { $$ = addNextNull($1, $2); }
|
|
||||||
//
|
|
||||||
| block_item_declarationList error ';' { $$ = $1; } // LCOV_EXCL_LINE
|
|
||||||
| error ';' { $$ = nullptr; } // LCOV_EXCL_LINE
|
| error ';' { $$ = nullptr; } // LCOV_EXCL_LINE
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
@ -3442,6 +3417,11 @@ block_item_declaration<nodep>: // ==IEEE: block_item_declaration
|
||||||
| let_declaration { $$ = $1; }
|
| let_declaration { $$ = $1; }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
stmtListE<nodeStmtp>:
|
||||||
|
/*empty*/ { $$ = nullptr; }
|
||||||
|
| stmtList { $$ = $1; }
|
||||||
|
;
|
||||||
|
|
||||||
stmtList<nodeStmtp>:
|
stmtList<nodeStmtp>:
|
||||||
stmt { $$ = $1; }
|
stmt { $$ = $1; }
|
||||||
| stmtList stmt { $$ = addNextNull($1, $2); }
|
| stmtList stmt { $$ = addNextNull($1, $2); }
|
||||||
|
|
@ -6092,6 +6072,11 @@ strAsIntIgnore<nodeExprp>: // strAsInt, but never matches for when expr
|
||||||
yaSTRING__IGNORE { $$ = nullptr; yyerror("Impossible token"); }
|
yaSTRING__IGNORE { $$ = nullptr; yyerror("Impossible token"); }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
startLabelE<strp>:
|
||||||
|
/* empty */ { $$ = nullptr; $<fl>$ = nullptr; }
|
||||||
|
| ':' idAny { $$ = $2; $<fl>$ = $<fl>2; }
|
||||||
|
;
|
||||||
|
|
||||||
endLabelE<strp>:
|
endLabelE<strp>:
|
||||||
/* empty */ { $$ = nullptr; $<fl>$ = nullptr; }
|
/* empty */ { $$ = nullptr; $<fl>$ = nullptr; }
|
||||||
| ':' idAny { $$ = $2; $<fl>$ = $<fl>2; }
|
| ':' idAny { $$ = $2; $<fl>$ = $<fl>2; }
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
{"type":"VAR","name":"p","addr":"(G)","loc":"d,69:11,69:12","dtypep":"(H)","origName":"p","isSc":false,"isPrimaryIO":false,"isPrimaryClock":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"lifetime":"VSTATICI","varType":"VAR","dtypeName":"Packet","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"ignorePostWrite":false,"ignoreSchedWrite":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
|
{"type":"VAR","name":"p","addr":"(G)","loc":"d,69:11,69:12","dtypep":"(H)","origName":"p","isSc":false,"isPrimaryIO":false,"isPrimaryClock":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"lifetime":"VSTATICI","varType":"VAR","dtypeName":"Packet","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"ignorePostWrite":false,"ignoreSchedWrite":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
|
||||||
{"type":"INITIAL","name":"","addr":"(I)","loc":"d,71:4,71:11","isSuspendable":false,"needProcess":false,
|
{"type":"INITIAL","name":"","addr":"(I)","loc":"d,71:4,71:11","isSuspendable":false,"needProcess":false,
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"BEGIN","name":"","addr":"(J)","loc":"d,71:12,71:17","implied":false,"needProcess":false,"unnamed":true,
|
{"type":"BEGIN","name":"","addr":"(J)","loc":"d,71:12,71:17","implied":false,"needProcess":false,"unnamed":true,"declsp": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"DISPLAY","name":"","addr":"(K)","loc":"d,73:7,73:13",
|
{"type":"DISPLAY","name":"","addr":"(K)","loc":"d,73:7,73:13",
|
||||||
"fmtp": [
|
"fmtp": [
|
||||||
|
|
|
||||||
|
|
@ -9,13 +9,104 @@ module t;
|
||||||
int x = 0;
|
int x = 0;
|
||||||
fork : fork_blk
|
fork : fork_blk
|
||||||
begin
|
begin
|
||||||
|
#1;
|
||||||
|
disable fork_blk; // Disables both forked processes
|
||||||
|
$stop;
|
||||||
|
end
|
||||||
|
begin
|
||||||
|
if ($time != 0) $stop;
|
||||||
x = 1;
|
x = 1;
|
||||||
disable fork_blk;
|
#2;
|
||||||
x = 2;
|
$stop;
|
||||||
end
|
end
|
||||||
join_none
|
join_none
|
||||||
#1;
|
#1;
|
||||||
if (x != 1) $stop;
|
if (x != 1) begin
|
||||||
|
$display(x);
|
||||||
|
$stop;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
int y = 0;
|
||||||
|
fork
|
||||||
|
begin : fork_branch
|
||||||
|
#1;
|
||||||
|
disable fork_branch; // Disables only this branch of the fork
|
||||||
|
$stop;
|
||||||
|
end
|
||||||
|
begin
|
||||||
|
if ($time != 0) $stop;
|
||||||
|
y = 1;
|
||||||
|
#2;
|
||||||
|
if ($time != 2) $stop;
|
||||||
|
y = 2;
|
||||||
|
end
|
||||||
|
join_none
|
||||||
|
#1;
|
||||||
|
if (y != 1) begin
|
||||||
|
$display(y);
|
||||||
|
$stop;
|
||||||
|
end
|
||||||
|
#1;
|
||||||
|
if (y != 2) begin
|
||||||
|
$display(y);
|
||||||
|
$stop;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// TODO: This doesn't work due to the second fork branch not being added to
|
||||||
|
// the killQueue when the 'disable' is executed with no delay after
|
||||||
|
// the fork starts. See the case below which is the same, but the
|
||||||
|
// fork branches are in the opposite order so it happens to work.
|
||||||
|
//initial begin
|
||||||
|
// fork : fork_blk2
|
||||||
|
// begin
|
||||||
|
// if ($time != 0) $stop;
|
||||||
|
// disable fork_blk2;
|
||||||
|
// $stop;
|
||||||
|
// end
|
||||||
|
// begin
|
||||||
|
// if ($time != 0) $stop;
|
||||||
|
// #1 $stop;
|
||||||
|
// end
|
||||||
|
// join_none
|
||||||
|
//end
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
fork : fork_blk3
|
||||||
|
begin
|
||||||
|
if ($time != 0) $stop;
|
||||||
|
#1 $stop;
|
||||||
|
end
|
||||||
|
begin
|
||||||
|
if ($time != 0) $stop;
|
||||||
|
disable fork_blk3;
|
||||||
|
$stop;
|
||||||
|
end
|
||||||
|
join_none
|
||||||
|
end
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
fork : fork_blk4
|
||||||
|
begin
|
||||||
|
if ($time != 0) $stop;
|
||||||
|
if ($c("false")) begin
|
||||||
|
disable fork_blk4;
|
||||||
|
$stop;
|
||||||
|
end
|
||||||
|
#1;
|
||||||
|
end
|
||||||
|
begin
|
||||||
|
if ($time != 0) $stop;
|
||||||
|
#1;
|
||||||
|
if ($time != 1) $stop;
|
||||||
|
end
|
||||||
|
join_none
|
||||||
|
end
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
#10;
|
||||||
$write("*-* All Finished *-*\n");
|
$write("*-* All Finished *-*\n");
|
||||||
$finish;
|
$finish;
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -166,7 +166,7 @@
|
||||||
]}
|
]}
|
||||||
],
|
],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"BEGIN","name":"","addr":"(ZC)","loc":"e,36:27,36:32","implied":false,"needProcess":false,"unnamed":true,
|
{"type":"BEGIN","name":"","addr":"(ZC)","loc":"e,36:27,36:32","implied":false,"needProcess":false,"unnamed":true,"declsp": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"ASSIGNDLY","name":"","addr":"(AD)","loc":"e,40:11,40:13","dtypep":"UNLINKED",
|
{"type":"ASSIGNDLY","name":"","addr":"(AD)","loc":"e,40:11,40:13","dtypep":"UNLINKED",
|
||||||
"rhsp": [
|
"rhsp": [
|
||||||
|
|
@ -314,7 +314,7 @@
|
||||||
]}
|
]}
|
||||||
],
|
],
|
||||||
"thensp": [
|
"thensp": [
|
||||||
{"type":"BEGIN","name":"","addr":"(BF)","loc":"e,43:21,43:26","implied":false,"needProcess":false,"unnamed":true,
|
{"type":"BEGIN","name":"","addr":"(BF)","loc":"e,43:21,43:26","implied":false,"needProcess":false,"unnamed":true,"declsp": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"ASSIGNDLY","name":"","addr":"(CF)","loc":"e,45:14,45:16","dtypep":"UNLINKED",
|
{"type":"ASSIGNDLY","name":"","addr":"(CF)","loc":"e,45:14,45:16","dtypep":"UNLINKED",
|
||||||
"rhsp": [
|
"rhsp": [
|
||||||
|
|
@ -344,7 +344,7 @@
|
||||||
]}
|
]}
|
||||||
],
|
],
|
||||||
"thensp": [
|
"thensp": [
|
||||||
{"type":"BEGIN","name":"","addr":"(OF)","loc":"e,48:26,48:31","implied":false,"needProcess":false,"unnamed":true,
|
{"type":"BEGIN","name":"","addr":"(OF)","loc":"e,48:26,48:31","implied":false,"needProcess":false,"unnamed":true,"declsp": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"ASSIGNDLY","name":"","addr":"(PF)","loc":"e,49:14,49:16","dtypep":"UNLINKED",
|
{"type":"ASSIGNDLY","name":"","addr":"(PF)","loc":"e,49:14,49:16","dtypep":"UNLINKED",
|
||||||
"rhsp": [
|
"rhsp": [
|
||||||
|
|
@ -367,7 +367,7 @@
|
||||||
]}
|
]}
|
||||||
],
|
],
|
||||||
"thensp": [
|
"thensp": [
|
||||||
{"type":"BEGIN","name":"","addr":"(XF)","loc":"e,51:26,51:31","implied":false,"needProcess":false,"unnamed":true,"stmtsp": []}
|
{"type":"BEGIN","name":"","addr":"(XF)","loc":"e,51:26,51:31","implied":false,"needProcess":false,"unnamed":true,"declsp": [],"stmtsp": []}
|
||||||
],
|
],
|
||||||
"elsesp": [
|
"elsesp": [
|
||||||
{"type":"IF","name":"","addr":"(YF)","loc":"e,53:12,53:14",
|
{"type":"IF","name":"","addr":"(YF)","loc":"e,53:12,53:14",
|
||||||
|
|
@ -381,7 +381,7 @@
|
||||||
]}
|
]}
|
||||||
],
|
],
|
||||||
"thensp": [
|
"thensp": [
|
||||||
{"type":"BEGIN","name":"","addr":"(CG)","loc":"e,53:27,53:32","implied":false,"needProcess":false,"unnamed":true,
|
{"type":"BEGIN","name":"","addr":"(CG)","loc":"e,53:27,53:32","implied":false,"needProcess":false,"unnamed":true,"declsp": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"DISPLAY","name":"","addr":"(DG)","loc":"e,54:10,54:16",
|
{"type":"DISPLAY","name":"","addr":"(DG)","loc":"e,54:10,54:16",
|
||||||
"fmtp": [
|
"fmtp": [
|
||||||
|
|
@ -485,7 +485,7 @@
|
||||||
]}
|
]}
|
||||||
],
|
],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"BEGIN","name":"","addr":"(WH)","loc":"e,82:26,82:31","implied":false,"needProcess":false,"unnamed":true,
|
{"type":"BEGIN","name":"","addr":"(WH)","loc":"e,82:26,82:31","implied":false,"needProcess":false,"unnamed":true,"declsp": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"ASSIGNDLY","name":"","addr":"(XH)","loc":"e,83:11,83:13","dtypep":"UNLINKED",
|
{"type":"ASSIGNDLY","name":"","addr":"(XH)","loc":"e,83:11,83:13","dtypep":"UNLINKED",
|
||||||
"rhsp": [
|
"rhsp": [
|
||||||
|
|
@ -535,7 +535,7 @@
|
||||||
"assertTypesp": [
|
"assertTypesp": [
|
||||||
{"type":"CONST","name":"?32?sh8","addr":"(QI)","loc":"e,90:25,90:26","dtypep":"(NF)"}
|
{"type":"CONST","name":"?32?sh8","addr":"(QI)","loc":"e,90:25,90:26","dtypep":"(NF)"}
|
||||||
],"directiveTypesp": []},
|
],"directiveTypesp": []},
|
||||||
{"type":"BEGIN","name":"blk","addr":"(RI)","loc":"e,91:15,91:18","implied":false,"needProcess":false,"unnamed":false,
|
{"type":"BEGIN","name":"blk","addr":"(RI)","loc":"e,91:7,91:12","implied":false,"needProcess":false,"unnamed":false,"declsp": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"DISABLE","name":"","addr":"(SI)","loc":"e,92:10,92:17",
|
{"type":"DISABLE","name":"","addr":"(SI)","loc":"e,92:10,92:17",
|
||||||
"targetRefp": [
|
"targetRefp": [
|
||||||
|
|
@ -547,9 +547,9 @@
|
||||||
]},
|
]},
|
||||||
{"type":"INITIAL","name":"","addr":"(UI)","loc":"e,95:4,95:11","isSuspendable":false,"needProcess":false,
|
{"type":"INITIAL","name":"","addr":"(UI)","loc":"e,95:4,95:11","isSuspendable":false,"needProcess":false,
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"BEGIN","name":"","addr":"(VI)","loc":"e,95:12,95:17","implied":false,"needProcess":false,"unnamed":true,
|
{"type":"BEGIN","name":"","addr":"(VI)","loc":"e,95:12,95:17","implied":false,"needProcess":false,"unnamed":true,"declsp": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"BEGIN","name":"assert_simple_immediate_else","addr":"(WI)","loc":"e,96:7,96:35","implied":false,"needProcess":false,"unnamed":false,
|
{"type":"BEGIN","name":"assert_simple_immediate_else","addr":"(WI)","loc":"e,96:7,96:35","implied":false,"needProcess":false,"unnamed":false,"declsp": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"ASSERT","name":"","addr":"(XI)","loc":"e,96:37,96:43","type":"[SIMPLE_IMMEDIATE]",
|
{"type":"ASSERT","name":"","addr":"(XI)","loc":"e,96:37,96:43","type":"[SIMPLE_IMMEDIATE]",
|
||||||
"propp": [
|
"propp": [
|
||||||
|
|
@ -565,7 +565,7 @@
|
||||||
],"filep": []}
|
],"filep": []}
|
||||||
],"passsp": []}
|
],"passsp": []}
|
||||||
]},
|
]},
|
||||||
{"type":"BEGIN","name":"assert_simple_immediate_stmt","addr":"(CJ)","loc":"e,97:7,97:35","implied":false,"needProcess":false,"unnamed":false,
|
{"type":"BEGIN","name":"assert_simple_immediate_stmt","addr":"(CJ)","loc":"e,97:7,97:35","implied":false,"needProcess":false,"unnamed":false,"declsp": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"ASSERT","name":"","addr":"(DJ)","loc":"e,97:37,97:43","type":"[SIMPLE_IMMEDIATE]",
|
{"type":"ASSERT","name":"","addr":"(DJ)","loc":"e,97:37,97:43","type":"[SIMPLE_IMMEDIATE]",
|
||||||
"propp": [
|
"propp": [
|
||||||
|
|
@ -581,7 +581,7 @@
|
||||||
],"filep": []}
|
],"filep": []}
|
||||||
]}
|
]}
|
||||||
]},
|
]},
|
||||||
{"type":"BEGIN","name":"assert_simple_immediate_stmt_else","addr":"(IJ)","loc":"e,98:7,98:40","implied":false,"needProcess":false,"unnamed":false,
|
{"type":"BEGIN","name":"assert_simple_immediate_stmt_else","addr":"(IJ)","loc":"e,98:7,98:40","implied":false,"needProcess":false,"unnamed":false,"declsp": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"ASSERT","name":"","addr":"(JJ)","loc":"e,98:42,98:48","type":"[SIMPLE_IMMEDIATE]",
|
{"type":"ASSERT","name":"","addr":"(JJ)","loc":"e,98:42,98:48","type":"[SIMPLE_IMMEDIATE]",
|
||||||
"propp": [
|
"propp": [
|
||||||
|
|
@ -606,14 +606,14 @@
|
||||||
],"filep": []}
|
],"filep": []}
|
||||||
]}
|
]}
|
||||||
]},
|
]},
|
||||||
{"type":"BEGIN","name":"assume_simple_immediate","addr":"(RJ)","loc":"e,100:7,100:30","implied":false,"needProcess":false,"unnamed":false,
|
{"type":"BEGIN","name":"assume_simple_immediate","addr":"(RJ)","loc":"e,100:7,100:30","implied":false,"needProcess":false,"unnamed":false,"declsp": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"ASSERT","name":"","addr":"(SJ)","loc":"e,100:32,100:38","type":"[SIMPLE_IMMEDIATE]",
|
{"type":"ASSERT","name":"","addr":"(SJ)","loc":"e,100:32,100:38","type":"[SIMPLE_IMMEDIATE]",
|
||||||
"propp": [
|
"propp": [
|
||||||
{"type":"CONST","name":"?32?sh0","addr":"(TJ)","loc":"e,100:39,100:40","dtypep":"(N)"}
|
{"type":"CONST","name":"?32?sh0","addr":"(TJ)","loc":"e,100:39,100:40","dtypep":"(N)"}
|
||||||
],"sentreep": [],"failsp": [],"passsp": []}
|
],"sentreep": [],"failsp": [],"passsp": []}
|
||||||
]},
|
]},
|
||||||
{"type":"BEGIN","name":"assume_simple_immediate_else","addr":"(UJ)","loc":"e,101:7,101:35","implied":false,"needProcess":false,"unnamed":false,
|
{"type":"BEGIN","name":"assume_simple_immediate_else","addr":"(UJ)","loc":"e,101:7,101:35","implied":false,"needProcess":false,"unnamed":false,"declsp": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"ASSERT","name":"","addr":"(VJ)","loc":"e,101:37,101:43","type":"[SIMPLE_IMMEDIATE]",
|
{"type":"ASSERT","name":"","addr":"(VJ)","loc":"e,101:37,101:43","type":"[SIMPLE_IMMEDIATE]",
|
||||||
"propp": [
|
"propp": [
|
||||||
|
|
@ -629,7 +629,7 @@
|
||||||
],"filep": []}
|
],"filep": []}
|
||||||
],"passsp": []}
|
],"passsp": []}
|
||||||
]},
|
]},
|
||||||
{"type":"BEGIN","name":"assume_simple_immediate_stmt","addr":"(AK)","loc":"e,102:7,102:35","implied":false,"needProcess":false,"unnamed":false,
|
{"type":"BEGIN","name":"assume_simple_immediate_stmt","addr":"(AK)","loc":"e,102:7,102:35","implied":false,"needProcess":false,"unnamed":false,"declsp": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"ASSERT","name":"","addr":"(BK)","loc":"e,102:37,102:43","type":"[SIMPLE_IMMEDIATE]",
|
{"type":"ASSERT","name":"","addr":"(BK)","loc":"e,102:37,102:43","type":"[SIMPLE_IMMEDIATE]",
|
||||||
"propp": [
|
"propp": [
|
||||||
|
|
@ -645,7 +645,7 @@
|
||||||
],"filep": []}
|
],"filep": []}
|
||||||
]}
|
]}
|
||||||
]},
|
]},
|
||||||
{"type":"BEGIN","name":"assume_simple_immediate_stmt_else","addr":"(GK)","loc":"e,103:7,103:40","implied":false,"needProcess":false,"unnamed":false,
|
{"type":"BEGIN","name":"assume_simple_immediate_stmt_else","addr":"(GK)","loc":"e,103:7,103:40","implied":false,"needProcess":false,"unnamed":false,"declsp": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"ASSERT","name":"","addr":"(HK)","loc":"e,103:42,103:48","type":"[SIMPLE_IMMEDIATE]",
|
{"type":"ASSERT","name":"","addr":"(HK)","loc":"e,103:42,103:48","type":"[SIMPLE_IMMEDIATE]",
|
||||||
"propp": [
|
"propp": [
|
||||||
|
|
@ -674,7 +674,7 @@
|
||||||
]},
|
]},
|
||||||
{"type":"ALWAYS","name":"","addr":"(PK)","loc":"e,106:4,106:38","keyword":"always_comb","isSuspendable":false,"needProcess":false,"sentreep": [],
|
{"type":"ALWAYS","name":"","addr":"(PK)","loc":"e,106:4,106:38","keyword":"always_comb","isSuspendable":false,"needProcess":false,"sentreep": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"BEGIN","name":"assert_observed_deferred_immediate","addr":"(QK)","loc":"e,106:4,106:38","implied":true,"needProcess":false,"unnamed":false,
|
{"type":"BEGIN","name":"assert_observed_deferred_immediate","addr":"(QK)","loc":"e,106:4,106:38","implied":true,"needProcess":false,"unnamed":false,"declsp": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"ASSERT","name":"","addr":"(RK)","loc":"e,106:40,106:46","type":"[OBSERVED_DEFERRED_IMMEDIATE]",
|
{"type":"ASSERT","name":"","addr":"(RK)","loc":"e,106:40,106:46","type":"[OBSERVED_DEFERRED_IMMEDIATE]",
|
||||||
"propp": [
|
"propp": [
|
||||||
|
|
@ -684,7 +684,7 @@
|
||||||
]},
|
]},
|
||||||
{"type":"ALWAYS","name":"","addr":"(TK)","loc":"e,107:4,107:43","keyword":"always_comb","isSuspendable":false,"needProcess":false,"sentreep": [],
|
{"type":"ALWAYS","name":"","addr":"(TK)","loc":"e,107:4,107:43","keyword":"always_comb","isSuspendable":false,"needProcess":false,"sentreep": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"BEGIN","name":"assert_observed_deferred_immediate_else","addr":"(UK)","loc":"e,107:4,107:43","implied":true,"needProcess":false,"unnamed":false,
|
{"type":"BEGIN","name":"assert_observed_deferred_immediate_else","addr":"(UK)","loc":"e,107:4,107:43","implied":true,"needProcess":false,"unnamed":false,"declsp": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"ASSERT","name":"","addr":"(VK)","loc":"e,107:45,107:51","type":"[OBSERVED_DEFERRED_IMMEDIATE]",
|
{"type":"ASSERT","name":"","addr":"(VK)","loc":"e,107:45,107:51","type":"[OBSERVED_DEFERRED_IMMEDIATE]",
|
||||||
"propp": [
|
"propp": [
|
||||||
|
|
@ -703,7 +703,7 @@
|
||||||
]},
|
]},
|
||||||
{"type":"ALWAYS","name":"","addr":"(AL)","loc":"e,108:4,108:43","keyword":"always_comb","isSuspendable":false,"needProcess":false,"sentreep": [],
|
{"type":"ALWAYS","name":"","addr":"(AL)","loc":"e,108:4,108:43","keyword":"always_comb","isSuspendable":false,"needProcess":false,"sentreep": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"BEGIN","name":"assert_observed_deferred_immediate_stmt","addr":"(BL)","loc":"e,108:4,108:43","implied":true,"needProcess":false,"unnamed":false,
|
{"type":"BEGIN","name":"assert_observed_deferred_immediate_stmt","addr":"(BL)","loc":"e,108:4,108:43","implied":true,"needProcess":false,"unnamed":false,"declsp": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"ASSERT","name":"","addr":"(CL)","loc":"e,108:45,108:51","type":"[OBSERVED_DEFERRED_IMMEDIATE]",
|
{"type":"ASSERT","name":"","addr":"(CL)","loc":"e,108:45,108:51","type":"[OBSERVED_DEFERRED_IMMEDIATE]",
|
||||||
"propp": [
|
"propp": [
|
||||||
|
|
@ -722,7 +722,7 @@
|
||||||
]},
|
]},
|
||||||
{"type":"ALWAYS","name":"","addr":"(HL)","loc":"e,109:4,109:48","keyword":"always_comb","isSuspendable":false,"needProcess":false,"sentreep": [],
|
{"type":"ALWAYS","name":"","addr":"(HL)","loc":"e,109:4,109:48","keyword":"always_comb","isSuspendable":false,"needProcess":false,"sentreep": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"BEGIN","name":"assert_observed_deferred_immediate_stmt_else","addr":"(IL)","loc":"e,109:4,109:48","implied":true,"needProcess":false,"unnamed":false,
|
{"type":"BEGIN","name":"assert_observed_deferred_immediate_stmt_else","addr":"(IL)","loc":"e,109:4,109:48","implied":true,"needProcess":false,"unnamed":false,"declsp": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"ASSERT","name":"","addr":"(JL)","loc":"e,109:50,109:56","type":"[OBSERVED_DEFERRED_IMMEDIATE]",
|
{"type":"ASSERT","name":"","addr":"(JL)","loc":"e,109:50,109:56","type":"[OBSERVED_DEFERRED_IMMEDIATE]",
|
||||||
"propp": [
|
"propp": [
|
||||||
|
|
@ -750,7 +750,7 @@
|
||||||
]},
|
]},
|
||||||
{"type":"ALWAYS","name":"","addr":"(RL)","loc":"e,111:4,111:38","keyword":"always_comb","isSuspendable":false,"needProcess":false,"sentreep": [],
|
{"type":"ALWAYS","name":"","addr":"(RL)","loc":"e,111:4,111:38","keyword":"always_comb","isSuspendable":false,"needProcess":false,"sentreep": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"BEGIN","name":"assume_observed_deferred_immediate","addr":"(SL)","loc":"e,111:4,111:38","implied":true,"needProcess":false,"unnamed":false,
|
{"type":"BEGIN","name":"assume_observed_deferred_immediate","addr":"(SL)","loc":"e,111:4,111:38","implied":true,"needProcess":false,"unnamed":false,"declsp": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"ASSERT","name":"","addr":"(TL)","loc":"e,111:40,111:46","type":"[OBSERVED_DEFERRED_IMMEDIATE]",
|
{"type":"ASSERT","name":"","addr":"(TL)","loc":"e,111:40,111:46","type":"[OBSERVED_DEFERRED_IMMEDIATE]",
|
||||||
"propp": [
|
"propp": [
|
||||||
|
|
@ -760,7 +760,7 @@
|
||||||
]},
|
]},
|
||||||
{"type":"ALWAYS","name":"","addr":"(VL)","loc":"e,112:4,112:43","keyword":"always_comb","isSuspendable":false,"needProcess":false,"sentreep": [],
|
{"type":"ALWAYS","name":"","addr":"(VL)","loc":"e,112:4,112:43","keyword":"always_comb","isSuspendable":false,"needProcess":false,"sentreep": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"BEGIN","name":"assume_observed_deferred_immediate_else","addr":"(WL)","loc":"e,112:4,112:43","implied":true,"needProcess":false,"unnamed":false,
|
{"type":"BEGIN","name":"assume_observed_deferred_immediate_else","addr":"(WL)","loc":"e,112:4,112:43","implied":true,"needProcess":false,"unnamed":false,"declsp": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"ASSERT","name":"","addr":"(XL)","loc":"e,112:45,112:51","type":"[OBSERVED_DEFERRED_IMMEDIATE]",
|
{"type":"ASSERT","name":"","addr":"(XL)","loc":"e,112:45,112:51","type":"[OBSERVED_DEFERRED_IMMEDIATE]",
|
||||||
"propp": [
|
"propp": [
|
||||||
|
|
@ -779,7 +779,7 @@
|
||||||
]},
|
]},
|
||||||
{"type":"ALWAYS","name":"","addr":"(CM)","loc":"e,113:4,113:43","keyword":"always_comb","isSuspendable":false,"needProcess":false,"sentreep": [],
|
{"type":"ALWAYS","name":"","addr":"(CM)","loc":"e,113:4,113:43","keyword":"always_comb","isSuspendable":false,"needProcess":false,"sentreep": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"BEGIN","name":"assume_observed_deferred_immediate_stmt","addr":"(DM)","loc":"e,113:4,113:43","implied":true,"needProcess":false,"unnamed":false,
|
{"type":"BEGIN","name":"assume_observed_deferred_immediate_stmt","addr":"(DM)","loc":"e,113:4,113:43","implied":true,"needProcess":false,"unnamed":false,"declsp": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"ASSERT","name":"","addr":"(EM)","loc":"e,113:45,113:51","type":"[OBSERVED_DEFERRED_IMMEDIATE]",
|
{"type":"ASSERT","name":"","addr":"(EM)","loc":"e,113:45,113:51","type":"[OBSERVED_DEFERRED_IMMEDIATE]",
|
||||||
"propp": [
|
"propp": [
|
||||||
|
|
@ -798,7 +798,7 @@
|
||||||
]},
|
]},
|
||||||
{"type":"ALWAYS","name":"","addr":"(JM)","loc":"e,114:4,114:48","keyword":"always_comb","isSuspendable":false,"needProcess":false,"sentreep": [],
|
{"type":"ALWAYS","name":"","addr":"(JM)","loc":"e,114:4,114:48","keyword":"always_comb","isSuspendable":false,"needProcess":false,"sentreep": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"BEGIN","name":"assume_observed_deferred_immediate_stmt_else","addr":"(KM)","loc":"e,114:4,114:48","implied":true,"needProcess":false,"unnamed":false,
|
{"type":"BEGIN","name":"assume_observed_deferred_immediate_stmt_else","addr":"(KM)","loc":"e,114:4,114:48","implied":true,"needProcess":false,"unnamed":false,"declsp": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"ASSERT","name":"","addr":"(LM)","loc":"e,114:50,114:56","type":"[OBSERVED_DEFERRED_IMMEDIATE]",
|
{"type":"ASSERT","name":"","addr":"(LM)","loc":"e,114:50,114:56","type":"[OBSERVED_DEFERRED_IMMEDIATE]",
|
||||||
"propp": [
|
"propp": [
|
||||||
|
|
@ -826,7 +826,7 @@
|
||||||
]},
|
]},
|
||||||
{"type":"ALWAYS","name":"","addr":"(TM)","loc":"e,116:4,116:35","keyword":"always_comb","isSuspendable":false,"needProcess":false,"sentreep": [],
|
{"type":"ALWAYS","name":"","addr":"(TM)","loc":"e,116:4,116:35","keyword":"always_comb","isSuspendable":false,"needProcess":false,"sentreep": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"BEGIN","name":"assert_final_deferred_immediate","addr":"(UM)","loc":"e,116:4,116:35","implied":true,"needProcess":false,"unnamed":false,
|
{"type":"BEGIN","name":"assert_final_deferred_immediate","addr":"(UM)","loc":"e,116:4,116:35","implied":true,"needProcess":false,"unnamed":false,"declsp": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"ASSERT","name":"","addr":"(VM)","loc":"e,116:37,116:43","type":"[FINAL_DEFERRED_IMMEDIATE]",
|
{"type":"ASSERT","name":"","addr":"(VM)","loc":"e,116:37,116:43","type":"[FINAL_DEFERRED_IMMEDIATE]",
|
||||||
"propp": [
|
"propp": [
|
||||||
|
|
@ -836,7 +836,7 @@
|
||||||
]},
|
]},
|
||||||
{"type":"ALWAYS","name":"","addr":"(XM)","loc":"e,117:4,117:40","keyword":"always_comb","isSuspendable":false,"needProcess":false,"sentreep": [],
|
{"type":"ALWAYS","name":"","addr":"(XM)","loc":"e,117:4,117:40","keyword":"always_comb","isSuspendable":false,"needProcess":false,"sentreep": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"BEGIN","name":"assert_final_deferred_immediate_else","addr":"(YM)","loc":"e,117:4,117:40","implied":true,"needProcess":false,"unnamed":false,
|
{"type":"BEGIN","name":"assert_final_deferred_immediate_else","addr":"(YM)","loc":"e,117:4,117:40","implied":true,"needProcess":false,"unnamed":false,"declsp": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"ASSERT","name":"","addr":"(ZM)","loc":"e,117:42,117:48","type":"[FINAL_DEFERRED_IMMEDIATE]",
|
{"type":"ASSERT","name":"","addr":"(ZM)","loc":"e,117:42,117:48","type":"[FINAL_DEFERRED_IMMEDIATE]",
|
||||||
"propp": [
|
"propp": [
|
||||||
|
|
@ -855,7 +855,7 @@
|
||||||
]},
|
]},
|
||||||
{"type":"ALWAYS","name":"","addr":"(EN)","loc":"e,118:4,118:40","keyword":"always_comb","isSuspendable":false,"needProcess":false,"sentreep": [],
|
{"type":"ALWAYS","name":"","addr":"(EN)","loc":"e,118:4,118:40","keyword":"always_comb","isSuspendable":false,"needProcess":false,"sentreep": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"BEGIN","name":"assert_final_deferred_immediate_stmt","addr":"(FN)","loc":"e,118:4,118:40","implied":true,"needProcess":false,"unnamed":false,
|
{"type":"BEGIN","name":"assert_final_deferred_immediate_stmt","addr":"(FN)","loc":"e,118:4,118:40","implied":true,"needProcess":false,"unnamed":false,"declsp": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"ASSERT","name":"","addr":"(GN)","loc":"e,118:42,118:48","type":"[FINAL_DEFERRED_IMMEDIATE]",
|
{"type":"ASSERT","name":"","addr":"(GN)","loc":"e,118:42,118:48","type":"[FINAL_DEFERRED_IMMEDIATE]",
|
||||||
"propp": [
|
"propp": [
|
||||||
|
|
@ -874,7 +874,7 @@
|
||||||
]},
|
]},
|
||||||
{"type":"ALWAYS","name":"","addr":"(LN)","loc":"e,119:4,119:45","keyword":"always_comb","isSuspendable":false,"needProcess":false,"sentreep": [],
|
{"type":"ALWAYS","name":"","addr":"(LN)","loc":"e,119:4,119:45","keyword":"always_comb","isSuspendable":false,"needProcess":false,"sentreep": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"BEGIN","name":"assert_final_deferred_immediate_stmt_else","addr":"(MN)","loc":"e,119:4,119:45","implied":true,"needProcess":false,"unnamed":false,
|
{"type":"BEGIN","name":"assert_final_deferred_immediate_stmt_else","addr":"(MN)","loc":"e,119:4,119:45","implied":true,"needProcess":false,"unnamed":false,"declsp": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"ASSERT","name":"","addr":"(NN)","loc":"e,119:47,119:53","type":"[FINAL_DEFERRED_IMMEDIATE]",
|
{"type":"ASSERT","name":"","addr":"(NN)","loc":"e,119:47,119:53","type":"[FINAL_DEFERRED_IMMEDIATE]",
|
||||||
"propp": [
|
"propp": [
|
||||||
|
|
@ -902,7 +902,7 @@
|
||||||
]},
|
]},
|
||||||
{"type":"ALWAYS","name":"","addr":"(VN)","loc":"e,121:4,121:35","keyword":"always_comb","isSuspendable":false,"needProcess":false,"sentreep": [],
|
{"type":"ALWAYS","name":"","addr":"(VN)","loc":"e,121:4,121:35","keyword":"always_comb","isSuspendable":false,"needProcess":false,"sentreep": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"BEGIN","name":"assume_final_deferred_immediate","addr":"(WN)","loc":"e,121:4,121:35","implied":true,"needProcess":false,"unnamed":false,
|
{"type":"BEGIN","name":"assume_final_deferred_immediate","addr":"(WN)","loc":"e,121:4,121:35","implied":true,"needProcess":false,"unnamed":false,"declsp": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"ASSERT","name":"","addr":"(XN)","loc":"e,121:37,121:43","type":"[FINAL_DEFERRED_IMMEDIATE]",
|
{"type":"ASSERT","name":"","addr":"(XN)","loc":"e,121:37,121:43","type":"[FINAL_DEFERRED_IMMEDIATE]",
|
||||||
"propp": [
|
"propp": [
|
||||||
|
|
@ -912,7 +912,7 @@
|
||||||
]},
|
]},
|
||||||
{"type":"ALWAYS","name":"","addr":"(ZN)","loc":"e,122:4,122:40","keyword":"always_comb","isSuspendable":false,"needProcess":false,"sentreep": [],
|
{"type":"ALWAYS","name":"","addr":"(ZN)","loc":"e,122:4,122:40","keyword":"always_comb","isSuspendable":false,"needProcess":false,"sentreep": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"BEGIN","name":"assume_final_deferred_immediate_else","addr":"(AO)","loc":"e,122:4,122:40","implied":true,"needProcess":false,"unnamed":false,
|
{"type":"BEGIN","name":"assume_final_deferred_immediate_else","addr":"(AO)","loc":"e,122:4,122:40","implied":true,"needProcess":false,"unnamed":false,"declsp": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"ASSERT","name":"","addr":"(BO)","loc":"e,122:42,122:48","type":"[FINAL_DEFERRED_IMMEDIATE]",
|
{"type":"ASSERT","name":"","addr":"(BO)","loc":"e,122:42,122:48","type":"[FINAL_DEFERRED_IMMEDIATE]",
|
||||||
"propp": [
|
"propp": [
|
||||||
|
|
@ -931,7 +931,7 @@
|
||||||
]},
|
]},
|
||||||
{"type":"ALWAYS","name":"","addr":"(GO)","loc":"e,123:4,123:40","keyword":"always_comb","isSuspendable":false,"needProcess":false,"sentreep": [],
|
{"type":"ALWAYS","name":"","addr":"(GO)","loc":"e,123:4,123:40","keyword":"always_comb","isSuspendable":false,"needProcess":false,"sentreep": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"BEGIN","name":"assume_final_deferred_immediate_stmt","addr":"(HO)","loc":"e,123:4,123:40","implied":true,"needProcess":false,"unnamed":false,
|
{"type":"BEGIN","name":"assume_final_deferred_immediate_stmt","addr":"(HO)","loc":"e,123:4,123:40","implied":true,"needProcess":false,"unnamed":false,"declsp": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"ASSERT","name":"","addr":"(IO)","loc":"e,123:42,123:48","type":"[FINAL_DEFERRED_IMMEDIATE]",
|
{"type":"ASSERT","name":"","addr":"(IO)","loc":"e,123:42,123:48","type":"[FINAL_DEFERRED_IMMEDIATE]",
|
||||||
"propp": [
|
"propp": [
|
||||||
|
|
@ -950,7 +950,7 @@
|
||||||
]},
|
]},
|
||||||
{"type":"ALWAYS","name":"","addr":"(NO)","loc":"e,124:4,124:45","keyword":"always_comb","isSuspendable":false,"needProcess":false,"sentreep": [],
|
{"type":"ALWAYS","name":"","addr":"(NO)","loc":"e,124:4,124:45","keyword":"always_comb","isSuspendable":false,"needProcess":false,"sentreep": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"BEGIN","name":"assume_final_deferred_immediate_stmt_else","addr":"(OO)","loc":"e,124:4,124:45","implied":true,"needProcess":false,"unnamed":false,
|
{"type":"BEGIN","name":"assume_final_deferred_immediate_stmt_else","addr":"(OO)","loc":"e,124:4,124:45","implied":true,"needProcess":false,"unnamed":false,"declsp": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"ASSERT","name":"","addr":"(PO)","loc":"e,124:47,124:53","type":"[FINAL_DEFERRED_IMMEDIATE]",
|
{"type":"ASSERT","name":"","addr":"(PO)","loc":"e,124:47,124:53","type":"[FINAL_DEFERRED_IMMEDIATE]",
|
||||||
"propp": [
|
"propp": [
|
||||||
|
|
@ -989,7 +989,7 @@
|
||||||
{"type":"CONST","name":"?32?sh0","addr":"(BP)","loc":"e,127:22,127:23","dtypep":"(N)"}
|
{"type":"CONST","name":"?32?sh0","addr":"(BP)","loc":"e,127:22,127:23","dtypep":"(N)"}
|
||||||
]}
|
]}
|
||||||
],"scopeNamep": []},
|
],"scopeNamep": []},
|
||||||
{"type":"BEGIN","name":"assert_concurrent","addr":"(CP)","loc":"e,130:4,130:21","implied":true,"needProcess":false,"unnamed":false,
|
{"type":"BEGIN","name":"assert_concurrent","addr":"(CP)","loc":"e,130:4,130:21","implied":true,"needProcess":false,"unnamed":false,"declsp": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"ASSERT","name":"","addr":"(DP)","loc":"e,130:23,130:29","type":"[CONCURRENT]",
|
{"type":"ASSERT","name":"","addr":"(DP)","loc":"e,130:23,130:29","type":"[CONCURRENT]",
|
||||||
"propp": [
|
"propp": [
|
||||||
|
|
@ -1002,7 +1002,7 @@
|
||||||
]}
|
]}
|
||||||
],"sentreep": [],"failsp": [],"passsp": []}
|
],"sentreep": [],"failsp": [],"passsp": []}
|
||||||
]},
|
]},
|
||||||
{"type":"BEGIN","name":"assert_concurrent_else","addr":"(HP)","loc":"e,131:4,131:26","implied":true,"needProcess":false,"unnamed":false,
|
{"type":"BEGIN","name":"assert_concurrent_else","addr":"(HP)","loc":"e,131:4,131:26","implied":true,"needProcess":false,"unnamed":false,"declsp": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"ASSERT","name":"","addr":"(IP)","loc":"e,131:28,131:34","type":"[CONCURRENT]",
|
{"type":"ASSERT","name":"","addr":"(IP)","loc":"e,131:28,131:34","type":"[CONCURRENT]",
|
||||||
"propp": [
|
"propp": [
|
||||||
|
|
@ -1024,7 +1024,7 @@
|
||||||
],"filep": []}
|
],"filep": []}
|
||||||
],"passsp": []}
|
],"passsp": []}
|
||||||
]},
|
]},
|
||||||
{"type":"BEGIN","name":"assert_concurrent_stmt","addr":"(PP)","loc":"e,132:4,132:26","implied":true,"needProcess":false,"unnamed":false,
|
{"type":"BEGIN","name":"assert_concurrent_stmt","addr":"(PP)","loc":"e,132:4,132:26","implied":true,"needProcess":false,"unnamed":false,"declsp": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"ASSERT","name":"","addr":"(QP)","loc":"e,132:28,132:34","type":"[CONCURRENT]",
|
{"type":"ASSERT","name":"","addr":"(QP)","loc":"e,132:28,132:34","type":"[CONCURRENT]",
|
||||||
"propp": [
|
"propp": [
|
||||||
|
|
@ -1046,7 +1046,7 @@
|
||||||
],"filep": []}
|
],"filep": []}
|
||||||
]}
|
]}
|
||||||
]},
|
]},
|
||||||
{"type":"BEGIN","name":"assert_concurrent_stmt_else","addr":"(XP)","loc":"e,133:4,133:31","implied":true,"needProcess":false,"unnamed":false,
|
{"type":"BEGIN","name":"assert_concurrent_stmt_else","addr":"(XP)","loc":"e,133:4,133:31","implied":true,"needProcess":false,"unnamed":false,"declsp": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"ASSERT","name":"","addr":"(YP)","loc":"e,133:33,133:39","type":"[CONCURRENT]",
|
{"type":"ASSERT","name":"","addr":"(YP)","loc":"e,133:33,133:39","type":"[CONCURRENT]",
|
||||||
"propp": [
|
"propp": [
|
||||||
|
|
@ -1077,7 +1077,7 @@
|
||||||
],"filep": []}
|
],"filep": []}
|
||||||
]}
|
]}
|
||||||
]},
|
]},
|
||||||
{"type":"BEGIN","name":"assume_concurrent","addr":"(IQ)","loc":"e,135:4,135:21","implied":true,"needProcess":false,"unnamed":false,
|
{"type":"BEGIN","name":"assume_concurrent","addr":"(IQ)","loc":"e,135:4,135:21","implied":true,"needProcess":false,"unnamed":false,"declsp": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"ASSERT","name":"","addr":"(JQ)","loc":"e,135:23,135:29","type":"[CONCURRENT]",
|
{"type":"ASSERT","name":"","addr":"(JQ)","loc":"e,135:23,135:29","type":"[CONCURRENT]",
|
||||||
"propp": [
|
"propp": [
|
||||||
|
|
@ -1090,7 +1090,7 @@
|
||||||
]}
|
]}
|
||||||
],"sentreep": [],"failsp": [],"passsp": []}
|
],"sentreep": [],"failsp": [],"passsp": []}
|
||||||
]},
|
]},
|
||||||
{"type":"BEGIN","name":"assume_concurrent_else","addr":"(NQ)","loc":"e,136:4,136:26","implied":true,"needProcess":false,"unnamed":false,
|
{"type":"BEGIN","name":"assume_concurrent_else","addr":"(NQ)","loc":"e,136:4,136:26","implied":true,"needProcess":false,"unnamed":false,"declsp": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"ASSERT","name":"","addr":"(OQ)","loc":"e,136:28,136:34","type":"[CONCURRENT]",
|
{"type":"ASSERT","name":"","addr":"(OQ)","loc":"e,136:28,136:34","type":"[CONCURRENT]",
|
||||||
"propp": [
|
"propp": [
|
||||||
|
|
@ -1112,7 +1112,7 @@
|
||||||
],"filep": []}
|
],"filep": []}
|
||||||
],"passsp": []}
|
],"passsp": []}
|
||||||
]},
|
]},
|
||||||
{"type":"BEGIN","name":"assume_concurrent_stmt","addr":"(VQ)","loc":"e,137:4,137:26","implied":true,"needProcess":false,"unnamed":false,
|
{"type":"BEGIN","name":"assume_concurrent_stmt","addr":"(VQ)","loc":"e,137:4,137:26","implied":true,"needProcess":false,"unnamed":false,"declsp": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"ASSERT","name":"","addr":"(WQ)","loc":"e,137:28,137:34","type":"[CONCURRENT]",
|
{"type":"ASSERT","name":"","addr":"(WQ)","loc":"e,137:28,137:34","type":"[CONCURRENT]",
|
||||||
"propp": [
|
"propp": [
|
||||||
|
|
@ -1134,7 +1134,7 @@
|
||||||
],"filep": []}
|
],"filep": []}
|
||||||
]}
|
]}
|
||||||
]},
|
]},
|
||||||
{"type":"BEGIN","name":"assume_concurrent_stmt_else","addr":"(DR)","loc":"e,138:4,138:31","implied":true,"needProcess":false,"unnamed":false,
|
{"type":"BEGIN","name":"assume_concurrent_stmt_else","addr":"(DR)","loc":"e,138:4,138:31","implied":true,"needProcess":false,"unnamed":false,"declsp": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"ASSERT","name":"","addr":"(ER)","loc":"e,138:33,138:39","type":"[CONCURRENT]",
|
{"type":"ASSERT","name":"","addr":"(ER)","loc":"e,138:33,138:39","type":"[CONCURRENT]",
|
||||||
"propp": [
|
"propp": [
|
||||||
|
|
@ -1165,7 +1165,7 @@
|
||||||
],"filep": []}
|
],"filep": []}
|
||||||
]}
|
]}
|
||||||
]},
|
]},
|
||||||
{"type":"BEGIN","name":"cover_concurrent","addr":"(OR)","loc":"e,140:4,140:20","implied":true,"needProcess":false,"unnamed":false,
|
{"type":"BEGIN","name":"cover_concurrent","addr":"(OR)","loc":"e,140:4,140:20","implied":true,"needProcess":false,"unnamed":false,"declsp": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"COVER","name":"","addr":"(PR)","loc":"e,140:22,140:27","type":"[CONCURRENT]",
|
{"type":"COVER","name":"","addr":"(PR)","loc":"e,140:22,140:27","type":"[CONCURRENT]",
|
||||||
"propp": [
|
"propp": [
|
||||||
|
|
@ -1175,7 +1175,7 @@
|
||||||
]}
|
]}
|
||||||
],"sentreep": [],"coverincsp": [],"passsp": []}
|
],"sentreep": [],"coverincsp": [],"passsp": []}
|
||||||
]},
|
]},
|
||||||
{"type":"BEGIN","name":"cover_concurrent_stmt","addr":"(SR)","loc":"e,141:4,141:25","implied":true,"needProcess":false,"unnamed":false,
|
{"type":"BEGIN","name":"cover_concurrent_stmt","addr":"(SR)","loc":"e,141:4,141:25","implied":true,"needProcess":false,"unnamed":false,"declsp": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"COVER","name":"","addr":"(TR)","loc":"e,141:27,141:32","type":"[CONCURRENT]",
|
{"type":"COVER","name":"","addr":"(TR)","loc":"e,141:27,141:32","type":"[CONCURRENT]",
|
||||||
"propp": [
|
"propp": [
|
||||||
|
|
@ -1301,7 +1301,7 @@
|
||||||
]}
|
]}
|
||||||
],
|
],
|
||||||
"thensp": [
|
"thensp": [
|
||||||
{"type":"BEGIN","name":"","addr":"(QT)","loc":"d,55:44,55:49","implied":false,"needProcess":false,"unnamed":true,
|
{"type":"BEGIN","name":"","addr":"(QT)","loc":"d,55:44,55:49","implied":false,"needProcess":false,"unnamed":true,"declsp": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"STMTEXPR","name":"","addr":"(RT)","loc":"d,56:16,56:17",
|
{"type":"STMTEXPR","name":"","addr":"(RT)","loc":"d,56:16,56:17",
|
||||||
"exprp": [
|
"exprp": [
|
||||||
|
|
@ -1357,7 +1357,7 @@
|
||||||
]}
|
]}
|
||||||
],
|
],
|
||||||
"thensp": [
|
"thensp": [
|
||||||
{"type":"BEGIN","name":"","addr":"(NU)","loc":"d,72:22,72:27","implied":false,"needProcess":false,"unnamed":true,
|
{"type":"BEGIN","name":"","addr":"(NU)","loc":"d,72:22,72:27","implied":false,"needProcess":false,"unnamed":true,"declsp": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"ASSIGN","name":"","addr":"(OU)","loc":"d,73:17,73:18","dtypep":"UNLINKED",
|
{"type":"ASSIGN","name":"","addr":"(OU)","loc":"d,73:17,73:18","dtypep":"UNLINKED",
|
||||||
"rhsp": [
|
"rhsp": [
|
||||||
|
|
@ -1410,7 +1410,7 @@
|
||||||
]}
|
]}
|
||||||
],
|
],
|
||||||
"thensp": [
|
"thensp": [
|
||||||
{"type":"BEGIN","name":"","addr":"(IV)","loc":"d,89:22,89:27","implied":false,"needProcess":false,"unnamed":true,
|
{"type":"BEGIN","name":"","addr":"(IV)","loc":"d,89:22,89:27","implied":false,"needProcess":false,"unnamed":true,"declsp": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"ASSIGN","name":"","addr":"(JV)","loc":"d,90:17,90:18","dtypep":"UNLINKED",
|
{"type":"ASSIGN","name":"","addr":"(JV)","loc":"d,90:17,90:18","dtypep":"UNLINKED",
|
||||||
"rhsp": [
|
"rhsp": [
|
||||||
|
|
@ -1516,7 +1516,7 @@
|
||||||
]}
|
]}
|
||||||
],
|
],
|
||||||
"thensp": [
|
"thensp": [
|
||||||
{"type":"BEGIN","name":"","addr":"(YW)","loc":"d,118:35,118:40","implied":false,"needProcess":false,"unnamed":true,
|
{"type":"BEGIN","name":"","addr":"(YW)","loc":"d,118:35,118:40","implied":false,"needProcess":false,"unnamed":true,"declsp": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"ASSIGN","name":"","addr":"(ZW)","loc":"d,119:20,119:22","dtypep":"UNLINKED",
|
{"type":"ASSIGN","name":"","addr":"(ZW)","loc":"d,119:20,119:22","dtypep":"UNLINKED",
|
||||||
"rhsp": [
|
"rhsp": [
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
%Error-NOTIMING: t/t_fork.v:10:14: Fork statements require --timing
|
%Error-NOTIMING: t/t_fork.v:10:7: Fork statements require --timing
|
||||||
: ... note: In instance 't'
|
: ... note: In instance 't'
|
||||||
10 | fork : fblk
|
10 | fork : fblk
|
||||||
| ^~~~
|
| ^~~~
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,11 @@ module t();
|
||||||
initial fork
|
initial fork
|
||||||
reg i;
|
reg i;
|
||||||
i = 1'b1;
|
i = 1'b1;
|
||||||
|
begin
|
||||||
|
#1;
|
||||||
if (i != 1'b1) $stop;
|
if (i != 1'b1) $stop;
|
||||||
$write("*-* All Finished *-*\n");
|
$write("*-* All Finished *-*\n");
|
||||||
$finish;
|
$finish;
|
||||||
|
end
|
||||||
join
|
join
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@
|
||||||
],"scopeNamep": []},
|
],"scopeNamep": []},
|
||||||
{"type":"INITIAL","name":"","addr":"(FB)","loc":"d,39:4,39:11","isSuspendable":false,"needProcess":false,
|
{"type":"INITIAL","name":"","addr":"(FB)","loc":"d,39:4,39:11","isSuspendable":false,"needProcess":false,
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"BEGIN","name":"","addr":"(GB)","loc":"d,39:12,39:17","implied":false,"needProcess":false,"unnamed":true,
|
{"type":"BEGIN","name":"","addr":"(GB)","loc":"d,39:12,39:17","implied":false,"needProcess":false,"unnamed":true,"declsp": [],
|
||||||
"stmtsp": [
|
"stmtsp": [
|
||||||
{"type":"STMTEXPR","name":"","addr":"(HB)","loc":"d,41:7,41:8",
|
{"type":"STMTEXPR","name":"","addr":"(HB)","loc":"d,41:7,41:8",
|
||||||
"exprp": [
|
"exprp": [
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
%Error: t/t_lint_block_redecl_bad.v:17:34: Duplicate declaration of block: 'COMB'
|
%Error: t/t_lint_block_redecl_bad.v:17:27: Duplicate declaration of block: 'COMB'
|
||||||
17 | for(i=0; i<9; i++ ) begin: COMB
|
17 | for(i=0; i<9; i++ ) begin: COMB
|
||||||
| ^~~~
|
| ^~~~~
|
||||||
t/t_lint_block_redecl_bad.v:14:35: ... Location of original declaration
|
t/t_lint_block_redecl_bad.v:14:28: ... Location of original declaration
|
||||||
14 | for(i=0; i<10; i++ ) begin: COMB
|
14 | for(i=0; i<10; i++ ) begin: COMB
|
||||||
| ^~~~
|
| ^~~~~
|
||||||
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
|
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
|
||||||
%Error: Exiting due to
|
%Error: Exiting due to
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue