Fix inout task arguments
git-svn-id: file://localhost/svn/verilator/trunk/verilator@795 77ca24e4-aefa-0310-84f0-b9a241c72d87
This commit is contained in:
parent
621ef70c31
commit
4f42c25c7c
2
Changes
2
Changes
|
|
@ -5,6 +5,8 @@ indicates the contributor was also the author of the fix; Thanks!
|
||||||
|
|
||||||
* Verilator 3.61*
|
* Verilator 3.61*
|
||||||
|
|
||||||
|
*** Support simple inout task ports. [Eugene Weber]
|
||||||
|
|
||||||
*** Allow overriding Perl, Flex and Bison versions. [by Robert Farrell]
|
*** Allow overriding Perl, Flex and Bison versions. [by Robert Farrell]
|
||||||
|
|
||||||
**** Default make no longer makes the docs; if you edit the documentation
|
**** Default make no longer makes the docs; if you edit the documentation
|
||||||
|
|
|
||||||
|
|
@ -85,7 +85,7 @@ int AstVar::widthTotalBytes() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
string AstVar::verilogKwd() const {
|
string AstVar::verilogKwd() const {
|
||||||
if (isTristate()) {
|
if (isInout()) {
|
||||||
return "inout";
|
return "inout";
|
||||||
} else if (isInput()) {
|
} else if (isInput()) {
|
||||||
return "input";
|
return "input";
|
||||||
|
|
@ -93,6 +93,8 @@ string AstVar::verilogKwd() const {
|
||||||
return "output";
|
return "output";
|
||||||
} else if (isInteger()) {
|
} else if (isInteger()) {
|
||||||
return "integer";
|
return "integer";
|
||||||
|
} else if (isTristate()) {
|
||||||
|
return "tri";
|
||||||
} else if (varType()==AstVarType::WIRE) {
|
} else if (varType()==AstVarType::WIRE) {
|
||||||
return "wire";
|
return "wire";
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -325,9 +327,12 @@ void AstVarRef::dump(ostream& str) {
|
||||||
void AstVar::dump(ostream& str) {
|
void AstVar::dump(ostream& str) {
|
||||||
this->AstNode::dump(str);
|
this->AstNode::dump(str);
|
||||||
if (isSc()) str<<" [SC]";
|
if (isSc()) str<<" [SC]";
|
||||||
if (isInput()) str<<" [I]";
|
if (isPrimaryIO()) str<<(isInout()?" [PIO]":(isInput()?" [PI]":" [PO]"));
|
||||||
if (isPrimaryIO()) str<<(isInput()?" [PI]":" [PO]");
|
else {
|
||||||
if (isOutput()) str<<" [O]";
|
if (isInout()) str<<" [IO]";
|
||||||
|
else if (isInput()) str<<" [I]";
|
||||||
|
else if (isOutput()) str<<" [O]";
|
||||||
|
}
|
||||||
if (isUsedClock()) str<<" [C]";
|
if (isUsedClock()) str<<" [C]";
|
||||||
if (isSigPublic()) str<<" [P]";
|
if (isSigPublic()) str<<" [P]";
|
||||||
if (attrClockEn()) str<<" [aCLKEN]";
|
if (attrClockEn()) str<<" [aCLKEN]";
|
||||||
|
|
|
||||||
|
|
@ -314,10 +314,13 @@ public:
|
||||||
void name(const string& name) { m_name = name; }
|
void name(const string& name) { m_name = name; }
|
||||||
bool isInput() const { return m_input; }
|
bool isInput() const { return m_input; }
|
||||||
bool isOutput() const { return m_output; }
|
bool isOutput() const { return m_output; }
|
||||||
bool isTristate() const { return (m_tristate); }
|
bool isInOnly() const { return m_input && !m_output; }
|
||||||
|
bool isOutOnly() const { return m_output && !m_input; }
|
||||||
|
bool isInout() const { return m_input && m_output; }
|
||||||
|
bool isTristate() const { return m_tristate; }
|
||||||
bool isPrimaryIO() const { return m_primaryIO; }
|
bool isPrimaryIO() const { return m_primaryIO; }
|
||||||
bool isPrimaryIn() const { return isPrimaryIO() && isInput(); }
|
bool isPrimaryIn() const { return isPrimaryIO() && isInput(); }
|
||||||
bool isIO() const { return (m_input||m_output||m_tristate); }
|
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::IMPLICIT
|
||||||
|| varType()==AstVarType::REG || varType()==AstVarType::INTEGER); }
|
|| varType()==AstVarType::REG || varType()==AstVarType::INTEGER); }
|
||||||
bool isTemp() const { return (varType()==AstVarType::BLOCKTEMP || varType()==AstVarType::MODULETEMP
|
bool isTemp() const { return (varType()==AstVarType::BLOCKTEMP || varType()==AstVarType::MODULETEMP
|
||||||
|
|
|
||||||
|
|
@ -702,7 +702,7 @@ void EmitCStmts::emitVarDecl(AstVar* nodep, const string& prefixIfImp) {
|
||||||
if (nodep->attrScClocked() && nodep->isInput()) {
|
if (nodep->attrScClocked() && nodep->isInput()) {
|
||||||
puts("sc_in_clk\t");
|
puts("sc_in_clk\t");
|
||||||
} else {
|
} else {
|
||||||
if (nodep->isTristate()) puts("sc_inout<");
|
if (nodep->isInout()) puts("sc_inout<");
|
||||||
else if (nodep->isInput()) puts("sc_in<");
|
else if (nodep->isInput()) puts("sc_in<");
|
||||||
else if (nodep->isOutput()) puts("sc_out<");
|
else if (nodep->isOutput()) puts("sc_out<");
|
||||||
else nodep->v3fatalSrc("Unknown type");
|
else nodep->v3fatalSrc("Unknown type");
|
||||||
|
|
@ -714,7 +714,7 @@ void EmitCStmts::emitVarDecl(AstVar* nodep, const string& prefixIfImp) {
|
||||||
puts(";\n");
|
puts(";\n");
|
||||||
} else { // C++ signals
|
} else { // C++ signals
|
||||||
ofp()->putAlign(nodep->isStatic(), nodep->widthAlignBytes());
|
ofp()->putAlign(nodep->isStatic(), nodep->widthAlignBytes());
|
||||||
if (nodep->isTristate()) puts("VL_INOUT");
|
if (nodep->isInout()) puts("VL_INOUT");
|
||||||
else if (nodep->isInput()) puts("VL_IN");
|
else if (nodep->isInput()) puts("VL_IN");
|
||||||
else if (nodep->isOutput()) puts("VL_OUT");
|
else if (nodep->isOutput()) puts("VL_OUT");
|
||||||
else nodep->v3fatalSrc("Unknown type");
|
else nodep->v3fatalSrc("Unknown type");
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@ private:
|
||||||
// or ASSIGNW(expr,VARXREF(p)) (if sub's output)
|
// or ASSIGNW(expr,VARXREF(p)) (if sub's output)
|
||||||
UINFO(4," PIN "<<nodep<<endl);
|
UINFO(4," PIN "<<nodep<<endl);
|
||||||
if (debug()>=9) nodep->dumpTree(cout," Pin_oldb: ");
|
if (debug()>=9) nodep->dumpTree(cout," Pin_oldb: ");
|
||||||
if (nodep->modVarp()->isOutput() && nodep->exprp()->castConst())
|
if (nodep->modVarp()->isOutOnly() && nodep->exprp()->castConst())
|
||||||
nodep->v3error("Output pin is assigned to a constant, electrical short");
|
nodep->v3error("Output pin is assigned to a constant, electrical short");
|
||||||
// Use userp on the PIN to indicate we created an assign for this pin
|
// Use userp on the PIN to indicate we created an assign for this pin
|
||||||
if (!nodep->user()) {
|
if (!nodep->user()) {
|
||||||
|
|
@ -90,7 +90,9 @@ private:
|
||||||
AstNode* exprp = nodep->exprp()->cloneTree(false);
|
AstNode* exprp = nodep->exprp()->cloneTree(false);
|
||||||
if (nodep->width() != nodep->modVarp()->width())
|
if (nodep->width() != nodep->modVarp()->width())
|
||||||
nodep->v3fatalSrc("Width mismatch, should have been handled in pinReconnectSimple\n");
|
nodep->v3fatalSrc("Width mismatch, should have been handled in pinReconnectSimple\n");
|
||||||
if (nodep->modVarp()->isOutput()) {
|
if (nodep->modVarp()->isInout()) {
|
||||||
|
nodep->v3fatalSrc("Unsupported: Verilator is a 2-state simulator");
|
||||||
|
} else if (nodep->modVarp()->isOutput()) {
|
||||||
AstNode* rhsp = new AstVarXRef (exprp->fileline(), nodep->modVarp(), m_cellp->name(), false);
|
AstNode* rhsp = new AstVarXRef (exprp->fileline(), nodep->modVarp(), m_cellp->name(), false);
|
||||||
rhsp->widthSignedFrom(nodep);
|
rhsp->widthSignedFrom(nodep);
|
||||||
AstAssignW* assp = new AstAssignW (exprp->fileline(), exprp, rhsp);
|
AstAssignW* assp = new AstAssignW (exprp->fileline(), exprp, rhsp);
|
||||||
|
|
@ -236,12 +238,14 @@ void V3Inst::pinReconnectSimple(AstPin* pinp, AstCell* cellp, AstModule* modp) {
|
||||||
} else {
|
} else {
|
||||||
// Make a new temp wire
|
// Make a new temp wire
|
||||||
//if (1||debug()>=9) { pinp->dumpTree(cout,"in_pin:"); }
|
//if (1||debug()>=9) { pinp->dumpTree(cout,"in_pin:"); }
|
||||||
AstAssignW* assignp;
|
AstAssignW* assignp = NULL;
|
||||||
AstNode* pinexprp = pinp->exprp()->unlinkFrBack();
|
AstNode* pinexprp = pinp->exprp()->unlinkFrBack();
|
||||||
string newvarname = "__Vcellinp__"+cellp->name()+"__"+pinp->name();
|
string newvarname = "__Vcellinp__"+cellp->name()+"__"+pinp->name();
|
||||||
AstVar* newvarp = new AstVar (pinVarp->fileline(), AstVarType::MODULETEMP, newvarname, pinVarp);
|
AstVar* newvarp = new AstVar (pinVarp->fileline(), AstVarType::MODULETEMP, newvarname, pinVarp);
|
||||||
modp->addStmtp(newvarp);
|
modp->addStmtp(newvarp);
|
||||||
if (pinVarp->isOutput()) {
|
if (pinVarp->isInout()) {
|
||||||
|
pinVarp->v3fatalSrc("Unsupported: Inout connections to pins must be direct one-to-one connection (without any expression)");
|
||||||
|
} else if (pinVarp->isOutput()) {
|
||||||
// See also V3Inst
|
// See also V3Inst
|
||||||
AstNode* rhsp = new AstVarRef(pinp->fileline(), newvarp, false);
|
AstNode* rhsp = new AstVarRef(pinp->fileline(), newvarp, false);
|
||||||
if (pinp->width() > rhsp->width()) {
|
if (pinp->width() > rhsp->width()) {
|
||||||
|
|
@ -265,7 +269,7 @@ void V3Inst::pinReconnectSimple(AstPin* pinp, AstCell* cellp, AstModule* modp) {
|
||||||
pinp->exprp(new AstVarRef (pinexprp->fileline(), newvarp, false));
|
pinp->exprp(new AstVarRef (pinexprp->fileline(), newvarp, false));
|
||||||
}
|
}
|
||||||
pinp->widthSignedFrom(pinp->exprp());
|
pinp->widthSignedFrom(pinp->exprp());
|
||||||
modp->addStmtp(assignp);
|
if (assignp) modp->addStmtp(assignp);
|
||||||
//if (1||debug()) { pinp->dumpTree(cout," out:"); }
|
//if (1||debug()) { pinp->dumpTree(cout," out:"); }
|
||||||
//if (1||debug()) { assignp->dumpTree(cout," aout:"); }
|
//if (1||debug()) { assignp->dumpTree(cout," aout:"); }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -140,7 +140,7 @@ void V3LinkLevel::wrapTop(AstNetlist* netlistp) {
|
||||||
AstVar* varp = oldvarp->cloneTree(false)->castVar();
|
AstVar* varp = oldvarp->cloneTree(false)->castVar();
|
||||||
newmodp->addStmtp(varp);
|
newmodp->addStmtp(varp);
|
||||||
varp->sigPublic(true); // User needs to be able to get to it...
|
varp->sigPublic(true); // User needs to be able to get to it...
|
||||||
if (oldvarp->isInput() || oldvarp->isOutput()) {
|
if (oldvarp->isIO()) {
|
||||||
oldvarp->primaryIO(true);
|
oldvarp->primaryIO(true);
|
||||||
varp->primaryIO(true);
|
varp->primaryIO(true);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,7 @@ private:
|
||||||
// VarRef: Resolve its reference
|
// VarRef: Resolve its reference
|
||||||
if (nodep->varp()) {
|
if (nodep->varp()) {
|
||||||
nodep->varp()->usedParam(true);
|
nodep->varp()->usedParam(true);
|
||||||
if (nodep->lvalue() && nodep->varp()->isInput()) {
|
if (nodep->lvalue() && nodep->varp()->isInOnly()) {
|
||||||
nodep->v3error("Assigning to input variable: "<<nodep->prettyName());
|
nodep->v3error("Assigning to input variable: "<<nodep->prettyName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -227,8 +227,14 @@ private:
|
||||||
nextpinp = pinp->nextp();
|
nextpinp = pinp->nextp();
|
||||||
pinp->unlinkFrBack(); // Relinked to assignment below
|
pinp->unlinkFrBack(); // Relinked to assignment below
|
||||||
//
|
//
|
||||||
if (portp->isTristate()) {
|
if (portp->isInout()) {
|
||||||
refp->v3error("Unsupported: Inouts in functions/tasks");
|
if (AstVarRef* varrefp = pinp->castVarRef()) {
|
||||||
|
// Connect to this exact variable
|
||||||
|
AstVarScope* localVscp = varrefp->varScopep(); if (!localVscp) varrefp->v3fatalSrc("Null var scope");
|
||||||
|
portp->user2p(localVscp);
|
||||||
|
} else {
|
||||||
|
pinp->v3error("Unsupported: Function/task input argument is not simple variable");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (portp->isOutput() && outvscp) {
|
else if (portp->isOutput() && outvscp) {
|
||||||
refp->v3error("Outputs not allowed in function declarations");
|
refp->v3error("Outputs not allowed in function declarations");
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// $Id:$
|
// $Id$
|
||||||
// DESCRIPTION: Verilator: Verilog Test module
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
//
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
|
@ -22,6 +22,12 @@ module t;
|
||||||
if (global != 32'h17) $stop;
|
if (global != 32'h17) $stop;
|
||||||
nop(32'h11);
|
nop(32'h11);
|
||||||
|
|
||||||
|
global = 32'h00000001;
|
||||||
|
flipbit(global,5'd8);
|
||||||
|
flipbit(global,5'd16);
|
||||||
|
flipbit(global,5'd24);
|
||||||
|
if (global !== 32'h01010101) $stop;
|
||||||
|
|
||||||
$write("*-* All Finished *-*\n");
|
$write("*-* All Finished *-*\n");
|
||||||
$finish;
|
$finish;
|
||||||
end
|
end
|
||||||
|
|
@ -70,4 +76,10 @@ module t;
|
||||||
end
|
end
|
||||||
endtask
|
endtask
|
||||||
|
|
||||||
|
task flipbit;
|
||||||
|
inout [31:0] vector;
|
||||||
|
input [4:0] bitnum;
|
||||||
|
vector[bitnum] = vector[bitnum] ^ 1'b1;
|
||||||
|
endtask
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue