Support byte, shortint, int, longint in variables, parameters and functions.
Internals: function/var sizing and signing now comes via dtypep() Internals: cleanup code that widths parameters (again)
This commit is contained in:
parent
4c26792c9b
commit
6bc81d3d26
5
Changes
5
Changes
|
|
@ -3,6 +3,11 @@ 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.7**
|
||||
|
||||
*** Support byte, shortint, int, longint in variables, parameters and
|
||||
functions.
|
||||
|
||||
* Verilator 3.720 2009/10/26
|
||||
|
||||
** Support little endian bit vectors ("reg [0:2] x;").
|
||||
|
|
|
|||
|
|
@ -1700,13 +1700,13 @@ This section describes specific limitations for each language keyword.
|
|||
|
||||
Fully supported.
|
||||
|
||||
=item always, always_comb, always_ff, always_latch, and, assign, begin,
|
||||
buf, case, casex, casez, default, defparam, do-while, else, end, endcase,
|
||||
endfunction, endgenerate, endmodule, endspecify, endtask, final, for,
|
||||
function, generate, genvar, if, initial, inout, input, integer, localparam,
|
||||
macromodule, module, nand, negedge, nor, not, or, output, parameter,
|
||||
posedge, reg, scalared, signed, supply0, supply1, task, tri, vectored,
|
||||
while, wire, xnor, xor
|
||||
=item int, shortint, longint, always, always_comb, always_ff, always_latch,
|
||||
and, assign, begin, buf, byte, case, casex, casez, default, defparam,
|
||||
do-while, else, end, endcase, endfunction, endgenerate, endmodule,
|
||||
endspecify, endtask, final, for, function, generate, genvar, if, initial,
|
||||
inout, input, integer, logic, localparam, macromodule, module, nand,
|
||||
negedge, nor, not, or, output, parameter, posedge, reg, scalared, signed,
|
||||
supply0, supply1, task, tri, vectored, while, wire, xnor, xor
|
||||
|
||||
Generally supported.
|
||||
|
||||
|
|
|
|||
42
src/V3Ast.h
42
src/V3Ast.h
|
|
@ -202,13 +202,16 @@ class AstBasicDTypeKwd {
|
|||
public:
|
||||
enum en {
|
||||
BYTE, SHORTINT, INT, LONGINT, INTEGER, TIME, BIT,
|
||||
LOGIC, REG, SHORTREAL, REAL, REALTIME
|
||||
LOGIC, SHORTREAL, REAL, REALTIME,
|
||||
// Internal types
|
||||
LOGIC_IMPLICIT
|
||||
};
|
||||
enum en m_e;
|
||||
const char* ascii() const {
|
||||
static const char* names[] = {
|
||||
"byte", "shortint", "int", "longint", "integer", "time", "bit",
|
||||
"logic", "reg", "shortreal", "real", "realtime"
|
||||
"logic", "shortreal", "real", "realtime",
|
||||
"LOGIC_IMPLICIT"
|
||||
};
|
||||
return names[m_e];
|
||||
};
|
||||
|
|
@ -216,6 +219,30 @@ public:
|
|||
inline AstBasicDTypeKwd (en _e) : m_e(_e) {}
|
||||
explicit inline AstBasicDTypeKwd (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
int width() const {
|
||||
switch (m_e) {
|
||||
case BYTE: return 8;
|
||||
case SHORTINT: return 16;
|
||||
case INT: return 32;
|
||||
case LONGINT: return 64;
|
||||
case INTEGER: return 32;
|
||||
case LOGIC: return 1;
|
||||
case BIT: return 1;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
int isSigned() const {
|
||||
return m_e==BYTE || m_e==SHORTINT || m_e==INT || m_e==LONGINT || m_e==INTEGER;
|
||||
}
|
||||
int isFourstate() const {
|
||||
return m_e==INTEGER || m_e==LOGIC || m_e==LOGIC_IMPLICIT;
|
||||
}
|
||||
int isSloppy() const { // Don't be as anal about width warnings
|
||||
return !(m_e==LOGIC || m_e==BIT);
|
||||
}
|
||||
int isBitLogic() const { // Don't be as anal about width warnings
|
||||
return (m_e==LOGIC || m_e==BIT);
|
||||
}
|
||||
};
|
||||
inline bool operator== (AstBasicDTypeKwd lhs, AstBasicDTypeKwd rhs) { return (lhs.m_e == rhs.m_e); }
|
||||
inline bool operator== (AstBasicDTypeKwd lhs, AstBasicDTypeKwd::en rhs) { return (lhs.m_e == rhs); }
|
||||
|
|
@ -244,7 +271,7 @@ public:
|
|||
SUPPLY0,
|
||||
SUPPLY1,
|
||||
WIRE,
|
||||
IMPLICIT,
|
||||
IMPLICITWIRE,
|
||||
TRIWIRE,
|
||||
PORT, // Temp type used in parser only
|
||||
BLOCKTEMP,
|
||||
|
|
@ -261,7 +288,7 @@ public:
|
|||
static const char* names[] = {
|
||||
"?","GPARAM","LPARAM","GENVAR",
|
||||
"VAR","INPUT","OUTPUT","INOUT",
|
||||
"SUPPLY0","SUPPLY1","WIRE","IMPLICIT","TRIWIRE","PORT",
|
||||
"SUPPLY0","SUPPLY1","WIRE","IMPLICITWIRE","TRIWIRE","PORT",
|
||||
"BLOCKTEMP","MODULETEMP","STMTTEMP","XTEMP"};
|
||||
return names[m_e]; }
|
||||
};
|
||||
|
|
@ -1176,12 +1203,13 @@ struct AstNodeSel : public AstNodeBiop {
|
|||
struct AstNodeFTask : public AstNode {
|
||||
private:
|
||||
string m_name; // Name of task
|
||||
bool m_taskPublic; // Public task
|
||||
bool m_taskPublic:1; // Public task
|
||||
bool m_didSigning:1; // V3Signed completed; can skip iteration
|
||||
public:
|
||||
// Node that simply puts name into the output stream
|
||||
AstNodeFTask(FileLine* fileline, const string& name, AstNode* stmtsp)
|
||||
: AstNode(fileline)
|
||||
, m_name(name), m_taskPublic(false) {
|
||||
, m_name(name), m_taskPublic(false), m_didSigning(false) {
|
||||
addNOp3p(stmtsp);
|
||||
}
|
||||
ASTNODE_BASE_FUNCS(NodeFTask)
|
||||
|
|
@ -1195,6 +1223,8 @@ public:
|
|||
void addStmtsp(AstNode* nodep) { addNOp3p(nodep); }
|
||||
void taskPublic(bool flag) { m_taskPublic=flag; }
|
||||
bool taskPublic() const { return m_taskPublic; }
|
||||
void didSigning(bool flag) { m_didSigning=flag; }
|
||||
bool didSigning() const { return m_didSigning; }
|
||||
};
|
||||
|
||||
struct AstNodeFTaskRef : public AstNode {
|
||||
|
|
|
|||
|
|
@ -98,14 +98,12 @@ string AstVar::verilogKwd() const {
|
|||
return "input";
|
||||
} else if (isOutput()) {
|
||||
return "output";
|
||||
} else if (isInteger()) {
|
||||
return "integer";
|
||||
} else if (isTristate()) {
|
||||
return "tri";
|
||||
} else if (varType()==AstVarType::WIRE) {
|
||||
return "wire";
|
||||
} else {
|
||||
return "reg";
|
||||
return dtypep()->name();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -327,6 +325,7 @@ void AstAttrOf::dump(ostream& str) {
|
|||
void AstBasicDType::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
str<<" ["<<keyword().ascii()<<"]";
|
||||
if (implicit()) str<<" [IMPLICIT]";
|
||||
}
|
||||
void AstCast::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
|
|
|
|||
|
|
@ -109,6 +109,7 @@ struct AstBasicDType : public AstNodeDType {
|
|||
// Builtin atomic/vectored data type
|
||||
private:
|
||||
AstBasicDTypeKwd m_keyword; // What keyword created it
|
||||
bool m_implicit; // Implicitly declared
|
||||
public:
|
||||
AstBasicDType(FileLine* fl, AstBasicDTypeKwd kwd, AstRange* rangep=NULL, AstSignedState signst=signedst_NOP)
|
||||
: AstNodeDType(fl), m_keyword(kwd) {
|
||||
|
|
@ -116,14 +117,24 @@ public:
|
|||
}
|
||||
private:
|
||||
void init(AstSignedState signst, AstRange* rangep) {
|
||||
if (rangep==NULL) { // Set based on keyword properties
|
||||
if (m_keyword == AstBasicDTypeKwd::INTEGER) {
|
||||
rangep = new AstRange(fileline(),31,0); signst = signedst_SIGNED;
|
||||
}
|
||||
// Implicitness: // "parameter X" is implicit and sized from initial value, "parameter reg x" not
|
||||
m_implicit = false;
|
||||
if (keyword()==AstBasicDTypeKwd::LOGIC_IMPLICIT) {
|
||||
if (!rangep) m_implicit = true;
|
||||
m_keyword = AstBasicDTypeKwd::LOGIC;
|
||||
}
|
||||
setNOp1p(rangep); setSignedState(signst);
|
||||
if (signst == signedst_NOP && keyword().isSigned()) signst = signedst_SIGNED;
|
||||
setSignedState(signst);
|
||||
if (!rangep) { // Set based on keyword properties
|
||||
// V3Width will pull from this width
|
||||
if (keyword().width() > 1) rangep = new AstRange(fileline(), keyword().width()-1, 0);
|
||||
width(keyword().width(), keyword().width());
|
||||
} else {
|
||||
widthFrom(rangep); // Maybe unknown if parameters underneath it
|
||||
}
|
||||
setNOp1p(rangep);
|
||||
}
|
||||
AstBasicDTypeKwd keyword() const { return m_keyword; }
|
||||
AstBasicDTypeKwd keyword() const { return m_keyword; } // private - use isSomething accessors instead
|
||||
public:
|
||||
ASTNODE_NODE_FUNCS(BasicDType, BASICDTYPE)
|
||||
virtual void dump(ostream& str);
|
||||
|
|
@ -137,13 +148,15 @@ public:
|
|||
if (signst!=signedst_NOP) isSigned(signst==signedst_SIGNED);
|
||||
}
|
||||
// METHODS
|
||||
bool isInteger() const { return (keyword() == AstBasicDTypeKwd::INTEGER); }
|
||||
bool isBitLogic() const { return keyword().isBitLogic(); }
|
||||
bool isSloppy() const { return keyword().isSloppy(); }
|
||||
int msb() const { if (!rangep()) return 0; return rangep()->msbConst(); }
|
||||
int lsb() const { if (!rangep()) return 0; return rangep()->lsbConst(); }
|
||||
int msbEndianed() const { if (!rangep()) return 0; return littleEndian()?rangep()->lsbConst():rangep()->msbConst(); }
|
||||
int lsbEndianed() const { if (!rangep()) return 0; return littleEndian()?rangep()->msbConst():rangep()->lsbConst(); }
|
||||
int msbMaxSelect() const { return (lsb()<0 ? msb()-lsb() : msb()); } // Maximum value a [] select may index
|
||||
bool littleEndian() const { return (rangep() && rangep()->littleEndian()); }
|
||||
bool implicit() const { return m_implicit; }
|
||||
};
|
||||
|
||||
struct AstArraySel : public AstNodeSel {
|
||||
|
|
@ -384,12 +397,12 @@ public:
|
|||
bool isPrimaryIO() const { return m_primaryIO; }
|
||||
bool isPrimaryIn() const { return isPrimaryIO() && isInput(); }
|
||||
bool isIO() const { return (m_input||m_output); }
|
||||
bool isSignal() const { return (varType()==AstVarType::WIRE || varType()==AstVarType::IMPLICIT
|
||||
bool isSignal() const { return (varType()==AstVarType::WIRE || varType()==AstVarType::IMPLICITWIRE
|
||||
|| varType()==AstVarType::VAR); }
|
||||
bool isTemp() const { return (varType()==AstVarType::BLOCKTEMP || varType()==AstVarType::MODULETEMP
|
||||
|| varType()==AstVarType::STMTTEMP || varType()==AstVarType::XTEMP); }
|
||||
bool isToggleCoverable() const { return ((isIO() || isSignal())
|
||||
&& (isIO() || !isInteger())
|
||||
&& (isIO() || isBitLogic())
|
||||
// Wrapper would otherwise duplicate wrapped module's coverage
|
||||
&& !isSc() && !isPrimaryIO()); }
|
||||
bool isStatementTemp() const { return (varType()==AstVarType::STMTTEMP); }
|
||||
|
|
@ -398,7 +411,7 @@ public:
|
|||
bool isParam() const { return (varType()==AstVarType::LPARAM || varType()==AstVarType::GPARAM); }
|
||||
bool isGParam() const { return (varType()==AstVarType::GPARAM); }
|
||||
bool isGenVar() const { return (varType()==AstVarType::GENVAR); }
|
||||
bool isInteger() const { return dtypep()->castBasicDType() && dtypep()->castBasicDType()->isInteger(); }
|
||||
bool isBitLogic() const { return dtypep()->castBasicDType() && dtypep()->castBasicDType()->isBitLogic(); }
|
||||
bool isUsedClock() const { return m_usedClock; }
|
||||
bool isUsedParam() const { return m_usedParam; }
|
||||
bool isSc() const { return m_sc; }
|
||||
|
|
|
|||
|
|
@ -138,7 +138,6 @@ private:
|
|||
|
||||
//=======
|
||||
// These have proper signedness set when they were created.
|
||||
virtual void visit(AstFunc* nodep, AstNUser*) { nodep->iterateChildren(*this); }
|
||||
virtual void visit(AstNodeDType* nodep, AstNUser*) { nodep->iterateChildren(*this); }
|
||||
|
||||
// Inherit from others
|
||||
|
|
@ -150,20 +149,28 @@ private:
|
|||
nodep->varp()->iterate(*this);
|
||||
nodep->signedFrom(nodep->varp());
|
||||
}
|
||||
virtual void visit(AstFuncRef* nodep, AstNUser* vup) {
|
||||
visit(nodep->castNodeFTaskRef(), vup); // Deal with as if was task
|
||||
nodep->signedFrom(nodep->taskp());
|
||||
}
|
||||
virtual void visit(AstConst* nodep, AstNUser*) {
|
||||
// The node got setup with the signed state of the node.
|
||||
// However a later operation may have changed the node->signed w/o changing
|
||||
// the number's sign. So we don't: nodep->isSigned(nodep->num().isSigned());
|
||||
}
|
||||
virtual void visit(AstNodeFTaskRef* nodep, AstNUser*) {
|
||||
// Fortunately, the input variables to the task keep whatever sign they are given
|
||||
// And we already did the function's output signedness above in visit(AstFuncRef,
|
||||
// so, it's just
|
||||
virtual void visit(AstFunc* nodep, AstNUser*) {
|
||||
// Avoid recursion; can't use user() as they're all full, and anyhow this is often called
|
||||
if (nodep->didSigning()) return;
|
||||
nodep->didSigning(true);
|
||||
nodep->iterateChildren(*this);
|
||||
nodep->signedFrom(nodep->fvarp()); // Which will get it from fvarp()->dtypep()
|
||||
}
|
||||
virtual void visit(AstTask* nodep, AstNUser*) {
|
||||
// Avoid recursion; can't use user() as they're all full, and anyhow this is often called
|
||||
if (nodep->didSigning()) return;
|
||||
nodep->didSigning(true);
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
virtual void visit(AstNodeFTaskRef* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (nodep->taskp()) nodep->taskp()->iterate(*this);
|
||||
nodep->signedFrom(nodep->taskp());
|
||||
}
|
||||
virtual void visit(AstNodeIf* nodep, AstNUser*) {
|
||||
if (!nodep->castGenIf()) { // for m_paramsOnly
|
||||
|
|
|
|||
|
|
@ -473,6 +473,14 @@ private:
|
|||
virtual void visit(AstScopeName* nodep, AstNUser* vup) {
|
||||
// Only used in Displays which don't care....
|
||||
}
|
||||
virtual void visit(AstBasicDType* nodep, AstNUser* vup) {
|
||||
if (nodep->rangep()) {
|
||||
nodep->rangep()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
||||
nodep->widthFrom(nodep->rangep());
|
||||
}
|
||||
// else width in node is correct; it was set based on keyword().width()
|
||||
// at construction time
|
||||
}
|
||||
virtual void visit(AstVar* nodep, AstNUser* vup) {
|
||||
//if (debug()) nodep->dumpTree(cout," InitPre: ");
|
||||
// Must have deterministic constant width
|
||||
|
|
@ -480,27 +488,18 @@ private:
|
|||
// with non-constant range gets size 1, not size 0.
|
||||
int width=1; int mwidth=1;
|
||||
nodep->arraysp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
||||
if (nodep->dtypep()->rangep()) {
|
||||
nodep->dtypep()->rangep()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
||||
width = mwidth = nodep->dtypep()->rangep()->width();
|
||||
}
|
||||
else if (nodep->isInteger() || nodep->isGenVar()) {
|
||||
width = 32;
|
||||
mwidth = 1; // Consider it unsized, as we want x[int] to work, and also want {int} to fail.
|
||||
}
|
||||
else if (nodep->isParam()) { // unranged
|
||||
width = mwidth = 0; // But see below later.
|
||||
}
|
||||
if (nodep->initp()) {
|
||||
nodep->initp()->iterateAndNext(*this,WidthVP(width,0,PRELIM).p());
|
||||
// Although nodep will get a different width for parameters just below,
|
||||
// we want the init numbers to retain their width/minwidth until parameters are replaced.
|
||||
nodep->initp()->iterateAndNext(*this,WidthVP(width,0,FINAL).p());
|
||||
if (nodep->isParam()) {
|
||||
if (nodep->dtypep()->rangep()) {
|
||||
// Parameters need to preserve widthMin from the value, not get a constant size
|
||||
mwidth = nodep->initp()->widthMin();
|
||||
} else if (nodep->initp()->widthSized()) {
|
||||
|
||||
// Parameters if implicit untyped inherit from what they are assigned to
|
||||
AstBasicDType* bdtypep = nodep->dtypep()->castBasicDType();
|
||||
if (nodep->isParam() && bdtypep && bdtypep->implicit()) {
|
||||
width = mwidth = 0;
|
||||
if (nodep->initp()) {
|
||||
nodep->initp()->iterateAndNext(*this,WidthVP(width,0,PRELIM).p());
|
||||
// Although nodep will get a different width for parameters just below,
|
||||
// we want the init numbers to retain their width/minwidth until parameters are replaced.
|
||||
// This prevents width warnings at the location the parameter is substituted in
|
||||
nodep->initp()->iterateAndNext(*this,WidthVP(width,0,FINAL).p());
|
||||
if (nodep->initp()->widthSized()) {
|
||||
width = mwidth = nodep->initp()->width();
|
||||
} else {
|
||||
if (nodep->initp()->width()>32) nodep->initp()->v3warn(WIDTH,"Assigning >32 bit to unranged parameter (defaults to 32 bits)\n");
|
||||
|
|
@ -508,34 +507,43 @@ private:
|
|||
mwidth = nodep->initp()->widthMin();
|
||||
}
|
||||
}
|
||||
//if (debug()) nodep->dumpTree(cout," final: ");
|
||||
}
|
||||
if (nodep->isParam() && !nodep->dtypep()->rangep()) {
|
||||
// Parameter sizes can come from the thing they get assigned from
|
||||
// They then "stick" to that width.
|
||||
if (!width) width=32; // Or, if nothing, they're 32 bits.
|
||||
AstBasicDType* bdtypep = nodep->dtypep()->castBasicDType();
|
||||
if (bdtypep->rangep()) bdtypep->rangep()->unlinkFrBackWithNext()->deleteTree();
|
||||
bdtypep->rangep(new AstRange(nodep->fileline(),width-1,0));
|
||||
bdtypep->rangep()->width(width,width);
|
||||
nodep->dtypep()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
||||
}
|
||||
else { // non param or sized param
|
||||
nodep->dtypep()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
||||
width = nodep->dtypep()->width(); mwidth = nodep->dtypep()->widthMin();
|
||||
if (nodep->initp()) {
|
||||
nodep->initp()->iterateAndNext(*this,WidthVP(width,0,BOTH).p());
|
||||
//if (debug()) nodep->dumpTree(cout," final: ");
|
||||
}
|
||||
}
|
||||
nodep->width(width,mwidth);
|
||||
// See above note about initp()->...FINAL
|
||||
if (nodep->initp()) widthCheck(nodep,"Initial value",nodep->initp(),width,mwidth);
|
||||
UINFO(4,"varWidthed "<<nodep<<endl);
|
||||
//if (debug()) nodep->dumpTree(cout," InitPos: ");
|
||||
//if (debug()) nodep->dumpTree(cout," InitOut: ");
|
||||
}
|
||||
virtual void visit(AstNodeVarRef* nodep, AstNUser* vup) {
|
||||
if (nodep->varp()->width()==0) {
|
||||
// Var hasn't been widthed, so make it so.
|
||||
nodep->varp()->iterate(*this);
|
||||
}
|
||||
if ((nodep->varp()->isInteger() || nodep->varp()->isGenVar())
|
||||
//if (debug()>=9) { nodep->dumpTree(cout," VRin "); nodep->varp()->dumpTree(cout," forvar "); }
|
||||
// Note genvar's are also entered as integers
|
||||
AstBasicDType* bdtypep = nodep->varp()->dtypep()->castBasicDType();
|
||||
if (bdtypep && bdtypep->isSloppy()
|
||||
&& nodep->backp()->castNodeAssign()) { // On LHS
|
||||
// Consider Integers on LHS to sized (else would be unsized.)
|
||||
nodep->width(32,32);
|
||||
nodep->width(bdtypep->width(),bdtypep->width());
|
||||
} else {
|
||||
nodep->width(nodep->varp()->width(), nodep->varp()->widthMin());
|
||||
nodep->widthFrom(nodep->varp());
|
||||
}
|
||||
//if (debug()>=9) nodep->dumpTree(cout," VRout ");
|
||||
}
|
||||
virtual void visit(AstPslClocked* nodep, AstNUser*) {
|
||||
nodep->propp()->iterateAndNext(*this,WidthVP(1,1,BOTH).p());
|
||||
|
|
@ -625,14 +633,14 @@ private:
|
|||
}
|
||||
nodep->condp()->iterateAndNext(*this,WidthVP(1,1,BOTH).p());
|
||||
widthCheckReduce(nodep,"If",nodep->condp(),1,1); // it's like an if() condition.
|
||||
//if (debug()) nodep->dumpTree(cout," IfPos: ");
|
||||
//if (debug()) nodep->dumpTree(cout," IfOut: ");
|
||||
}
|
||||
virtual void visit(AstNodeAssign* nodep, AstNUser*) {
|
||||
// TOP LEVEL NODE
|
||||
//if (debug()) nodep->dumpTree(cout," AssignPre: ");
|
||||
nodep->lhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
||||
nodep->rhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,PRELIM).p());
|
||||
if(!nodep->lhsp()->widthSized()) nodep->v3fatalSrc("How can LHS be unsized?");
|
||||
if (!nodep->lhsp()->widthSized()) nodep->v3fatalSrc("How can LHS be unsized?");
|
||||
int awidth = nodep->lhsp()->width();
|
||||
if (awidth==0) {
|
||||
awidth = nodep->rhsp()->width(); // Parameters can propagate by unsized assignment
|
||||
|
|
@ -643,7 +651,7 @@ private:
|
|||
// than using "width" and have the optimizer truncate the result, we do
|
||||
// it using the normal width reduction checks.
|
||||
widthCheck(nodep,"Assign RHS",nodep->rhsp(),awidth,awidth);
|
||||
//if (debug()) nodep->dumpTree(cout," AssignPos: ");
|
||||
//if (debug()) nodep->dumpTree(cout," AssignOut: ");
|
||||
}
|
||||
virtual void visit(AstNodePli* nodep, AstNUser*) {
|
||||
// Excludes NodeDisplay, see below
|
||||
|
|
@ -797,7 +805,7 @@ private:
|
|||
widthCheckPin(nodep, nodep->exprp(), pinwidth, inputPin);
|
||||
}
|
||||
}
|
||||
//if (debug()) nodep->dumpTree(cout,"- PinPos: ");
|
||||
//if (debug()) nodep->dumpTree(cout,"- PinOut: ");
|
||||
}
|
||||
virtual void visit(AstCell* nodep, AstNUser*) {
|
||||
if (!m_paramsOnly) {
|
||||
|
|
@ -822,6 +830,7 @@ private:
|
|||
virtual void visit(AstFuncRef* nodep, AstNUser* vup) {
|
||||
visit(nodep->castNodeFTaskRef(), vup);
|
||||
nodep->widthSignedFrom(nodep->taskp());
|
||||
//if (debug()) nodep->dumpTree(cout," FuncOut: ");
|
||||
}
|
||||
virtual void visit(AstNodeFTaskRef* nodep, AstNUser* vup) {
|
||||
// Function hasn't been widthed, so make it so.
|
||||
|
|
|
|||
|
|
@ -196,6 +196,7 @@ escid \\[^ \t\f\r\n]+
|
|||
"buf" { FL; return yBUF; }
|
||||
"bufif0" { FL; return yBUFIF0; }
|
||||
"bufif1" { FL; return yBUFIF1; }
|
||||
"byte" { FL; return yBYTE; }
|
||||
"case" { FL; return yCASE; }
|
||||
"casex" { FL; return yCASEX; }
|
||||
"casez" { FL; return yCASEZ; }
|
||||
|
|
@ -217,7 +218,9 @@ escid \\[^ \t\f\r\n]+
|
|||
"initial" { FL; return yINITIAL; }
|
||||
"inout" { FL; return yINOUT; }
|
||||
"input" { FL; return yINPUT; }
|
||||
"int" { FL; return yINT; }
|
||||
"integer" { FL; return yINTEGER; }
|
||||
"longint" { FL; return yLONGINT; }
|
||||
"macromodule" { FL; return yMODULE; }
|
||||
"module" { FL; return yMODULE; }
|
||||
"nand" { FL; return yNAND; }
|
||||
|
|
@ -235,6 +238,7 @@ escid \\[^ \t\f\r\n]+
|
|||
"reg" { FL; return yREG; }
|
||||
"repeat" { FL; return yREPEAT; }
|
||||
"scalared" { FL; return ySCALARED; }
|
||||
"shortint" { FL; return ySHORTINT; }
|
||||
"specify" { FL; return ySPECIFY; }
|
||||
"specparam" { FL; return ySPECPARAM; }
|
||||
"supply0" { FL; return ySUPPLY0; }
|
||||
|
|
@ -382,7 +386,6 @@ escid \\[^ \t\f\r\n]+
|
|||
"bins" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||
"binsof" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||
"break" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||
"byte" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||
"chandle" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||
"class" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||
"constraint" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||
|
|
@ -410,13 +413,11 @@ escid \\[^ \t\f\r\n]+
|
|||
"illegal_bins" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||
"import" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||
"inside" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||
"int" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||
"interface" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||
"intersect" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||
"join_any" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||
"join_none" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||
"local" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||
"longint" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||
"matches" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||
"modport" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||
"new" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||
|
|
@ -433,7 +434,6 @@ escid \\[^ \t\f\r\n]+
|
|||
"randsequence" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||
"ref" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||
"return" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||
"shortint" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||
"shortreal" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||
"solve" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||
"string" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||
|
|
|
|||
|
|
@ -103,6 +103,7 @@ public:
|
|||
#define GRAMMARP V3ParseGrammar::singletonp()
|
||||
|
||||
const AstBasicDTypeKwd LOGIC = AstBasicDTypeKwd::LOGIC; // Shorthand "LOGIC"
|
||||
const AstBasicDTypeKwd LOGIC_IMPLICIT = AstBasicDTypeKwd::LOGIC_IMPLICIT;
|
||||
|
||||
//======================================================================
|
||||
// Macro functions
|
||||
|
|
@ -208,6 +209,7 @@ class AstSenTree;
|
|||
%token<fl> yBUF "buf"
|
||||
%token<fl> yBUFIF0 "bufif0"
|
||||
%token<fl> yBUFIF1 "bufif1"
|
||||
%token<fl> yBYTE "byte"
|
||||
%token<fl> yCASE "case"
|
||||
%token<fl> yCASEX "casex"
|
||||
%token<fl> yCASEZ "casez"
|
||||
|
|
@ -235,12 +237,14 @@ class AstSenTree;
|
|||
%token<fl> yGENVAR "genvar"
|
||||
%token<fl> yIF "if"
|
||||
%token<fl> yIFF "iff"
|
||||
%token<fl> yLOGIC "logic"
|
||||
%token<fl> yINITIAL "initial"
|
||||
%token<fl> yINOUT "inout"
|
||||
%token<fl> yINPUT "input"
|
||||
%token<fl> yINT "int"
|
||||
%token<fl> yINTEGER "integer"
|
||||
%token<fl> yLOCALPARAM "localparam"
|
||||
%token<fl> yLOGIC "logic"
|
||||
%token<fl> yLONGINT "longint"
|
||||
%token<fl> yMODULE "module"
|
||||
%token<fl> yNAND "nand"
|
||||
%token<fl> yNEGEDGE "negedge"
|
||||
|
|
@ -259,6 +263,7 @@ class AstSenTree;
|
|||
%token<fl> yREG "reg"
|
||||
%token<fl> yREPEAT "repeat"
|
||||
%token<fl> ySCALARED "scalared"
|
||||
%token<fl> ySHORTINT "shortint"
|
||||
%token<fl> ySIGNED "signed"
|
||||
%token<fl> ySPECIFY "specify"
|
||||
%token<fl> ySPECPARAM "specparam"
|
||||
|
|
@ -626,7 +631,7 @@ port<nodep>: // ==IEEE: port
|
|||
portDirNetE data_type portSig variable_dimensionListE sigAttrListE { $$=$3; VARDTYPE($2); $$->addNextNull(VARDONEP($$,$4,$5)); }
|
||||
//UNSUP portDirNetE yVAR data_type portSig variable_dimensionListE sigAttrListE { $$=$4; VARDTYPE($3); $$->addNextNull(VARDONEP($$,$5,$6)); }
|
||||
//UNSUP portDirNetE yVAR implicit_type portSig variable_dimensionListE sigAttrListE { $$=$4; VARDTYPE($3); $$->addNextNull(VARDONEP($$,$5,$6)); }
|
||||
| portDirNetE signingE rangeList portSig variable_dimensionListE sigAttrListE { $$=$4; VARDTYPE(new AstBasicDType($3->fileline(), LOGIC, $3, $2)); $$->addNextNull(VARDONEP($$,$5,$6)); }
|
||||
| portDirNetE signingE rangeList portSig variable_dimensionListE sigAttrListE { $$=$4; VARDTYPE(new AstBasicDType($3->fileline(), LOGIC_IMPLICIT, $3, $2)); $$->addNextNull(VARDONEP($$,$5,$6)); }
|
||||
| portDirNetE /*implicit*/ portSig variable_dimensionListE sigAttrListE { $$=$2; /*VARDTYPE-same*/ $$->addNextNull(VARDONEP($$,$3,$4)); }
|
||||
//
|
||||
| portDirNetE data_type portSig variable_dimensionListE sigAttrListE '=' constExpr { $$=$3; VARDTYPE($2); $$->addNextNull(VARDONEP($$,$4,$5)); $$->addNextNull(GRAMMARP->newVarInit($6,$$,$7)); }
|
||||
|
|
@ -693,13 +698,13 @@ parameter_declaration<nodep>: // IEEE: parameter_declaration
|
|||
|
||||
local_parameter_declarationFront: // IEEE: local_parameter_declaration w/o assignment
|
||||
varLParamReset implicit_type { /*VARRESET-in-varLParam*/ VARDTYPE($2); }
|
||||
//UNSUP varLParamReset data_type { /*VARRESET-in-varLParam*/ VARDTYPE($2); }
|
||||
| varLParamReset data_type { /*VARRESET-in-varLParam*/ VARDTYPE($2); }
|
||||
//UNSUP varLParamReset yTYPE { /*VARRESET-in-varLParam*/ VARDTYPE($2); }
|
||||
;
|
||||
|
||||
parameter_declarationFront: // IEEE: parameter_declaration w/o assignment
|
||||
varGParamReset implicit_type { /*VARRESET-in-varGParam*/ VARDTYPE($2); }
|
||||
//UNSUP varGParamReset data_type { /*VARRESET-in-varGParam*/ VARDTYPE($2); }
|
||||
| varGParamReset data_type { /*VARRESET-in-varGParam*/ VARDTYPE($2); }
|
||||
//UNSUP varGParamReset yTYPE { /*VARRESET-in-varGParam*/ VARDTYPE($2); }
|
||||
;
|
||||
|
||||
|
|
@ -779,9 +784,9 @@ port_declaration<nodep>: // ==IEEE: port_declaration
|
|||
list_of_variable_decl_assignments { $$ = $5; }
|
||||
//UNSUP port_directionReset port_declNetE yVAR data_type { VARDTYPE($4); } list_of_variable_decl_assignments { $$ = $6; }
|
||||
//UNSUP port_directionReset port_declNetE yVAR implicit_type { VARDTYPE($4); } list_of_variable_decl_assignments { $$ = $6; }
|
||||
| port_directionReset port_declNetE signingE rangeList { VARDTYPE(new AstBasicDType($4->fileline(), LOGIC, $4, $3)); }
|
||||
| port_directionReset port_declNetE signingE rangeList { VARDTYPE(new AstBasicDType($4->fileline(), LOGIC_IMPLICIT, $4, $3)); }
|
||||
list_of_variable_decl_assignments { $$ = $6; }
|
||||
| port_directionReset port_declNetE signing { VARDTYPE(new AstBasicDType($<fl>3, LOGIC, NULL, $3)); }
|
||||
| port_directionReset port_declNetE signing { VARDTYPE(new AstBasicDType($<fl>3, LOGIC_IMPLICIT, NULL, $3)); }
|
||||
list_of_variable_decl_assignments { $$ = $5; }
|
||||
| port_directionReset port_declNetE /*implicit*/ { VARDTYPE(NULL);/*default_nettype*/}
|
||||
list_of_variable_decl_assignments { $$ = $4; }
|
||||
|
|
@ -798,18 +803,18 @@ tf_port_declaration<nodep>: // ==IEEE: tf_port_declaration
|
|||
;
|
||||
|
||||
integer_atom_type<bdtypep>: // ==IEEE: integer_atom_type
|
||||
//UNSUP yBYTE { $$ = new AstBasicDType($1,AstBasicDTypeKwd::BYTE); }
|
||||
//UNSUP ySHORTINT { $$ = new AstBasicDType($1,AstBasicDTypeKwd::SHORTINT); }
|
||||
//UNSUP yINT { $$ = new AstBasicDType($1,AstBasicDTypeKwd::INT); }
|
||||
//UNSUP yLONGINT { $$ = new AstBasicDType($1,AstBasicDTypeKwd::LONGINT); }
|
||||
yINTEGER { $$ = new AstBasicDType($1,AstBasicDTypeKwd::INTEGER); }
|
||||
yBYTE { $$ = new AstBasicDType($1,AstBasicDTypeKwd::BYTE); }
|
||||
| ySHORTINT { $$ = new AstBasicDType($1,AstBasicDTypeKwd::SHORTINT); }
|
||||
| yINT { $$ = new AstBasicDType($1,AstBasicDTypeKwd::INT); }
|
||||
| yLONGINT { $$ = new AstBasicDType($1,AstBasicDTypeKwd::LONGINT); }
|
||||
| yINTEGER { $$ = new AstBasicDType($1,AstBasicDTypeKwd::INTEGER); }
|
||||
//UNSUP yTIME { $$ = new AstBasicDType($1,AstBasicDTypeKwd::TIME); }
|
||||
;
|
||||
|
||||
integer_vector_type<bdtypep>: // ==IEEE: integer_atom_type
|
||||
yBIT { $$ = new AstBasicDType($1,AstBasicDTypeKwd::BIT); }
|
||||
| yLOGIC { $$ = new AstBasicDType($1,AstBasicDTypeKwd::LOGIC); }
|
||||
| yREG { $$ = new AstBasicDType($1,AstBasicDTypeKwd::REG); }
|
||||
| yREG { $$ = new AstBasicDType($1,AstBasicDTypeKwd::LOGIC); } // logic==reg
|
||||
;
|
||||
|
||||
signingE<signstate>: // IEEE: signing - plus empty
|
||||
|
|
@ -961,8 +966,8 @@ data_declarationVarFront: // IEEE: part of data_declaration
|
|||
implicit_type<typep>: // IEEE: part of *data_type_or_implicit
|
||||
// // Also expanded in data_declaration
|
||||
/* empty */ { $$ = NULL; }
|
||||
| signingE rangeList { $$ = new AstBasicDType($2->fileline(), LOGIC, $2, $1); }
|
||||
| signing { $$ = new AstBasicDType($<fl>1, LOGIC, NULL, $1); }
|
||||
| signingE rangeList { $$ = new AstBasicDType($2->fileline(), LOGIC_IMPLICIT, $2, $1); }
|
||||
| signing { $$ = new AstBasicDType($<fl>1, LOGIC_IMPLICIT, NULL, $1); }
|
||||
;
|
||||
|
||||
//************************************************
|
||||
|
|
@ -1240,9 +1245,9 @@ rangeList<rangep>: // IEEE: {packed_dimension}
|
|||
| rangeList anyrange { $$ = $1; $1->addNext($2); }
|
||||
;
|
||||
|
||||
regrangeE<bdtypep>:
|
||||
/* empty */ { $$ = new AstBasicDType(CRELINE(), LOGIC, NULL); }
|
||||
| anyrange { $$ = new AstBasicDType(CRELINE(), LOGIC, $1); }
|
||||
wirerangeE<bdtypep>:
|
||||
/* empty */ { $$ = new AstBasicDType(CRELINE(), LOGIC, NULL); } // not implicit
|
||||
| anyrange { $$ = new AstBasicDType(CRELINE(), LOGIC, $1); } // not implicit
|
||||
;
|
||||
|
||||
// IEEE: select
|
||||
|
|
@ -1253,9 +1258,9 @@ anyrange<rangep>:
|
|||
;
|
||||
|
||||
delayrange<bdtypep>:
|
||||
regrangeE delayE { $$ = $1; }
|
||||
| ySCALARED regrangeE delayE { $$ = $2; }
|
||||
| yVECTORED regrangeE delayE { $$ = $2; }
|
||||
wirerangeE delayE { $$ = $1; }
|
||||
| ySCALARED wirerangeE delayE { $$ = $2; }
|
||||
| yVECTORED wirerangeE delayE { $$ = $2; }
|
||||
//UNSUP: ySCALARED/yVECTORED ignored
|
||||
;
|
||||
|
||||
|
|
@ -1744,15 +1749,17 @@ task_declaration<taskp>: // ==IEEE: task_declaration
|
|||
;
|
||||
|
||||
function_declaration<funcp>: // IEEE: function_declaration + function_body_declaration
|
||||
yFUNCTION lifetimeE funcTypeE funcId tfGuts yENDFUNCTION endLabelE
|
||||
{ $$ = $4; $$->addFvarp($3); $$->addStmtsp($5); if ($3) $$->isSigned($3->isSigned());
|
||||
SYMP->popScope($$); }
|
||||
| yFUNCTION lifetimeE funcTypeE funcId yVL_ISOLATE_ASSIGNMENTS tfGuts yENDFUNCTION endLabelE
|
||||
{ $$ = $4; $$->addFvarp($3); $$->addStmtsp($6); $$->attrIsolateAssign(true); if ($3) $$->isSigned($3->isSigned());
|
||||
yFUNCTION lifetimeE funcId funcIsolateE tfGuts yENDFUNCTION endLabelE
|
||||
{ $$ = $3; $$->attrIsolateAssign($4); $$->addStmtsp($5);
|
||||
SYMP->popScope($$); }
|
||||
//UNSUP: Generic function return types
|
||||
;
|
||||
|
||||
funcIsolateE<cint>:
|
||||
/* empty */ { $$ = 0; }
|
||||
| yVL_ISOLATE_ASSIGNMENTS { $$ = 1; }
|
||||
;
|
||||
|
||||
lifetimeE: // IEEE: [lifetime]
|
||||
/* empty */ { }
|
||||
| lifetime { }
|
||||
|
|
@ -1773,11 +1780,23 @@ taskId<taskp>:
|
|||
funcId<funcp>: // IEEE: function_data_type_or_implicit + part of function_body_declaration
|
||||
// // IEEE: function_data_type_or_implicit must be expanded here to prevent conflict
|
||||
// // function_data_type expanded here to prevent conflicts with implicit_type:empty vs data_type:ID
|
||||
tfIdScoped
|
||||
/**/ tfIdScoped
|
||||
{ $$ = new AstFunc ($<fl>1,*$<strp>1,NULL,NULL);
|
||||
$$->addFvarp(new AstBasicDType($$->fileline(), LOGIC_IMPLICIT, NULL));
|
||||
SYMP->pushNewUnder($$, NULL); }
|
||||
| signingE rangeList tfIdScoped
|
||||
{ $$ = new AstFunc ($<fl>3,*$<strp>3,NULL,NULL);
|
||||
$$->addFvarp(new AstBasicDType($$->fileline(), LOGIC_IMPLICIT, $2, $1));
|
||||
SYMP->pushNewUnder($$, NULL); }
|
||||
| signing tfIdScoped
|
||||
{ $$ = new AstFunc ($<fl>2,*$<strp>2,NULL,NULL);
|
||||
$$->addFvarp(new AstBasicDType($$->fileline(), LOGIC_IMPLICIT, NULL, $1));
|
||||
SYMP->pushNewUnder($$, NULL); }
|
||||
//UNSUP yVOID tfIdScoped { UNSUP }
|
||||
| data_type tfIdScoped
|
||||
{ $$ = new AstFunc ($<fl>2,*$<strp>2,NULL,NULL);
|
||||
$$->addFvarp($1);
|
||||
SYMP->pushNewUnder($$, NULL); }
|
||||
//UNSUP id/*interface_identifier*/ '.' id { UNSUP }
|
||||
//UNSUP class_scope_id { UNSUP }
|
||||
;
|
||||
|
||||
tfIdScoped<strp>: // IEEE: part of function_body_declaration/task_body_declaration
|
||||
|
|
@ -1799,14 +1818,6 @@ tfBodyE<nodep>: // IEEE: part of function_body_declaration/task_body_declarati
|
|||
| stmtList { $$ = $1; }
|
||||
;
|
||||
|
||||
funcTypeE<typep>:
|
||||
/* empty */ { $$ = NULL; }
|
||||
| yINTEGER { $$ = new AstBasicDType($1,AstBasicDTypeKwd::INTEGER); }
|
||||
| ySIGNED { $$ = new AstBasicDType($1,LOGIC, NULL); $$->isSigned(true); }
|
||||
| ySIGNED '[' constExpr ':' constExpr ']' { $$ = new AstBasicDType($1,LOGIC, new AstRange($1,$3,$5)); $$->isSigned(true); }
|
||||
| '[' constExpr ':' constExpr ']' { $$ = new AstBasicDType($1,LOGIC, new AstRange($1,$2,$4)); }
|
||||
;
|
||||
|
||||
tf_item_declarationList<nodep>:
|
||||
tf_item_declaration { $$ = $1; }
|
||||
| tf_item_declarationList tf_item_declaration { $$ = $1->addNextNull($2); }
|
||||
|
|
@ -1842,15 +1853,15 @@ tf_port_item<nodep>: // ==IEEE: tf_port_item
|
|||
|
||||
tf_port_itemFront: // IEEE: part of tf_port_item, which has the data type
|
||||
data_type { VARDTYPE($1); }
|
||||
| signingE rangeList { VARDTYPE(new AstBasicDType($2->fileline(), LOGIC, $2, $1)); }
|
||||
| signing { VARDTYPE(new AstBasicDType($<fl>1, LOGIC, NULL, $1)); }
|
||||
| signingE rangeList { VARDTYPE(new AstBasicDType($2->fileline(), LOGIC_IMPLICIT, $2, $1)); }
|
||||
| signing { VARDTYPE(new AstBasicDType($<fl>1, LOGIC_IMPLICIT, NULL, $1)); }
|
||||
//UNSUP yVAR data_type { VARDTYPE($2); }
|
||||
//UNSUP yVAR implicit_type { VARDTYPE($2); }
|
||||
//
|
||||
| tf_port_itemDir /*implicit*/ { VARDTYPE(NULL); /*default_nettype-see spec*/ }
|
||||
| tf_port_itemDir data_type { VARDTYPE($2); }
|
||||
| tf_port_itemDir signingE rangeList { VARDTYPE(new AstBasicDType($3->fileline(), LOGIC, $3, $2)); }
|
||||
| tf_port_itemDir signing { VARDTYPE(new AstBasicDType($<fl>2, LOGIC, NULL, $2)); }
|
||||
| tf_port_itemDir signingE rangeList { VARDTYPE(new AstBasicDType($3->fileline(), LOGIC_IMPLICIT, $3, $2)); }
|
||||
| tf_port_itemDir signing { VARDTYPE(new AstBasicDType($<fl>2, LOGIC_IMPLICIT, NULL, $2)); }
|
||||
//UNSUP tf_port_itemDir yVAR data_type { VARDTYPE($3); }
|
||||
//UNSUP tf_port_itemDir yVAR implicit_type { VARDTYPE($3); }
|
||||
;
|
||||
|
|
@ -2588,8 +2599,7 @@ AstVar* V3ParseGrammar::createVariable(FileLine* fileline, string name, AstRange
|
|||
}
|
||||
AstVarType type = GRAMMARP->m_varIO;
|
||||
if (!dtypep) { // Created implicitly
|
||||
// We also make them for standalone ports, which is a bit silly, but we'll clean up later
|
||||
dtypep = new AstBasicDType(fileline, LOGIC);
|
||||
dtypep = new AstBasicDType(fileline, LOGIC_IMPLICIT);
|
||||
} else { // May make new variables with same type, so clone
|
||||
dtypep = dtypep->cloneTree(false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,83 +0,0 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2009 by Wilson Snyder.
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
input clk;
|
||||
|
||||
|
||||
integer cyc=0;
|
||||
// Test that we can actually use the logic keyword without an error popping up
|
||||
//reg [63:0] crc;
|
||||
logic [63:0] crc;
|
||||
reg [63:0] sum;
|
||||
|
||||
|
||||
// Take CRC data and apply to testblock inputs
|
||||
wire [31:0] in = crc[31:0];
|
||||
|
||||
/*AUTOWIRE*/
|
||||
// Beginning of automatic wires (for undeclared instantiated-module outputs)
|
||||
wire [31:0] out; // From test of Test.v
|
||||
// End of automatics
|
||||
|
||||
Test test (/*AUTOINST*/
|
||||
// Outputs
|
||||
.out (out[31:0]),
|
||||
// Inputs
|
||||
.clk (clk),
|
||||
.in (in[31:0]));
|
||||
|
||||
// Aggregate outputs into a single result vector
|
||||
wire [63:0] result = {32'h0, out};
|
||||
|
||||
// Test loop
|
||||
always @ (posedge clk) begin
|
||||
`ifdef TEST_VERBOSE
|
||||
$write("[%0t] cyc==%0d crc=%x result=%x\n",$time, cyc, crc, result);
|
||||
`endif
|
||||
cyc <= cyc + 1;
|
||||
crc <= {crc[62:0], crc[63]^crc[2]^crc[0]};
|
||||
sum <= result ^ {sum[62:0],sum[63]^sum[2]^sum[0]};
|
||||
if (cyc==0) begin
|
||||
// Setup
|
||||
crc <= 64'h5aef0c8d_d70a4497;
|
||||
sum <= 64'h0;
|
||||
end
|
||||
else if (cyc<10) begin
|
||||
sum <= 64'h0;
|
||||
end
|
||||
else if (cyc<90) begin
|
||||
end
|
||||
else if (cyc==99) begin
|
||||
$write("[%0t] cyc==%0d crc=%x sum=%x\n",$time, cyc, crc, sum);
|
||||
if (crc !== 64'hc77bb9b3784ea091) $stop;
|
||||
// What checksum will we end up with (above print should match)
|
||||
`define EXPECTED_SUM 64'h4afe43fb79d7b71e
|
||||
if (sum !== `EXPECTED_SUM) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
module Test (/*AUTOARG*/
|
||||
// Outputs
|
||||
out,
|
||||
// Inputs
|
||||
clk, in
|
||||
);
|
||||
|
||||
input clk;
|
||||
input [31:0] in;
|
||||
output reg [31:0] out;
|
||||
|
||||
always @(posedge clk) begin
|
||||
out <= in;
|
||||
end
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2009 by Wilson Snyder.
|
||||
|
||||
module t (/*AUTOARG*/);
|
||||
|
||||
// IEEE: integer_atom_type
|
||||
byte d_byte;
|
||||
shortint d_shortint;
|
||||
int d_int;
|
||||
longint d_longint;
|
||||
integer d_integer;
|
||||
//UNSUP time d_time;
|
||||
|
||||
// IEEE: integer_atom_type
|
||||
bit d_bit;
|
||||
logic d_logic;
|
||||
reg d_reg;
|
||||
|
||||
bit [1:0] d_bit2;
|
||||
logic [1:0] d_logic2;
|
||||
reg [1:0] d_reg2;
|
||||
|
||||
// IEEE: non_integer_type
|
||||
//UNSUP shortreal d_shortreal;
|
||||
//UNSUP real d_real;
|
||||
//UNSUP realtime d_realtime;
|
||||
|
||||
// verilator lint_off WIDTH
|
||||
localparam p_implicit = {96{1'b1}};
|
||||
localparam [89:0] p_explicit = {96{1'b1}};
|
||||
localparam byte p_byte = {96{1'b1}};
|
||||
localparam shortint p_shortint = {96{1'b1}};
|
||||
localparam int p_int = {96{1'b1}};
|
||||
localparam longint p_longint = {96{1'b1}};
|
||||
localparam integer p_integer = {96{1'b1}};
|
||||
localparam reg p_reg = {96{1'b1}};
|
||||
localparam bit p_bit = {96{1'b1}};
|
||||
localparam logic p_logic = {96{1'b1}};
|
||||
localparam reg [1:0] p_reg2 = {96{1'b1}};
|
||||
localparam bit [1:0] p_bit2 = {96{1'b1}};
|
||||
localparam logic [1:0] p_logic2= {96{1'b1}};
|
||||
// verilator lint_on WIDTH
|
||||
|
||||
// verilator lint_off WIDTH
|
||||
function f_implicit; f_implicit = {96{1'b1}}; endfunction
|
||||
function [89:0] f_explicit; f_explicit = {96{1'b1}}; endfunction
|
||||
function byte f_byte; f_byte = {96{1'b1}}; endfunction
|
||||
function shortint f_shortint; f_shortint = {96{1'b1}}; endfunction
|
||||
function int f_int; f_int = {96{1'b1}}; endfunction
|
||||
function longint f_longint; f_longint = {96{1'b1}}; endfunction
|
||||
function integer f_integer; f_integer = {96{1'b1}}; endfunction
|
||||
function reg f_reg; f_reg = {96{1'b1}}; endfunction
|
||||
function bit f_bit; f_bit = {96{1'b1}}; endfunction
|
||||
function logic f_logic; f_logic = {96{1'b1}}; endfunction
|
||||
function reg [1:0] f_reg2; f_reg2 = {96{1'b1}}; endfunction
|
||||
function bit [1:0] f_bit2; f_bit2 = {96{1'b1}}; endfunction
|
||||
function logic [1:0] f_logic2; f_logic2 = {96{1'b1}}; endfunction
|
||||
// verilator lint_on WIDTH
|
||||
|
||||
`define CHECK_ALL(name,bits,issigned,twostate) \
|
||||
name = {96{1'b1}}; \
|
||||
if (name !== {(bits){1'b1}}) begin $display("%%Error: Bad size for %s",`"name`"); $stop; end \
|
||||
if (issigned ? (name > 0) : (name < 0)) begin $display("%%Error: Bad signed for %s",`"name`"); $stop; end \
|
||||
name = {96{1'bx}}; \
|
||||
|
||||
//Everything is twostate in Verilator
|
||||
// if (name !== {(bits){twostate ? 1'b0 : 1'bx}}) begin $display("%%Error: Bad twostate for %s",`"name`"); $stop; end \
|
||||
|
||||
initial begin
|
||||
// verilator lint_off WIDTH
|
||||
// verilator lint_off UNSIGNED
|
||||
// name b sign twost
|
||||
`CHECK_ALL(d_byte ,8 ,1'b1,1'b1);
|
||||
`CHECK_ALL(d_shortint ,16,1'b1,1'b1);
|
||||
`CHECK_ALL(d_int ,32,1'b1,1'b1);
|
||||
`CHECK_ALL(d_longint ,64,1'b1,1'b1);
|
||||
`CHECK_ALL(d_integer ,32,1'b1,1'b0);
|
||||
`CHECK_ALL(d_bit ,1 ,1'b0,1'b1);
|
||||
`CHECK_ALL(d_logic ,1 ,1'b0,1'b0);
|
||||
`CHECK_ALL(d_reg ,1 ,1'b0,1'b0);
|
||||
`CHECK_ALL(d_bit2 ,2 ,1'b0,1'b1);
|
||||
`CHECK_ALL(d_logic2 ,2 ,1'b0,1'b0);
|
||||
`CHECK_ALL(d_reg2 ,2 ,1'b0,1'b0);
|
||||
// verilator lint_on WIDTH
|
||||
// verilator lint_on UNSIGNED
|
||||
|
||||
`define CHECK_P(name,bits) \
|
||||
if (name !== {(bits){1'b1}}) begin $display("%%Error: Bad size for %s",`"name`"); $stop; end \
|
||||
|
||||
`CHECK_P(p_implicit ,96);
|
||||
`CHECK_P(p_explicit ,90);
|
||||
`CHECK_P(p_byte ,8 );
|
||||
`CHECK_P(p_shortint ,16);
|
||||
`CHECK_P(p_int ,32);
|
||||
`CHECK_P(p_longint ,64);
|
||||
`CHECK_P(p_integer ,32);
|
||||
`CHECK_P(p_bit ,1 );
|
||||
`CHECK_P(p_logic ,1 );
|
||||
`CHECK_P(p_reg ,1 );
|
||||
`CHECK_P(p_bit2 ,2 );
|
||||
`CHECK_P(p_logic2 ,2 );
|
||||
`CHECK_P(p_reg2 ,2 );
|
||||
|
||||
`define CHECK_F(name,bits) \
|
||||
if (name() !== {(bits){1'b1}}) begin $display("%%Error: Bad size for %s",`"name`"); $stop; end \
|
||||
|
||||
`CHECK_F(f_implicit ,1 ); // Note 1 bit, not 96
|
||||
`CHECK_F(f_explicit ,90);
|
||||
`CHECK_F(f_byte ,8 );
|
||||
`CHECK_F(f_shortint ,16);
|
||||
`CHECK_F(f_int ,32);
|
||||
`CHECK_F(f_longint ,64);
|
||||
`CHECK_F(f_integer ,32);
|
||||
`CHECK_F(f_bit ,1 );
|
||||
`CHECK_F(f_logic ,1 );
|
||||
`CHECK_F(f_reg ,1 );
|
||||
`CHECK_F(f_bit2 ,2 );
|
||||
`CHECK_F(f_logic2 ,2 );
|
||||
`CHECK_F(f_reg2 ,2 );
|
||||
|
||||
// For unpacked types we don't want width warnings for unsized numbers that fit
|
||||
d_byte = 2;
|
||||
d_shortint= 2;
|
||||
d_int = 2;
|
||||
d_longint = 2;
|
||||
d_integer = 2;
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
Loading…
Reference in New Issue