Internals: cppcheck fixes. No functional change. (#6687)
This commit is contained in:
parent
67094f6a88
commit
5c0ad5bd1f
|
|
@ -133,6 +133,7 @@ unsigned getProcessAvailableParallelism() VL_MT_SAFE {
|
||||||
|
|
||||||
unsigned getProcessDefaultParallelism() VL_MT_SAFE {
|
unsigned getProcessDefaultParallelism() VL_MT_SAFE {
|
||||||
const unsigned n = getProcessAvailableParallelism();
|
const unsigned n = getProcessAvailableParallelism();
|
||||||
|
// cppcheck-suppress knownConditionTrueFalse
|
||||||
return n ? n : std::thread::hardware_concurrency();
|
return n ? n : std::thread::hardware_concurrency();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -280,9 +280,8 @@ class AssertVisitor final : public VNVisitor {
|
||||||
return newp;
|
return newp;
|
||||||
}
|
}
|
||||||
|
|
||||||
static AstIf* assertCond(AstNodeCoverOrAssert* nodep, AstNodeExpr* propp, AstNode* passsp,
|
static AstIf* assertCond(const AstNodeCoverOrAssert* nodep, AstNodeExpr* propp,
|
||||||
AstNode* failsp) {
|
AstNode* passsp, AstNode* failsp) {
|
||||||
|
|
||||||
AstIf* const ifp = new AstIf{nodep->fileline(), propp, passsp, failsp};
|
AstIf* const ifp = new AstIf{nodep->fileline(), propp, passsp, failsp};
|
||||||
// It's more LIKELY that we'll take the nullptr if clause
|
// It's more LIKELY that we'll take the nullptr if clause
|
||||||
// than the sim-killing else clause:
|
// than the sim-killing else clause:
|
||||||
|
|
@ -291,7 +290,7 @@ class AssertVisitor final : public VNVisitor {
|
||||||
return ifp;
|
return ifp;
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode* assertBody(AstNodeCoverOrAssert* nodep, AstNode* propp, AstNode* passsp,
|
AstNode* assertBody(const AstNodeCoverOrAssert* nodep, AstNode* propp, AstNode* passsp,
|
||||||
AstNode* failsp) {
|
AstNode* failsp) {
|
||||||
AstNode* bodyp = nullptr;
|
AstNode* bodyp = nullptr;
|
||||||
if (AstPExpr* const pexprp = VN_CAST(propp, PExpr)) {
|
if (AstPExpr* const pexprp = VN_CAST(propp, PExpr)) {
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,7 @@ class AssertPropBuildVisitor final : public VNVisitorConst {
|
||||||
bool m_underSExpr = false; // Is under sequence expression, for creating a start node
|
bool m_underSExpr = false; // Is under sequence expression, for creating a start node
|
||||||
size_t m_underLogNots = 0; // Number of 'not' operators before sequence
|
size_t m_underLogNots = 0; // Number of 'not' operators before sequence
|
||||||
|
|
||||||
DfaStmtVertex* makeClause(AstSExpr* nodep, bool pass) {
|
DfaStmtVertex* makeClause(const AstSExpr* nodep, bool pass) {
|
||||||
return new DfaStmtVertex{
|
return new DfaStmtVertex{
|
||||||
&m_graph,
|
&m_graph,
|
||||||
new AstPExprClause{nodep->fileline(), m_underLogNots % 2 == 0 ? pass : !pass}};
|
new AstPExprClause{nodep->fileline(), m_underLogNots % 2 == 0 ? pass : !pass}};
|
||||||
|
|
@ -227,7 +227,7 @@ class AssertPropTransformer final {
|
||||||
m_current = passsp;
|
m_current = passsp;
|
||||||
return processEdge(vtxp->outEdges().frontp());
|
return processEdge(vtxp->outEdges().frontp());
|
||||||
}
|
}
|
||||||
V3GraphVertex* processEdge(V3GraphEdge* edgep) {
|
V3GraphVertex* processEdge(const V3GraphEdge* edgep) {
|
||||||
if (edgep) return processVtx(edgep->top());
|
if (edgep) return processVtx(edgep->top());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,14 +55,14 @@ V3AST_VCMETHOD_ITEMDATA_DECL;
|
||||||
// VCMethod information
|
// VCMethod information
|
||||||
|
|
||||||
VCMethod VCMethod::arrayMethod(const string& name) {
|
VCMethod VCMethod::arrayMethod(const string& name) {
|
||||||
for (auto& it : s_itemData)
|
for (const auto& it : s_itemData)
|
||||||
if (it.m_name == name) return it.m_e;
|
if (it.m_name == name) return it.m_e;
|
||||||
v3fatalSrc("Not a method name known to VCMethod::s_itemData: '" << name << '\'');
|
v3fatalSrc("Not a method name known to VCMethod::s_itemData: '" << name << '\'');
|
||||||
return VCMethod{};
|
return VCMethod{};
|
||||||
}
|
}
|
||||||
void VCMethod::selfTest() {
|
void VCMethod::selfTest() {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (auto& it : s_itemData) {
|
for (const auto& it : s_itemData) {
|
||||||
VCMethod exp{i};
|
VCMethod exp{i};
|
||||||
UASSERT_STATIC(it.m_e == exp,
|
UASSERT_STATIC(it.m_e == exp,
|
||||||
"VCMethod::s_itemData table rows are out-of-order, starting at row "s
|
"VCMethod::s_itemData table rows are out-of-order, starting at row "s
|
||||||
|
|
|
||||||
|
|
@ -583,7 +583,7 @@ class AstCExpr final : public AstNodeExpr {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
class Pure {};
|
class Pure {};
|
||||||
AstCExpr(FileLine* fl, const string& text = "", int setwidth = 0)
|
explicit AstCExpr(FileLine* fl, const string& text = "", int setwidth = 0)
|
||||||
: ASTGEN_SUPER_CExpr(fl)
|
: ASTGEN_SUPER_CExpr(fl)
|
||||||
, m_pure{false} {
|
, m_pure{false} {
|
||||||
init(text, setwidth);
|
init(text, setwidth);
|
||||||
|
|
@ -617,7 +617,7 @@ class AstCExprUser final : public AstNodeExpr {
|
||||||
const bool m_pure; // Whether the function is pure
|
const bool m_pure; // Whether the function is pure
|
||||||
public:
|
public:
|
||||||
class Pure {};
|
class Pure {};
|
||||||
AstCExprUser(FileLine* fl)
|
explicit AstCExprUser(FileLine* fl)
|
||||||
: ASTGEN_SUPER_CExprUser(fl)
|
: ASTGEN_SUPER_CExprUser(fl)
|
||||||
, m_pure{false} {}
|
, m_pure{false} {}
|
||||||
AstCExprUser(FileLine* fl, Pure)
|
AstCExprUser(FileLine* fl, Pure)
|
||||||
|
|
|
||||||
|
|
@ -1613,10 +1613,10 @@ class AstTextBlock final : public AstNode {
|
||||||
const std::string m_separator; // Separator to print between each element in 'nodesp'
|
const std::string m_separator; // Separator to print between each element in 'nodesp'
|
||||||
const std::string m_suffix; // Suffix to pring after last element in 'nodesp'
|
const std::string m_suffix; // Suffix to pring after last element in 'nodesp'
|
||||||
public:
|
public:
|
||||||
AstTextBlock(FileLine* fl, //
|
explicit AstTextBlock(FileLine* fl, //
|
||||||
const std::string& prefix = "", //
|
const std::string& prefix = "", //
|
||||||
const std::string& separator = "", //
|
const std::string& separator = "", //
|
||||||
const std::string& suffix = "")
|
const std::string& suffix = "")
|
||||||
: ASTGEN_SUPER_TextBlock(fl)
|
: ASTGEN_SUPER_TextBlock(fl)
|
||||||
, m_prefix{prefix}
|
, m_prefix{prefix}
|
||||||
, m_separator{separator}
|
, m_separator{separator}
|
||||||
|
|
@ -2641,7 +2641,7 @@ public:
|
||||||
, m_keyword{keyword} {
|
, m_keyword{keyword} {
|
||||||
this->sentreep(sentreep);
|
this->sentreep(sentreep);
|
||||||
}
|
}
|
||||||
inline AstAlways(AstAssignW* assignp);
|
explicit inline AstAlways(AstAssignW* assignp);
|
||||||
ASTGEN_MEMBERS_AstAlways;
|
ASTGEN_MEMBERS_AstAlways;
|
||||||
//
|
//
|
||||||
void dump(std::ostream& str) const override;
|
void dump(std::ostream& str) const override;
|
||||||
|
|
|
||||||
|
|
@ -289,7 +289,7 @@ class AstCStmt final : public AstNodeStmt {
|
||||||
// C statement emitted into output, with some arbitrary nodes interspersed
|
// C statement emitted into output, with some arbitrary nodes interspersed
|
||||||
// @astgen op1 := nodesp : List[AstNode<AstNodeStmt|AstNodeExpr|AstText>]
|
// @astgen op1 := nodesp : List[AstNode<AstNodeStmt|AstNodeExpr|AstText>]
|
||||||
public:
|
public:
|
||||||
AstCStmt(FileLine* fl, const std::string& text = "")
|
explicit AstCStmt(FileLine* fl, const std::string& text = "")
|
||||||
: ASTGEN_SUPER_CStmt(fl) {
|
: ASTGEN_SUPER_CStmt(fl) {
|
||||||
if (!text.empty()) add(text);
|
if (!text.empty()) add(text);
|
||||||
}
|
}
|
||||||
|
|
@ -315,7 +315,7 @@ class AstCStmtUser final : public AstNodeStmt {
|
||||||
// @astgen op1 := nodesp : List[AstNode<AstNodeExpr|AstText>]
|
// @astgen op1 := nodesp : List[AstNode<AstNodeExpr|AstText>]
|
||||||
const bool m_fromDollarC; // Is from source '$c', emit decoration
|
const bool m_fromDollarC; // Is from source '$c', emit decoration
|
||||||
public:
|
public:
|
||||||
AstCStmtUser(FileLine* fl, bool fromDollarC = false)
|
explicit AstCStmtUser(FileLine* fl, bool fromDollarC = false)
|
||||||
: ASTGEN_SUPER_CStmtUser(fl)
|
: ASTGEN_SUPER_CStmtUser(fl)
|
||||||
, m_fromDollarC{fromDollarC} {}
|
, m_fromDollarC{fromDollarC} {}
|
||||||
ASTGEN_MEMBERS_AstCStmtUser;
|
ASTGEN_MEMBERS_AstCStmtUser;
|
||||||
|
|
@ -763,7 +763,7 @@ class AstLoop final : public AstNodeStmt {
|
||||||
// @astgen op2 := contsp : List[AstNode] // Empty after LinkJump
|
// @astgen op2 := contsp : List[AstNode] // Empty after LinkJump
|
||||||
VOptionBool m_unroll; // Full, none, or default unrolling
|
VOptionBool m_unroll; // Full, none, or default unrolling
|
||||||
public:
|
public:
|
||||||
AstLoop(FileLine* fl)
|
explicit AstLoop(FileLine* fl)
|
||||||
: ASTGEN_SUPER_Loop(fl) {}
|
: ASTGEN_SUPER_Loop(fl) {}
|
||||||
ASTGEN_MEMBERS_AstLoop;
|
ASTGEN_MEMBERS_AstLoop;
|
||||||
void dump(std::ostream& str) const override;
|
void dump(std::ostream& str) const override;
|
||||||
|
|
|
||||||
|
|
@ -88,6 +88,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private: // for V3Broken only
|
private: // for V3Broken only
|
||||||
|
// cppcheck-suppress unusedPrivateFunction
|
||||||
bool isAllocated(const AstNode* nodep) const VL_REQUIRES(m_mutex) {
|
bool isAllocated(const AstNode* nodep) const VL_REQUIRES(m_mutex) {
|
||||||
return m_allocated.count(nodep) != 0;
|
return m_allocated.count(nodep) != 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1122,7 +1122,7 @@ class ConstVisitor final : public VNVisitor {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool matchCondCond(AstCond* nodep) {
|
bool matchCondCond(const AstCond* nodep) {
|
||||||
// Same condition on either leg of a condition means that
|
// Same condition on either leg of a condition means that
|
||||||
// expression is either always true or always false
|
// expression is either always true or always false
|
||||||
if (VN_IS(nodep->backp(), Cond)) return false; // Was checked when visited parent
|
if (VN_IS(nodep->backp(), Cond)) return false; // Was checked when visited parent
|
||||||
|
|
@ -1133,14 +1133,14 @@ class ConstVisitor final : public VNVisitor {
|
||||||
matchCondCondRecurse(nodep, truesp /*ref*/, falsesp /*ref*/);
|
matchCondCondRecurse(nodep, truesp /*ref*/, falsesp /*ref*/);
|
||||||
return false; // Can optimize further
|
return false; // Can optimize further
|
||||||
}
|
}
|
||||||
void matchCondCondRecurse(AstCond* nodep, std::vector<AstNodeExpr*>& truesp,
|
void matchCondCondRecurse(const AstCond* nodep, std::vector<AstNodeExpr*>& truesp,
|
||||||
std::vector<AstNodeExpr*>& falsesp) {
|
std::vector<AstNodeExpr*>& falsesp) {
|
||||||
// Avoid O(n^2) compares
|
// Avoid O(n^2) compares
|
||||||
// Could reduce cost with hash table, but seems unlikely to be worth cost
|
// Could reduce cost with hash table, but seems unlikely to be worth cost
|
||||||
if (truesp.size() > 4 || falsesp.size() > 4) return;
|
if (truesp.size() > 4 || falsesp.size() > 4) return;
|
||||||
if (!nodep->condp()->isPure()) return;
|
if (!nodep->condp()->isPure()) return;
|
||||||
bool replaced = false;
|
bool replaced = false;
|
||||||
for (AstNodeExpr* condp : truesp) {
|
for (const AstNodeExpr* condp : truesp) {
|
||||||
if (replaced) break;
|
if (replaced) break;
|
||||||
if (!operandsSame(nodep->condp(), condp)) continue;
|
if (!operandsSame(nodep->condp(), condp)) continue;
|
||||||
UINFO(9, "COND(c, CONDb(c, tt, tf), f) -> CONDb(1, tt, tf) " << nodep);
|
UINFO(9, "COND(c, CONDb(c, tt, tf), f) -> CONDb(1, tt, tf) " << nodep);
|
||||||
|
|
@ -1148,7 +1148,7 @@ class ConstVisitor final : public VNVisitor {
|
||||||
replaced = true;
|
replaced = true;
|
||||||
++m_statCondExprRedundant;
|
++m_statCondExprRedundant;
|
||||||
}
|
}
|
||||||
for (AstNodeExpr* condp : falsesp) {
|
for (const AstNodeExpr* condp : falsesp) {
|
||||||
if (replaced) break;
|
if (replaced) break;
|
||||||
if (!operandsSame(nodep->condp(), condp)) continue;
|
if (!operandsSame(nodep->condp(), condp)) continue;
|
||||||
UINFO(9, "COND(c, t, CONDb(c, ft, ff)) -> CONDb(0, ft, ff) " << nodep);
|
UINFO(9, "COND(c, t, CONDb(c, ft, ff)) -> CONDb(0, ft, ff) " << nodep);
|
||||||
|
|
@ -1156,18 +1156,18 @@ class ConstVisitor final : public VNVisitor {
|
||||||
replaced = true;
|
replaced = true;
|
||||||
++m_statCondExprRedundant;
|
++m_statCondExprRedundant;
|
||||||
}
|
}
|
||||||
if (AstCond* subCondp = VN_CAST(nodep->thenp(), Cond)) {
|
if (const AstCond* subCondp = VN_CAST(nodep->thenp(), Cond)) {
|
||||||
if (!replaced) truesp.emplace_back(nodep->condp());
|
if (!replaced) truesp.emplace_back(nodep->condp());
|
||||||
matchCondCondRecurse(subCondp, truesp /*ref*/, falsesp /*ref*/);
|
matchCondCondRecurse(subCondp, truesp /*ref*/, falsesp /*ref*/);
|
||||||
if (!replaced) truesp.pop_back();
|
if (!replaced) truesp.pop_back();
|
||||||
}
|
}
|
||||||
if (AstCond* subCondp = VN_CAST(nodep->elsep(), Cond)) {
|
if (const AstCond* subCondp = VN_CAST(nodep->elsep(), Cond)) {
|
||||||
if (!replaced) falsesp.emplace_back(nodep->condp());
|
if (!replaced) falsesp.emplace_back(nodep->condp());
|
||||||
matchCondCondRecurse(subCondp, truesp /*ref*/, falsesp /*ref*/);
|
matchCondCondRecurse(subCondp, truesp /*ref*/, falsesp /*ref*/);
|
||||||
if (!replaced) falsesp.pop_back();
|
if (!replaced) falsesp.pop_back();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void matchIfCondCond(AstNodeIf* nodep) {
|
void matchIfCondCond(const AstNodeIf* nodep) {
|
||||||
// Same condition on either leg of a condition means that
|
// Same condition on either leg of a condition means that
|
||||||
// expression is either always true or always false
|
// expression is either always true or always false
|
||||||
if (VN_IS(nodep->backp(), If)) return; // Was checked when visited parent
|
if (VN_IS(nodep->backp(), If)) return; // Was checked when visited parent
|
||||||
|
|
@ -1176,14 +1176,14 @@ class ConstVisitor final : public VNVisitor {
|
||||||
std::vector<AstNodeExpr*> falsesp;
|
std::vector<AstNodeExpr*> falsesp;
|
||||||
matchIfCondCondRecurse(nodep, truesp /*ref*/, falsesp /*ref*/);
|
matchIfCondCondRecurse(nodep, truesp /*ref*/, falsesp /*ref*/);
|
||||||
}
|
}
|
||||||
void matchIfCondCondRecurse(AstNodeIf* nodep, std::vector<AstNodeExpr*>& truesp,
|
void matchIfCondCondRecurse(const AstNodeIf* nodep, std::vector<AstNodeExpr*>& truesp,
|
||||||
std::vector<AstNodeExpr*>& falsesp) {
|
std::vector<AstNodeExpr*>& falsesp) {
|
||||||
// Avoid O(n^2) compares
|
// Avoid O(n^2) compares
|
||||||
// Could reduce cost with hash table, but seems unlikely to be worth cost
|
// Could reduce cost with hash table, but seems unlikely to be worth cost
|
||||||
if (truesp.size() > 4 || falsesp.size() > 4) return;
|
if (truesp.size() > 4 || falsesp.size() > 4) return;
|
||||||
if (!nodep->condp()->isPure()) return;
|
if (!nodep->condp()->isPure()) return;
|
||||||
bool replaced = false;
|
bool replaced = false;
|
||||||
for (AstNodeExpr* condp : truesp) {
|
for (const AstNodeExpr* condp : truesp) {
|
||||||
if (replaced) break;
|
if (replaced) break;
|
||||||
if (!operandsSame(nodep->condp(), condp)) continue;
|
if (!operandsSame(nodep->condp(), condp)) continue;
|
||||||
UINFO(9, "COND(c, CONDb(c, tt, tf), f) -> CONDb(1, tt, tf) " << nodep);
|
UINFO(9, "COND(c, CONDb(c, tt, tf), f) -> CONDb(1, tt, tf) " << nodep);
|
||||||
|
|
@ -1191,7 +1191,7 @@ class ConstVisitor final : public VNVisitor {
|
||||||
replaced = true;
|
replaced = true;
|
||||||
++m_statIfCondExprRedundant;
|
++m_statIfCondExprRedundant;
|
||||||
}
|
}
|
||||||
for (AstNodeExpr* condp : falsesp) {
|
for (const AstNodeExpr* condp : falsesp) {
|
||||||
if (replaced) break;
|
if (replaced) break;
|
||||||
if (!operandsSame(nodep->condp(), condp)) continue;
|
if (!operandsSame(nodep->condp(), condp)) continue;
|
||||||
UINFO(9, "COND(c, t, CONDb(c, ft, ff)) -> CONDb(0, ft, ff) " << nodep);
|
UINFO(9, "COND(c, t, CONDb(c, ft, ff)) -> CONDb(0, ft, ff) " << nodep);
|
||||||
|
|
@ -1202,12 +1202,12 @@ class ConstVisitor final : public VNVisitor {
|
||||||
// We only check the first statement of parent IF is an If
|
// We only check the first statement of parent IF is an If
|
||||||
// So we don't need to check for effects in the executing thensp/elsesp
|
// So we don't need to check for effects in the executing thensp/elsesp
|
||||||
// altering the child't condition. e.g. 'if (x) begin x=1; if (x) end'
|
// altering the child't condition. e.g. 'if (x) begin x=1; if (x) end'
|
||||||
if (AstNodeIf* subIfp = VN_CAST(nodep->thensp(), NodeIf)) {
|
if (const AstNodeIf* subIfp = VN_CAST(nodep->thensp(), NodeIf)) {
|
||||||
if (!replaced) truesp.emplace_back(nodep->condp());
|
if (!replaced) truesp.emplace_back(nodep->condp());
|
||||||
matchIfCondCondRecurse(subIfp, truesp /*ref*/, falsesp /*ref*/);
|
matchIfCondCondRecurse(subIfp, truesp /*ref*/, falsesp /*ref*/);
|
||||||
if (!replaced) truesp.pop_back();
|
if (!replaced) truesp.pop_back();
|
||||||
}
|
}
|
||||||
if (AstNodeIf* subIfp = VN_CAST(nodep->elsesp(), NodeIf)) {
|
if (const AstNodeIf* subIfp = VN_CAST(nodep->elsesp(), NodeIf)) {
|
||||||
if (!replaced) falsesp.emplace_back(nodep->condp());
|
if (!replaced) falsesp.emplace_back(nodep->condp());
|
||||||
matchIfCondCondRecurse(subIfp, truesp /*ref*/, falsesp /*ref*/);
|
matchIfCondCondRecurse(subIfp, truesp /*ref*/, falsesp /*ref*/);
|
||||||
if (!replaced) falsesp.pop_back();
|
if (!replaced) falsesp.pop_back();
|
||||||
|
|
@ -2635,7 +2635,7 @@ class ConstVisitor final : public VNVisitor {
|
||||||
}
|
}
|
||||||
bool matchToStringNConst(AstToStringN* nodep) {
|
bool matchToStringNConst(AstToStringN* nodep) {
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
if (AstInitArray* const initp = VN_CAST(nodep->lhsp(), InitArray)) {
|
if (const AstInitArray* const initp = VN_CAST(nodep->lhsp(), InitArray)) {
|
||||||
if (!(m_doExpensive || m_params)) return false;
|
if (!(m_doExpensive || m_params)) return false;
|
||||||
// At present only support 1D unpacked arrays
|
// At present only support 1D unpacked arrays
|
||||||
const auto initOfConst = [](const AstNode* const nodep) -> bool { //
|
const auto initOfConst = [](const AstNode* const nodep) -> bool { //
|
||||||
|
|
@ -2823,9 +2823,9 @@ class ConstVisitor final : public VNVisitor {
|
||||||
// cppcheck-suppress constVariablePointer // children unlinked below
|
// cppcheck-suppress constVariablePointer // children unlinked below
|
||||||
AstReplicate* const rep2p = VN_AS(nodep->srcp(), Replicate);
|
AstReplicate* const rep2p = VN_AS(nodep->srcp(), Replicate);
|
||||||
AstNodeExpr* const from2p = rep2p->srcp();
|
AstNodeExpr* const from2p = rep2p->srcp();
|
||||||
AstConst* const cnt1p = VN_CAST(nodep->countp(), Const);
|
const AstConst* const cnt1p = VN_CAST(nodep->countp(), Const);
|
||||||
if (!cnt1p) return false;
|
if (!cnt1p) return false;
|
||||||
AstConst* const cnt2p = VN_CAST(rep2p->countp(), Const);
|
const AstConst* const cnt2p = VN_CAST(rep2p->countp(), Const);
|
||||||
if (!cnt2p) return false;
|
if (!cnt2p) return false;
|
||||||
//
|
//
|
||||||
from2p->unlinkFrBack();
|
from2p->unlinkFrBack();
|
||||||
|
|
@ -3606,7 +3606,7 @@ class ConstVisitor final : public VNVisitor {
|
||||||
bool thisLoopHasJumpDelay = m_hasJumpDelay;
|
bool thisLoopHasJumpDelay = m_hasJumpDelay;
|
||||||
m_hasJumpDelay = thisLoopHasJumpDelay || oldHasJumpDelay;
|
m_hasJumpDelay = thisLoopHasJumpDelay || oldHasJumpDelay;
|
||||||
// If the first statement always break, the loop is useless
|
// If the first statement always break, the loop is useless
|
||||||
if (AstLoopTest* const testp = VN_CAST(nodep->stmtsp(), LoopTest)) {
|
if (const AstLoopTest* const testp = VN_CAST(nodep->stmtsp(), LoopTest)) {
|
||||||
if (testp->condp()->isZero()) {
|
if (testp->condp()->isZero()) {
|
||||||
nodep->v3warn(UNUSEDLOOP, "Loop condition is always false");
|
nodep->v3warn(UNUSEDLOOP, "Loop condition is always false");
|
||||||
VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep);
|
VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep);
|
||||||
|
|
@ -3680,8 +3680,8 @@ class ConstVisitor final : public VNVisitor {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Remove calls to empty functions
|
// Remove calls to empty functions
|
||||||
if (AstCCall* const callp = VN_CAST(nodep->exprp(), CCall)) {
|
if (const AstCCall* const callp = VN_CAST(nodep->exprp(), CCall)) {
|
||||||
AstCFunc* const funcp = callp->funcp();
|
const AstCFunc* const funcp = callp->funcp();
|
||||||
if (!callp->argsp() && funcp->emptyBody()) {
|
if (!callp->argsp() && funcp->emptyBody()) {
|
||||||
VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep);
|
VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep);
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -796,7 +796,7 @@ void V3Control::applyFTask(AstNodeModule* modulep, AstNodeFTask* ftaskp) {
|
||||||
|
|
||||||
void V3Control::applyVarAttr(const AstNodeModule* modulep, const AstNodeFTask* ftaskp,
|
void V3Control::applyVarAttr(const AstNodeModule* modulep, const AstNodeFTask* ftaskp,
|
||||||
AstVar* varp) {
|
AstVar* varp) {
|
||||||
V3ControlVar* vp;
|
const V3ControlVar* vp;
|
||||||
V3ControlModule* const modp
|
V3ControlModule* const modp
|
||||||
= V3ControlResolver::s().modules().resolve(modulep->prettyDehashOrigOrName());
|
= V3ControlResolver::s().modules().resolve(modulep->prettyDehashOrigOrName());
|
||||||
if (!modp) return;
|
if (!modp) return;
|
||||||
|
|
|
||||||
|
|
@ -378,7 +378,7 @@ class DeadVisitor final : public VNVisitor {
|
||||||
});
|
});
|
||||||
taskp->user1(-1); // we don't want to try deleting twice
|
taskp->user1(-1); // we don't want to try deleting twice
|
||||||
deleting(taskp);
|
deleting(taskp);
|
||||||
m_statFTasksDeadified++;
|
++m_statFTasksDeadified;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -181,7 +181,7 @@ class AstToDfgVisitor final : public VNVisitor {
|
||||||
const VAlwaysKwd kwd = nodep->keyword();
|
const VAlwaysKwd kwd = nodep->keyword();
|
||||||
if (kwd == VAlwaysKwd::CONT_ASSIGN) {
|
if (kwd == VAlwaysKwd::CONT_ASSIGN) {
|
||||||
// TODO: simplify once CFG analysis can handle arrays
|
// TODO: simplify once CFG analysis can handle arrays
|
||||||
if (AstAssignW* const ap = VN_CAST(nodep->stmtsp(), AssignW)) {
|
if (const AstAssignW* const ap = VN_CAST(nodep->stmtsp(), AssignW)) {
|
||||||
if (ap->nextp()) return false;
|
if (ap->nextp()) return false;
|
||||||
// Cannot handle assignment with timing control
|
// Cannot handle assignment with timing control
|
||||||
if (ap->timingControlp()) return false;
|
if (ap->timingControlp()) return false;
|
||||||
|
|
|
||||||
|
|
@ -269,8 +269,9 @@ class DataflowOptimize final {
|
||||||
}
|
}
|
||||||
// TODO: remove once Actives can tolerate NEVER SenItems
|
// TODO: remove once Actives can tolerate NEVER SenItems
|
||||||
if (AstSenItem* senItemp = VN_CAST(nodep, SenItem)) {
|
if (AstSenItem* senItemp = VN_CAST(nodep, SenItem)) {
|
||||||
senItemp->foreach(
|
senItemp->foreach([](const AstVarRef* refp) {
|
||||||
[](AstVarRef* refp) { DfgVertexVar::setHasExtRdRefs(refp->varScopep()); });
|
DfgVertexVar::setHasExtRdRefs(refp->varScopep());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (AstVar* const varp = VN_CAST(nodep, Var)) {
|
if (AstVar* const varp = VN_CAST(nodep, Var)) {
|
||||||
|
|
|
||||||
|
|
@ -273,7 +273,7 @@ std::pair<string, FileLine*> EmitCBaseVisitorConst::scSection(const AstNodeModul
|
||||||
FileLine* fl = nullptr;
|
FileLine* fl = nullptr;
|
||||||
int last_line = -999;
|
int last_line = -999;
|
||||||
for (AstNode* nodep = modp->stmtsp(); nodep; nodep = nodep->nextp()) {
|
for (AstNode* nodep = modp->stmtsp(); nodep; nodep = nodep->nextp()) {
|
||||||
AstSystemCSection* const ssp = VN_CAST(nodep, SystemCSection);
|
const AstSystemCSection* const ssp = VN_CAST(nodep, SystemCSection);
|
||||||
if (!ssp) continue;
|
if (!ssp) continue;
|
||||||
if (ssp->sectionType() != type) continue;
|
if (ssp->sectionType() != type) continue;
|
||||||
if (text.empty()) {
|
if (text.empty()) {
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// VISITOR
|
// VISITOR
|
||||||
void visit(AstNode* nodep) { nodep->v3fatalSrc("Unused"); }
|
void visit(AstNode* nodep) override { nodep->v3fatalSrc("Unused"); }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit EmitCPch() { emitPch(); }
|
explicit EmitCPch() { emitPch(); }
|
||||||
|
|
|
||||||
|
|
@ -108,11 +108,11 @@ class EmitCSyms final : EmitCBaseVisitorConst {
|
||||||
void emitSymHdr();
|
void emitSymHdr();
|
||||||
void emitSymImpPreamble();
|
void emitSymImpPreamble();
|
||||||
void emitScopeHier(std::vector<std::string>& stmts, bool destroy);
|
void emitScopeHier(std::vector<std::string>& stmts, bool destroy);
|
||||||
void emitSymImp(AstNetlist* netlistp);
|
void emitSymImp(const AstNetlist* netlistp);
|
||||||
void emitDpiHdr();
|
void emitDpiHdr();
|
||||||
void emitDpiImp();
|
void emitDpiImp();
|
||||||
|
|
||||||
void emitSplit(std::vector<std::string>& stmts, const std::string name, size_t max_stmts);
|
void emitSplit(std::vector<std::string>& stmts, const std::string& name, size_t max_stmts);
|
||||||
|
|
||||||
std::vector<std::string> getSymCtorStmts();
|
std::vector<std::string> getSymCtorStmts();
|
||||||
std::vector<std::string> getSymDtorStmts();
|
std::vector<std::string> getSymDtorStmts();
|
||||||
|
|
@ -863,7 +863,7 @@ std::vector<std::string> EmitCSyms::getSymDtorStmts() {
|
||||||
return stmts;
|
return stmts;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitCSyms::emitSplit(std::vector<std::string>& stmts, const std::string name,
|
void EmitCSyms::emitSplit(std::vector<std::string>& stmts, const std::string& name,
|
||||||
size_t maxCost) {
|
size_t maxCost) {
|
||||||
size_t nSubFunctions = 0;
|
size_t nSubFunctions = 0;
|
||||||
// Reduce into a balanced tree of sub-function calls until we end up with a single statement
|
// Reduce into a balanced tree of sub-function calls until we end up with a single statement
|
||||||
|
|
@ -912,7 +912,7 @@ void EmitCSyms::emitSplit(std::vector<std::string>& stmts, const std::string nam
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitCSyms::emitSymImp(AstNetlist* netlistp) {
|
void EmitCSyms::emitSymImp(const AstNetlist* netlistp) {
|
||||||
UINFO(6, __FUNCTION__ << ": ");
|
UINFO(6, __FUNCTION__ << ": ");
|
||||||
|
|
||||||
// Get the body of the constructor and destructor
|
// Get the body of the constructor and destructor
|
||||||
|
|
|
||||||
|
|
@ -118,11 +118,11 @@ class V3EmitMkJsonEmitter final {
|
||||||
// really have to, but verilator-config.cmake.in depends on order.
|
// really have to, but verilator-config.cmake.in depends on order.
|
||||||
for (const V3GraphVertex& vtx : vlstd::reverse_view(graphp->vertices())) {
|
for (const V3GraphVertex& vtx : vlstd::reverse_view(graphp->vertices())) {
|
||||||
const V3HierBlock* const hblockp = vtx.as<V3HierBlock>();
|
const V3HierBlock* const hblockp = vtx.as<V3HierBlock>();
|
||||||
std::vector<std::string> deps;
|
std::vector<std::string> hierDeps;
|
||||||
std::vector<std::string> sources;
|
std::vector<std::string> sources;
|
||||||
for (const V3GraphEdge& edge : hblockp->outEdges()) {
|
for (const V3GraphEdge& edge : hblockp->outEdges()) {
|
||||||
const V3HierBlock* const dependencyp = edge.top()->as<V3HierBlock>();
|
const V3HierBlock* const dependencyp = edge.top()->as<V3HierBlock>();
|
||||||
deps.emplace_back(dependencyp->hierPrefix());
|
hierDeps.emplace_back(dependencyp->hierPrefix());
|
||||||
sources.emplace_back(makeDir + "/" + dependencyp->hierWrapperFilename(true));
|
sources.emplace_back(makeDir + "/" + dependencyp->hierWrapperFilename(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -137,7 +137,7 @@ class V3EmitMkJsonEmitter final {
|
||||||
of.begin()
|
of.begin()
|
||||||
.put("prefix", hblockp->hierPrefix())
|
.put("prefix", hblockp->hierPrefix())
|
||||||
.put("top", hblockp->modp()->name())
|
.put("top", hblockp->modp()->name())
|
||||||
.putList("deps", deps)
|
.putList("deps", hierDeps)
|
||||||
.put("directory", makeDir + "/" + hblockp->hierPrefix())
|
.put("directory", makeDir + "/" + hblockp->hierPrefix())
|
||||||
.putList("sources", sources)
|
.putList("sources", sources)
|
||||||
.putList("cflags", {"-fPIC"})
|
.putList("cflags", {"-fPIC"})
|
||||||
|
|
|
||||||
|
|
@ -35,13 +35,13 @@ VL_DEFINE_DEBUG_FUNCTIONS;
|
||||||
|
|
||||||
AstCFunc* ExecMTask::createCFunc(AstExecGraph* execGraphp, AstScope* scopep, AstNodeStmt* stmtsp,
|
AstCFunc* ExecMTask::createCFunc(AstExecGraph* execGraphp, AstScope* scopep, AstNodeStmt* stmtsp,
|
||||||
uint32_t id) {
|
uint32_t id) {
|
||||||
const std::string name = execGraphp->name() + "_mtask" + std::to_string(id);
|
const std::string newName = execGraphp->name() + "_mtask" + std::to_string(id);
|
||||||
AstCFunc* const funcp = new AstCFunc{execGraphp->fileline(), name, scopep};
|
AstCFunc* const newp = new AstCFunc{execGraphp->fileline(), newName, scopep};
|
||||||
funcp->isLoose(true);
|
newp->isLoose(true);
|
||||||
funcp->dontCombine(true);
|
newp->dontCombine(true);
|
||||||
funcp->addStmtsp(stmtsp);
|
newp->addStmtsp(stmtsp);
|
||||||
if (scopep) scopep->addBlocksp(funcp);
|
if (scopep) scopep->addBlocksp(newp);
|
||||||
return funcp;
|
return newp;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExecMTask::ExecMTask(AstExecGraph* execGraphp, AstScope* scopep,
|
ExecMTask::ExecMTask(AstExecGraph* execGraphp, AstScope* scopep,
|
||||||
|
|
|
||||||
|
|
@ -234,7 +234,7 @@ class ExpandVisitor final : public VNVisitor {
|
||||||
static AstNodeExpr* newWordIndex(AstNodeExpr* lsbp, uint32_t wordOffset = 0) {
|
static AstNodeExpr* newWordIndex(AstNodeExpr* lsbp, uint32_t wordOffset = 0) {
|
||||||
// This is indexing a WordSel, so a 32 bit constants are fine
|
// This is indexing a WordSel, so a 32 bit constants are fine
|
||||||
FileLine* const flp = lsbp->fileline();
|
FileLine* const flp = lsbp->fileline();
|
||||||
if (AstConst* constp = VN_CAST(lsbp, Const)) {
|
if (const AstConst* constp = VN_CAST(lsbp, Const)) {
|
||||||
return new AstConst{flp, wordOffset + VL_BITWORD_E(constp->toUInt())};
|
return new AstConst{flp, wordOffset + VL_BITWORD_E(constp->toUInt())};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -250,7 +250,7 @@ class ExpandVisitor final : public VNVisitor {
|
||||||
uint32_t wordOffset = 0) {
|
uint32_t wordOffset = 0) {
|
||||||
UASSERT_OBJ(fromp->isWide(), fromp, "Only need AstWordSel on wide from's");
|
UASSERT_OBJ(fromp->isWide(), fromp, "Only need AstWordSel on wide from's");
|
||||||
|
|
||||||
if (AstConst* const constp = VN_CAST(indexp, Const)) {
|
if (const AstConst* const constp = VN_CAST(indexp, Const)) {
|
||||||
indexp = nullptr;
|
indexp = nullptr;
|
||||||
wordOffset += constp->toUInt();
|
wordOffset += constp->toUInt();
|
||||||
}
|
}
|
||||||
|
|
@ -545,7 +545,7 @@ class ExpandVisitor final : public VNVisitor {
|
||||||
V3Const::constifyEditCpp(rhsp->lsbp());
|
V3Const::constifyEditCpp(rhsp->lsbp());
|
||||||
|
|
||||||
// If it's a constant select and aligned, we can just copy the words
|
// If it's a constant select and aligned, we can just copy the words
|
||||||
if (AstConst* const lsbConstp = VN_CAST(rhsp->lsbp(), Const)) {
|
if (const AstConst* const lsbConstp = VN_CAST(rhsp->lsbp(), Const)) {
|
||||||
const uint32_t lsb = lsbConstp->toUInt();
|
const uint32_t lsb = lsbConstp->toUInt();
|
||||||
if (VL_BITBIT_E(lsb) == 0) {
|
if (VL_BITBIT_E(lsb) == 0) {
|
||||||
UINFO(8, " Wordize ASSIGN(SEL,align) " << nodep);
|
UINFO(8, " Wordize ASSIGN(SEL,align) " << nodep);
|
||||||
|
|
@ -577,7 +577,7 @@ class ExpandVisitor final : public VNVisitor {
|
||||||
AstNodeExpr* loShftp = nullptr;
|
AstNodeExpr* loShftp = nullptr;
|
||||||
AstNodeExpr* hiShftp = nullptr;
|
AstNodeExpr* hiShftp = nullptr;
|
||||||
AstNodeExpr* hiMaskp = nullptr;
|
AstNodeExpr* hiMaskp = nullptr;
|
||||||
if (AstConst* const lsbConstp = VN_CAST(rhsp->lsbp(), Const)) {
|
if (const AstConst* const lsbConstp = VN_CAST(rhsp->lsbp(), Const)) {
|
||||||
const uint32_t bitOffset = VL_BITBIT_E(lsbConstp->toUInt());
|
const uint32_t bitOffset = VL_BITBIT_E(lsbConstp->toUInt());
|
||||||
// Must be unaligned, otherwise we would have handled it above
|
// Must be unaligned, otherwise we would have handled it above
|
||||||
UASSERT_OBJ(bitOffset, nodep, "Missed aligned wide select");
|
UASSERT_OBJ(bitOffset, nodep, "Missed aligned wide select");
|
||||||
|
|
|
||||||
|
|
@ -752,7 +752,7 @@ void V3OutFormatter::putns(const AstNode* nodep, const char* strg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (putNodeDecoration) {
|
if (putNodeDecoration) {
|
||||||
FileLine* const flp = nodep->fileline();
|
const FileLine* const flp = nodep->fileline();
|
||||||
m_sourceLastLineno = flp->firstLineno();
|
m_sourceLastLineno = flp->firstLineno();
|
||||||
m_sourceLastFilenameno = flp->filenameno();
|
m_sourceLastFilenameno = flp->filenameno();
|
||||||
const std::string lineno = std::to_string(flp->lineno());
|
const std::string lineno = std::to_string(flp->lineno());
|
||||||
|
|
|
||||||
|
|
@ -173,9 +173,7 @@ VStringList V3HierBlock::commandArgs(bool forMkJson) const {
|
||||||
|
|
||||||
const StrGParams gparamsStr = stringifyParams(m_params, true);
|
const StrGParams gparamsStr = stringifyParams(m_params, true);
|
||||||
for (const StrGParam& param : gparamsStr) {
|
for (const StrGParam& param : gparamsStr) {
|
||||||
const string name = param.first;
|
opts.push_back("-G" + param.first + "=" + param.second + "");
|
||||||
const string value = param.second;
|
|
||||||
opts.push_back("-G" + name + "=" + value + "");
|
|
||||||
}
|
}
|
||||||
if (!m_typeParams.empty()) {
|
if (!m_typeParams.empty()) {
|
||||||
opts.push_back(" --hierarchical-params-file " + typeParametersFilename());
|
opts.push_back(" --hierarchical-params-file " + typeParametersFilename());
|
||||||
|
|
@ -382,7 +380,7 @@ class HierBlockUsageCollectVisitor final : public VNVisitorConst {
|
||||||
void visit(AstNode* nodep) override { iterateChildrenConst(nodep); }
|
void visit(AstNode* nodep) override { iterateChildrenConst(nodep); }
|
||||||
|
|
||||||
// CONSTRUCTOR
|
// CONSTRUCTOR
|
||||||
HierBlockUsageCollectVisitor(AstNetlist* netlistp) {
|
explicit HierBlockUsageCollectVisitor(AstNetlist* netlistp) {
|
||||||
iterateChildrenConst(netlistp);
|
iterateChildrenConst(netlistp);
|
||||||
if (dumpGraphLevel() >= 3) m_graphp->dumpDotFilePrefixed("hierblocks_initial");
|
if (dumpGraphLevel() >= 3) m_graphp->dumpDotFilePrefixed("hierblocks_initial");
|
||||||
// Simplify dependencies
|
// Simplify dependencies
|
||||||
|
|
|
||||||
|
|
@ -429,7 +429,7 @@ namespace ModuleInliner {
|
||||||
// against it later in V3Scope (and also for tracing, which is inserted
|
// against it later in V3Scope (and also for tracing, which is inserted
|
||||||
//later). Returns ture iff the given port variable should be inlined,
|
//later). Returns ture iff the given port variable should be inlined,
|
||||||
// and false if a continuous assignment should be used.
|
// and false if a continuous assignment should be used.
|
||||||
bool inlinePort(AstVar* nodep) {
|
bool inlinePort(const AstVar* nodep) {
|
||||||
// Interface references are always inlined
|
// Interface references are always inlined
|
||||||
if (nodep->isIfaceRef()) return true;
|
if (nodep->isIfaceRef()) return true;
|
||||||
// Ref ports must be always inlined
|
// Ref ports must be always inlined
|
||||||
|
|
@ -544,7 +544,6 @@ void inlineCell(AstNodeModule* modp, AstCell* cellp, bool last) {
|
||||||
: cellp->modp()->cloneTree(false);
|
: cellp->modp()->cloneTree(false);
|
||||||
|
|
||||||
// Compute map from original port variables and cells to their clones
|
// Compute map from original port variables and cells to their clones
|
||||||
std::unordered_map<const AstVar*, AstVar*> modVar2Clone;
|
|
||||||
for (AstNode *ap = cellp->modp()->stmtsp(), *bp = inlinedp->stmtsp(); ap || bp;
|
for (AstNode *ap = cellp->modp()->stmtsp(), *bp = inlinedp->stmtsp(); ap || bp;
|
||||||
ap = ap->nextp(), bp = bp->nextp()) {
|
ap = ap->nextp(), bp = bp->nextp()) {
|
||||||
UASSERT_OBJ(ap && bp, ap ? ap : bp, "Clone has different number of children");
|
UASSERT_OBJ(ap && bp, ap ? ap : bp, "Clone has different number of children");
|
||||||
|
|
|
||||||
|
|
@ -133,7 +133,7 @@ public:
|
||||||
, m_statep{statep} {}
|
, m_statep{statep} {}
|
||||||
~LifeBlock() = default;
|
~LifeBlock() = default;
|
||||||
// METHODS
|
// METHODS
|
||||||
void checkRemoveAssign(AstVarScope* vscp, LifeVarEntry& entr) {
|
void checkRemoveAssign(const AstVarScope* vscp, LifeVarEntry& entr) {
|
||||||
const AstVar* const varp = vscp->varp();
|
const AstVar* const varp = vscp->varp();
|
||||||
// We don't optimize any public sigs
|
// We don't optimize any public sigs
|
||||||
if (varp->isSigPublic()) return;
|
if (varp->isSigPublic()) return;
|
||||||
|
|
|
||||||
|
|
@ -920,6 +920,7 @@ string V3Number::emitC() const VL_MT_STABLE {
|
||||||
} else if (words() == 2) { // Quad
|
} else if (words() == 2) { // Quad
|
||||||
const uint64_t qnum = static_cast<uint64_t>(toUQuad());
|
const uint64_t qnum = static_cast<uint64_t>(toUQuad());
|
||||||
const char* const fmt = (qnum < 10) ? ("%" PRIx64 "ULL") : ("0x%016" PRIx64 "ULL");
|
const char* const fmt = (qnum < 10) ? ("%" PRIx64 "ULL") : ("0x%016" PRIx64 "ULL");
|
||||||
|
// cppcheck-suppress wrongPrintfScanfArgNum
|
||||||
VL_SNPRINTF(sbuf, bufsize, fmt, qnum);
|
VL_SNPRINTF(sbuf, bufsize, fmt, qnum);
|
||||||
return sbuf;
|
return sbuf;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -930,6 +931,7 @@ string V3Number::emitC() const VL_MT_STABLE {
|
||||||
: (width() > 16) ? ("0x%08" PRIx32 "U")
|
: (width() > 16) ? ("0x%08" PRIx32 "U")
|
||||||
: (width() > 8) ? ("0x%04" PRIx32 "U")
|
: (width() > 8) ? ("0x%04" PRIx32 "U")
|
||||||
: ("0x%02" PRIx32 "U");
|
: ("0x%02" PRIx32 "U");
|
||||||
|
// cppcheck-suppress wrongPrintfScanfArgNum
|
||||||
VL_SNPRINTF(sbuf, bufsize, fmt, unum);
|
VL_SNPRINTF(sbuf, bufsize, fmt, unum);
|
||||||
return sbuf;
|
return sbuf;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -486,7 +486,8 @@ std::vector<std::string> V3Options::traceClassBases() const VL_MT_SAFE {
|
||||||
}
|
}
|
||||||
std::vector<std::string> V3Options::traceClassLangs() const VL_MT_SAFE {
|
std::vector<std::string> V3Options::traceClassLangs() const VL_MT_SAFE {
|
||||||
std::vector<std::string> result;
|
std::vector<std::string> result;
|
||||||
for (auto& cbase : traceClassBases()) result.emplace_back(cbase + (systemC() ? "Sc" : "C"));
|
for (const auto& cbase : traceClassBases())
|
||||||
|
result.emplace_back(cbase + (systemC() ? "Sc" : "C"));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
std::vector<std::string> V3Options::traceSourceBases() const VL_MT_SAFE {
|
std::vector<std::string> V3Options::traceSourceBases() const VL_MT_SAFE {
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ AstNodeStmt* createSerial(OrderMoveGraph& moveGraph, //
|
||||||
const std::string& tag, //
|
const std::string& tag, //
|
||||||
bool slow);
|
bool slow);
|
||||||
|
|
||||||
AstNodeStmt* createParallel(OrderGraph& orderGraph, //
|
AstNodeStmt* createParallel(const OrderGraph& orderGraph, //
|
||||||
OrderMoveGraph& moveGraph, //
|
OrderMoveGraph& moveGraph, //
|
||||||
const std::string& tag, //
|
const std::string& tag, //
|
||||||
bool slow);
|
bool slow);
|
||||||
|
|
|
||||||
|
|
@ -2394,7 +2394,7 @@ struct MTaskVxIdLessThan final {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
AstNodeStmt* V3Order::createParallel(OrderGraph& orderGraph, OrderMoveGraph& moveGraph,
|
AstNodeStmt* V3Order::createParallel(const OrderGraph& orderGraph, OrderMoveGraph& moveGraph,
|
||||||
const std::string& tag, bool slow) {
|
const std::string& tag, bool slow) {
|
||||||
UINFO(2, " Constructing parallel code for '" + tag + "'");
|
UINFO(2, " Constructing parallel code for '" + tag + "'");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -771,10 +771,10 @@ class ParamProcessor final {
|
||||||
UINFOTREE(1, pinp, "", "errnode");
|
UINFOTREE(1, pinp, "", "errnode");
|
||||||
pinp->v3error("Can't convert defparam value to constant: Param "
|
pinp->v3error("Can't convert defparam value to constant: Param "
|
||||||
<< pinp->prettyNameQ() << " of " << nodep->prettyNameQ());
|
<< pinp->prettyNameQ() << " of " << nodep->prettyNameQ());
|
||||||
AstNode* const exprp = pinp->exprp();
|
AstNode* const pinExprp = pinp->exprp();
|
||||||
exprp->replaceWith(new AstConst{pinp->fileline(), AstConst::WidthedValue{},
|
pinExprp->replaceWith(new AstConst{pinp->fileline(), AstConst::WidthedValue{},
|
||||||
modvarp->width(), 0});
|
modvarp->width(), 0});
|
||||||
VL_DO_DANGLING(exprp->deleteTree(), exprp);
|
VL_DO_DANGLING(pinExprp->deleteTree(), pinExprp);
|
||||||
} else if (origp && exprp->sameTree(origp)) {
|
} else if (origp && exprp->sameTree(origp)) {
|
||||||
// Setting parameter to its default value. Just ignore it.
|
// Setting parameter to its default value. Just ignore it.
|
||||||
// This prevents making additional modules, and makes coverage more
|
// This prevents making additional modules, and makes coverage more
|
||||||
|
|
@ -1087,7 +1087,7 @@ class ParamProcessor final {
|
||||||
// We need to relink the pins to the new module
|
// We need to relink the pins to the new module
|
||||||
relinkPinsByName(pinsp, paramedModp);
|
relinkPinsByName(pinsp, paramedModp);
|
||||||
newModp = paramedModp;
|
newModp = paramedModp;
|
||||||
any_overrides = true;
|
// any_overrides = true; // Unused later, so not needed
|
||||||
} else if (!any_overrides) {
|
} else if (!any_overrides) {
|
||||||
UINFO(8, "Cell parameters all match original values, skipping expansion.");
|
UINFO(8, "Cell parameters all match original values, skipping expansion.");
|
||||||
// If it's the first use of the default instance, create a copy and store it in user3p.
|
// If it's the first use of the default instance, create a copy and store it in user3p.
|
||||||
|
|
@ -1281,7 +1281,7 @@ class ParamVisitor final : public VNVisitor {
|
||||||
m_isCircular; // Stores information whether `AstRefDType` is circular
|
m_isCircular; // Stores information whether `AstRefDType` is circular
|
||||||
|
|
||||||
// STATE - for current visit position (use VL_RESTORER)
|
// STATE - for current visit position (use VL_RESTORER)
|
||||||
AstNodeModule* m_modp; // Module iterating
|
AstNodeModule* m_modp = nullptr; // Module iterating
|
||||||
std::unordered_set<std::string> m_ifacePortNames; // Interface port names in current module
|
std::unordered_set<std::string> m_ifacePortNames; // Interface port names in current module
|
||||||
std::unordered_set<std::string> m_ifaceInstNames; // Interface decl names in current module
|
std::unordered_set<std::string> m_ifaceInstNames; // Interface decl names in current module
|
||||||
string m_generateHierName; // Generate portion of hierarchy name
|
string m_generateHierName; // Generate portion of hierarchy name
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ public:
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
AstArg* argWrapList(AstNodeExpr* nodep) VL_MT_DISABLED;
|
AstArg* argWrapList(AstNodeExpr* nodep) VL_MT_DISABLED;
|
||||||
bool allTracingOn(FileLine* fl) {
|
bool allTracingOn(const FileLine* fl) const {
|
||||||
return v3Global.opt.trace() && m_tracingParse && fl->tracingOn();
|
return v3Global.opt.trace() && m_tracingParse && fl->tracingOn();
|
||||||
}
|
}
|
||||||
AstRange* scrubRange(AstNodeRange* rangep) VL_MT_DISABLED;
|
AstRange* scrubRange(AstNodeRange* rangep) VL_MT_DISABLED;
|
||||||
|
|
@ -99,11 +99,13 @@ public:
|
||||||
nodep->addStmtsp(defaultVarp);
|
nodep->addStmtsp(defaultVarp);
|
||||||
|
|
||||||
// IEEE: function void sample()
|
// IEEE: function void sample()
|
||||||
AstFunc* const funcp = new AstFunc{nodep->fileline(), "sample", nullptr, nullptr};
|
{
|
||||||
funcp->addStmtsp(sampleArgs);
|
AstFunc* const funcp = new AstFunc{nodep->fileline(), "sample", nullptr, nullptr};
|
||||||
funcp->classMethod(true);
|
funcp->addStmtsp(sampleArgs);
|
||||||
funcp->dtypep(funcp->findVoidDType());
|
funcp->classMethod(true);
|
||||||
nodep->addMembersp(funcp);
|
funcp->dtypep(funcp->findVoidDType());
|
||||||
|
nodep->addMembersp(funcp);
|
||||||
|
}
|
||||||
|
|
||||||
// IEEE: function void start(), void stop()
|
// IEEE: function void start(), void stop()
|
||||||
for (const string& name : {"start"s, "stop"s}) {
|
for (const string& name : {"start"s, "stop"s}) {
|
||||||
|
|
@ -200,10 +202,10 @@ public:
|
||||||
V3ParseImp::parsep()->tagNodep(nodep);
|
V3ParseImp::parsep()->tagNodep(nodep);
|
||||||
return nodep;
|
return nodep;
|
||||||
}
|
}
|
||||||
void endLabel(FileLine* fl, AstNode* nodep, string* endnamep) {
|
void endLabel(FileLine* fl, const AstNode* nodep, const string* endnamep) {
|
||||||
endLabel(fl, nodep->prettyName(), endnamep);
|
endLabel(fl, nodep->prettyName(), endnamep);
|
||||||
}
|
}
|
||||||
void endLabel(FileLine* fl, const string& name, string* endnamep) {
|
void endLabel(FileLine* fl, const string& name, const string* endnamep) {
|
||||||
if (fl && endnamep && *endnamep != "" && name != *endnamep
|
if (fl && endnamep && *endnamep != "" && name != *endnamep
|
||||||
&& name != AstNode::prettyName(*endnamep)) {
|
&& name != AstNode::prettyName(*endnamep)) {
|
||||||
fl->v3warn(ENDLABEL, "End label '" << *endnamep << "' does not match begin label '"
|
fl->v3warn(ENDLABEL, "End label '" << *endnamep << "' does not match begin label '"
|
||||||
|
|
|
||||||
|
|
@ -607,8 +607,8 @@ TriggerKit TriggerKit::create(AstNetlist* netlistp, //
|
||||||
for (uint32_t level = 0; level < WORD_SIZE_LOG2; ++level) {
|
for (uint32_t level = 0; level < WORD_SIZE_LOG2; ++level) {
|
||||||
const uint32_t stride = 1 << level;
|
const uint32_t stride = 1 << level;
|
||||||
for (uint32_t j = 0; j < WORD_SIZE; j += 2 * stride) {
|
for (uint32_t j = 0; j < WORD_SIZE; j += 2 * stride) {
|
||||||
FileLine* const flp = trigps[i + j]->fileline();
|
trigps[i + j] = new AstConcat{trigps[i + j]->fileline(), trigps[i + j + stride],
|
||||||
trigps[i + j] = new AstConcat{flp, trigps[i + j + stride], trigps[i + j]};
|
trigps[i + j]};
|
||||||
trigps[i + j + stride] = nullptr;
|
trigps[i + j + stride] = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -668,11 +668,11 @@ TriggerKit TriggerKit::create(AstNetlist* netlistp, //
|
||||||
for (AstNodeStmt* const nodep : senResults.m_postUpdates) fp->addStmtsp(nodep);
|
for (AstNodeStmt* const nodep : senResults.m_postUpdates) fp->addStmtsp(nodep);
|
||||||
// Add the initialization time triggers
|
// Add the initialization time triggers
|
||||||
if (initialTrigsp) {
|
if (initialTrigsp) {
|
||||||
AstVarScope* const vscp = scopep->createTemp("__V" + name + "DidInit", 1);
|
AstVarScope* const initVscp = scopep->createTemp("__V" + name + "DidInit", 1);
|
||||||
AstIf* const ifp = new AstIf{flp, new AstNot{flp, rd(vscp)}};
|
AstIf* const ifp = new AstIf{flp, new AstNot{flp, rd(initVscp)}};
|
||||||
fp->addStmtsp(ifp);
|
fp->addStmtsp(ifp);
|
||||||
ifp->branchPred(VBranchPred::BP_UNLIKELY);
|
ifp->branchPred(VBranchPred::BP_UNLIKELY);
|
||||||
ifp->addThensp(util::setVar(vscp, 1));
|
ifp->addThensp(util::setVar(initVscp, 1));
|
||||||
ifp->addThensp(initialTrigsp);
|
ifp->addThensp(initialTrigsp);
|
||||||
}
|
}
|
||||||
// If there are 'pre' triggers, compute them
|
// If there are 'pre' triggers, compute them
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,7 @@ AstNodeStmt* checkIterationLimit(AstNetlist* netlistp, const string& name, AstVa
|
||||||
ifp->addThensp(dumpCallp);
|
ifp->addThensp(dumpCallp);
|
||||||
AstCStmt* const stmtp = new AstCStmt{flp};
|
AstCStmt* const stmtp = new AstCStmt{flp};
|
||||||
ifp->addThensp(stmtp);
|
ifp->addThensp(stmtp);
|
||||||
FileLine* const locp = netlistp->topModulep()->fileline();
|
const FileLine* const locp = netlistp->topModulep()->fileline();
|
||||||
const std::string& file = VIdProtect::protect(locp->filename());
|
const std::string& file = VIdProtect::protect(locp->filename());
|
||||||
const std::string& line = std::to_string(locp->lineno());
|
const std::string& line = std::to_string(locp->lineno());
|
||||||
stmtp->add("VL_FATAL_MT(\"" + V3OutFormatter::quoteNameControls(file) + "\", " + line
|
stmtp->add("VL_FATAL_MT(\"" + V3OutFormatter::quoteNameControls(file) + "\", " + line
|
||||||
|
|
|
||||||
|
|
@ -1204,7 +1204,7 @@ private:
|
||||||
}
|
}
|
||||||
// Apply value to the function
|
// Apply value to the function
|
||||||
if (!m_checkOnly && optimizable())
|
if (!m_checkOnly && optimizable())
|
||||||
for (auto& it : portValues) {
|
for (const auto& it : portValues) {
|
||||||
if (!m_checkOnly && optimizable()) newValue(it.first, it.second);
|
if (!m_checkOnly && optimizable()) newValue(it.first, it.second);
|
||||||
}
|
}
|
||||||
SimStackNode stackNode{nodep, &tconnects};
|
SimStackNode stackNode{nodep, &tconnects};
|
||||||
|
|
@ -1222,7 +1222,7 @@ private:
|
||||||
// Evaluate the function
|
// Evaluate the function
|
||||||
iterateConst(funcp);
|
iterateConst(funcp);
|
||||||
m_callStack.pop_back();
|
m_callStack.pop_back();
|
||||||
AstNodeExpr* returnp = nullptr;
|
const AstNodeExpr* returnp = nullptr;
|
||||||
if (!m_checkOnly && optimizable()) {
|
if (!m_checkOnly && optimizable()) {
|
||||||
// Grab return value from output variable
|
// Grab return value from output variable
|
||||||
UASSERT_OBJ(funcp->fvarp(), nodep, "Function reference points at non-function");
|
UASSERT_OBJ(funcp->fvarp(), nodep, "Function reference points at non-function");
|
||||||
|
|
|
||||||
|
|
@ -551,10 +551,11 @@ class UnknownVisitor final : public VNVisitor {
|
||||||
} else if (!lvalue) { // Mid-multidimension read, just use zero
|
} else if (!lvalue) { // Mid-multidimension read, just use zero
|
||||||
// ARRAYSEL(...) -> ARRAYSEL(COND(LT(bit<maxbit), bit, 0))
|
// ARRAYSEL(...) -> ARRAYSEL(COND(LT(bit<maxbit), bit, 0))
|
||||||
VNRelinker replaceHandle;
|
VNRelinker replaceHandle;
|
||||||
AstNodeExpr* const bitp = nodep->bitp()->unlinkFrBack(&replaceHandle);
|
AstNodeExpr* const asBitp = nodep->bitp()->unlinkFrBack(&replaceHandle);
|
||||||
AstNodeExpr* const newp = new AstCond{
|
AstNodeExpr* const newp
|
||||||
bitp->fileline(), condp, bitp,
|
= new AstCond{asBitp->fileline(), condp, asBitp,
|
||||||
new AstConst{bitp->fileline(), AstConst::WidthedValue{}, bitp->width(), 0}};
|
new AstConst{asBitp->fileline(), AstConst::WidthedValue{},
|
||||||
|
asBitp->width(), 0}};
|
||||||
// Added X's, tristate them too
|
// Added X's, tristate them too
|
||||||
UINFOTREE(9, newp, "", "_new");
|
UINFOTREE(9, newp, "", "_new");
|
||||||
replaceHandle.relink(newp);
|
replaceHandle.relink(newp);
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ struct UnrollStats final {
|
||||||
const char* const m_name; // Name for stats file and UDEBUG
|
const char* const m_name; // Name for stats file and UDEBUG
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Stat(const char* const name)
|
explicit Stat(const char* const name)
|
||||||
: m_name{name} {}
|
: m_name{name} {}
|
||||||
~Stat() { V3Stats::addStat("Optimizations, Loop unrolling, "s + m_name, m_value); }
|
~Stat() { V3Stats::addStat("Optimizations, Loop unrolling, "s + m_name, m_value); }
|
||||||
const char* name() const { return m_name; }
|
const char* name() const { return m_name; }
|
||||||
|
|
@ -384,7 +384,7 @@ class UnrollAllVisitor final : VNVisitor {
|
||||||
void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||||
|
|
||||||
// CONSTRUCTOR
|
// CONSTRUCTOR
|
||||||
UnrollAllVisitor(AstNetlist* netlistp) { iterate(netlistp); }
|
explicit UnrollAllVisitor(AstNetlist* netlistp) { iterate(netlistp); }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static void apply(AstNetlist* netlistp) { UnrollAllVisitor{netlistp}; }
|
static void apply(AstNetlist* netlistp) { UnrollAllVisitor{netlistp}; }
|
||||||
|
|
|
||||||
|
|
@ -124,7 +124,7 @@ class UnrollGenVisitor final : public VNVisitor {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool simulateTree(AstNodeExpr* nodep, const V3Number* loopValue, AstNode* dtypep,
|
bool simulateTree(AstNodeExpr* nodep, const V3Number* loopValue, const AstNode* dtypep,
|
||||||
V3Number& outNum) {
|
V3Number& outNum) {
|
||||||
AstNode* clonep = nodep->cloneTree(true);
|
AstNode* clonep = nodep->cloneTree(true);
|
||||||
UASSERT_OBJ(clonep, nodep, "Failed to clone tree");
|
UASSERT_OBJ(clonep, nodep, "Failed to clone tree");
|
||||||
|
|
@ -146,7 +146,7 @@ class UnrollGenVisitor final : public VNVisitor {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Fetch the result
|
// Fetch the result
|
||||||
V3Number* resp = simvis.fetchNumberNull(clonep);
|
const V3Number* resp = simvis.fetchNumberNull(clonep);
|
||||||
if (!resp) {
|
if (!resp) {
|
||||||
UINFO(3, "No number returned from simulation");
|
UINFO(3, "No number returned from simulation");
|
||||||
VL_DO_DANGLING(clonep->deleteTree(), clonep);
|
VL_DO_DANGLING(clonep->deleteTree(), clonep);
|
||||||
|
|
@ -231,7 +231,7 @@ class UnrollGenVisitor final : public VNVisitor {
|
||||||
}
|
}
|
||||||
|
|
||||||
// loopValue += valInc
|
// loopValue += valInc
|
||||||
AstAssign* const incpass = VN_AS(incp, Assign);
|
const AstAssign* const incpass = VN_AS(incp, Assign);
|
||||||
V3Number newLoopValue{nodep};
|
V3Number newLoopValue{nodep};
|
||||||
if (!simulateTree(incpass->rhsp(), &loopValue, incpass, newLoopValue)) {
|
if (!simulateTree(incpass->rhsp(), &loopValue, incpass, newLoopValue)) {
|
||||||
nodep->v3error("Loop unrolling failed");
|
nodep->v3error("Loop unrolling failed");
|
||||||
|
|
|
||||||
|
|
@ -748,7 +748,7 @@ static bool verilate(const string& argString) {
|
||||||
|
|
||||||
V3Error::abortIfWarnings();
|
V3Error::abortIfWarnings();
|
||||||
|
|
||||||
if (V3HierGraph* const hierGraphp
|
if (const V3HierGraph* const hierGraphp
|
||||||
= v3Global.hierGraphp()) { // This run is for just write a makefile
|
= v3Global.hierGraphp()) { // This run is for just write a makefile
|
||||||
UASSERT(v3Global.opt.hierarchical(), "hierarchical must be set");
|
UASSERT(v3Global.opt.hierarchical(), "hierarchical must be set");
|
||||||
UASSERT(!v3Global.opt.hierChild(), "This must not be a hierarchical-child run");
|
UASSERT(!v3Global.opt.hierChild(), "This must not be a hierarchical-child run");
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,12 @@ unmatchedSuppression
|
||||||
*:verilog.c
|
*:verilog.c
|
||||||
*:V3Lexer_pregen.yy.cpp
|
*:V3Lexer_pregen.yy.cpp
|
||||||
*:V3PreLex_pregen.yy.cpp
|
*:V3PreLex_pregen.yy.cpp
|
||||||
|
constParameterPointer:V3ParseBison.c
|
||||||
|
cstyleCast:../V3PreLex.l
|
||||||
|
cstyleCast:../verilog.l
|
||||||
|
cstyleCast:../verilog.y
|
||||||
|
cstyleCast:V3ParseBison.c
|
||||||
|
redundantContinue:V3ParseBison.c
|
||||||
// Just check the hand written code
|
// Just check the hand written code
|
||||||
missingInclude:examples/*
|
missingInclude:examples/*
|
||||||
// We intentionally redefine AstNode methods to improve type safety
|
// We intentionally redefine AstNode methods to improve type safety
|
||||||
|
|
|
||||||
|
|
@ -136,7 +136,7 @@ const VBasicDTypeKwd LOGIC_IMPLICIT = VBasicDTypeKwd::LOGIC_IMPLICIT;
|
||||||
|
|
||||||
#define DEL(...) \
|
#define DEL(...) \
|
||||||
{ \
|
{ \
|
||||||
AstNode* nodeps[] = {__VA_ARGS__}; \
|
AstNode* const nodeps[] = {__VA_ARGS__}; \
|
||||||
for (AstNode* const nodep : nodeps) \
|
for (AstNode* const nodep : nodeps) \
|
||||||
if (nodep) nodep->deleteTree(); \
|
if (nodep) nodep->deleteTree(); \
|
||||||
}
|
}
|
||||||
|
|
@ -5500,9 +5500,9 @@ gateBuf<nodep>:
|
||||||
AstAssignW* const ap = new AstAssignW{$<fl>1, $2, rhsp};
|
AstAssignW* const ap = new AstAssignW{$<fl>1, $2, rhsp};
|
||||||
$$->addNext(new AstAlways{ap});
|
$$->addNext(new AstAlways{ap});
|
||||||
for (AstNodeExpr* outp = $4; outp->nextp(); outp = VN_CAST(outp->nextp(), NodeExpr)) {
|
for (AstNodeExpr* outp = $4; outp->nextp(); outp = VN_CAST(outp->nextp(), NodeExpr)) {
|
||||||
AstNodeExpr* const rhsp = GRAMMARP->createGatePin(inp->cloneTree(false));
|
AstNodeExpr* const pinRhsp = GRAMMARP->createGatePin(inp->cloneTree(false));
|
||||||
AstAssignW* const ap = new AstAssignW{$<fl>1, outp->cloneTree(false), rhsp};
|
AstAssignW* const pinAssp = new AstAssignW{$<fl>1, outp->cloneTree(false), pinRhsp};
|
||||||
$$->addNext(new AstAlways{ap});
|
$$->addNext(new AstAlways{pinAssp});
|
||||||
}
|
}
|
||||||
DEL($1); DEL($4); }
|
DEL($1); DEL($4); }
|
||||||
;
|
;
|
||||||
|
|
@ -5515,9 +5515,9 @@ gateNot<nodep>:
|
||||||
AstAssignW* const ap = new AstAssignW{$<fl>1, $2, rhsp};
|
AstAssignW* const ap = new AstAssignW{$<fl>1, $2, rhsp};
|
||||||
$$->addNext(new AstAlways{ap});
|
$$->addNext(new AstAlways{ap});
|
||||||
for (AstNodeExpr* outp = $4; outp->nextp(); outp = VN_CAST(outp->nextp(), NodeExpr)) {
|
for (AstNodeExpr* outp = $4; outp->nextp(); outp = VN_CAST(outp->nextp(), NodeExpr)) {
|
||||||
AstNodeExpr* const rhsp = new AstNot{$<fl>1, GRAMMARP->createGatePin(inp->cloneTree(false))};
|
AstNodeExpr* const pinRhsp = new AstNot{$<fl>1, GRAMMARP->createGatePin(inp->cloneTree(false))};
|
||||||
AstAssignW* const ap = new AstAssignW{$<fl>1, outp->cloneTree(false), rhsp};
|
AstAssignW* const pinAssp = new AstAssignW{$<fl>1, outp->cloneTree(false), pinRhsp};
|
||||||
$$->addNext(new AstAlways{ap});
|
$$->addNext(new AstAlways{pinAssp});
|
||||||
}
|
}
|
||||||
DEL($1, $4); }
|
DEL($1, $4); }
|
||||||
;
|
;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue