mirror of
https://github.com/verilator/verilator.git
synced 2026-10-05 17:43:31 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f1ef30a5bb | ||
|
|
f1d9437c55 | ||
|
|
bcba5075e8 | ||
|
|
d6e8b0263c | ||
|
|
9aba617bad | ||
|
|
c24f7b1391 | ||
|
|
d4e27b635f |
@@ -3,6 +3,19 @@ Revision history for Verilator
|
||||
The contributors that suggested a given feature are shown in []. [by ...]
|
||||
indicates the contributor was also the author of the fix; Thanks!
|
||||
|
||||
* Verilator 3.852 2013-09-29
|
||||
|
||||
*** Support named function and task arguments. [Chris Randall]
|
||||
|
||||
*** Report SELRANGE warning for non-generate if, bug675. [Roland Kruse]
|
||||
|
||||
**** Fix ordering of $fgetc, msg1229. [Frederic Requin]
|
||||
|
||||
**** Fix --output-split-cfunc to count internal functions. [Chris Randall]
|
||||
|
||||
**** Fix crash on 32-bit Ubuntu, bug670. [Mark Jackson Pulver]
|
||||
|
||||
|
||||
* Verilator 3.851 2013-08-15
|
||||
|
||||
*** Fix ordering of clock enables with delayed assigns, bug613. [Jeremy Bennett]
|
||||
|
||||
+7
-1
@@ -300,7 +300,8 @@ descriptions in the next sections for more information.
|
||||
-O<optimization-letter> Selectable optimizations
|
||||
-o <executable> Name of final executable
|
||||
--output-split <bytes> Split .cpp files into pieces
|
||||
--output-split-cfuncs <statements> Split .ccp functions
|
||||
--output-split-cfuncs <statements> Split .cpp functions
|
||||
--output-split-ctrace <statements> Split tracing functions
|
||||
--pins-bv <bits> Specify types for top level ports
|
||||
--pins-sc-uint Specify types for top level ports
|
||||
--pins-sc-biguint Specify types for top level ports
|
||||
@@ -810,6 +811,11 @@ worse with decreasing split values. Note that this option is stronger than
|
||||
--output-split in the sense that --output-split will not split inside a
|
||||
function.
|
||||
|
||||
=item --output-split-ctrace I<statements>
|
||||
|
||||
Enables splitting trace functions in the output .cpp/.sp files into
|
||||
multiple functions. Defaults to same setting as --output-split-cfuncs.
|
||||
|
||||
=item --pins64
|
||||
|
||||
Backward compatible alias for "--pins-bv 65". Note that's a 65, not a 64.
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
|
||||
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
|
||||
#AC_INIT([Verilator],[#.### devel])
|
||||
AC_INIT([Verilator],[3.851 2013-08-15])
|
||||
AC_INIT([Verilator],[3.852 2013-09-29])
|
||||
AC_CONFIG_HEADER(src/config_build.h)
|
||||
AC_CONFIG_FILES(Makefile src/Makefile src/Makefile_obj include/verilated.mk include/verilated_config.h)
|
||||
|
||||
|
||||
@@ -965,6 +965,14 @@ void AstNode::dumpTreeFileGdb(const char* filenamep) { // For GDB only
|
||||
v3Global.rootp()->dumpTreeFile(filename);
|
||||
}
|
||||
|
||||
void AstNode::checkIter() const {
|
||||
if (m_iterpp) {
|
||||
dumpPtrs(cout);
|
||||
// Perhaps something forgot to clear m_iterpp?
|
||||
this->v3fatalSrc("Iteration link should be NULL");
|
||||
}
|
||||
}
|
||||
|
||||
void AstNode::dumpPtrs(ostream& os) const {
|
||||
os<<"This="<<typeName()<<" "<<(void*)this;
|
||||
os<<" back="<<(void*)backp();
|
||||
|
||||
@@ -1153,6 +1153,8 @@ public:
|
||||
bool sameTree(AstNode* node2p); // Does tree of this == node2p?
|
||||
void deleteTree(); // Always deletes the next link
|
||||
void checkTree(); // User Interface version
|
||||
void checkIter() const;
|
||||
void clearIter() { m_iterpp=NULL; }
|
||||
void dumpPtrs(ostream& str=cout) const;
|
||||
void dumpTree(ostream& str=cout, const string& indent=" ", int maxDepth=0);
|
||||
void dumpTree(const string& indent, int maxDepth=0) { dumpTree(cout,indent,maxDepth); }
|
||||
|
||||
@@ -1294,6 +1294,25 @@ public:
|
||||
void svImplicit(bool flag) { m_svImplicit=flag; }
|
||||
};
|
||||
|
||||
struct AstArg : public AstNode {
|
||||
// An argument to a function/task
|
||||
private:
|
||||
string m_name; // Pin name, or "" for number based interconnect
|
||||
public:
|
||||
AstArg(FileLine* fl, const string& name, AstNode* exprp)
|
||||
: AstNode(fl)
|
||||
,m_name(name) {
|
||||
setNOp1p(exprp);
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(Arg, ARG)
|
||||
virtual string name() const { return m_name; } // * = Pin name, ""=go by number
|
||||
virtual void name(const string& name) { m_name = name; }
|
||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||
void exprp(AstNode* nodep) { addOp1p(nodep); }
|
||||
AstNode* exprp() const { return op1p()->castNode(); } // op1 = Expression connected to pin, NULL if unconnected
|
||||
bool emptyConnectNoNext() const { return !exprp() && name()=="" && !nextp(); }
|
||||
};
|
||||
|
||||
struct AstModule : public AstNodeModule {
|
||||
// A module declaration
|
||||
AstModule(FileLine* fl, const string& name)
|
||||
@@ -3359,6 +3378,7 @@ struct AstFEof : public AstNodeUniop {
|
||||
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;}
|
||||
virtual int instrCount() const { return widthInstrs()*16; }
|
||||
virtual bool isPure() const { return false; } // SPECIAL: $display has 'visual' ordering
|
||||
AstNode* filep() const { return lhsp(); }
|
||||
};
|
||||
|
||||
@@ -3372,6 +3392,7 @@ struct AstFGetC : public AstNodeUniop {
|
||||
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;}
|
||||
virtual int instrCount() const { return widthInstrs()*64; }
|
||||
virtual bool isPure() const { return false; } // SPECIAL: $display has 'visual' ordering
|
||||
AstNode* filep() const { return lhsp(); }
|
||||
};
|
||||
|
||||
|
||||
+8
-2
@@ -815,9 +815,10 @@ private:
|
||||
|
||||
bool varNotReferenced(AstNode* nodep, AstVar* varp, int level=0) {
|
||||
// Return true if varp never referenced under node.
|
||||
// Return false if referenced, or tree too deep to be worth it
|
||||
// Return false if referenced, or tree too deep to be worth it, or side effects
|
||||
if (!nodep) return true;
|
||||
if (level>2) return false;
|
||||
if (nodep->isPure()) return false; // For example a $fgetc can't be reordered
|
||||
if (nodep->castNodeVarRef() && nodep->castNodeVarRef()->varp()==varp) return false;
|
||||
return (varNotReferenced (nodep->nextp(),varp,level+1)
|
||||
&& varNotReferenced(nodep->op1p(),varp,level+1)
|
||||
@@ -1230,6 +1231,8 @@ private:
|
||||
&& ((!m_params // Can reduce constant wires into equations
|
||||
&& m_doNConst
|
||||
&& v3Global.opt.oConst()
|
||||
&& !(nodep->varp()->isFuncLocal() // Default value, not a "known" constant for this usage
|
||||
&& nodep->varp()->isInput())
|
||||
&& !nodep->varp()->isSigPublic())
|
||||
|| nodep->varp()->isParam())) {
|
||||
AstConst* constp = nodep->varp()->valuep()->castConst();
|
||||
@@ -1643,7 +1646,10 @@ private:
|
||||
replaceWithSimulation(nodep);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstArg* nodep, AstNUser*) {
|
||||
// replaceWithSimulation on the Arg's parent FuncRef replaces these
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
virtual void visit(AstWhile* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (m_doNConst) {
|
||||
|
||||
+13
-2
@@ -58,8 +58,9 @@ public:
|
||||
int splitFilenum() const { return m_splitFilenum; }
|
||||
int splitFilenumInc() { m_splitSize = 0; return ++m_splitFilenum; }
|
||||
int splitSize() const { return m_splitSize; }
|
||||
void splitSizeInc(AstNode* nodep) { m_splitSize += EmitCBaseCounterVisitor(nodep).count(); }
|
||||
bool splitNeeded() { return (splitSize() && v3Global.opt.outputSplit() > 1
|
||||
void splitSizeInc(int count) { m_splitSize += count; }
|
||||
void splitSizeInc(AstNode* nodep) { splitSizeInc(EmitCBaseCounterVisitor(nodep).count()); }
|
||||
bool splitNeeded() { return (splitSize() && v3Global.opt.outputSplit()
|
||||
&& v3Global.opt.outputSplit() < splitSize()); }
|
||||
|
||||
// METHODS
|
||||
@@ -1418,9 +1419,11 @@ void EmitCImp::emitConfigureImp(AstNodeModule* modp) {
|
||||
puts("// Coverage Declarations\n");
|
||||
}
|
||||
nodep->accept(*this);
|
||||
splitSizeInc(nodep);
|
||||
}
|
||||
}
|
||||
puts("}\n");
|
||||
splitSizeInc(10);
|
||||
}
|
||||
|
||||
void EmitCImp::emitCoverageImp(AstNodeModule* modp) {
|
||||
@@ -1444,6 +1447,7 @@ void EmitCImp::emitCoverageImp(AstNodeModule* modp) {
|
||||
puts( " \"page\",pagep,");
|
||||
puts( " \"comment\",commentp);\n");
|
||||
puts("}\n");
|
||||
splitSizeInc(10);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1453,6 +1457,7 @@ void EmitCImp::emitDestructorImp(AstNodeModule* modp) {
|
||||
emitTextSection(AstType::atSCDTOR);
|
||||
if (modp->isTop()) puts("delete __VlSymsp; __VlSymsp=NULL;\n");
|
||||
puts("}\n");
|
||||
splitSizeInc(10);
|
||||
}
|
||||
|
||||
void EmitCImp::emitSavableImp(AstNodeModule* modp) {
|
||||
@@ -1631,6 +1636,7 @@ void EmitCImp::emitWrapEval(AstNodeModule* modp) {
|
||||
puts("}\n");
|
||||
#endif
|
||||
puts("}\n");
|
||||
splitSizeInc(10);
|
||||
|
||||
//
|
||||
puts("\nvoid "+modClassName(modp)+"::_eval_initial_loop("+EmitCBaseVisitor::symClassVar()+") {\n");
|
||||
@@ -1651,6 +1657,7 @@ void EmitCImp::emitWrapEval(AstNodeModule* modp) {
|
||||
puts( "}\n");
|
||||
#endif
|
||||
puts("}\n");
|
||||
splitSizeInc(10);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
@@ -2111,6 +2118,7 @@ class EmitCTrace : EmitCStmts {
|
||||
+", &"+topClassName()+"::traceFull"
|
||||
+", &"+topClassName()+"::traceChg, this);\n");
|
||||
puts("}\n");
|
||||
splitSizeInc(10);
|
||||
|
||||
puts("void "+topClassName()+"::traceInit("
|
||||
+v3Global.opt.traceClassBase()+"* vcdp, void* userthis, uint32_t code) {\n");
|
||||
@@ -2123,6 +2131,7 @@ class EmitCTrace : EmitCStmts {
|
||||
puts("t->traceInitThis (vlSymsp, vcdp, code);\n");
|
||||
puts("vcdp->scopeEscape('.');\n"); // Restore so SystemPerl traced files won't break
|
||||
puts("}\n");
|
||||
splitSizeInc(10);
|
||||
|
||||
puts("void "+topClassName()+"::traceFull("
|
||||
+v3Global.opt.traceClassBase()+"* vcdp, void* userthis, uint32_t code) {\n");
|
||||
@@ -2131,6 +2140,7 @@ class EmitCTrace : EmitCStmts {
|
||||
puts(EmitCBaseVisitor::symClassVar()+" = t->__VlSymsp; // Setup global symbol table\n");
|
||||
puts("t->traceFullThis (vlSymsp, vcdp, code);\n");
|
||||
puts("}\n");
|
||||
splitSizeInc(10);
|
||||
|
||||
puts("\n//======================\n\n");
|
||||
}
|
||||
@@ -2147,6 +2157,7 @@ class EmitCTrace : EmitCStmts {
|
||||
puts("t->traceChgThis (vlSymsp, vcdp, code);\n");
|
||||
puts("}\n");
|
||||
puts("}\n");
|
||||
splitSizeInc(10);
|
||||
|
||||
puts("\n//======================\n\n");
|
||||
}
|
||||
|
||||
@@ -525,6 +525,9 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
||||
nodep->pinsp()->iterateAndNext(*this);
|
||||
puts(")");
|
||||
}
|
||||
virtual void visit(AstArg* nodep, AstNUser*) {
|
||||
nodep->exprp()->iterateAndNext(*this);
|
||||
}
|
||||
// Terminals
|
||||
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
||||
if (nodep->varScopep())
|
||||
|
||||
@@ -71,6 +71,7 @@ void V3LinkLevel::modSortByLevel() {
|
||||
UINFO(9,"modSortByLevel() sorted\n"); // Comment required for gcc4.6.3 / bug666
|
||||
for (ModVec::iterator it = vec.begin(); it != vec.end(); ++it) {
|
||||
AstNodeModule* nodep = *it;
|
||||
nodep->clearIter(); // Because we didn't iterate to find the node pointers, may have a stale m_iterp() needing cleanup
|
||||
nodep->unlinkFrBack();
|
||||
}
|
||||
if (v3Global.rootp()->modulesp()) v3Global.rootp()->v3fatalSrc("Unlink didn't work");
|
||||
|
||||
+1
-1
@@ -607,7 +607,7 @@ private:
|
||||
V3TaskConnects tconnects = V3Task::taskConnects(nodep, nodep->taskp()->stmtsp());
|
||||
for (V3TaskConnects::iterator it=tconnects.begin(); it!=tconnects.end(); ++it) {
|
||||
AstVar* portp = it->first;
|
||||
AstNode* pinp = it->second;
|
||||
AstNode* pinp = it->second->exprp();
|
||||
if (pinp==NULL) {
|
||||
// Too few arguments in function call - ignore it
|
||||
} else {
|
||||
|
||||
+90
-24
@@ -370,7 +370,8 @@ private:
|
||||
V3TaskConnects tconnects = V3Task::taskConnects(refp, beginp);
|
||||
for (V3TaskConnects::iterator it=tconnects.begin(); it!=tconnects.end(); ++it) {
|
||||
AstVar* portp = it->first;
|
||||
AstNode* pinp = it->second;
|
||||
AstArg* argp = it->second;
|
||||
AstNode* pinp = argp->exprp();
|
||||
portp->unlinkFrBack(); pushDeletep(portp); // Remove it from the clone (not original)
|
||||
if (pinp==NULL) {
|
||||
// Too few arguments in function call
|
||||
@@ -378,6 +379,7 @@ private:
|
||||
UINFO(9, " Port "<<portp<<endl);
|
||||
UINFO(9, " pin "<<pinp<<endl);
|
||||
pinp->unlinkFrBack(); // Relinked to assignment below
|
||||
argp->unlinkFrBack()->deleteTree(); // Args no longer needed
|
||||
//
|
||||
if ((portp->isInout()||portp->isOutput()) && pinp->castConst()) {
|
||||
pinp->v3error("Function/task output connected to constant instead of variable: "+portp->prettyName());
|
||||
@@ -476,7 +478,7 @@ private:
|
||||
V3TaskConnects tconnects = V3Task::taskConnects(refp, refp->taskp()->stmtsp());
|
||||
for (V3TaskConnects::iterator it=tconnects.begin(); it!=tconnects.end(); ++it) {
|
||||
AstVar* portp = it->first;
|
||||
AstNode* pinp = it->second;
|
||||
AstNode* pinp = it->second->exprp();
|
||||
if (!pinp) {
|
||||
// Too few arguments in function call
|
||||
} else {
|
||||
@@ -532,9 +534,10 @@ private:
|
||||
AstNode* nextpinp;
|
||||
for (AstNode* pinp = refp->pinsp(); pinp; pinp=nextpinp) {
|
||||
nextpinp = pinp->nextp();
|
||||
// Move pin to the CCall
|
||||
pinp->unlinkFrBack();
|
||||
ccallp->addArgsp(pinp);
|
||||
// Move pin to the CCall, removing all Arg's
|
||||
AstNode* exprp = pinp->castArg()->exprp();
|
||||
exprp->unlinkFrBack();
|
||||
ccallp->addArgsp(exprp);
|
||||
}
|
||||
|
||||
if (outvscp) {
|
||||
@@ -1177,20 +1180,20 @@ V3TaskConnects V3Task::taskConnects(AstNodeFTaskRef* nodep, AstNode* taskStmtsp)
|
||||
// Missing pin/expr? We return (pinvar, NULL)
|
||||
// Extra pin/expr? We clean it up
|
||||
|
||||
typedef map<string,int> NameToIndex;
|
||||
NameToIndex nameToIndex;
|
||||
V3TaskConnects tconnects;
|
||||
if (!nodep->taskp()) nodep->v3fatalSrc("unlinked");
|
||||
|
||||
// Find ports
|
||||
//map<string,int> name_to_pinnum;
|
||||
int tpinnum = 0; // Note grammar starts pin counting at one
|
||||
int tpinnum = 0;
|
||||
AstVar* sformatp = NULL;
|
||||
for (AstNode* stmtp = taskStmtsp; stmtp; stmtp=stmtp->nextp()) {
|
||||
if (AstVar* portp = stmtp->castVar()) {
|
||||
if (portp->isIO()) {
|
||||
tconnects.push_back(make_pair(portp, (AstNode*)NULL));
|
||||
// Eventually we'll do name based connections
|
||||
// That'll require a AstTpin or somesuch which will replace the ppinnum counting
|
||||
//name_to_pinnum.insert(make_pair(portp->name(), tpinnum));
|
||||
tconnects.push_back(make_pair(portp, (AstArg*)NULL));
|
||||
nameToIndex.insert(make_pair(portp->name(), tpinnum)); // For name based connections
|
||||
tpinnum++;
|
||||
if (portp->attrSFormat()) {
|
||||
sformatp = portp;
|
||||
@@ -1201,27 +1204,90 @@ V3TaskConnects V3Task::taskConnects(AstNodeFTaskRef* nodep, AstNode* taskStmtsp)
|
||||
}
|
||||
}
|
||||
|
||||
// Connect pins
|
||||
// Find pins
|
||||
int ppinnum = 0;
|
||||
for (AstNode* pinp = nodep->pinsp(); pinp; pinp=pinp->nextp()) {
|
||||
if (ppinnum >= tpinnum) {
|
||||
if (sformatp) {
|
||||
tconnects.push_back(make_pair(sformatp, (AstNode*)NULL));
|
||||
bool reorganize = false;
|
||||
for (AstNode* nextp, *pinp = nodep->pinsp(); pinp; pinp=nextp) {
|
||||
nextp = pinp->nextp();
|
||||
AstArg* argp = pinp->castArg(); if (!argp) pinp->v3fatalSrc("Non-arg under ftask reference");
|
||||
if (argp->name() != "") {
|
||||
// By name
|
||||
NameToIndex::iterator it = nameToIndex.find(argp->name());
|
||||
if (it == nameToIndex.end()) {
|
||||
pinp->v3error("No such argument '"<<argp->prettyName()
|
||||
<<"' in function call to "<<nodep->taskp()->prettyTypeName());
|
||||
// We'll just delete it; seems less error prone than making a false argument
|
||||
pinp->unlinkFrBack()->deleteTree(); pinp=NULL;
|
||||
} else {
|
||||
pinp->v3error("Too many arguments in function call to "<<nodep->taskp()->prettyTypeName());
|
||||
// We'll just delete them; seems less error prone than making a false argument
|
||||
pinp->unlinkFrBackWithNext()->deleteTree(); pinp=NULL;
|
||||
break;
|
||||
if (tconnects[it->second].second) {
|
||||
pinp->v3error("Duplicate argument '"<<argp->prettyName()
|
||||
<<"' in function call to "<<nodep->taskp()->prettyTypeName());
|
||||
}
|
||||
argp->name(""); // Can forget name as will add back in pin order
|
||||
tconnects[it->second].second = argp;
|
||||
reorganize = true;
|
||||
}
|
||||
} else { // By pin number
|
||||
if (ppinnum >= tpinnum) {
|
||||
if (sformatp) {
|
||||
tconnects.push_back(make_pair(sformatp, (AstArg*)NULL));
|
||||
tconnects[ppinnum].second = argp;
|
||||
tpinnum++;
|
||||
} else {
|
||||
pinp->v3error("Too many arguments in function call to "<<nodep->taskp()->prettyTypeName());
|
||||
// We'll just delete it; seems less error prone than making a false argument
|
||||
pinp->unlinkFrBack()->deleteTree(); pinp=NULL;
|
||||
}
|
||||
} else {
|
||||
tconnects[ppinnum].second = argp;
|
||||
}
|
||||
}
|
||||
tconnects[ppinnum].second = pinp;
|
||||
ppinnum++;
|
||||
}
|
||||
|
||||
while (ppinnum < tpinnum) {
|
||||
nodep->v3error("Too few arguments in function call to "<<nodep->taskp()->prettyTypeName());
|
||||
UINFO(1,"missing argument for '"<<tconnects[ppinnum].first->prettyName()<<"'"<<endl);
|
||||
ppinnum++;
|
||||
// Connect missing ones
|
||||
for (int i=0; i<tpinnum; ++i) {
|
||||
AstVar* portp = tconnects[i].first;
|
||||
if (!tconnects[i].second || !tconnects[i].second->exprp()) {
|
||||
AstNode* newvaluep = NULL;
|
||||
if (!portp->valuep()) {
|
||||
nodep->v3error("Missing argument on non-defaulted argument '"<<portp->prettyName()
|
||||
<<"' in function call to "<<nodep->taskp()->prettyTypeName());
|
||||
newvaluep = new AstConst(nodep->fileline(), AstConst::Unsized32(), 0);
|
||||
} else if (!portp->valuep()->castConst()) {
|
||||
// Problem otherwise is we might have a varref, task call, or something else that only
|
||||
// makes sense in the domain of the function, not the callee.
|
||||
nodep->v3error("Unsupported: Non-constant default value in missing argument '"<<portp->prettyName()
|
||||
<<"' in function call to "<<nodep->taskp()->prettyTypeName());
|
||||
newvaluep = new AstConst(nodep->fileline(), AstConst::Unsized32(), 0);
|
||||
} else {
|
||||
newvaluep = portp->valuep()->cloneTree(true);
|
||||
}
|
||||
// To avoid problems with callee needing to know to deleteTree or not, we make this into a pin
|
||||
UINFO(9,"Default pin for "<<portp<<endl);
|
||||
AstArg* newp = new AstArg(nodep->fileline(), portp->name(), newvaluep);
|
||||
if (tconnects[i].second) { // Have a "NULL" pin already defined for it
|
||||
tconnects[i].second->unlinkFrBack()->deleteTree(); tconnects[i].second=NULL;
|
||||
}
|
||||
tconnects[i].second = newp;
|
||||
reorganize = true;
|
||||
}
|
||||
if (tconnects[i].second) { UINFO(9,"Connect "<<portp<<" -> "<<tconnects[i].second<<endl); }
|
||||
else { UINFO(9,"Connect "<<portp<<" -> NONE"<<endl); }
|
||||
}
|
||||
|
||||
if (reorganize) {
|
||||
// To simplify downstream, put argument list back into pure pinnumber ordering
|
||||
while (nodep->pinsp()) nodep->pinsp()->unlinkFrBack(); // Must unlink each pin, not all pins linked together as one list
|
||||
for (int i=0; i<tpinnum; ++i) {
|
||||
AstArg* argp = tconnects[i].second; if (!argp) nodep->v3fatalSrc("Lost argument in func conversion");
|
||||
nodep->addPinsp(argp);
|
||||
}
|
||||
}
|
||||
|
||||
if (debug()>=9) {
|
||||
nodep->dumpTree(cout,"-ftref-out: ");
|
||||
for (int i=0; i<tpinnum; ++i) UINFO(0," pin "<<i<<" conn="<<(void*)tconnects[i].second<<endl);
|
||||
}
|
||||
return tconnects;
|
||||
}
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@
|
||||
|
||||
//============================================================================
|
||||
|
||||
typedef pair<AstVar*,AstNode*> V3TaskConnect; // [port, pin-connects-to]
|
||||
typedef pair<AstVar*,AstArg*> V3TaskConnect; // [port, pin-connects-to]
|
||||
typedef vector<V3TaskConnect> V3TaskConnects; // [ [port, pin-connects-to] ... ]
|
||||
|
||||
//============================================================================
|
||||
|
||||
+12
-8
@@ -468,9 +468,9 @@ private:
|
||||
if (m_doGenerate) {
|
||||
UINFO(5, "Selection index out of range inside generate."<<endl);
|
||||
} else {
|
||||
nodep->v3error("Selection index out of range: "
|
||||
<<nodep->msbConst()<<":"<<nodep->lsbConst()
|
||||
<<" outside "<<frommsb<<":"<<fromlsb);
|
||||
nodep->v3warn(SELRANGE,"Selection index out of range: "
|
||||
<<nodep->msbConst()<<":"<<nodep->lsbConst()
|
||||
<<" outside "<<frommsb<<":"<<fromlsb);
|
||||
UINFO(1," Related node: "<<nodep<<endl);
|
||||
}
|
||||
}
|
||||
@@ -1686,7 +1686,8 @@ private:
|
||||
V3TaskConnects tconnects = V3Task::taskConnects(nodep, nodep->taskp()->stmtsp());
|
||||
for (V3TaskConnects::iterator it=tconnects.begin(); it!=tconnects.end(); ++it) {
|
||||
AstVar* portp = it->first;
|
||||
AstNode* pinp = it->second;
|
||||
AstArg* argp = it->second;
|
||||
AstNode* pinp = argp->exprp();
|
||||
if (pinp!=NULL) { // Else argument error we'll find later
|
||||
if (accept_mode==0) {
|
||||
// Prelim may cause the node to get replaced; we've lost our
|
||||
@@ -1695,18 +1696,21 @@ private:
|
||||
&& (!pinp->castSFormatF() || pinp->nextp())) { // Not already done
|
||||
UINFO(4," sformat via metacomment: "<<nodep<<endl);
|
||||
AstNRelinker handle;
|
||||
pinp->unlinkFrBackWithNext(&handle); // Format + additional args, if any
|
||||
argp->unlinkFrBackWithNext(&handle); // Format + additional args, if any
|
||||
AstNode* argsp = NULL;
|
||||
if (pinp->nextp()) argsp = pinp->nextp()->unlinkFrBackWithNext();
|
||||
while (AstArg* nextargp = argp->nextp()->castArg()) {
|
||||
argsp = argsp->addNext(nextargp->exprp()->unlinkFrBackWithNext()); // Expression goes to SFormatF
|
||||
nextargp->unlinkFrBack()->deleteTree(); // Remove the call's Arg wrapper
|
||||
}
|
||||
string format;
|
||||
if (pinp->castConst()) format = pinp->castConst()->num().toString();
|
||||
else pinp->v3error("Format to $display-like function must have constant format string");
|
||||
pushDeletep(pinp); pinp=NULL;
|
||||
pushDeletep(argp); argp=NULL;
|
||||
AstSFormatF* newp = new AstSFormatF(nodep->fileline(), format, false, argsp);
|
||||
if (!newp->scopeNamep() && newp->formatScopeTracking()) {
|
||||
newp->scopeNamep(new AstScopeName(newp->fileline()));
|
||||
}
|
||||
handle.relink(newp);
|
||||
handle.relink(new AstArg(newp->fileline(), "", newp));
|
||||
// Connection list is now incorrect (has extra args in it).
|
||||
goto reloop; // so exit early; next loop will correct it
|
||||
}
|
||||
|
||||
+38
-5
@@ -85,6 +85,7 @@ public:
|
||||
}
|
||||
|
||||
// METHODS
|
||||
void argWrapList(AstNodeFTaskRef* nodep);
|
||||
AstNodeDType* createArray(AstNodeDType* basep, AstRange* rangep, bool isPacked);
|
||||
AstVar* createVariable(FileLine* fileline, string name, AstRange* arrayp, AstNode* attrsp);
|
||||
AstNode* createSupplyExpr(FileLine* fileline, string name, int value);
|
||||
@@ -2470,6 +2471,7 @@ funcRef<nodep>: // IEEE: part of tf_call
|
||||
// // property_instance property_identifier property_actual_arg
|
||||
// // sequence_instance sequence_identifier sequence_actual_arg
|
||||
// // let_expression let_identifier let_actual_arg
|
||||
//
|
||||
id '(' list_of_argumentsE ')' { $$ = new AstFuncRef($2, *$1, $3); }
|
||||
| package_scopeIdFollows id '(' list_of_argumentsE ')' { $$ = AstDot::newIfPkg($<fl>2, $1, new AstFuncRef($<fl>2,*$2,$4)); }
|
||||
//UNSUP: idDotted is really just id to allow dotted method calls
|
||||
@@ -2497,7 +2499,7 @@ system_t_call<nodep>: // IEEE: system_tf_call (as task)
|
||||
| yaD_IGNORE '(' exprList ')' { $$ = new AstSysIgnore($<fl>1,$3); }
|
||||
//
|
||||
| yaD_DPI parenE { $$ = new AstTaskRef($<fl>1,*$1,NULL); }
|
||||
| yaD_DPI '(' exprList ')' { $$ = new AstTaskRef($2,*$1,$3); }
|
||||
| yaD_DPI '(' exprList ')' { $$ = new AstTaskRef($2,*$1,$3); GRAMMARP->argWrapList($$->castTaskRef()); }
|
||||
//
|
||||
| yD_C '(' cStrList ')' { $$ = (v3Global.opt.ignc() ? NULL : new AstUCStmt($1,$3)); }
|
||||
| yD_FCLOSE '(' idClassSel ')' { $$ = new AstFClose($1, $3); }
|
||||
@@ -2542,7 +2544,7 @@ system_f_call<nodep>: // IEEE: system_tf_call (as func)
|
||||
| yaD_IGNORE '(' exprList ')' { $$ = new AstConst($2,V3Number($2,"'b0")); } // Unsized 0
|
||||
//
|
||||
| yaD_DPI parenE { $$ = new AstFuncRef($<fl>1,*$1,NULL); }
|
||||
| yaD_DPI '(' exprList ')' { $$ = new AstFuncRef($2,*$1,$3); }
|
||||
| yaD_DPI '(' exprList ')' { $$ = new AstFuncRef($2,*$1,$3); GRAMMARP->argWrapList($$->castFuncRef()); }
|
||||
//
|
||||
| yD_BITS '(' data_type ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_BITS,$3); }
|
||||
| yD_BITS '(' data_type ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_BITS,$3,$5); }
|
||||
@@ -2598,9 +2600,10 @@ system_f_call<nodep>: // IEEE: system_tf_call (as func)
|
||||
;
|
||||
|
||||
list_of_argumentsE<nodep>: // IEEE: [list_of_arguments]
|
||||
/* empty */ { $$ = NULL; }
|
||||
| argsExprList { $$ = $1; }
|
||||
//UNSUP empty arguments with just ,,
|
||||
argsDottedList { $$ = $1; }
|
||||
| argsExprListE { if ($1->castArg() && $1->castArg()->emptyConnectNoNext()) { $1->deleteTree(); $$ = NULL; } // Mis-created when have 'func()'
|
||||
/*cont*/ else $$ = $1; }
|
||||
| argsExprListE ',' argsDottedList { $$ = $1->addNextNull($3); }
|
||||
;
|
||||
|
||||
task_declaration<ftaskp>: // ==IEEE: task_declaration
|
||||
@@ -3063,6 +3066,26 @@ argsExprList<nodep>: // IEEE: part of list_of_arguments (used where ,, isn't le
|
||||
| argsExprList ',' expr { $$ = $1->addNext($3); }
|
||||
;
|
||||
|
||||
argsExprListE<nodep>: // IEEE: part of list_of_arguments
|
||||
argsExprOneE { $$ = $1; }
|
||||
| argsExprListE ',' argsExprOneE { $$ = $1->addNext($3); }
|
||||
;
|
||||
|
||||
argsExprOneE<nodep>: // IEEE: part of list_of_arguments
|
||||
/*empty*/ { $$ = new AstArg(CRELINE(),"",NULL); }
|
||||
| expr { $$ = new AstArg(CRELINE(),"",$1); }
|
||||
;
|
||||
|
||||
argsDottedList<nodep>: // IEEE: part of list_of_arguments
|
||||
argsDotted { $$ = $1; }
|
||||
| argsDottedList ',' argsDotted { $$ = $1->addNextNull($3); }
|
||||
;
|
||||
|
||||
argsDotted<nodep>: // IEEE: part of list_of_arguments
|
||||
'.' idAny '(' ')' { $$ = new AstArg($1,*$2,NULL); }
|
||||
| '.' idAny '(' expr ')' { $$ = new AstArg($1,*$2,$4); }
|
||||
;
|
||||
|
||||
stream_expression<nodep>: // ==IEEE: stream_expression
|
||||
// // IEEE: array_range_expression expanded below
|
||||
expr { $$ = $1; }
|
||||
@@ -3590,6 +3613,16 @@ void V3ParseImp::parserClear() {
|
||||
VARDTYPE(NULL);
|
||||
}
|
||||
|
||||
void V3ParseGrammar::argWrapList(AstNodeFTaskRef* nodep) {
|
||||
// Convert list of expressions to list of arguments
|
||||
AstNode* outp = NULL;
|
||||
while (nodep->pinsp()) {
|
||||
AstNode* exprp = nodep->pinsp()->unlinkFrBack();
|
||||
outp = outp->addNext(new AstArg(exprp->fileline(), "", exprp));
|
||||
}
|
||||
if (outp) nodep->addPinsp(outp);
|
||||
}
|
||||
|
||||
AstNode* V3ParseGrammar::createSupplyExpr(FileLine* fileline, string name, int value) {
|
||||
FileLine* newfl = new FileLine (fileline);
|
||||
newfl->warnOff(V3ErrorCode::WIDTH, true);
|
||||
|
||||
@@ -320,6 +320,7 @@ sub new {
|
||||
make_pli => 0, # need to compile pli
|
||||
sim_time => 1100,
|
||||
benchmark => $opt_benchmark,
|
||||
verbose => $opt_verbose,
|
||||
run_env => '',
|
||||
# All compilers
|
||||
v_flags => [split(/\s+/,(" -f input.vc "
|
||||
|
||||
Executable
+55
@@ -0,0 +1,55 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
$Self->{vlt} or $Self->skip("Verilator only test");
|
||||
|
||||
compile (
|
||||
v_flags2 => ["--trace --output-split 1 --output-split-cfuncs 1"],
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
my $got1;
|
||||
foreach my $file (glob("$Self->{obj_dir}/*.cpp")) {
|
||||
$got1 = 1 if $file =~ /__1/;
|
||||
check($file);
|
||||
}
|
||||
$got1 or $Self->error("No __1 split file found");
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
|
||||
|
||||
sub check {
|
||||
my $filename = shift;
|
||||
my $size = -s $filename;
|
||||
printf " File %6d %s\n", $size, $filename if $Self->{verbose};
|
||||
my $fh = IO::File->new("<$filename") or $Self->error("$! $filenme");
|
||||
my @funcs;
|
||||
while (defined (my $line = $fh->getline)) {
|
||||
if ($line =~ /^(void|IData)\s+(.*::.*)/) {
|
||||
my $func = $2;
|
||||
$func =~ s/\(.*$//;
|
||||
print "\tFunc $func\n" if $Self->{verbose};
|
||||
if ($func !~ /::_eval_initial_loop$/
|
||||
&& $func !~ /::__Vconfigure$/
|
||||
&& $func !~ /::trace$/
|
||||
&& $func !~ /::traceInit$/
|
||||
&& $func !~ /::traceFull$/
|
||||
) {
|
||||
push @funcs, $func;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($#funcs > 0) {
|
||||
$Self->error("Split had multiple functions in $filename\n\t".join("\n\t",@funcs));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2005 by Wilson Snyder.
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
input clk;
|
||||
|
||||
integer cyc=0;
|
||||
|
||||
parameter CNT = 10;
|
||||
|
||||
wire [31:0] w [CNT:0];
|
||||
|
||||
generate
|
||||
for (genvar g=0; g<CNT; g++)
|
||||
sub sub (.clk(clk), .i(w[g]), .z(w[g+1]));
|
||||
endgenerate
|
||||
|
||||
// Test loop
|
||||
always @ (posedge clk) begin
|
||||
cyc <= cyc + 1;
|
||||
if (cyc==0) begin
|
||||
// Setup
|
||||
w[0] = 32'h1234;
|
||||
end
|
||||
else if (cyc<90) begin
|
||||
end
|
||||
else if (cyc==99) begin
|
||||
`define EXPECTED_SUM 32'h123e
|
||||
`ifdef TEST_VERBOSE
|
||||
$write("[%0t] cyc==%0d sum=%x\n",$time, cyc, w[CNT]);
|
||||
`endif
|
||||
if (w[CNT] !== `EXPECTED_SUM) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
module sub (input clk, input [31:0] i, output [31:0] z);
|
||||
always @(posedge clk)
|
||||
z <= i+1+$c("0"); // $c so doesn't optimize away
|
||||
endmodule
|
||||
@@ -11,9 +11,13 @@ compile (
|
||||
v_flags2 => ["--lint-only"],
|
||||
fails=>1,
|
||||
expect=>
|
||||
q{%Error: t/t_func_bad.v:\d+: Too few arguments in function call to FUNC 'add'
|
||||
q{%Error: t/t_func_bad.v:\d+: Missing argument on non-defaulted argument 'from2' in function call to FUNC 'add'
|
||||
%Error: t/t_func_bad.v:\d+: Too many arguments in function call to FUNC 'add'
|
||||
%Error: t/t_func_bad.v:\d+: Too few arguments in function call to TASK 'x'
|
||||
%Error: t/t_func_bad.v:\d+: Missing argument on non-defaulted argument 'y' in function call to TASK 'x'
|
||||
%Error: t/t_func_bad.v:\d+: Unsupported: Function output argument 'y' requires 1 bits, but connection's CONST '.*' generates 32 bits.
|
||||
%Error: t/t_func_bad.v:\d+: No such argument 'no_such' in function call to FUNC 'f'
|
||||
%Error: t/t_func_bad.v:\d+: Duplicate argument 'dup' in function call to FUNC 'f'
|
||||
%Error: t/t_func_bad.v:\d+: Too many arguments in function call to FUNC 'f'
|
||||
%Error: Exiting due to},
|
||||
);
|
||||
|
||||
|
||||
@@ -9,6 +9,10 @@ module t;
|
||||
if (add(3'd1, 3'd2, 3'd3) != 0) $stop; // Too many args
|
||||
x; // Too few args
|
||||
if (hasout(3'd1) != 0) $stop; // outputs
|
||||
//
|
||||
f(.j(1), .no_such(2)); // Name mismatch
|
||||
f(.dup(1), .dup(3)); // Duplicate
|
||||
f(1,2,3); // Too many
|
||||
end
|
||||
|
||||
function [2:0] add;
|
||||
@@ -29,4 +33,8 @@ module t;
|
||||
hasout = 0;
|
||||
endfunction
|
||||
|
||||
function int f( int j = 1, int dup = 0 );
|
||||
return (j<<16) | dup;
|
||||
endfunction
|
||||
|
||||
endmodule
|
||||
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,28 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2013 by Wilson Snyder.
|
||||
|
||||
module t (/*AUTOARG*/);
|
||||
|
||||
function int f( int j = 1, int s = 0 );
|
||||
return (j<<16) | s;
|
||||
endfunction
|
||||
|
||||
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
|
||||
|
||||
initial begin
|
||||
`checkh( f(.j(2), .s(1)) , 32'h2_0001 );
|
||||
`checkh( f(.s(1)) , 32'h1_0001 );
|
||||
`checkh( f(, 1) , 32'h1_0001 );
|
||||
`checkh( f(.j(2)) , 32'h2_0000 );
|
||||
`checkh( f(.s(1), .j(2)) , 32'h2_0001 );
|
||||
`checkh( f(.s(), .j()) , 32'h1_0000 );
|
||||
`checkh( f(2) , 32'h2_0000 );
|
||||
`checkh( f() , 32'h1_0000 );
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule
|
||||
@@ -11,10 +11,11 @@ compile (
|
||||
v_flags2 => ["--lint-only"],
|
||||
fails=>1,
|
||||
expect=>
|
||||
q{%Error: t/t_gen_cond_bitrange_bad.v:\d+: Selection index out of range: 2:2 outside 1:0
|
||||
%Error: t/t_gen_cond_bitrange_bad.v:\d+: Selection index out of range: 2:2 outside 1:0
|
||||
%Error: t/t_gen_cond_bitrange_bad.v:\d+: Selection index out of range: 2:2 outside 1:0
|
||||
%Error: t/t_gen_cond_bitrange_bad.v:\d+: Selection index out of range: 2:2 outside 1:0
|
||||
q{%Warning-SELRANGE: t/t_gen_cond_bitrange_bad.v:\d+: Selection index out of range: 2:2 outside 1:0
|
||||
%Warning-SELRANGE: Use .*
|
||||
%Warning-SELRANGE: t/t_gen_cond_bitrange_bad.v:\d+: Selection index out of range: 2:2 outside 1:0
|
||||
%Warning-SELRANGE: t/t_gen_cond_bitrange_bad.v:\d+: Selection index out of range: 2:2 outside 1:0
|
||||
%Warning-SELRANGE: t/t_gen_cond_bitrange_bad.v:\d+: Selection index out of range: 2:2 outside 1:0
|
||||
%Error: Exiting due to .*},
|
||||
);
|
||||
|
||||
|
||||
@@ -11,8 +11,9 @@ compile (
|
||||
v_flags2 => ["--lint-only"],
|
||||
fails=>$Self->{v3},
|
||||
expect=>
|
||||
'%Error: t/t_select_bad_range.v:\d+: Selection index out of range: 44:44 outside 43:0
|
||||
%Error: t/t_select_bad_range.v:\d+: Selection index out of range: 44:41 outside 43:0
|
||||
'%Warning-SELRANGE: t/t_select_bad_range.v:\d+: Selection index out of range: 44:44 outside 43:0
|
||||
%Warning-SELRANGE: Use .*
|
||||
%Warning-SELRANGE: t/t_select_bad_range.v:\d+: Selection index out of range: 44:41 outside 43:0
|
||||
%Error: Exiting due to.*',
|
||||
);
|
||||
|
||||
|
||||
@@ -11,7 +11,8 @@ compile (
|
||||
v_flags2 => ["--lint-only"],
|
||||
fails=>$Self->{v3},
|
||||
expect=>
|
||||
'%Error: t/t_select_bad_range2.v:\d+: Selection index out of range: 3:2 outside 1:0
|
||||
'%Warning-SELRANGE: t/t_select_bad_range2.v:\d+: Selection index out of range: 3:2 outside 1:0
|
||||
%Warning-SELRANGE: Use .*
|
||||
%Error: Exiting due to.*',
|
||||
);
|
||||
|
||||
|
||||
Executable
+15
@@ -0,0 +1,15 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
v_flags2 => ["--lint-only"],
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,36 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2013 by Wilson Snyder.
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
input clk;
|
||||
|
||||
reg [7:0] x;
|
||||
wire [3:0] en;
|
||||
wire sel;
|
||||
wire a;
|
||||
|
||||
// bug675
|
||||
generate
|
||||
genvar g_k;
|
||||
for ( g_k = 0; g_k < 8; g_k = g_k + 1 )
|
||||
begin: g_index
|
||||
always @* begin
|
||||
// Note this isn't a genif, but normal if
|
||||
// verilator lint_off SELRANGE
|
||||
if(g_k<4) begin
|
||||
x[g_k] = (sel == 1'b1) ? 1'b1 : (en[g_k] == 1'b0) ? 1'b1 : a;
|
||||
end
|
||||
else begin
|
||||
x[g_k] = (sel == 1'b0) ? 1'b1 : (en[g_k-4] == 1'b0) ? 1'b1 : a;
|
||||
end
|
||||
// verilator lint_on SELRANGE
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
||||
endmodule
|
||||
@@ -15,6 +15,10 @@ module t;
|
||||
reg [16*8:1] letterz;
|
||||
real r;
|
||||
|
||||
reg [7:0] v_a,v_b,v_c,v_d;
|
||||
reg [31:0] v_worda;
|
||||
reg [31:0] v_wordb;
|
||||
|
||||
`ifdef TEST_VERBOSE
|
||||
`define verbose 1'b1
|
||||
`else
|
||||
@@ -174,6 +178,22 @@ module t;
|
||||
if (chars != 1) $stop;
|
||||
if (letterl != "\n") $stop;
|
||||
|
||||
// msg1229
|
||||
v_a = $fgetc(file);
|
||||
v_b = $fgetc(file);
|
||||
v_c = $fgetc(file);
|
||||
v_d = $fgetc(file);
|
||||
v_worda = { v_d, v_c, v_b, v_a };
|
||||
if (v_worda != "4321") $stop;
|
||||
|
||||
v_wordb[7:0] = $fgetc(file);
|
||||
v_wordb[15:8] = $fgetc(file);
|
||||
v_wordb[23:16] = $fgetc(file);
|
||||
v_wordb[31:24] = $fgetc(file);
|
||||
if (v_wordb != "9876") $stop;
|
||||
|
||||
if ($fgetc(file) != "\n") $stop;
|
||||
|
||||
$fclose(file);
|
||||
end
|
||||
|
||||
|
||||
@@ -6,3 +6,4 @@ widestuff
|
||||
*oa=23 ob=12563
|
||||
*d=-236123
|
||||
*fredfishblah
|
||||
12346789
|
||||
|
||||
Reference in New Issue
Block a user