Split V3LinkResolve into V3LinkLValue, and remove lvalue determination from bison code

git-svn-id: file://localhost/svn/verilator/trunk/verilator@858 77ca24e4-aefa-0310-84f0-b9a241c72d87
This commit is contained in:
Wilson Snyder 2006-12-21 14:35:19 +00:00
parent 26bab12257
commit dc6a164e01
7 changed files with 252 additions and 96 deletions

View File

@ -46,6 +46,9 @@ if (! GetOptions (
defined $Opt_A or die "%Error: No old diff filename\n";
defined $Opt_B or die "%Error: No new diff filename\n";
-e $Opt_A or die "%Error: No old diff filename found: $Opt_A\n";
-e $Opt_B or die "%Error: No new diff filename found: $Opt_B\n";
if (-d $Opt_A && -d $Opt_B) {
diff_dir ($Opt_A, $Opt_B);
} elsif (-f $Opt_A && -f $Opt_B) {

View File

@ -142,6 +142,7 @@ RAW_OBJS = \
V3LinkCells.o \
V3LinkDot.o \
V3LinkLevel.o \
V3LinkLValue.o \
V3LinkResolve.o \
V3Localize.o \
V3Name.o \

174
src/V3LinkLValue.cpp Normal file
View File

@ -0,0 +1,174 @@
// $Id$
//*************************************************************************
// DESCRIPTION: Verilator: LValue module/signal name references
//
// Code available from: http://www.veripool.com/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// General Public License or the Perl Artistic License.
//
// Verilator is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//*************************************************************************
// LinkLValue TRANSFORMATIONS:
// Top-down traversal
// Set lvalue() attributes on appropriate VARREFs.
//*************************************************************************
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
#include <map>
#include <algorithm>
#include <vector>
#include "V3Global.h"
#include "V3LinkLValue.h"
#include "V3Ast.h"
//######################################################################
// Link state, as a visitor of each AstNode
class LinkLValueVisitor : public AstNVisitor {
private:
// NODE STATE
// STATE
bool m_setRefLvalue; // Set VarRefs to lvalues for pin assignments
//int debug() { return 9; }
// METHODS
// VISITs
// Result handing
virtual void visit(AstNodeVarRef* nodep, AstNUser*) {
// VarRef: LValue its reference
if (m_setRefLvalue) {
nodep->lvalue(true);
}
if (nodep->varp()) {
if (nodep->lvalue() && nodep->varp()->isInOnly()) {
nodep->v3error("Assigning to input variable: "<<nodep->prettyName());
}
}
nodep->iterateChildren(*this);
}
// Nodes that start propagating down lvalues
virtual void visit(AstPin* nodep, AstNUser*) {
if (nodep->modVarp() && nodep->modVarp()->isOutput()) {
// When the varref's were created, we didn't know the I/O state
// Now that we do, and it's from a output, we know it's a lvalue
m_setRefLvalue = true;
nodep->iterateChildren(*this);
m_setRefLvalue = false;
} else {
nodep->iterateChildren(*this);
}
}
virtual void visit(AstNodeAssign* nodep, AstNUser*) {
bool last_setRefLvalue = m_setRefLvalue;
{
m_setRefLvalue = true;
nodep->lhsp()->iterateAndNext(*this);
m_setRefLvalue = false;
nodep->rhsp()->iterateAndNext(*this);
}
m_setRefLvalue = last_setRefLvalue;
}
virtual void visit(AstFOpen* nodep, AstNUser*) {
bool last_setRefLvalue = m_setRefLvalue;
{
m_setRefLvalue = true;
nodep->filep()->iterateAndNext(*this);
m_setRefLvalue = false;
nodep->filenamep()->iterateAndNext(*this);
nodep->modep()->iterateAndNext(*this);
}
m_setRefLvalue = last_setRefLvalue;
}
virtual void visit(AstFClose* nodep, AstNUser*) {
bool last_setRefLvalue = m_setRefLvalue;
{
m_setRefLvalue = true;
nodep->filep()->iterateAndNext(*this);
}
m_setRefLvalue = last_setRefLvalue;
}
virtual void visit(AstReadMem* nodep, AstNUser*) {
bool last_setRefLvalue = m_setRefLvalue;
{
m_setRefLvalue = true;
nodep->memp()->iterateAndNext(*this);
m_setRefLvalue = false;
nodep->filenamep()->iterateAndNext(*this);
nodep->lsbp()->iterateAndNext(*this);
nodep->msbp()->iterateAndNext(*this);
}
m_setRefLvalue = last_setRefLvalue;
}
// Nodes that change LValue state
virtual void visit(AstSel* nodep, AstNUser*) {
bool last_setRefLvalue = m_setRefLvalue;
{
nodep->lhsp()->iterateAndNext(*this);
// Only set lvalues on the from
m_setRefLvalue = false;
nodep->rhsp()->iterateAndNext(*this);
nodep->thsp()->iterateAndNext(*this);
}
m_setRefLvalue = last_setRefLvalue;
}
virtual void visit(AstNodeSel* nodep, AstNUser*) {
bool last_setRefLvalue = m_setRefLvalue;
{ // Only set lvalues on the from
nodep->lhsp()->iterateAndNext(*this);
m_setRefLvalue = false;
nodep->rhsp()->iterateAndNext(*this);
}
m_setRefLvalue = last_setRefLvalue;
}
virtual void visit(AstNodePreSel* nodep, AstNUser*) {
bool last_setRefLvalue = m_setRefLvalue;
{ // Only set lvalues on the from
nodep->lhsp()->iterateAndNext(*this);
m_setRefLvalue = false;
nodep->rhsp()->iterateAndNext(*this);
nodep->thsp()->iterateAndNext(*this);
}
m_setRefLvalue = last_setRefLvalue;
}
virtual void visit(AstNode* nodep, AstNUser*) {
// Default: Just iterate
nodep->iterateChildren(*this);
}
public:
// CONSTUCTORS
LinkLValueVisitor(AstNetlist* rootp) {
m_setRefLvalue = false;
rootp->accept(*this);
}
virtual ~LinkLValueVisitor() {}
};
//######################################################################
// Link class functions
void V3LinkLValue::linkLValue(AstNetlist* rootp) {
UINFO(4,__FUNCTION__<<": "<<endl);
LinkLValueVisitor visitor(rootp);
}

36
src/V3LinkLValue.h Normal file
View File

@ -0,0 +1,36 @@
// $Id$ //-*- C++ -*-
//*************************************************************************
// DESCRIPTION: Verilator: Link modules/signals together
//
// Code available from: http://www.veripool.com/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// General Public License or the Perl Artistic License.
//
// Verilator is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//*************************************************************************
#ifndef _V3LINKLVALUE_H_
#define _V3LINKLVALUE_H_ 1
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3Ast.h"
//============================================================================
class V3LinkLValue {
public:
static void linkLValue(AstNetlist* nodep);
};
#endif // Guard

View File

@ -54,7 +54,6 @@ private:
// Below state needs to be preserved between each module call.
AstModule* m_modp; // Current module
AstNodeFTask* m_ftaskp; // Function or task we're inside
bool m_setRefLvalue; // Set VarRefs to lvalues for pin assignments
//int debug() { return 9; }
@ -86,12 +85,6 @@ private:
// VarRef: Resolve its reference
if (nodep->varp()) {
nodep->varp()->usedParam(true);
if (nodep->lvalue() && nodep->varp()->isInOnly()) {
nodep->v3error("Assigning to input variable: "<<nodep->prettyName());
}
}
if (m_setRefLvalue) {
nodep->lvalue(true);
}
nodep->iterateChildren(*this);
}
@ -104,46 +97,8 @@ private:
m_ftaskp = NULL;
}
virtual void visit(AstPin* nodep, AstNUser*) {
if (nodep->modVarp() && nodep->modVarp()->isOutput()) {
// When the varref's were created, we didn't know the I/O state
// Now that we do, and it's from a output, we know it's a lvalue
m_setRefLvalue = true;
nodep->iterateChildren(*this);
m_setRefLvalue = false;
} else {
nodep->iterateChildren(*this);
}
}
virtual void visit(AstSel* nodep, AstNUser*) {
nodep->lhsp()->iterateAndNext(*this);
{ // Only set lvalues on the from
bool last_setRefLvalue = m_setRefLvalue;
m_setRefLvalue = false;
nodep->rhsp()->iterateAndNext(*this);
nodep->thsp()->iterateAndNext(*this);
m_setRefLvalue = last_setRefLvalue;
}
}
virtual void visit(AstArraySel* nodep, AstNUser*) {
nodep->lhsp()->iterateAndNext(*this);
{ // Only set lvalues on the from
bool last_setRefLvalue = m_setRefLvalue;
m_setRefLvalue = false;
nodep->rhsp()->iterateAndNext(*this);
m_setRefLvalue = last_setRefLvalue;
}
}
void iterateSelTriop(AstNodePreSel* nodep) {
nodep->lhsp()->iterateAndNext(*this);
{ // Only set lvalues on the from
bool last_setRefLvalue = m_setRefLvalue;
m_setRefLvalue = false;
nodep->rhsp()->iterateAndNext(*this);
nodep->thsp()->iterateAndNext(*this);
m_setRefLvalue = last_setRefLvalue;
}
nodep->iterateChildren(*this);
}
AstNode* newSubAttrOf(AstNode* underp, AstNode* fromp, AstAttrType attrType) {
@ -362,7 +317,6 @@ public:
LinkResolveVisitor(AstNetlist* rootp) {
m_ftaskp = NULL;
m_modp = NULL;
m_setRefLvalue = false;
//
rootp->accept(*this);
}

View File

@ -58,6 +58,7 @@
#include "V3LinkCells.h"
#include "V3LinkDot.h"
#include "V3LinkLevel.h"
#include "V3LinkLValue.h"
#include "V3LinkResolve.h"
#include "V3Localize.h"
#include "V3Name.h"
@ -110,8 +111,10 @@ void process () {
V3Link::link(v3Global.rootp());
// Cross-link dotted hierarchical references
V3LinkDot::linkDotPrearrayed(v3Global.rootp());
// Correct state we couldn't know at parse time, repair SEL's, set lvalue's
// Correct state we couldn't know at parse time, repair SEL's
V3LinkResolve::linkResolve(v3Global.rootp());
// Set Lvalue's in variable refs
V3LinkLValue::linkLValue(v3Global.rootp());
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("link.tree"));
V3Error::abortIfErrors();

View File

@ -248,13 +248,11 @@ class AstSenTree;
%type<strp> pathDotted
%type<varrefp> idVarRef
%type<varnodep> idVarXRef
%type<varrefp> lhIdVarRef
%type<varnodep> lhIdVarXRef
%type<taskrefp> taskRef
%type<funcrefp> funcRef
%type<nodep> idRanged lhIdRanged
%type<nodep> idArrayed lhIdArrayed
%type<nodep> strAsInt strAsText lhConcIdList
%type<nodep> idRanged
%type<nodep> idArrayed
%type<nodep> strAsInt strAsText concIdList
%type<nodep> taskDecl
%type<nodep> varDeclList funcDecl funcVarList funcVar
%type<rangep> funcRange
@ -460,7 +458,7 @@ genItem: modOrGenItem { $$ = $1; }
| yCASE '(' expr ')' genCaseList yENDCASE { $$ = new AstGenCase($1,$3,$5); }
| yIF expr genItemBlock %prec yLOWER_THAN_ELSE { $$ = new AstGenIf($1,$2,$3,NULL); }
| yIF expr genItemBlock yELSE genItemBlock { $$ = new AstGenIf($1,$2,$3,$5); }
| yFOR '(' lhIdVarRef '=' expr ';' expr ';' lhIdVarRef '=' expr ')' genItemBlock
| yFOR '(' idVarRef '=' expr ';' expr ';' idVarRef '=' expr ')' genItemBlock
{ $$ = new AstGenFor($1, new AstAssign($4,$3,$5)
,$7, new AstAssign($10,$9,$11)
,$13);}
@ -485,8 +483,8 @@ assignList: assignOne { $$ = $1; }
| assignList ',' assignOne { $$ = $1->addNext($3); }
;
assignOne: lhIdRanged '=' expr { $$ = new AstAssignW($2,$1,$3); }
| '{' lhConcIdList '}' '=' expr { $$ = new AstAssignW($1,$2,$5); }
assignOne: idRanged '=' expr { $$ = new AstAssignW($2,$1,$3); }
| '{' concIdList '}' '=' expr { $$ = new AstAssignW($1,$2,$5); }
;
delayE: /* empty */
@ -660,12 +658,12 @@ stmtList: stmtBlock { $$ = $1; }
;
stmt: ';' { $$ = NULL; }
| lhIdRanged yLTE delayE expr ';' { $$ = new AstAssignDly($2,$1,$4); }
| lhIdRanged '=' delayE expr ';' { $$ = new AstAssign($2,$1,$4); }
| lhIdRanged '=' yD_FOPEN '(' expr ',' expr ')' ';' { $$ = new AstFOpen($3,$1,$5,$7); }
| yASSIGN lhIdRanged '=' delayE expr ';' { $$ = new AstAssign($1,$2,$5); }
| '{' lhConcIdList '}' yLTE delayE expr ';' { $$ = new AstAssignDly($4,$2,$6); }
| '{' lhConcIdList '}' '=' delayE expr ';' { $$ = new AstAssign($4,$2,$6); }
| idRanged yLTE delayE expr ';' { $$ = new AstAssignDly($2,$1,$4); }
| idRanged '=' delayE expr ';' { $$ = new AstAssign($2,$1,$4); }
| idRanged '=' yD_FOPEN '(' expr ',' expr ')' ';' { $$ = new AstFOpen($3,$1,$5,$7); }
| yASSIGN idRanged '=' delayE expr ';' { $$ = new AstAssign($1,$2,$5); }
| '{' concIdList '}' yLTE delayE expr ';' { $$ = new AstAssignDly($4,$2,$6); }
| '{' concIdList '}' '=' delayE expr ';' { $$ = new AstAssign($4,$2,$6); }
| yD_C '(' cStrList ')' ';' { $$ = (v3Global.opt.ignc() ? NULL : new AstUCStmt($1,$3)); }
| yD_FCLOSE '(' idVarXRef ')' ';' { $$ = new AstFClose($1, $3); }
| yD_FINISH ';' { $$ = new AstFinish($1); }
@ -683,18 +681,18 @@ stmt: ';' { $$ = NULL; }
| yD_FDISPLAY '(' idVarXRef ',' ySTRING ',' eList ')' ';' { $$ = new AstDisplay($1,'\n',*$5,$3,$7); }
| yD_FWRITE '(' idVarXRef ',' ySTRING ')' ';' { $$ = new AstDisplay($1,'\0',*$5,$3,NULL); }
| yD_FWRITE '(' idVarXRef ',' ySTRING ',' eList ')' ';' { $$ = new AstDisplay($1,'\0',*$5,$3,$7); }
| yD_READMEMB '(' expr ',' lhIdArrayed ')' ';' { $$ = new AstReadMem($1,false,$3,$5,NULL,NULL); }
| yD_READMEMB '(' expr ',' lhIdArrayed ',' expr ')' ';' { $$ = new AstReadMem($1,false,$3,$5,$7,NULL); }
| yD_READMEMB '(' expr ',' lhIdArrayed ',' expr ',' expr ')' ';' { $$ = new AstReadMem($1,false,$3,$5,$7,$9); }
| yD_READMEMH '(' expr ',' lhIdArrayed ')' ';' { $$ = new AstReadMem($1,true, $3,$5,NULL,NULL); }
| yD_READMEMH '(' expr ',' lhIdArrayed ',' expr ')' ';' { $$ = new AstReadMem($1,true, $3,$5,$7,NULL); }
| yD_READMEMH '(' expr ',' lhIdArrayed ',' expr ',' expr ')' ';' { $$ = new AstReadMem($1,true, $3,$5,$7,$9); }
| yD_READMEMB '(' expr ',' idArrayed ')' ';' { $$ = new AstReadMem($1,false,$3,$5,NULL,NULL); }
| yD_READMEMB '(' expr ',' idArrayed ',' expr ')' ';' { $$ = new AstReadMem($1,false,$3,$5,$7,NULL); }
| yD_READMEMB '(' expr ',' idArrayed ',' expr ',' expr ')' ';' { $$ = new AstReadMem($1,false,$3,$5,$7,$9); }
| yD_READMEMH '(' expr ',' idArrayed ')' ';' { $$ = new AstReadMem($1,true, $3,$5,NULL,NULL); }
| yD_READMEMH '(' expr ',' idArrayed ',' expr ')' ';' { $$ = new AstReadMem($1,true, $3,$5,$7,NULL); }
| yD_READMEMH '(' expr ',' idArrayed ',' expr ',' expr ')' ';' { $$ = new AstReadMem($1,true, $3,$5,$7,$9); }
;
stateCaseForIf: caseStmt caseAttrE caseList yENDCASE { $$ = $1; $1->addItemsp($3); }
| yIF expr stmtBlock %prec yLOWER_THAN_ELSE { $$ = new AstIf($1,$2,$3,NULL); }
| yIF expr stmtBlock yELSE stmtBlock { $$ = new AstIf($1,$2,$3,$5); }
| yFOR '(' lhIdVarRef '=' expr ';' expr ';' lhIdVarRef '=' expr ')' stmtBlock
| yFOR '(' idVarRef '=' expr ';' expr ';' idVarRef '=' expr ')' stmtBlock
{ $$ = new AstFor($1, new AstAssign($4,$3,$5)
,$7, new AstAssign($10,$9,$11)
,$13);}
@ -877,21 +875,21 @@ gateIdE: /*empty*/ {}
| yID {}
;
gateBuf: gateIdE '(' lhIdRanged ',' expr ')' { $$ = new AstAssignW ($2,$3,$5); $$->allowImplicit(true); }
gateBuf: gateIdE '(' idRanged ',' expr ')' { $$ = new AstAssignW ($2,$3,$5); $$->allowImplicit(true); }
;
gateNot: gateIdE '(' lhIdRanged ',' expr ')' { $$ = new AstAssignW ($2,$3,new AstNot($4,$5)); $$->allowImplicit(true); }
gateNot: gateIdE '(' idRanged ',' expr ')' { $$ = new AstAssignW ($2,$3,new AstNot($4,$5)); $$->allowImplicit(true); }
;
gateAnd: gateIdE '(' lhIdRanged ',' gateAndPinList ')' { $$ = new AstAssignW ($2,$3,$5); $$->allowImplicit(true); }
gateAnd: gateIdE '(' idRanged ',' gateAndPinList ')' { $$ = new AstAssignW ($2,$3,$5); $$->allowImplicit(true); }
;
gateNand: gateIdE '(' lhIdRanged ',' gateAndPinList ')' { $$ = new AstAssignW ($2,$3,new AstNot($4,$5)); $$->allowImplicit(true); }
gateNand: gateIdE '(' idRanged ',' gateAndPinList ')' { $$ = new AstAssignW ($2,$3,new AstNot($4,$5)); $$->allowImplicit(true); }
;
gateOr: gateIdE '(' lhIdRanged ',' gateOrPinList ')' { $$ = new AstAssignW ($2,$3,$5); $$->allowImplicit(true); }
gateOr: gateIdE '(' idRanged ',' gateOrPinList ')' { $$ = new AstAssignW ($2,$3,$5); $$->allowImplicit(true); }
;
gateNor: gateIdE '(' lhIdRanged ',' gateOrPinList ')' { $$ = new AstAssignW ($2,$3,new AstNot($4,$5)); $$->allowImplicit(true); }
gateNor: gateIdE '(' idRanged ',' gateOrPinList ')' { $$ = new AstAssignW ($2,$3,new AstNot($4,$5)); $$->allowImplicit(true); }
;
gateXor: gateIdE '(' lhIdRanged ',' gateXorPinList ')' { $$ = new AstAssignW ($2,$3,$5); $$->allowImplicit(true); }
gateXor: gateIdE '(' idRanged ',' gateXorPinList ')' { $$ = new AstAssignW ($2,$3,$5); $$->allowImplicit(true); }
;
gateXnor: gateIdE '(' lhIdRanged ',' gateXorPinList ')' { $$ = new AstAssignW ($2,$3,new AstNot($4,$5)); $$->allowImplicit(true); }
gateXnor: gateIdE '(' idRanged ',' gateXorPinList ')' { $$ = new AstAssignW ($2,$3,new AstNot($4,$5)); $$->allowImplicit(true); }
;
gateAndPinList: expr { $$ = $1; }
@ -964,13 +962,6 @@ pathDotted: yID { $$ = $1; }
| pathDotted '.' yID { $$ = V3Read::newString(*$1+string(".")+*$3); }
;
lhIdVarRef: yID { $$ = new AstVarRef(CRELINE(),*$1,true);}
;
lhIdVarXRef: lhIdVarRef { $$ = $1; }
| pathDotted '.' yID { $$ = new AstVarXRef(CRELINE(),*$3,*$1,true);}
;
idVarRef: yID { $$ = new AstVarRef(CRELINE(),*$1,false);}
;
@ -992,30 +983,20 @@ idArrayed: idVarXRef { $$ = $1; }
| idArrayed '[' expr ']' { $$ = new AstSelBit($2,$1,$3); } // Or AstArraySel, don't know yet.
;
lhIdArrayed: lhIdVarXRef { $$ = $1; }
| lhIdArrayed '[' expr ']' { $$ = new AstSelBit($2,$1,$3); } // Or AstArraySel, don't know yet.
;
idRanged: idArrayed { $$ = $1; }
| idArrayed '[' constExpr ':' constExpr ']' { $$ = new AstSelExtract($2,$1,$3,$5); }
| idArrayed '[' expr yPLUSCOLON constExpr ']' { $$ = new AstSelPlus($2,$1,$3,$5); }
| idArrayed '[' expr yMINUSCOLON constExpr ']' { $$ = new AstSelMinus($2,$1,$3,$5); }
;
lhIdRanged: lhIdArrayed { $$ = $1; }
| lhIdArrayed '[' constExpr ':' constExpr ']' { $$ = new AstSelExtract($2,$1,$3,$5); }
| lhIdArrayed '[' expr yPLUSCOLON constExpr ']' { $$ = new AstSelPlus($2,$1,$3,$5); }
| lhIdArrayed '[' expr yMINUSCOLON constExpr ']' { $$ = new AstSelMinus($2,$1,$3,$5); }
;
strAsInt: ySTRING { $$ = new AstConst(CRELINE(),V3Number(V3Number::VerilogString(),CRELINE(),V3Parse::deQuote(CRELINE(),*$1)));}
;
strAsText: ySTRING { $$ = V3Parse::createTextQuoted(CRELINE(),*$1);}
;
lhConcIdList: lhIdRanged { $$ = $1; }
| lhConcIdList ',' lhIdRanged { $$ = new AstConcat($2,$1,$3); }
concIdList: idRanged { $$ = $1; }
| concIdList ',' idRanged { $$ = new AstConcat($2,$1,$3); }
;
//************************************************
@ -1177,3 +1158,7 @@ AstText* V3Parse::createTextQuoted(FileLine* fileline, string text) {
string newtext = deQuote(fileline, text);
return new AstText(fileline, newtext);
}
// Local Variables:
// compile-command: "cd obj_dbg ; /usr/bin/bison -y -d -v ../verilog.y ; cat y.output"
// End: