Internals: Refactor input/output to new class in prep for ref support.

This commit is contained in:
Wilson Snyder
2018-10-27 17:29:00 -04:00
parent dc26815b1c
commit b8098098d8
34 changed files with 456 additions and 391 deletions
+46 -35
View File
@@ -332,9 +332,9 @@ private:
AstVarScope* createInputVar(AstCFunc* funcp, const string& name, AstBasicDTypeKwd kwd) {
AstVar* newvarp = new AstVar(funcp->fileline(), AstVarType::BLOCKTEMP, name,
funcp->findBasicDType(kwd));
newvarp->funcLocal(true);
newvarp->combineType(AstVarType::INPUT);
funcp->addArgsp(newvarp);
newvarp->funcLocal(true);
newvarp->direction(VDirection::INPUT);
funcp->addArgsp(newvarp);
AstVarScope* newvscp = new AstVarScope(funcp->fileline(), m_scopep, newvarp);
m_scopep->addVarp(newvscp);
return newvscp;
@@ -378,10 +378,13 @@ private:
pinp->unlinkFrBack(); // Relinked to assignment below
argp->unlinkFrBack()->deleteTree(); // Args no longer needed
//
if ((portp->isInout() || portp->isOutput()) && VN_IS(pinp, Const)) {
pinp->v3error("Function/task output connected to constant instead of variable: "+portp->prettyName());
}
else if (portp->isInout()) {
if (portp->isWritable() && VN_IS(pinp, Const)) {
pinp->v3error("Function/task "
+portp->direction().prettyName() // e.g. "output"
+" connected to constant instead of variable: "
+portp->prettyName());
}
else if (portp->isInoutish()) {
// Correct lvalue; see comments below
V3LinkLValue::linkLValueSet(pinp);
@@ -393,9 +396,9 @@ private:
} else {
pinp->v3warn(E_TASKNSVAR,"Unsupported: Function/task input argument is not simple variable");
}
}
else if (portp->isOutput()) {
// Make output variables
}
else if (portp->isWritable()) {
// Make output variables
// Correct lvalue; we didn't know when we linked
// This is slightly scary; are we sure no decisions were made
// before here based on this not being a lvalue?
@@ -412,9 +415,9 @@ private:
assp->fileline()->modifyWarnOff(V3ErrorCode::BLKSEQ, true); // Ok if in <= block
// Put assignment BEHIND of all other statements
beginp->addNext(assp);
}
else if (portp->isInput()) {
// Make input variable
}
else if (portp->isNonOutput()) {
// Make input variable
AstVarScope* inVscp = createVarScope(portp, namePrefix+"__"+portp->shortName());
portp->user2p(inVscp);
AstAssign* assp = new AstAssign(pinp->fileline(),
@@ -483,10 +486,13 @@ private:
} else {
UINFO(9, " Port "<<portp<<endl);
UINFO(9, " pin "<<pinp<<endl);
if ((portp->isInout() || portp->isOutput()) && VN_IS(pinp, Const)) {
pinp->v3error("Function/task output connected to constant instead of variable: "+portp->prettyName());
}
else if (portp->isInout()) {
if (portp->isWritable() && VN_IS(pinp, Const)) {
pinp->v3error("Function/task "
+portp->direction().prettyName() // e.g. "output"
+" connected to constant instead of variable: "
+portp->prettyName());
}
else if (portp->isInoutish()) {
// Correct lvalue; see comments below
V3LinkLValue::linkLValueSet(pinp);
@@ -495,9 +501,9 @@ private:
} else {
pinp->v3warn(E_TASKNSVAR,"Unsupported: Function/task input argument is not simple variable");
}
}
else if (portp->isOutput()) {
// Make output variables
}
else if (portp->isWritable()) {
// Make output variables
// Correct lvalue; we didn't know when we linked
// This is slightly scary; are we sure no decisions were made
// before here based on this not being a lvalue?
@@ -718,12 +724,17 @@ private:
// No createDpiTemp; we make a real internal variable instead
// SAME CODE BELOW
args+= ", ";
if (args != "") { argnodesp = argnodesp->addNext(new AstText(portp->fileline(), args, true)); args=""; }
if (args != "") {
argnodesp = argnodesp->addNext(
new AstText(portp->fileline(), args, true));
args="";
}
AstVarScope* outvscp = createFuncVar(dpip, portp->name()+"__Vcvt", portp);
AstVarRef* refp = new AstVarRef(portp->fileline(), outvscp, portp->isOutput());
argnodesp = argnodesp->addNextNull(refp);
AstVarRef* refp = new AstVarRef(portp->fileline(), outvscp,
portp->isWritable());
argnodesp = argnodesp->addNextNull(refp);
if (portp->isInput()) {
if (portp->isNonOutput()) {
dpip->addStmtsp(createAssignDpiToInternal(outvscp, portp->name(), false));
}
}
@@ -736,9 +747,9 @@ private:
args+= ", ";
if (args != "") { argnodesp = argnodesp->addNext(new AstText(portp->fileline(), args, true)); args=""; }
AstVarScope* outvscp = createFuncVar(dpip, portp->name()+"__Vcvt", portp);
AstVarRef* refp = new AstVarRef(portp->fileline(), outvscp, portp->isOutput());
argnodesp = argnodesp->addNextNull(refp);
}
AstVarRef* refp = new AstVarRef(portp->fileline(), outvscp, portp->isWritable());
argnodesp = argnodesp->addNextNull(refp);
}
{// Call the user function
// Add the variables referenced as VarRef's so that lifetime analysis
@@ -755,11 +766,11 @@ private:
// Convert output/inout arguments back to internal type
for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp=stmtp->nextp()) {
if (AstVar* portp = VN_CAST(stmtp, Var)) {
if (portp->isIO() && portp->isOutput() && !portp->isFuncReturn()) {
dpip->addStmtsp(createAssignInternalToDpi(portp,false,true,"__Vcvt",""));
}
}
}
if (portp->isIO() && portp->isWritable() && !portp->isFuncReturn()) {
dpip->addStmtsp(createAssignInternalToDpi(portp,false,true,"__Vcvt",""));
}
}
}
if (rtnvarp) {
dpip->addStmtsp(createDpiTemp(rtnvarp,""));
@@ -867,14 +878,14 @@ private:
else {
if (bitvec) {}
else if (logicvec) {}
else if (portp->isOutput()) args += "&";
else if (portp->isWritable()) args += "&";
else if (portp->basicp() && portp->basicp()->keyword().isDpiBitVal()
&& portp->width() != 1) args += "&"; // it's a svBitVecVal (2-32 bits wide)
args += portp->name()+"__Vcvt";
cfuncp->addStmtsp(createDpiTemp(portp,"__Vcvt"));
if (portp->isInput()) {
if (portp->isNonOutput()) {
cfuncp->addStmtsp(createAssignInternalToDpi(portp,false,false,"","__Vcvt"));
}
}
@@ -900,7 +911,7 @@ private:
// Convert output/inout arguments back to internal type
for (AstNode* stmtp = cfuncp->argsp(); stmtp; stmtp=stmtp->nextp()) {
if (AstVar* portp = VN_CAST(stmtp, Var)) {
if (portp->isIO() && (portp->isOutput() || portp->isFuncReturn())
if (portp->isIO() && (portp->isWritable() || portp->isFuncReturn())
&& !portp->isDpiOpenArray()) {
AstVarScope* portvscp = VN_CAST(portp->user2p(), VarScope); // Remembered when we created it earlier
cfuncp->addStmtsp(createAssignDpiToInternal(portvscp,portp->name()+"__Vcvt",true));