Fix extra evaluation of pure combo blocks in SystemC output.
This commit is contained in:
parent
500dc2170f
commit
3463080a71
2
Changes
2
Changes
|
|
@ -12,6 +12,8 @@ indicates the contributor was also the author of the fix; Thanks!
|
||||||
|
|
||||||
*** Add by-design and by-module subtotals to verilator_profcfunc.
|
*** Add by-design and by-module subtotals to verilator_profcfunc.
|
||||||
|
|
||||||
|
*** Fix extra evaluation of pure combo blocks in SystemC output.
|
||||||
|
|
||||||
**** Add IMPERFECTSCH warning, disabled by default.
|
**** Add IMPERFECTSCH warning, disabled by default.
|
||||||
|
|
||||||
* Verilator 3.670 2008/07/23
|
* Verilator 3.670 2008/07/23
|
||||||
|
|
|
||||||
|
|
@ -417,3 +417,7 @@ void AstCCall::dump(ostream& str) {
|
||||||
funcp()->dump(str);
|
funcp()->dump(str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void AstCFunc::dump(ostream& str) {
|
||||||
|
this->AstNode::dump(str);
|
||||||
|
if (slow()) str<<" [SLOW]";
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -3143,6 +3143,7 @@ public:
|
||||||
virtual string name() const { return m_name; }
|
virtual string name() const { return m_name; }
|
||||||
virtual bool broken() const { return ( (m_scopep && !m_scopep->brokeExists())); }
|
virtual bool broken() const { return ( (m_scopep && !m_scopep->brokeExists())); }
|
||||||
virtual bool maybePointedTo() const { return true; }
|
virtual bool maybePointedTo() const { return true; }
|
||||||
|
virtual void dump(ostream& str=cout);
|
||||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||||
virtual bool same(AstNode* samep) const { return ((funcType()==samep->castCFunc()->funcType())
|
virtual bool same(AstNode* samep) const { return ((funcType()==samep->castCFunc()->funcType())
|
||||||
&& (rtnTypeVoid()==samep->castCFunc()->rtnTypeVoid())
|
&& (rtnTypeVoid()==samep->castCFunc()->rtnTypeVoid())
|
||||||
|
|
|
||||||
|
|
@ -256,7 +256,7 @@ private:
|
||||||
AstSenTree* m_deleteDomainp;// Delete this from tree
|
AstSenTree* m_deleteDomainp;// Delete this from tree
|
||||||
AstSenTree* m_settleDomainp;// Initial activation tree
|
AstSenTree* m_settleDomainp;// Initial activation tree
|
||||||
OrderInputsVertex* m_inputsVxp; // Top level vertex all inputs point from
|
OrderInputsVertex* m_inputsVxp; // Top level vertex all inputs point from
|
||||||
OrderSettleVertex* m_settleVxp; // Top level vertex all inputs point from
|
OrderSettleVertex* m_settleVxp; // Top level vertex all settlement vertexes point from
|
||||||
OrderLogicVertex* m_logicVxp; // Current statement being tracked, NULL=ignored
|
OrderLogicVertex* m_logicVxp; // Current statement being tracked, NULL=ignored
|
||||||
AstTopScope* m_topScopep; // Current top scope being processed
|
AstTopScope* m_topScopep; // Current top scope being processed
|
||||||
AstScope* m_scopetopp; // Scope under TOPSCOPE
|
AstScope* m_scopetopp; // Scope under TOPSCOPE
|
||||||
|
|
@ -341,6 +341,8 @@ private:
|
||||||
OrderVarVertex* processInsLoopNewVar(OrderVarVertex* oldVertexp, bool& createdr);
|
OrderVarVertex* processInsLoopNewVar(OrderVarVertex* oldVertexp, bool& createdr);
|
||||||
void processBrokeLoop();
|
void processBrokeLoop();
|
||||||
void processCircular();
|
void processCircular();
|
||||||
|
void processInputs();
|
||||||
|
void processInputsIterate(OrderEitherVertex* vertexp);
|
||||||
void processSensitive();
|
void processSensitive();
|
||||||
void processDomains();
|
void processDomains();
|
||||||
void processDomainsIterate(OrderEitherVertex* vertexp);
|
void processDomainsIterate(OrderEitherVertex* vertexp);
|
||||||
|
|
@ -927,6 +929,39 @@ void OrderVisitor::processBrokeLoop() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//######################################################################
|
||||||
|
// Clock propagation
|
||||||
|
|
||||||
|
void OrderVisitor::processInputs() {
|
||||||
|
m_graph.userClearVertices(); // Vertex::user() // true if added as begin/end
|
||||||
|
processInputsIterate(m_inputsVxp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OrderVisitor::processInputsIterate(OrderEitherVertex* vertexp) {
|
||||||
|
// Propagate PrimaryIn through simple assignments
|
||||||
|
if (vertexp->user()) return; // Already processed
|
||||||
|
//UINFO(9," InIt "<<vertexp<<endl);
|
||||||
|
vertexp->user(true);
|
||||||
|
if (OrderVarStdVertex* vvertexp = dynamic_cast<OrderVarStdVertex*>(vertexp)) {
|
||||||
|
vvertexp->isFromInput(true);
|
||||||
|
}
|
||||||
|
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) {
|
||||||
|
OrderEitherVertex* toVertexp = (OrderEitherVertex*)edgep->top();
|
||||||
|
if (OrderVarStdVertex* vvertexp = dynamic_cast<OrderVarStdVertex*>(toVertexp)) {
|
||||||
|
processInputsIterate(vvertexp);
|
||||||
|
}
|
||||||
|
if (OrderLogicVertex* vvertexp = dynamic_cast<OrderLogicVertex*>(toVertexp)) {
|
||||||
|
if (AstNodeAssign* nodep = vvertexp->nodep()->castNodeAssign()) {
|
||||||
|
if (nodep->lhsp()->castVarRef()
|
||||||
|
&& nodep->rhsp()->castVarRef()) {
|
||||||
|
UINFO(9," Input reassignment: "<<vvertexp<<endl);
|
||||||
|
processInputsIterate(vvertexp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
// Circular detection
|
// Circular detection
|
||||||
|
|
||||||
|
|
@ -936,7 +971,7 @@ void OrderVisitor::processCircular() {
|
||||||
// The change detect code will use this to force changedets
|
// The change detect code will use this to force changedets
|
||||||
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) {
|
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) {
|
||||||
if (OrderVarStdVertex* vvertexp = dynamic_cast<OrderVarStdVertex*>(itp)) {
|
if (OrderVarStdVertex* vvertexp = dynamic_cast<OrderVarStdVertex*>(itp)) {
|
||||||
if (vvertexp->isClock() && !vvertexp->varScp()->varp()->isPrimaryIn()) {
|
if (vvertexp->isClock() && !vvertexp->isFromInput()) {
|
||||||
// If a clock is generated internally, we need to do another loop
|
// If a clock is generated internally, we need to do another loop
|
||||||
// through the entire evaluation. This fixes races; see t_clk_dpulse test.
|
// through the entire evaluation. This fixes races; see t_clk_dpulse test.
|
||||||
UINFO(5,"Circular Clock "<<vvertexp<<endl);
|
UINFO(5,"Circular Clock "<<vvertexp<<endl);
|
||||||
|
|
@ -947,6 +982,7 @@ void OrderVisitor::processCircular() {
|
||||||
if (edgep->weight()==0) { // was cut
|
if (edgep->weight()==0) { // was cut
|
||||||
OrderEdge* oedgep = dynamic_cast<OrderEdge*>(edgep);
|
OrderEdge* oedgep = dynamic_cast<OrderEdge*>(edgep);
|
||||||
if (!oedgep) vvertexp->varScp()->v3fatalSrc("Cuttable edge not of proper type");
|
if (!oedgep) vvertexp->varScp()->v3fatalSrc("Cuttable edge not of proper type");
|
||||||
|
UINFO(6," CutCircularO: "<<vvertexp->name()<<endl);
|
||||||
nodeMarkCircular(vvertexp, oedgep);
|
nodeMarkCircular(vvertexp, oedgep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -954,6 +990,7 @@ void OrderVisitor::processCircular() {
|
||||||
if (edgep->weight()==0) { // was cut
|
if (edgep->weight()==0) { // was cut
|
||||||
OrderEdge* oedgep = dynamic_cast<OrderEdge*>(edgep);
|
OrderEdge* oedgep = dynamic_cast<OrderEdge*>(edgep);
|
||||||
if (!oedgep) vvertexp->varScp()->v3fatalSrc("Cuttable edge not of proper type");
|
if (!oedgep) vvertexp->varScp()->v3fatalSrc("Cuttable edge not of proper type");
|
||||||
|
UINFO(6," CutCircularI: "<<vvertexp->name()<<endl);
|
||||||
nodeMarkCircular(vvertexp, oedgep);
|
nodeMarkCircular(vvertexp, oedgep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1542,6 +1579,9 @@ void OrderVisitor::process() {
|
||||||
m_graph.order();
|
m_graph.order();
|
||||||
m_graph.dumpDotFilePrefixed("orderg_order");
|
m_graph.dumpDotFilePrefixed("orderg_order");
|
||||||
|
|
||||||
|
UINFO(2," Process Clocks...\n");
|
||||||
|
processInputs(); // must be before processCircular
|
||||||
|
|
||||||
#ifndef NEW_ORDERING
|
#ifndef NEW_ORDERING
|
||||||
UINFO(2," Process Circulars...\n");
|
UINFO(2," Process Circulars...\n");
|
||||||
processCircular(); // must be before processDomains
|
processCircular(); // must be before processDomains
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,30 @@
|
||||||
// GNU General Public License for more details.
|
// GNU General Public License for more details.
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
|
// OrderGraph Class Hiearchy:
|
||||||
|
//
|
||||||
|
// V3GraphVertex
|
||||||
|
// OrderMoveVertex
|
||||||
|
// OrderEitherVertex
|
||||||
|
// OrderInputsVertex
|
||||||
|
// OrderSettleVertex
|
||||||
|
// OrderLogicVertex
|
||||||
|
// OrderLoopBeginVertex
|
||||||
|
// OrderLoopEndVertex
|
||||||
|
// OrderVarVertex
|
||||||
|
// OrderVarStdVertex
|
||||||
|
// OrderVarPreVertex
|
||||||
|
// OrderVarPostVertex
|
||||||
|
// OrderVarPordVertex
|
||||||
|
// OrderVarSettleVertex
|
||||||
|
//
|
||||||
|
// V3GraphEdge
|
||||||
|
// OrderEdge
|
||||||
|
// OrderChangeDetEdge
|
||||||
|
// OrderComboCutEdge
|
||||||
|
// OrderPostCutEdge
|
||||||
|
// OrderPreCutEdge
|
||||||
|
//*************************************************************************
|
||||||
|
|
||||||
#include "config_build.h"
|
#include "config_build.h"
|
||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
|
|
@ -168,20 +192,23 @@ public:
|
||||||
|
|
||||||
class OrderVarVertex : public OrderEitherVertex {
|
class OrderVarVertex : public OrderEitherVertex {
|
||||||
AstVarScope* m_varScp;
|
AstVarScope* m_varScp;
|
||||||
bool m_isClock; // Used as clock
|
|
||||||
OrderVarVertex* m_pilNewVertexp; // for processInsLoopNewVar
|
OrderVarVertex* m_pilNewVertexp; // for processInsLoopNewVar
|
||||||
|
bool m_isClock; // Used as clock
|
||||||
|
bool m_isFromInput; // From input, or derrived therefrom (conservatively false)
|
||||||
public:
|
public:
|
||||||
OrderVarVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp)
|
OrderVarVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp)
|
||||||
: OrderEitherVertex(graphp, scopep, NULL), m_varScp(varScp), m_isClock(false)
|
: OrderEitherVertex(graphp, scopep, NULL), m_varScp(varScp)
|
||||||
, m_pilNewVertexp(NULL)
|
, m_pilNewVertexp(NULL), m_isClock(false), m_isFromInput(false)
|
||||||
{}
|
{}
|
||||||
virtual ~OrderVarVertex() {}
|
virtual ~OrderVarVertex() {}
|
||||||
virtual OrderVarVertex* clone (V3Graph* graphp) const = 0;
|
virtual OrderVarVertex* clone (V3Graph* graphp) const = 0;
|
||||||
virtual OrderVEdgeType type() const = 0;
|
virtual OrderVEdgeType type() const = 0;
|
||||||
// Accessors
|
// Accessors
|
||||||
AstVarScope* varScp() const { return m_varScp; }
|
AstVarScope* varScp() const { return m_varScp; }
|
||||||
void isClock(bool clk) { m_isClock=clk; }
|
void isClock(bool flag) { m_isClock=flag; }
|
||||||
bool isClock() const { return m_isClock; }
|
bool isClock() const { return m_isClock; }
|
||||||
|
void isFromInput(bool flag) { m_isFromInput=flag; }
|
||||||
|
bool isFromInput() const { return m_isFromInput; }
|
||||||
OrderVarVertex* pilNewVertexp() const { return m_pilNewVertexp; }
|
OrderVarVertex* pilNewVertexp() const { return m_pilNewVertexp; }
|
||||||
void pilNewVertexp (OrderVarVertex* vertexp) { m_pilNewVertexp = vertexp; }
|
void pilNewVertexp (OrderVarVertex* vertexp) { m_pilNewVertexp = vertexp; }
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,9 @@
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
// without warranty, 2003 by Wilson Snyder.
|
// without warranty, 2003 by Wilson Snyder.
|
||||||
|
|
||||||
|
// Also check that SystemC is ordering properly
|
||||||
|
// verilator lint_on IMPERFECTSCH
|
||||||
|
|
||||||
module t (/*AUTOARG*/
|
module t (/*AUTOARG*/
|
||||||
// Inputs
|
// Inputs
|
||||||
clk
|
clk
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue