[logo] 
 
Home
News
Activity
About/Contact
Major Tools
  Dinotrace
  Verilator
  Verilog-mode
  Verilog-Perl
Other Tools
  BugVise
  CovVise
  Force-Gate-Sim
  Gspice
  IPC::Locker
  Rsvn
  SVN::S4
  SystemPerl
  Voneline
  WFH
General Info
  Papers

0001-Support-interfaces-and-modports.patch

Byron Bradley, 02/01/2010 05:07 pm

Download (60.5 kB)

b/src/Makefile_obj.in
188 188
	V3Hashed.o \
189 189
	V3Inline.o \
190 190
	V3Inst.o \
191
	V3Interface.o \
191 192
	V3Life.o \
192 193
	V3LifePost.o \
193 194
	V3Link.o \
b/src/V3Ast.h
310 310
	BLOCKTEMP,
311 311
	MODULETEMP,
312 312
	STMTTEMP,
313
	XTEMP
313
	XTEMP,
314
        INTERFACE,      // Used to link Interfaces between modules
314 315
    };
315 316
    enum en m_e;
316 317
    inline AstVarType () {}
......
322 323
	    "?","GPARAM","LPARAM","GENVAR",
323 324
	    "VAR","INPUT","OUTPUT","INOUT",
324 325
	    "SUPPLY0","SUPPLY1","WIRE","IMPLICITWIRE","TRIWIRE","PORT",
325
	    "BLOCKTEMP","MODULETEMP","STMTTEMP","XTEMP"};
326
	    "BLOCKTEMP","MODULETEMP","STMTTEMP","XTEMP", "INTERFACE"};
326 327
	return names[m_e]; }
327 328
  };
328 329
  inline bool operator== (AstVarType lhs, AstVarType rhs) { return (lhs.m_e == rhs.m_e); }
b/src/V3AstNodes.cpp
508 508
    this->AstNode::dump(str);
509 509
    if (littleEndian()) str<<" [LITTLE]";
510 510
}
511
void AstInterfaceDType::dump(ostream& str) {
512
    this->AstNode::dump(str);
513
    if (interfacep()) { str<<" -> "; interfacep()->dump(str); }
514
    else { str<<" -> UNLINKED"; }
515
}
516
void AstModportVar::dump(ostream& str) {
517
    this->AstNode::dump(str);
518
    str<<" "<<varType();
519
    if (varp()) { str<<" -> "; varp()->dump(str); }
520
    else { str<<" -> UNLINKED"; }
521
}
511 522
void AstRefDType::dump(ostream& str) {
512 523
    this->AstNode::dump(str);
513 524
    if (defp()) { str<<" -> "; defp()->dump(str); }
......
539 550
    if (varp()) { str<<" -> "; varp()->dump(str); }
540 551
    else { str<<" ->UNLINKED"; }
541 552
}
553
void AstScopeAlias::dump(ostream& str) {
554
    this->AstNode::dump(str);
555
    if (aliasp()) { str<<" -> " << aliasp(); }
556
    else { str<<" ->UNLINKED"; }
557
}
542 558
void AstVarRef::dump(ostream& str) {
543 559
    this->AstNode::dump(str);
544 560
    if (lvalue()) str<<" [LV] => ";
b/src/V3AstNodes.h
295 295
    void	implicit(bool flag) { m_implicit = flag; }
296 296
};
297 297

  
298
struct AstInterfaceDType : public AstNodeDType {
299
private:
300
    AstInterface*	m_interfacep;
301
    string		m_name;
302
    string		m_varName;
303
    string		m_modportName;
304
    AstModport*		m_modportp;
305
public:
306
    AstInterfaceDType(FileLine* fl, const string& name)
307
	: AstNodeDType(fl), m_interfacep(NULL), m_name(name), m_varName(name),
308
	  m_modportName(""), m_modportp(NULL) { }
309
    AstInterfaceDType(FileLine* fl, const string& name, const string& modport)
310
	: AstNodeDType(fl), m_interfacep(NULL), m_name(name), m_varName(name),
311
	  m_modportName(modport), m_modportp(NULL) { }
312
    ASTNODE_NODE_FUNCS(InterfaceDType, INTERFACEDTYPE)
313
    // METHODS
314
    virtual void dump(ostream& str=cout);
315
    virtual string name() const { return m_name; }
316
    virtual AstBasicDType* basicp() const { return NULL; }
317
    virtual int widthAlignBytes() const { return 1; }
318
    virtual int widthTotalBytes() const { return 1; }
319
    virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; }
320
    AstInterface* interfacep() const { return m_interfacep; }
321
    void interfacep(AstInterface* nodep) { m_interfacep=nodep; }
322
    string varName() const { return m_varName; }
323
    void varName(const string& name) { m_varName=name; }
324
    string modportName() const { return m_modportName; }
325
    void modportName(const string& name) { m_modportName=name; }
326
    AstModport* modportp() const { return m_modportp; }
327
    void modportp(AstModport* modportp) { m_modportp=modportp; }
328
    bool isModport() { return !!modportName().size(); }
329
};
330

  
298 331
struct AstRefDType : public AstNodeDType {
299 332
private:
300 333
    AstTypedef*	m_defp;
......
534 567
    // A variable (in/out/wire/reg/param) inside a module
535 568
private:
536 569
    string	m_name;		// Name of variable
570
    string	m_origName;	// Original name before dot addition
537 571
    AstVarType	m_varType;	// Type of variable
538 572
    bool	m_input:1;	// Input or inout
539 573
    bool	m_output:1;	// Output or inout
......
570 604
public:
571 605
    AstVar(FileLine* fl, AstVarType type, const string& name, AstNodeDType* dtypep)
572 606
	:AstNode(fl)
573
	, m_name(name) {
607
	, m_name(name), m_origName(name) {
574 608
	init();
575 609
	combineType(type); setOp1p(dtypep);
576 610
	if (dtypep && dtypep->basicp()) {
......
579 613
    }
580 614
    AstVar(FileLine* fl, AstVarType type, const string& name, AstLogicPacked, int wantwidth)
581 615
	:AstNode(fl)
582
	, m_name(name) {
616
	, m_name(name), m_origName(name) {
583 617
	init();
584 618
	combineType(type);
585 619
	setOp1p(new AstBasicDType(fl, AstLogicPacked(), wantwidth));
......
587 621
    }
588 622
    AstVar(FileLine* fl, AstVarType type, const string& name, AstVar* examplep)
589 623
	:AstNode(fl)
590
	, m_name(name) {
624
	, m_name(name), m_origName(name) {
591 625
	init();
592 626
	combineType(type);
593 627
	if (examplep->dtypep()) {
......
598 632
    ASTNODE_NODE_FUNCS(Var, VAR)
599 633
    virtual void dump(ostream& str);
600 634
    virtual string name()	const { return m_name; }		// * = Var name
635
    string origName()		const { return m_origName; }		// * = Original name
601 636
    virtual bool maybePointedTo() const { return true; }
602 637
    virtual bool broken() const { return !dtypep(); }
603 638
    AstVarType	varType()	const { return m_varType; }		// * = Type of variable
639
    AstVarType	varType(AstVarType::en type) { m_varType == type; }
604 640
    void varType2Out() { m_tristate=0; m_input=0; m_output=1; }
605 641
    void varType2In() {  m_tristate=0; m_input=1; m_output=0; }
606 642
    string	scType() const;	  // Return SysC type: bool, uint32_t, uint64_t, sc_bv
......
647 683
    bool	isPrimaryIO() const { return m_primaryIO; }
648 684
    bool	isPrimaryIn() const { return isPrimaryIO() && isInput(); }
649 685
    bool	isIO() const  { return (m_input||m_output); }
686
    bool	isInterface() const { return (varType()==AstVarType::INTERFACE); }
650 687
    bool	isSignal() const  { return (varType()==AstVarType::WIRE || varType()==AstVarType::IMPLICITWIRE
651 688
					    || varType()==AstVarType::VAR); }
652 689
    bool	isTemp() const { return (varType()==AstVarType::BLOCKTEMP || varType()==AstVarType::MODULETEMP
......
826 863
    void	circular(bool flag) { m_circular = flag; }
827 864
};
828 865

  
866
struct AstScopeAlias : public AstVarScope {
867
    // An Alias to another Scope
868
private:
869
    AstScope*	m_aliasp;	// The scope this points to
870
public:
871
    AstScopeAlias(FileLine* fl, AstScope* scopep, AstVar* varp, AstScope* aliasp)
872
	:AstVarScope(fl, scopep, varp), m_aliasp(aliasp) {}
873
    ASTNODE_NODE_FUNCS(ScopeAlias, SCOPEALIAS)
874
    AstScope* aliasp() const { return m_aliasp; }
875
    void aliasp(AstScope* aliasp) { m_aliasp = aliasp; }
876
    virtual void dump(ostream& str);
877
    virtual string name() const {return scopep()->name()+"."+varp()->name();}	// * = Var name
878
};
879

  
829 880
struct AstVarRef : public AstNodeVarRef {
830 881
    // A reference to a variable (lvalue or rvalue)
831 882
    AstVarRef(FileLine* fl, const string& name, bool lvalue)
......
953 1004
    void packagep(AstPackage* nodep) { m_packagep=nodep; }
954 1005
};
955 1006

  
1007
struct AstInterface : public AstNodeModule {
1008
    // A module declaration
1009
    AstInterface(FileLine* fl, const string& name)
1010
	: AstNodeModule (fl,name) { }
1011
    ASTNODE_NODE_FUNCS(Interface, INTERFACE)
1012
};
1013

  
1014
struct AstModportVar : public AstNode {
1015
    // A Var under a modport
1016
private:
1017
    string	m_name;		// Name of the variable
1018
    AstVarType	m_type;		// Type of the variable
1019
    AstVar*	m_varp;		// Link to the actual Var
1020
public:
1021
    AstModportVar(FileLine* fl, const string& name, AstVarType::en type)
1022
	: AstNode(fl), m_name(name), m_type(type), m_varp(NULL) { }
1023
    ASTNODE_NODE_FUNCS(ModportVar, MODPORTVAR)
1024
    virtual void dump(ostream& str);
1025
    AstVarType	varType()	const { return m_type; }		// * = Type of variable
1026
    virtual string name()	const { return m_name; }
1027
    bool	isInput() const { return (varType()==AstVarType::INPUT || varType()==AstVarType::INOUT); }
1028
    bool	isOutput() const { return (varType()==AstVarType::OUTPUT || varType()==AstVarType::INOUT); }
1029
    AstVar*	varp()	const { return m_varp; }		// [After Link] Pointer to variable
1030
    void	varp(AstVar* varp) { m_varp=varp; }
1031
};
1032

  
1033
struct AstModport : public AstNode {
1034
    // A modport in an interface
1035
private:
1036
    string	m_name;		// Name of the modport
1037
public:
1038
    AstModport(FileLine* fl, const string& name, AstModportVar* varsp)
1039
	: AstNode(fl), m_name(name) {
1040
        addNOp1p(varsp); }
1041
    virtual string name()	const { return m_name; }
1042
    ASTNODE_NODE_FUNCS(Modport, MODPORT)
1043
    AstModportVar* varsp()	const { return op1p()->castModportVar(); }	// op1 = List of Vars
1044
};
1045

  
956 1046
struct AstCell : public AstNode {
957 1047
    // A instantiation cell or interface call (don't know which until link)
958 1048
private:
......
960 1050
    string	m_origName;	// Original name before dot addition
961 1051
    string	m_modName;	// Module the cell instances
962 1052
    AstNodeModule*	m_modp;		// [AfterLink] Pointer to module instanced
1053
    bool	m_hasVar;	// True if a Var has been created for this cell
963 1054
public:
964 1055
    AstCell(FileLine* fl, const string& instName, const string& modName,
965 1056
	    AstPin* pinsp, AstPin* paramsp, AstRange* rangep)
966 1057
	: AstNode(fl)
967 1058
	, m_name(instName), m_origName(instName), m_modName(modName)
968
	, m_modp(NULL) {
1059
	, m_modp(NULL), m_hasVar(false) {
969 1060
	addNOp1p(pinsp); addNOp2p(paramsp); setNOp3p(rangep); }
970 1061
    ASTNODE_NODE_FUNCS(Cell, CELL)
971 1062
    // No cloneRelink, we presume cloneee's want the same module linkages
......
986 1077
    void addPinsp(AstPin* nodep) { addOp1p(nodep); }
987 1078
    void addParamsp(AstPin* nodep) { addOp2p(nodep); }
988 1079
    void modp(AstNodeModule* nodep)	{ m_modp = nodep; }
1080
    virtual bool hasVar()	const { return m_hasVar; }
1081
    virtual void hasVar(bool status) { m_hasVar = status; }
989 1082
};
990 1083

  
991 1084
struct AstCellInline : public AstNode {
......
1320 1413
    }
1321 1414
};
1322 1415

  
1416
struct AstAssignVarScope : public AstNodeAssign {
1417
    // Assign two VarScopes to each other
1418
    AstAssignVarScope(FileLine* fileline, AstNode* lhsp, AstNode* rhsp)
1419
	: AstNodeAssign(fileline, lhsp, rhsp) { }
1420
    ASTNODE_NODE_FUNCS(AssignVarScope, ASSIGNVARSCOPE)
1421
    virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstAssignVarScope(this->fileline(), lhsp, rhsp); }
1422
};
1423

  
1323 1424
struct AstPull : public AstNode {
1324 1425
private:
1325 1426
    bool m_direction;
b/src/V3Const.cpp
1309 1309
    virtual void visit(AstAssignAlias* nodep, AstNUser*) {
1310 1310
	// Don't perform any optimizations, keep the alias around
1311 1311
    }
1312
    virtual void visit(AstAssignVarScope* nodep, AstNUser*) {
1313
	// Don't perform any optimizations, the node won't be linked yet
1314
    }
1312 1315
    virtual void visit(AstAssignW* nodep, AstNUser*) {
1313 1316
	nodep->iterateChildren(*this);
1314 1317
	if (replaceNodeAssign(nodep)) return;
b/src/V3Inline.cpp
182 182
		    m_modp->addStmtp(new AstAssignW(nodep->fileline(),
183 183
						    new AstVarRef(nodep->fileline(), nodep, true),
184 184
						    exprconstp->cloneTree(true)));
185
		} else {
185
		} else if (!nodep->isInterface()) {
186 186
		    m_modp->addStmtp(new AstAssignAlias(nodep->fileline(),
187 187
							new AstVarRef(nodep->fileline(), nodep, true),
188 188
							new AstVarRef(nodep->fileline(), exprvarrefp->varp(), false)));
189 189
		    AstNode* nodebp=exprvarrefp->varp();
190 190
		    nodep ->fileline()->modifyStateInherit(nodebp->fileline());
191 191
		    nodebp->fileline()->modifyStateInherit(nodep ->fileline());
192
		} else {
193
		    m_modp->addStmtp(new AstAssignVarScope(nodep->fileline(),
194
							new AstVarRef(nodep->fileline(), nodep, true),
195
							new AstVarRef(nodep->fileline(), exprvarrefp->varp(), false)));
196
		    AstNode* nodebp=exprvarrefp->varp();
197
		    nodep ->fileline()->modifyStateInherit(nodebp->fileline());
198
		    nodebp->fileline()->modifyStateInherit(nodep ->fileline());
192 199
		}
193 200
	    }
194 201
	    // Variable under the inline cell, need to rename to avoid conflicts
......
330 337
    virtual void visit(AstNodeModule* nodep, AstNUser*) {
331 338
	m_stmtCnt = 0;
332 339
	m_modp = nodep;
333
	m_modp->user2(true);  // Allowed = true
340
	if (nodep->castInterface()) {
341
	    m_modp->user2(false);
342
	} else {
343
	    m_modp->user2(true);  // Allowed = true
344
	}
334 345
	if (m_modp->modPublic()) cantInline("modPublic");
335 346
	//
336 347
	nodep->iterateChildren(*this);
......
399 410
	nodep->iterateChildren(*this);
400 411
	m_stmtCnt = oldcnt;
401 412
    }
413
    virtual void visit(AstInterfaceDType* nodep, AstNUser*) {
414
	// Unsupported: Inlining of modules with interfaces
415
	m_modp->user2(false);
416
    }
402 417
    //--------------------
403 418
    // Default: Just iterate
404 419
    virtual void visit(AstNode* nodep, AstNUser*) {
b/src/V3Inst.cpp
113 113
		     exprp);
114 114
		m_modp->addStmtp(assp);
115 115
		if (debug()>=9) assp->dumpTree(cout,"     _new: ");
116
	    } else if (nodep->modVarp()->isInterface()) {
117
		// Create an AstAssignVarScope for Vars to Cells so we can link with their scope later
118
		AstNode* rhsp = new AstVarXRef (exprp->fileline(), nodep->modVarp()->name(), m_cellp->name(), false);
119
		rhsp->widthSignedFrom(nodep);
120
		if (AstVarRef* refp = exprp->castVarRef()) {
121
		    refp->varp(NULL);
122
		} else {
123
		    exprp->v3fatalSrc("Interfaces: Pin is not connected to a VarRef");
124
		}
125
		AstAssignVarScope* assp = new AstAssignVarScope(exprp->fileline(), exprp, rhsp);
126
		m_modp->addStmtp(assp);
116 127
	    } else {
117 128
		nodep->v3error("Assigned pin is neither input nor output");
118 129
	    }
b/src/V3Interface.cpp
1
//*************************************************************************
2
// DESCRIPTION: Verilator: Parse module/signal name references
3
//
4
// Code available from: http://www.veripool.org/verilator
5
//
6
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
7
//
8
//*************************************************************************
9
//
10
// Copyright 2003-2010 by Wilson Snyder.  This program is free software; you can
11
// redistribute it and/or modify it under the terms of either the GNU
12
// Lesser General Public License Version 3 or the Perl Artistic License
13
// Version 2.0.
14
//
15
// Verilator is distributed in the hope that it will be useful,
16
// but WITHOUT ANY WARRANTY; without even the implied warranty of
17
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
// GNU General Public License for more details.
19
//
20
//*************************************************************************
21
// Interface TRANSFORMATIONS:
22
//	Top-down traversal:
23
//	  MODPORT
24
//	    Delete tree
25
//*************************************************************************
26

27
#include "config_build.h"
28
#include "verilatedos.h"
29
#include <cstdio>
30
#include <cstdarg>
31
#include <unistd.h>
32

  
33
#include "V3Global.h"
34
#include "V3Interface.h"
35
#include "V3Ast.h"
36

  
37
//######################################################################
38
// Lint interfaces/modports, as a visitor of each AstNode
39

  
40
class InterfaceCleanup : public AstNVisitor {
41
private:
42
    // NODE STATE
43

  
44
    // ENUMS
45

  
46
    // STATE
47

  
48
    // METHODS
49
    virtual void visit(AstModport* nodep, AstNUser*) {
50
	// Modports aren't needed anymore, delete them
51
	nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
52
    }
53

  
54
    virtual void visit(AstNode* nodep, AstNUser*) {
55
	// Default: Just iterate
56
	nodep->iterateChildren(*this);
57
    }
58

  
59
public:
60
    // CONSTUCTORS
61
    InterfaceCleanup(AstNetlist* rootp) {
62
	rootp->accept(*this);
63
    }
64
    virtual ~InterfaceCleanup() {}
65
};
66

  
67
//######################################################################
68
// Interface class functions
69

  
70
void V3Interface::lint(AstNetlist* rootp) {
71
    UINFO(4,__FUNCTION__<<": "<<endl);
72
    InterfaceCleanup visitor(rootp);
73
}
b/src/V3Interface.h
1
// -*- C++ -*-
2
//*************************************************************************
3
// DESCRIPTION: Verilator: Link modules/signals together
4
//
5
// Code available from: http://www.veripool.org/verilator
6
//
7
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
8
//
9
//*************************************************************************
10
//
11
// Copyright 2003-2009 by Wilson Snyder.  This program is free software; you can
12
// redistribute it and/or modify it under the terms of either the GNU
13
// Lesser General Public License Version 3 or the Perl Artistic License
14
// Version 2.0.
15
//
16
// Verilator is distributed in the hope that it will be useful,
17
// but WITHOUT ANY WARRANTY; without even the implied warranty of
18
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
// GNU General Public License for more details.
20
//
21
//*************************************************************************
22

23
#ifndef _V3INTERFACE_H_
24
#define _V3INTERFACE_H 1
25
#include "config_build.h"
26
#include "verilatedos.h"
27
#include "V3Error.h"
28
#include "V3Ast.h"
29

  
30
//============================================================================
31

  
32
class V3Interface {
33
public:
34
    static void lint(AstNetlist* nodep);
35
};
36

  
37
#endif // Guard
b/src/V3Link.cpp
530 530
	nodep->iterateChildren(*this);
531 531
    }
532 532
    virtual void visit(AstCell* nodep, AstNUser*) {
533
	// Cell: Resolve its filename.  If necessary, parse it.
534 533
	m_cellp = nodep;
535
	if (m_idState==ID_FIND) {
536
	    // Add to list of all cells, for error checking and defparam's
537
	    findAndInsertAndCheck(nodep, nodep->name());
538
	}
539 534
	if (!nodep->modp()) {
540 535
	    nodep->v3fatalSrc("Cell has unlinked module"); // V3LinkCell should have errored out
541 536
	}
542 537
	else {
543
	    // Need to pass the module info to this cell, so we can link up the pin names
544
	    if (m_idState==ID_RESOLVE) {
538
	    if (m_idState==ID_FIND) {
539
		if (AstInterface* interfacep = nodep->modp()->castInterface()) {
540
		    if (!nodep->hasVar()) {
541
			// If the Cell connects to an interface, create a new Var with a CellDType
542
			AstNodeDType* iDTypep = new AstInterfaceDType(nodep->fileline(), interfacep->name());
543
			iDTypep->castInterfaceDType()->interfacep(nodep->modp()->castInterface());
544
			AstVar* varp = new AstVar(nodep->fileline(), AstVarType::INTERFACE, nodep->name(), iDTypep);
545
			nodep->addNext(varp);
546
		    }
547
		} else {
548
		    // Add to list of all cells, for error checking and defparam's
549
		    findAndInsertAndCheck(nodep, nodep->name());
550
		}
551
	    } else if (m_idState==ID_RESOLVE) {
552
		// Need to pass the module info to this cell, so we can link up the pin names
545 553
		m_cellVarsp = nodep->modp()->user4p()->castSymTable();
546 554
		UINFO(4,"(Backto) Link Cell: "<<nodep<<endl);
547 555
		//if (debug()) { nodep->dumpTree(cout,"linkcell:"); }
......
558 566
	// This is done bottom up in the LinkBotupVisitor stage
559 567
    }
560 568

  
569
    virtual void visit(AstInterfaceDType* nodep, AstNUser*) {
570
	nodep->iterateChildren(*this);
571
	// Link Modport names to the Modport Node under the Interface
572
	if (m_idState==ID_RESOLVE) {
573
	    if (nodep->isModport() && !nodep->modportp()) {
574
		for (AstNode* subnodep=nodep->interfacep()->stmtsp(); subnodep; subnodep = subnodep->nextp()) {
575
		    if (AstModport* modportp = subnodep->castModport()) {
576
			if (modportp->name() == nodep->modportName()) {
577
			    nodep->modportp(modportp);
578
			    UINFO(4,"Link Modport: "<<modportp<<endl);
579
			}
580
		    }
581
		}
582
	    }
583
	}
584
    }
585

  
586
    virtual void visit(AstModport* nodep, AstNUser*) {
587
	nodep->iterateChildren(*this);
588
    }
589

  
590
    virtual void visit(AstModportVar* nodep, AstNUser*) {
591
	nodep->iterateChildren(*this);
592
	if (m_idState==ID_RESOLVE) {
593
	    AstVar* varp = m_curVarsp->findIdUpward(nodep->name())->castVar();
594
	    nodep->varp(varp);
595
	    UINFO(4,"Link ModportVar: "<<nodep<<endl);
596
	}
597
    }
598

  
561 599
    virtual void visit(AstPort* nodep, AstNUser*) {
562 600
	// Port: Stash the pin number
563 601
	if (!m_curVarsp) nodep->v3fatalSrc("Port not under module??\n");
......
567 605
	    AstVar* refp = m_curVarsp->findIdFlat(nodep->name())->castVar();
568 606
	    if (!refp) {
569 607
		nodep->v3error("Input/output/inout declaration not found for port: "<<nodep->prettyName());
570
	    } else if (!refp->isIO()) {
571
		nodep->v3error("Pin is not an in/out/inout: "<<nodep->prettyName());
608
	    } else if (!refp->isIO() && !refp->isInterface()) {
609
		nodep->v3error("Pin is not an in/out/inout/interface: "<<nodep->prettyName());
572 610
	    } else {
573 611
		symsInsert("__pinNumber"+cvtToStr(nodep->pinNum()), refp);
574 612
		refp->user2(true);
......
612 650
		    return;
613 651
		}
614 652
		nodep->v3error("Pin not found: "<<nodep->prettyName());
615
	    } else if (!refp->isIO() && !refp->isParam()) {
616
		nodep->v3error("Pin is not an in/out/inout/param: "<<nodep->prettyName());
653
	    } else if (!refp->isIO() && !refp->isParam() && !refp->isInterface()) {
654
		nodep->v3error("Pin is not an in/out/inout/param/interface: "<<nodep->prettyName());
617 655
	    } else {
618 656
		nodep->modVarp(refp);
619 657
	    }
b/src/V3LinkCells.cpp
269 269
	//if (debug()>=9) m_mods.dump(cout, "-syms: ");
270 270
    }
271 271

  
272
    virtual void visit(AstInterfaceDType* nodep, AstNUser*) {
273
	// Cell: Resolve its filename.  If necessary, parse it.
274
	if (!nodep->interfacep()) {
275
	    UINFO(4,"Link Cell: "<<nodep<<endl);
276
	    // Use findIdUpward instead of findIdFlat; it doesn't matter for now
277
	    // but we might support modules-under-modules someday.
278
	    AstNodeModule* modp = m_mods.findIdUpward(nodep->name())->castNodeModule();
279
	    if (!modp) {
280
		// Read-subfile
281
		V3Parse parser (v3Global.rootp(), m_filterp);
282
		parser.parseFile(nodep->fileline(), nodep->name(), false);
283
		V3Error::abortIfErrors();
284
		// We've read new modules, grab new pointers to their names
285
		readModNames();
286
		// Check again
287
		modp = m_mods.findIdUpward(nodep->name())->castNodeModule();
288
		if (!modp) {
289
		    nodep->v3error("Can't resolve interface reference: "<<nodep->name());
290
		}
291
	    }
292
	    if (modp) {
293
		// Track module depths, so can sort list from parent down to children
294
		new V3GraphEdge(&m_graph, vertex(m_modp), vertex(modp), 1, false);
295
		nodep->interfacep(modp->castInterface());
296
	    }
297
	}
298
    }
299

  
300

  
272 301
public:
273 302
    // CONSTUCTORS
274 303
    LinkCellsVisitor(AstNetlist* rootp, V3InFilter* filterp) {
b/src/V3LinkDot.cpp
122 122
    virtual string modName() const { return (modp() ? modp()->origName() : "*NULL*"); }
123 123
    virtual string cellName() const { return (cellp() ? cellp()->origName() : "*NULL*"); }
124 124
    virtual string name() const { return (string)("C:")+cellName()+" M:"+modName(); }
125
    virtual string dotColor() const { return (modp()->castInterface() ? "green" : "black"); }
125 126
};
126 127

  
127 128
class LinkDotInlineVertex : public LinkDotBaseVertex {
......
181 182

  
182 183
    // TYPES
183 184
    typedef std::multimap<string,LinkDotCellVertex*> NameScopeMap;
185
    typedef std::multimap<string,AstScope*> NameAstScopeMap;
186
    typedef std::map<string,string> ScopenameAliasMap;
187

  
184 188
    // MEMBERS
185 189
    LinkDotGraph	m_graph;		// Graph of hierarchy
186 190
    NameScopeMap	m_nameScopeMap;		// Hash of scope referenced by non-pretty textual name
191
    NameAstScopeMap	m_nameAstScopeMap;	// Hash of AstScope nodes referenced by non-pretty textual name
192
    ScopenameAliasMap	m_scopenameMap;		// Map of scopename aliases
187 193
    bool		m_forPrearray;		// Compress cell__[array] refs
188 194
    bool		m_forScopeCreation;	// Remove VarXRefs for V3Scope
189 195
public:
......
270 276
	}
271 277
	return iter->second;
272 278
    }
279
    void insertScopeAlias(const string& lhs, const string& rhs) {
280
	m_scopenameMap.insert(make_pair(lhs, rhs));
281
    }
282
    void insertScope(AstScope* nodep) {
283
	m_nameAstScopeMap.insert(make_pair(nodep->name(), nodep));
284
    }
285
    AstScope* findScopeByName(const string& scopename, bool useAlias) {
286
	NameAstScopeMap::iterator iter = m_nameAstScopeMap.find(scopename);
287
	if (iter == m_nameAstScopeMap.end()) {
288
	    if (useAlias) {
289
		ScopenameAliasMap::iterator itera = m_scopenameMap.find(scopename);
290
		if (itera != m_scopenameMap.end())
291
		    return findScopeByName(itera->second, useAlias);
292
	    }
293
	    return NULL;
294
	}
295
	return iter->second;
296
    }
273 297
    void dump() {
274 298
	if (debug()>=6) m_graph.dumpDotFilePrefixed("linkdot");
275 299
    }
......
372 396

  
373 397
class LinkDotFindVisitor : public AstNVisitor {
374 398
private:
399
    // TYPEs
400
    typedef std::multimap<AstInterfaceDType*,LinkDotCellVertex*> InterfaceVarMap;
401

  
375 402
    // STATE
376 403
    LinkDotState*	m_statep;	// State to pass between visitors, including symbol table
377 404
    LinkDotCellVertex*	m_cellVxp;	// Vertex for current module
378 405
    LinkDotBaseVertex*	m_inlineVxp;	// Vertex for current module, possibly a fake inlined one
379 406
    string		m_scope;	// Scope text
380 407
    AstBegin*		m_beginp;	// Current Begin/end block
408
    AstInterfaceDType*	m_interfaceDTypep;	// InterfaceDType for the current Var
409
    InterfaceVarMap	m_interfaceVarMap;	// A map of unconnected Interface Vars
381 410

  
382 411
    int debug() { return LinkDotState::debug(); }
383 412

  
......
420 449
    }
421 450
    virtual void visit(AstScope* nodep, AstNUser*) {
422 451
	if (!m_statep->forScopeCreation()) v3fatalSrc("Scopes should only exist right after V3Scope");
423
	// Ignored.  Processed in next step
452
	// Store the scope in case it is aliased elsewhere (Interfaces). Otherwise ignored.  Processed in next step
453
	m_statep->insertScope(nodep);
424 454
    }
425 455
    virtual void visit(AstCell* nodep, AstNUser*) {
426 456
	UINFO(5,"   CELL under "<<m_scope<<" is "<<nodep<<endl);
......
455 485
	m_cellVxp = oldVxp;
456 486
	m_inlineVxp = oldInlineVxp;
457 487
    }
488
    virtual void visit(AstInterfaceDType* nodep, AstNUser*) {
489
	m_interfaceDTypep = nodep;
490
	nodep->iterateChildren(*this);
491
    }
458 492
    virtual void visit(AstCellInline* nodep, AstNUser*) {
459 493
	UINFO(5,"   CELLINLINE under "<<m_scope<<" is "<<nodep<<endl);
460 494
	LinkDotBaseVertex* aboveVxp = m_inlineVxp;
......
488 522
	m_beginp = oldbegin;
489 523
    }
490 524
    virtual void visit(AstVar* nodep, AstNUser*) {
491
	if (!m_statep->forScopeCreation()
492
	    && !m_beginp	// For now, we don't support xrefs into begin blocks
493
	    && !nodep->isFuncLocal()) {
525
	// Look for any InterfaceDTypes, these use dotted variables
526
	m_interfaceDTypep = NULL;
527
	nodep->iterateChildren(*this);
528
	if (m_interfaceDTypep && !m_statep->forScopeCreation()) {
529
	    // Interfaces need to be added as sub-cells and syms, but not before we've found all the modules
530
	    m_interfaceDTypep->varName(nodep->origName());
531
	    m_interfaceVarMap.insert(make_pair(m_interfaceDTypep, m_cellVxp));
494 532
	    m_statep->insertSym(m_cellVxp, nodep->name(), nodep);
495 533
	} else {
496
	    UINFO(9,"       Not allowing dot refs to: "<<nodep<<endl);
534
	    if (!m_statep->forScopeCreation()
535
		&& !m_beginp	// For now, we don't support xrefs into begin blocks
536
		&& !nodep->isFuncLocal()) {
537
		m_statep->insertSym(m_cellVxp, nodep->name(), nodep);
538
	    } else {
539
		UINFO(9,"       Not allowing dot refs to: "<<nodep<<endl);
540
	    }
497 541
	}
498 542
    }
499 543
    virtual void visit(AstNodeFTask* nodep, AstNUser*) {
......
519 563
	m_cellVxp = NULL;
520 564
	m_statep = statep;
521 565
	m_beginp = NULL;
566
	m_interfaceDTypep = NULL;
522 567
	//
523 568
	rootp->accept(*this);
569

  
570
	// Insert any interfaces as sub-cells
571
	InterfaceVarMap::iterator iter = m_interfaceVarMap.begin();
572
	for (; iter != m_interfaceVarMap.end(); ++iter) {
573
	    AstInterfaceDType* interfaceDTypep = iter->first;
574
	    LinkDotCellVertex* aboveVxp = iter->second;
575
	    LinkDotCellVertex* cellVxp = m_statep->findModScope(interfaceDTypep->interfacep());
576
	    aboveVxp->insertSubcellName(interfaceDTypep->varName(), cellVxp);
577
	}
524 578
    }
525 579
    virtual ~LinkDotFindVisitor() {}
526 580
};
......
529 583

  
530 584
class LinkDotScopeVisitor : public AstNVisitor {
531 585
private:
586
    // TYPEs
587
    typedef std::map<string,LinkDotCellVertex*> NameScopeVxpMap;
588

  
532 589
    // STATE
590
    AstScope*		m_scopep;	// The current scope
533 591
    LinkDotState*	m_statep;	// State to pass between visitors, including symbol table
534 592
    LinkDotCellVertex*	m_cellVxp;	// Vertex for current module
593
    NameScopeVxpMap	m_scopeMap;	// Map of unlinked scope alias to CellVertex
535 594

  
536 595
    int debug() { return LinkDotState::debug(); }
537 596

  
......
542 601
	// Using the CELL names, we created all hierarchy.  We now need to match this Scope
543 602
	// up with the hierarchy created by the CELL names.
544 603
	m_cellVxp = m_statep->findScope(nodep);
604
	m_scopep = nodep;
545 605
	nodep->iterateChildren(*this);
546 606
	m_cellVxp = NULL;
547 607
    }
......
550 610
	    m_statep->insertSym(m_cellVxp, nodep->varp()->name(), nodep);
551 611
	}
552 612
    }
613
    virtual void visit(AstScopeAlias* nodep, AstNUser*) {
614
	// Link the ScopeAlias to its Scope, may be NULL
615
	AstScope* scope = m_statep->findScopeByName(nodep->name(), false);
616
	if (scope) {
617
	    nodep->aliasp(scope);
618
	} else {
619
	    NameScopeVxpMap::const_iterator iter = m_scopeMap.find(nodep->name());
620
	    if (iter == m_scopeMap.end()) {
621
		nodep->v3fatalSrc("Could not link scope for "+nodep->varp()->name());
622
	    } else {
623
		m_cellVxp->insertSubcellName(nodep->varp()->name(), iter->second);
624
	    }
625
	}
626
    }
553 627
    virtual void visit(AstNodeFTask* nodep, AstNUser*) {
554 628
	m_statep->insertSym(m_cellVxp, nodep->name(), nodep);
555 629
	// No recursion, we don't want to pick up variables
556 630
    }
631
    virtual void visit(AstAssignVarScope* nodep, AstNUser*) {
632
	LinkDotCellVertex* linkedVxp = NULL;
633
	string lhspScopename;
634
	string rhspScopename;
635
	if (AstVarRef* refp = nodep->lhsp()->castVarRef()) {
636
	    lhspScopename = m_scopep->name()+"."+refp->name();
637
	    AstScope* scopep = m_statep->findScopeByName(lhspScopename, true);
638
	    LinkDotCellVertex* scopeVxp = m_statep->findScope(scopep);
639
	    if (scopep) {
640
		UINFO(5, "       Found a linked scope: "<<lhspScopename<<endl);
641
		linkedVxp = scopeVxp;
642
	    } else {
643
		nodep->v3fatalSrc("Unsupported: Found a scopep on a VarXRef");
644
	    }
645
	} else {
646
	    nodep->v3fatalSrc("Unsupported: Non VarRef on lhsp of AssignVarScope");
647
	}
648
	if (AstVarXRef* refp = nodep->rhsp()->castVarXRef()) {
649
	    rhspScopename = m_scopep->name()+"."+refp->dotted()+"."+refp->name();
650
	    AstScope* scopep = m_statep->findScopeByName(rhspScopename, true);
651
	    if (scopep) {
652
		UINFO(5,"       "<<scopep<<endl);
653
		nodep->v3fatalSrc("Unsupported: Found a scopep on a VarXRef");
654
	    } else {
655
		UINFO(5, "       Found an unlinked scope: "<<rhspScopename<<endl);
656
		m_scopeMap.insert(make_pair(rhspScopename,linkedVxp));
657
		m_statep->insertScopeAlias(rhspScopename, lhspScopename);
658
	    }
659
	} else {
660
	    nodep->v3fatalSrc("Unsupported: Non VarXRef on rhsp of AssignVarScope");
661
	}
662
	// We have stored the link, we don't need these any more
663
	nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
664
    }
557 665
    virtual void visit(AstAssignAlias* nodep, AstNUser*) {
558 666
	// Track aliases created by V3Inline; if we get a VARXREF(aliased_from)
559 667
	// we'll need to replace it with a VARXREF(aliased_to)
......
647 755
		nodep->varp(varp);
648 756
		UINFO(7,"         Resolved "<<nodep<<endl);  // Also prints varp
649 757
		if (!nodep->varp()) {
758
		    // If this is an interface, that might be a modport not a signal
759
		    LinkDotCellVertex* cellVxp = dynamic_cast<LinkDotCellVertex*>(dotVxp);
760
		    if (cellVxp) {
761
			AstInterface* interfacep = cellVxp->modp()->castInterface();
762
			if (interfacep) {
763
			    // Look for a modport under the Interface
764
			    for (AstNode* subnodep=interfacep->stmtsp(); subnodep; subnodep = subnodep->nextp()) {
765
			        if (AstModport* modportp = subnodep->castModport()) {
766
				    if (modportp->name() == nodep->name()) {
767
					// Change this VarXRef into a VarRef and link it to the Var
768
					AstVar* varp = (m_statep->findSym(m_cellVxp, nodep->dotted(), baddot)
769
							->castVar());  // maybe NULL
770
					if (!varp) {
771
					    nodep->v3error("Can't find definition of '"<<baddot<<"' (interface) in dotted signal: "<<nodep->dotted()+"."+nodep->prettyName());
772
					    return;
773
					}
774
					AstVarRef* refp = new AstVarRef(nodep->fileline(), varp, false);
775
					nodep->replaceWith(refp);
776
					// :TODO: byronb - Link the modport to the InterfaceDType under the Var
777
					return;
778
				    }
779
				}
780
			    }
781
			}
782
		    }
650 783
		    nodep->v3error("Can't find definition of '"<<baddot<<"' in dotted signal: "<<nodep->dotted()+"."+nodep->prettyName());
651 784
		    okVxp->errorScopes(nodep);
652 785
		}
b/src/V3LinkLevel.cpp
125 125
		pinp->modVarp(oldvarp);
126 126
		pinp->widthSignedFrom(oldvarp);
127 127
		cellp->addPinsp(pinp);
128
	    } else if (oldvarp->isInterface()) {
129
		// Link the interface at the top-level
130
		AstInterfaceDType* dtypep = oldvarp->dtypep()->castInterfaceDType();
131
		if (!dtypep || !dtypep->isModport())
132
		    continue;
133
		for (AstNode* inodep=dtypep->modportp()->varsp(); inodep; inodep = inodep->nextp()) {
134
		    AstModportVar* ivarp = inodep->castModportVar();
135
		    if (ivarp) {
136
			AstVar* newvarp = ivarp->varp()->cloneTree(false);
137
			newvarp->name(oldvarp->name()+"__DOT__"+newvarp->name());
138
			newvarp->varType(ivarp->varType());
139
			if (ivarp->isInput()) {
140
			    newvarp->varType2In();
141
			    AstVarXRef* lhsp = new AstVarXRef(newvarp->fileline(), ivarp->varp()->name(),
142
							      oldvarp->name(), true);
143
			    AstVarRef* rhsp = new AstVarRef(newvarp->fileline(), newvarp->name(), false);
144
			    rhsp->varp(newvarp);
145
			    AstAssignW* assignp = new AstAssignW(newvarp->fileline(), lhsp, rhsp);
146
			    lhsp->widthSignedFrom(newvarp);
147
			    rhsp->widthSignedFrom(newvarp);
148
			    assignp->widthSignedFrom(newvarp);
149
			    oldmodp->addStmtp(newvarp);
150
			    oldmodp->addStmtp(assignp);
151
			} else {
152
			    newvarp->varType2Out();
153
			    AstVarRef* lhsp = new AstVarRef(newvarp->fileline(), newvarp->name(), true);
154
			    AstVarXRef* rhsp = new AstVarXRef(newvarp->fileline(), ivarp->varp()->name(),
155
							      oldvarp->name(), false);
156
			    lhsp->varp(newvarp);
157
			    AstAssignW* assignp = new AstAssignW(newvarp->fileline(), lhsp, rhsp);
158
			    lhsp->widthSignedFrom(newvarp);
159
			    rhsp->widthSignedFrom(newvarp);
160
			    assignp->widthSignedFrom(newvarp);
161
			    oldmodp->addStmtp(newvarp);
162
			    oldmodp->addStmtp(assignp);
163
			}
164
		    }
165
		}
128 166
	    }
129 167
	}
130 168
    }
b/src/V3LinkParse.cpp
60 60
    AstText*	m_baseTextp;	// Lowest TEXT node that needs replacement with varref
61 61
    AstVar*	m_varp;		// Variable we're under
62 62
    ImplTypedefMap	m_implTypedef;	// Created typedefs for each <container,name>
63
    AstModule*	m_topModule;	// The top-level module we are under
63 64

  
64 65
    // METHODS
65 66
    static int debug() {
......
329 330
	nodep->deleteTree(); nodep=NULL;
330 331
    }
331 332

  
333
    virtual void visit(AstModule* nodep, AstNUser*) {
334
	// Look for interfaces in the port list of the top-level module
335
	if (nodep->level() == 2) {
336
	    m_topModule = nodep;
337
	}
338
	nodep->iterateChildren(*this);
339
	m_topModule = NULL;
340
    }
341

  
342
    virtual void visit(AstInterfaceDType* nodep, AstNUser*) {
343
	if (m_topModule) {
344
	    AstCell* cellp = new AstCell(nodep->fileline(), m_varp->name(), nodep->name(), NULL, NULL, NULL);
345
	    cellp->hasVar(true); // We created the Cell from an existing Var
346
	    m_topModule->addStmtp(cellp);
347
	}
348
    }
349

  
332 350
    virtual void visit(AstNode* nodep, AstNUser*) {
333 351
	// Default: Just iterate
334 352
	checkExpected(nodep);  // So we detect node types we forgot to list here
......
342 360
	m_exp = AstParseRefExp::NONE;
343 361
	m_baseTextp = NULL;
344 362
	m_varp = NULL;
363
	m_topModule = NULL;
345 364
	rootp->accept(*this);
346 365
    }
347 366
    virtual ~LinkParseVisitor() {}
b/src/V3Param.cpp
334 334
		// Note we allow multiple users of a parameterized model, thus we need to stash this info.
335 335
		for (AstNode* stmtp=modp->stmtsp(); stmtp; stmtp = stmtp->nextp()) {
336 336
		    if (AstVar* varp = stmtp->castVar()) {
337
			if (varp->isIO() || varp->isGParam()) {
337
			if (varp->isIO() || varp->isGParam() || varp->isInterface()) {
338 338
			    // Cloning saved a pointer to the new node for us, so just follow that link.
339 339
			    AstVar* oldvarp = varp->clonep()->castVar();
340 340
			    //UINFO(8,"Clone list 0x"<<hex<<(uint32_t)oldvarp<<" -> 0x"<<(uint32_t)varp<<endl);
b/src/V3ParseImp.h
65 65
	AstCase*	casep;
66 66
	AstCaseItem*	caseitemp;
67 67
	AstConst*	constp;
68
        AstModportVar*  modportvarp;
68 69
	AstNodeModule*	modulep;
69 70
	AstNodeDType*	dtypep;
70 71
	AstNodeFTask*	ftaskp;
b/src/V3Scope.cpp
149 149
	m_scopep->addActivep(clonep);
150 150
	clonep->iterateChildren(*this);	// We iterate under the *clone*
151 151
    }
152
    virtual void visit(AstAssignVarScope* nodep, AstNUser*) {
153
	// Copy under the scope but don't recurse, interfaces aren't linked yet
154
	UINFO(4,"    Move "<<nodep<<endl);
155
	AstNode* clonep = nodep->cloneTree(false);
156
	nodep->user2p(clonep);
157
	m_scopep->addActivep(clonep);
158
    }
152 159
    virtual void visit(AstAssignW* nodep, AstNUser*) {
153 160
	// Add to list of blocks under this scope
154 161
	UINFO(4,"    Move "<<nodep<<endl);
......
195 202
    virtual void visit(AstVar* nodep, AstNUser*) {
196 203
	// Make new scope variable
197 204
	if (!nodep->user1p()) {
198
	    AstVarScope* varscp = new AstVarScope(nodep->fileline(), m_scopep, nodep);
199
	    UINFO(6,"   New scope "<<varscp<<endl);
200
	    nodep->user1p(varscp);
201
	    m_scopep->addVarp(varscp);
205
	    if (nodep->isInterface()) {
206
		AstVarScope* varscp = new AstScopeAlias(nodep->fileline(), m_scopep, nodep, NULL);
207
		UINFO(6,"   New scope alias "<<varscp<<endl);
208
		nodep->user1p(varscp);
209
		m_scopep->addVarp(varscp);
210
	    } else {
211
		AstVarScope* varscp = new AstVarScope(nodep->fileline(), m_scopep, nodep);
212
		UINFO(6,"   New scope "<<varscp<<endl);
213
		nodep->user1p(varscp);
214
		m_scopep->addVarp(varscp);
215
	    }
202 216
	}
203 217
    }
204 218
    virtual void visit(AstVarRef* nodep, AstNUser*) {
205 219
	// VarRef needs to point to VarScope
206 220
	// Make sure variable has made user1p.
207
	nodep->varp()->accept(*this);
208
	AstVarScope* varscp = (AstVarScope*)nodep->varp()->user1p();
209
	if (!varscp) nodep->v3fatalSrc("Can't locate varref scope");
210
	nodep->varScopep(varscp);
221
	if (!nodep->varp()->isInterface()) {
222
	    nodep->varp()->accept(*this);
223
	    AstVarScope* varscp = (AstVarScope*)nodep->varp()->user1p();
224
	    if (!varscp) nodep->v3fatalSrc("Can't locate varref scope");
225
	    nodep->varScopep(varscp);
226
	} else {
227
	    nodep->varScopep(NULL);
228
	}
211 229
    }
212 230
    virtual void visit(AstScopeName* nodep, AstNUser*) {
213 231
	// If there's a %m in the display text, we add a special node that will contain the name()
......
285 303
    virtual void visit(AstAssignAlias* nodep, AstNUser*) {
286 304
	movedDeleteOrIterate(nodep);
287 305
    }
306
    virtual void visit(AstAssignVarScope* nodep, AstNUser*) {
307
	movedDeleteOrIterate(nodep);
308
    }
288 309
    virtual void visit(AstAssignW* nodep, AstNUser*) {
289 310
	movedDeleteOrIterate(nodep);
290 311
    }
b/src/V3Width.cpp
513 513
	// else width in node is correct; it was set based on keyword().width()
514 514
	// at construction time
515 515
    }
516
    virtual void visit(AstInterfaceDType* nodep, AstNUser* vup) {
517
	nodep->iterateChildren(*this, vup);
518
	nodep->width(1, 1);
519
    }
516 520
    virtual void visit(AstRefDType* nodep, AstNUser* vup) {
517 521
	nodep->iterateChildren(*this, vup);
518 522
	if (nodep->defp()) nodep->defp()->iterate(*this,vup);
b/src/Verilator.cpp
56 56
#include "V3GenClk.h"
57 57
#include "V3Inline.h"
58 58
#include "V3Inst.h"
59
#include "V3Interface.h"
59 60
#include "V3Life.h"
60 61
#include "V3LifePost.h"
61 62
#include "V3Link.h"
......
135 136

  
136 137
    // Convert parseref's to varrefs, and other directly post parsing fixups
137 138
    V3LinkParse::linkParse(v3Global.rootp());
139
    // Link any new cells created from interfaces (empty filter)
140
    V3InFilter filter (v3Global.opt.pipeFilter());
141
    V3LinkCells::link(v3Global.rootp(), &filter);
138 142
    // Cross-link signal names
139 143
    V3Link::link(v3Global.rootp());
140 144
    // Cross-link dotted hierarchical references
......
145 149
    V3LinkLValue::linkLValue(v3Global.rootp());
146 150
    v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("link.tree"));
147 151
    V3Error::abortIfErrors();
148

  
149 152
    if (v3Global.opt.stats()) V3Stats::statsStageAll(v3Global.rootp(), "Link");
150 153

  
151 154
    // Remove parameters by cloning modules to de-parameterized versions
......
194 197
    // Must do this after we know the width of any parameters
195 198
    // We also do it after coverage/assertion insertion so we don't 'cover' the top level.
196 199
    V3LinkLevel::wrapTop(v3Global.rootp());
200
    v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("linklevel.tree"));
201

  
202
    // Lint interfaces
203
    V3Interface::lint(v3Global.rootp());
204
    v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("interface.tree"));
197 205

  
198 206
    // Propagate constants into expressions
199 207
    V3Const::constifyAllLint(v3Global.rootp());
b/src/verilog.l
389 389
  "do"			{ FL; return yDO; }
390 390
  "endclocking"		{ FL; return yENDCLOCKING; }
391 391
  "endpackage"		{ FL; return yENDPACKAGE; }
392
  "endinterface"	{ FL; return yENDINTERFACE; }
392 393
  "endprogram"		{ FL; return yENDPROGRAM; }
393 394
  "endproperty"		{ FL; return yENDPROPERTY; }
394 395
  "enum"		{ FL; return yENUM; }
......
396 397
  "final"		{ FL; return yFINAL; }
397 398
  "iff"			{ FL; return yIFF; }
398 399
  "import"		{ FL; return yIMPORT; }
400
  "interface"		{ FL; return yINTERFACE; }
399 401
  "int"			{ FL; return yINT; }
400 402
  "logic"		{ FL; return yLOGIC; }
401 403
  "longint"		{ FL; return yLONGINT; }
404
  "modport"		{ FL; return yMODPORT; }
402 405
  "package"		{ FL; return yPACKAGE; }
403 406
  "priority"		{ FL; return yPRIORITY; }
404 407
  "program"		{ FL; return yPROGRAM; }
......
429 432
  "dist"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
430 433
  "endclass"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
431 434
  "endgroup"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
432
  "endinterface"	{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
433 435
  "endsequence"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
434 436
  "expect"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
435 437
  "extends"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
......
440 442
  "ignore_bins"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
441 443
  "illegal_bins"	{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
442 444
  "inside"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
443
  "interface"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
444 445
  "intersect"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
445 446
  "join_any"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
446 447
  "join_none"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
447 448
  "local"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
448 449
  "matches"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
449
  "modport"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
450 450
  "new"			{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
451 451
  "null"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
452 452
  "packed"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
b/src/verilog.y
287 287
%token<fl>		yENDCLOCKING	"endclocking"
288 288
%token<fl>		yENDFUNCTION	"endfunction"
289 289
%token<fl>		yENDGENERATE	"endgenerate"
290
%token<fl>		yENDINTERFACE	"endinterface"
290 291
%token<fl>		yENDMODULE	"endmodule"
291 292
%token<fl>		yENDPACKAGE	"endpackage"
292 293
%token<fl>		yENDPRIMITIVE	"endprimitive"
......
311 312
%token<fl>		yINITIAL	"initial"
312 313
%token<fl>		yINOUT		"inout"
313 314
%token<fl>		yINPUT		"input"
315
%token<fl>		yINTERFACE	"interface"
314 316
%token<fl>		yINT		"int"
315 317
%token<fl>		yINTEGER	"integer"
316 318
%token<fl>		yLOCALPARAM	"localparam"
317 319
%token<fl>		yLOGIC		"logic"
318 320
%token<fl>		yLONGINT	"longint"
321
%token<fl>		yMODPORT	"modport"
319 322
%token<fl>		yMODULE		"module"
320 323
%token<fl>		yNAND		"nand"
321 324
%token<fl>		yNEGEDGE	"negedge"
......
549 552
//  Blank lines for type insertion
550 553
//  Blank lines for type insertion
551 554
//  Blank lines for type insertion
555
//  Blank lines for type insertion
552 556

  
553 557
%start source_text
554 558

  
......
583 587

  
584 588
description:			// ==IEEE: description
585 589
		module_declaration			{ }
586
	//UNSUP	interface_declaration			{ }
590
	|	interface_declaration			{ }
587 591
	|	program_declaration			{ }
588 592
	|	package_declaration			{ }
589 593
	|	package_item				{ if ($1) GRAMMARP->unitPackage($1->fileline())->addStmtp($1); }
......
771 775
	//			// IEEE: interface_port_header port_identifier { unpacked_dimension }
772 776
	//			// Expanded interface_port_header
773 777
	//			// We use instantCb here because the non-port form looks just like a module instantiation
774
	//UNSUP	portDirNetE id/*interface*/                      idAny/*port*/ rangeListE sigAttrListE	{ VARDTYPE($2); VARDONEA($3, $4); PARSEP->instantCb(CRELINE(), $2, $3, $4); PINNUMINC(); }
778
		portDirNetE id/*interface*/                      idAny/*port*/ /* UNSUPP variable_dimensionListE*/ /* UNSUPP sigAttrListE */
779
			{ $$ = new AstPort(CRELINE(),PINNUMINC(),*$3);
780
			  $$->addNext(new AstVar($<fl>2,AstVarType(AstVarType::INTERFACE),*$3,new AstInterfaceDType($<fl>2,*$2))); }
775 781
	//UNSUP	portDirNetE yINTERFACE                           idAny/*port*/ rangeListE sigAttrListE	{ VARDTYPE($2); VARDONEA($3, $4); PINNUMINC(); }
776
	//UNSUP	portDirNetE id/*interface*/ '.' idAny/*modport*/ idAny/*port*/ rangeListE sigAttrListE	{ VARDTYPE($2); VARDONEA($5, $6); PARSEP->instantCb(CRELINE(), $2, $5, $6); PINNUMINC(); }
782
	|	portDirNetE id/*interface*/ '.' idAny/*modport*/ idAny/*port*/ /* UNSUPP rangeListE sigAttrListE */
783
			{ $$ = new AstPort(CRELINE(),PINNUMINC(),*$5);
784
			  $$->addNext(new AstVar($3,AstVarType(AstVarType::INTERFACE),*$5,new AstInterfaceDType($3,*$2,*$4))); }
777 785
	//UNSUP	portDirNetE yINTERFACE      '.' idAny/*modport*/ idAny/*port*/ rangeListE sigAttrListE	{ VARDTYPE($2); VARDONEA($5, $6); PINNUMINC(); }
786

  
778 787
	//
779 788
	//			// IEEE: ansi_port_declaration, with [port_direction] removed
780 789
	//			//   IEEE: [ net_port_header | interface_port_header ] port_identifier { unpacked_dimension }
......
807 816
	//UNSUP	portDirNetE signingE rangeList '.' portSig '(' portAssignExprE ')' sigAttrListE	{ UNSUP }
808 817
	//UNSUP	portDirNetE /*implicit*/       '.' portSig '(' portAssignExprE ')' sigAttrListE	{ UNSUP }
809 818
	//
810
		portDirNetE data_type           portSig variable_dimensionListE sigAttrListE
819
	|	portDirNetE data_type          portSig variable_dimensionListE sigAttrListE
811 820
			{ $$=$3; VARDTYPE($2); $$->addNextNull(VARDONEP($$,$4,$5)); }
812 821
	|	portDirNetE yVAR data_type      portSig variable_dimensionListE sigAttrListE
813 822
			{ $$=$4; VARDTYPE($3); $$->addNextNull(VARDONEP($$,$5,$6)); }
......
850 859
//**********************************************************************
851 860
// Interface headers
852 861

  
862
interface_declaration:		// IEEE: interface_declaration + interface_nonansi_header + interface_ansi_header:
863
	//			// timeunits_delcarationE is instead in interface_item
864
		intFront parameter_port_listE portsStarE ';'
865
			interface_itemListE yENDINTERFACE endLabelE
866
			{ if ($2) { $1->addStmtp($2); $2->v3error("Unsupported: Interfaces with parameters"); }
867
			  if ($3) $1->addStmtp($3);
868
			  if ($5) $1->addStmtp($5);
869
			  SYMP->popScope($1); }
870
	//UNSUPP yEXTERN	intFront parameter_port_listE portsStarE ';'	{ }
871
	;
872

  
873
intFront<modulep>:
874
		yINTERFACE lifetimeE idAny/*new_interface*/
875
			{ $$ = new AstInterface($1,*$3);
876
			  $$->inLibrary(true);
877
			  PARSEP->rootp()->addModulep($$);
878
			  SYMP->pushNew($$); }
879
	;
880

  
881
interface_itemListE<nodep>:
882
		/* empty */				{ $$ = NULL; }
883
	|	interface_itemList			{ $$ = $1; }
884
	;
885

  
886
interface_itemList<nodep>:
887
		interface_item				{ $$ = $1 }
888
	|	interface_itemList interface_item	{ $$ = $1->addNextNull($2) }
889
	;
890

  
891
interface_item<nodep>:		// IEEE: interface_item + non_port_interface_item
892
		port_declaration ';'			{ $$ = $1; }
893
	//			// IEEE: non_port_interface_item
894
	//UNSUP	generate_region				{ $$ = $1; }
895
	|	interface_or_generate_item		{ $$ = $1; }
896
	//UNSUP	program_declaration			{ $$ = $1; }
897
	//UNSUP	interface_declaration			{ $$ = $1; }
898
	|	timeunits_declaration			{ $$ = $1; }
899
	//			// See note in interface_or_generate item
900
	|	module_common_item			{ $$ = $1; }
901
	;
902

  
903
interface_or_generate_item<nodep>:  // ==IEEE: interface_or_generate_item
904
	//			    // module_common_item in interface_item, as otherwise duplicated
905
	//			    // with module_or_generate_item's module_common_item
906
		modport_declaration			{ $$ = $1; }
907
	//UNSUP	extern_tf_declaration			{ }
908
	;
909

  
853 910
//**********************************************************************
854 911
// Program headers
855 912

  
......
905 962
	|	generate_region				{ $$ = $1; }
906 963
	;
907 964

  
965
modport_declaration<nodep>:		// ==IEEE: modport_declaration
966
		yMODPORT modport_itemList ';'		{ $$ = $2; }
967
	;
968

  
969
modport_itemList<nodep>:		// IEEE: part of modport_declaration
970
		modport_item				{ $$ = $1; }
971
	|	modport_itemList ',' modport_item	{ $$ = $1->addNextNull($3) }
972
	;
973

  
974
modport_item<nodep>:			// ==IEEE: modport_item
975
		id/*new-modport*/ '(' modportPortsDeclList ')'		{ $$ = new AstModport($2,*$1,$3); }
976
	;
977

  
978
modportPortsDeclList<modportvarp>:
979
		modportPortsDecl			    { $$ = $1; }
980
	|	modportPortsDeclList ',' modportPortsDecl   { $$ = $1->addNextNull($3)->castModportVar(); }
981
	;
982

  
983
// IEEE: modport_ports_declaration  + modport_simple_ports_declaration
984
//	+ (modport_tf_ports_declaration+import_export) + modport_clocking_declaration
985
// We've expanded the lists each take to instead just have standalone ID ports.
986
// We track the type as with the V2k series of defines, then create as each ID is seen.
987
modportPortsDecl<modportvarp>:
988
	//			// IEEE: modport_simple_ports_declaration
989
		port_direction modportSimplePort	{ $$ = new AstModportVar($<fl>1,*$2,GRAMMARP->m_varIO); }
990
	//			// IEEE: modport_clocking_declaration
991
	//UNSUP	yCLOCKING idAny/*clocking_identifier*/	{ }
992
	//UNSUP	yIMPORT modport_tf_port			{ }
993
	//UNSUP	yEXPORT modport_tf_port			{ }
994
	// Continuations of above after a comma.
995
	//			// IEEE: modport_simple_ports_declaration
996
	|	modportSimplePort			{ $$ = new AstModportVar($<fl>1,*$1,AstVarType::INOUT); }
997
	;
998

  
999
modportSimplePort<strp>:	// IEEE: modport_simple_port or modport_tf_port, depending what keyword was earlier
1000
		id					{ $$ = $1; }
1001
	//UNSUP	'.' idAny '(' ')'			{ }
1002
	//UNSUP	'.' idAny '(' expr ')'			{ }
1003
	;
1004

  
908 1005
//************************************************
909 1006
// Variable Declarations
910 1007

  
b/test_regress/t/t_interface.pl
1
#!/usr/bin/perl
2
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
4
#
5
# Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
6
# redistribute it and/or modify it under the terms of either the GNU
7
# Lesser General Public License Version 3 or the Perl Artistic License
8
# Version 2.0.
9

  
10
compile (
11
	 v_flags => []
12
	 );
13

  
14
execute (
15
	 check_finished=>1,
16
     );
17

  
18
ok(1);
19
1;
b/test_regress/t/t_interface.v
1
// DESCRIPTION: Verilator: Verilog Test module
2
//
3
// This file ONLY is placed into the Public Domain, for any use,
4
// without warranty, 2006 by Wilson Snyder.
5

  
6
interface counter_io;
7
   logic [3:0] value;
8
   logic       reset;
9
endinterface
10

  
11
module t (/*AUTOARG*/
12
   // Inputs
13
   clk
14
   );
15

  
16
   input clk;
17
   integer cyc=1;
18

  
19
   counter_io c1_data();
20
   counter_io c2_data();
21

  
22
   counter    c1 (.clkm(clk),
23
	      .c_data(c1_data),
24
	      .i_value(4'h1));
25
   counter    c2 (.clkm(clk),
26
	      .c_data(c2_data),
27
	      .i_value(4'h2));
28

  
29
   initial begin
30
      c1_data.value = 4'h4;
31
      c2_data.value = 4'h5;
32
   end
33

  
34
   always @ (posedge clk) begin
35
      cyc <= cyc + 1;
36
      if (cyc<2) begin
37
	 c1_data.reset <= 1;
38
	 c2_data.reset <= 1;
39
      end
40
      if (cyc==2) begin
41
	 c1_data.reset <= 0;
42
	 c2_data.reset <= 0;
43
      end
44
      if (cyc==20) begin
45
	 $write("[%0t] c1 cyc%0d: %0x %0x\n", $time, cyc, c1_data.value, c1_data.reset);
46
	 $write("[%0t] c2 cyc%0d: %0x %0x\n", $time, cyc, c2_data.value, c2_data.reset);
47
	 if (c1_data.value != 2) $stop;
48
	 if (c2_data.value != 3) $stop;
49
	 $write("*-* All Finished *-*\n");
50
	 $finish;
51
      end
52
   end
53
endmodule
54

  
55
module counter
56
   (
57
   input clkm,
58
   counter_io c_data,
59
   input logic [3:0] i_value
60
   );
61

  
62
   always @ (posedge clkm) begin
63
      if (c_data.reset)
64
	 c_data.value <= i_value;
65
      else
66
	 c_data.value <= c_data.value + 1;
67
   end
68
endmodule : counter
b/test_regress/t/t_interface_inl.pl
1
#!/usr/bin/perl
2
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
4
#
5
# Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
6
# redistribute it and/or modify it under the terms of either the GNU
7
# Lesser General Public License Version 3 or the Perl Artistic License
8
# Version 2.0.
9

  
10
top_filename("t/t_interface.v");
11

  
12
compile (
13
	 # Avoid inlining so we find bugs in the non-inliner connection code
14
	 v_flags => ["-Oi"],
15
	 );
16

  
17
execute (
18
	 check_finished=>1,
19
     );
20

  
21
ok(1);
22
1;
... This diff was truncated because it exceeds the maximum size that can be displayed.