Support SystemVerilog .name and .* interconnect.

git-svn-id: file://localhost/svn/verilator/trunk/verilator@906 77ca24e4-aefa-0310-84f0-b9a241c72d87
This commit is contained in:
Wilson Snyder 2007-03-14 13:06:08 +00:00
parent 01e9bc4855
commit d2ce499b59
9 changed files with 149 additions and 11 deletions

View File

@ -5,6 +5,8 @@ indicates the contributor was also the author of the fix; Thanks!
* Verilator 3.64**
*** Support SystemVerilog .name and .* interconnect.
*** Support while and do-while loops.
**** Fix dotted bit reference to local memory. [Eugene Weber]

View File

@ -893,7 +893,7 @@ as the build system.
=head1 VERILOG 2001 (IEEE 1364-2001) SUPPORT
Verilator supports the more common Verilog 2001 language features. This
Verilator supports almost all Verilog 2001 language features. This
includes signed numbers, "always @*", comma separated sensitivity lists,
generate statements, multidimensional arrays, localparam, and C-style
declarations inside port lists.
@ -907,15 +907,16 @@ Verilator partially supports the uwire keyword.
=head1 SYSTEMVERILOG (IEEE 1800-2005) SUPPORT
Verilator currently has very minimal support for SystemVerilog as they
become more common, contact the author if a feature you need is missing.
Verilator currently has very minimal support for SystemVerilog. As
SystemVerilog features enter common usage they will be added. Contact the
author if a feature you need is missing.
Verilator implements the full SystemVerilog 1800-2005 preprocessor subset,
including function call-like preprocessor defines.
Verilator supports $bits, $countones, $error, $fatal, $info, $isunknown,
$onehot, $onehot0, $warning, always_comb, always_ff, always_latch, and
final.
$onehot, $onehot0, $warning, always_comb, always_ff, always_latch,
do-while, and final. It also supports .name and .* interconnection.
Verilator partially supports assert.

View File

@ -298,6 +298,7 @@ void AstCell::dump(ostream& str) {
this->AstNode::dump(str);
if (modp()) { str<<" -> "; modp()->dump(str); }
else { str<<" ->UNLINKED:"<<modName(); }
if (pinStar()) str<<" [.*]";
}
void AstCellInline::dump(ostream& str) {
this->AstNode::dump(str);
@ -307,6 +308,7 @@ void AstPin::dump(ostream& str) {
this->AstNode::dump(str);
if (modVarp()) { str<<" -> "; modVarp()->dump(str); }
else { str<<" ->UNLINKED"; }
if (svImplicit()) str<<" [.SV]";
}
void AstVarXRef::dump(ostream& str) {
this->AstNode::dump(str);

View File

@ -576,10 +576,11 @@ private:
int m_pinNum; // Pin number
string m_name; // Pin name, or "" for number based interconnect
AstVar* m_modVarp; // Input/output this pin connects to on submodule.
bool m_svImplicit; // Pin is SystemVerilog .name'ed
public:
AstPin(FileLine* fl, int pinNum, const string& name, AstNode* exprp)
:AstNode(fl)
,m_name(name) {
,m_name(name), m_svImplicit(false) {
m_pinNum = pinNum;
m_modVarp = NULL;
setNOp1p(exprp); }
@ -596,6 +597,8 @@ public:
AstNode* exprp() const { return op1p()->castNode(); } // op1 = Expression connected to pin
AstVar* modVarp() const { return m_modVarp; } // [After Link] Pointer to variable
void modVarp(AstVar* varp) { m_modVarp=varp; }
bool svImplicit() const { return m_svImplicit; }
void svImplicit(bool flag) { m_svImplicit=flag; }
};
struct AstModule : public AstNode {
@ -652,12 +655,14 @@ private:
string m_name; // Cell name
string m_origName; // Original name before dot addition
string m_modName; // Module the cell instances
bool m_pinStar; // Pin list has .*
AstModule* m_modp; // [AfterLink] Pointer to module instanced
public:
AstCell(FileLine* fl, const string& instName, const string& modName,
AstPin* pinsp, AstPin* paramsp, AstRange* rangep)
: AstNode(fl)
, m_name(instName), m_origName(instName), m_modName(modName), m_modp(NULL) {
, m_name(instName), m_origName(instName), m_modName(modName)
, m_pinStar(false), m_modp(NULL) {
addNOp1p(pinsp); addNOp2p(paramsp); setNOp3p(rangep); }
virtual ~AstCell() {}
virtual AstType type() const { return AstType::CELL;}
@ -674,6 +679,8 @@ public:
void origName(const string& name) { m_origName = name; }
string modName() const { return m_modName; } // * = Instance name
void modName(const string& name) { m_modName = name; }
bool pinStar() const { return m_pinStar; }
void pinStar(bool flag) { m_pinStar = flag; }
AstPin* pinsp() const { return op1p()->castPin(); } // op1 = List of cell ports
AstPin* paramsp() const { return op2p()->castPin(); } // op2 = List of parameter #(##) values
AstRange* rangep() const { return op3p()->castRange(); } // op3 = Range of arrayed instants (NULL=not ranged)

View File

@ -372,7 +372,8 @@ private:
}
}
// Deal with implicit definitions
if (m_idState==ID_RESOLVE && nodep->modVarp()) {
if (m_idState==ID_RESOLVE && nodep->modVarp()
&& !nodep->svImplicit()) { // SV 19.11.3: .name pins don't allow implicit decls
pinImplicitExprRecurse(nodep->exprp());
}
nodep->iterateChildren(*this);

View File

@ -163,6 +163,32 @@ private:
new V3GraphEdge(&m_graph, vertex(m_modp), vertex(modp), 1, false);
}
}
// Convert .* to list of pins
if (nodep->modp() && nodep->pinStar()) {
// Note what pins exist
UINFO(9," CELL .* connect "<<nodep<<endl);
V3SymTable ports; // Symbol table of all connected port names
for (AstPin* pinp = nodep->pinsp(); pinp; pinp=pinp->nextp()->castPin()) {
if (pinp->name()=="") pinp->v3error("Connect by position is illegal in .* connected cells");
if (!ports.findIdName(pinp->name())) {
ports.insert(pinp->name(), pinp);
}
}
// We search ports, rather then in/out declarations as they aren't resolved yet,
// and it's easier to do it now then in V3Link when we'd need to repeat steps.
for (AstNode* portnodep = nodep->modp()->stmtsp(); portnodep; portnodep=portnodep->nextp()) {
if (AstPort* portp = portnodep->castPort()) {
if (!ports.findIdName(portp->name())) {
UINFO(9," need PORT "<<portp<<endl);
// Create any not already connected
AstPin* newp = new AstPin(nodep->fileline(),0,portp->name(),
new AstVarRef(nodep->fileline(),portp->name(),false));
newp->svImplicit(true);
nodep->addPinsp(newp);
}
}
}
}
// Convert unnamed pins to pin number based assignments
for (AstPin* pinp = nodep->pinsp(); pinp; pinp=pinp->nextp()->castPin()) {
if (pinp->name()=="") pinp->name("__pinNumber"+cvtToStr(pinp->pinNum()));

View File

@ -53,6 +53,7 @@ public:
static AstCase* s_caseAttrp; // Current case statement for attribute adding
static AstRange* s_varRangep; // Pointer to range for next signal declaration
static int s_pinNum; // Pin number currently parsing
static bool s_pinStar; // Encountered SystemVerilog .*
static string s_instModule; // Name of module referenced for instantiations
static AstPin* s_instParamp; // Parameters for instantiations
static bool s_trace; // Tracing is turned on
@ -75,6 +76,7 @@ AstVarType V3Parse::s_varIO = AstVarType::UNKNOWN;
bool V3Parse::s_varSigned = false;
AstRange* V3Parse::s_varRangep = NULL;
int V3Parse::s_pinNum = -1;
bool V3Parse::s_pinStar = false;
string V3Parse::s_instModule;
AstPin* V3Parse::s_instParamp = NULL;
AstVar* V3Parse::s_varAttrp = NULL;
@ -108,6 +110,7 @@ class AstSenTree;
AstBegin* beginp;
AstCase* casep;
AstCaseItem* caseitemp;
AstCell* cellp;
AstConst* constp;
AstFunc* funcp;
AstFuncRef* funcrefp;
@ -240,7 +243,8 @@ class AstSenTree;
%type<varp> netSig netSigList
%type<rangep> rangeListE regrangeE anyrange rangeList delayrange portrangeE
%type<varp> param paramList
%type<nodep> instnameList instname
%type<nodep> instnameList
%type<cellp> instname
%type<pinp> cellpinList cellpinlist2 cellpinitemE instparamListE
%type<nodep> defpList defpOne
%type<sentreep> sensitivityE
@ -614,10 +618,10 @@ instnameList: instname { $$ = $1; }
| instnameList ',' instname { $$ = $1->addNext($3); }
;
instname: yID funcRange '(' cellpinList ')' { $$ = new AstCell($3,*$1,V3Parse::s_instModule,$4,V3Parse::s_instParamp,$2); }
instname: yID funcRange '(' cellpinList ')' { $$ = new AstCell($3,*$1,V3Parse::s_instModule,$4,V3Parse::s_instParamp,$2); $$->pinStar(V3Parse::s_pinStar); }
;
cellpinList: {V3Parse::s_pinNum=1;} cellpinlist2 { $$ = $2; }
cellpinList: {V3Parse::s_pinNum=1; V3Parse::s_pinStar=false; } cellpinlist2 { $$ = $2; }
;
cellpinlist2: cellpinitemE { $$ = $1; }
@ -625,6 +629,8 @@ cellpinlist2: cellpinitemE { $$ = $1; }
;
cellpinitemE: /* empty */ { $$ = NULL; V3Parse::s_pinNum++; }
| '.' '*' { $$ = NULL; if (V3Parse::s_pinStar) $1->v3error("Duplicate .* in a cell"); V3Parse::s_pinStar=true; }
| '.' yID { $$ = new AstPin($1,V3Parse::s_pinNum++,*$2,new AstVarRef($1,*$2,false)); $$->svImplicit(true);}
| '.' yID '(' ')' { $$ = NULL; V3Parse::s_pinNum++; }
| '.' yID '(' expr ')' { $$ = new AstPin($1,V3Parse::s_pinNum++,*$2,$4); }
| expr { $$ = new AstPin(CRELINE(),V3Parse::s_pinNum++,"",$1); }

18
test_regress/t/t_inst_sv.pl Executable file
View File

@ -0,0 +1,18 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; }
# $Id$
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 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.
compile (
);
execute (
check_finished=>1,
);
ok(1);
1;

View File

@ -0,0 +1,75 @@
// $Id$
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2007 by Wilson Snyder.
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
integer cyc; initial cyc=1;
supply0 [1:0] low;
supply1 [1:0] high;
reg [7:0] isizedwire;
reg ionewire;
wire oonewire;
wire [7:0] osizedreg; // From sub of t_inst_v2k_sub.v
t_inst sub
(
.osizedreg,
.oonewire,
// Inputs
.isizedwire (isizedwire[7:0]),
.*
//.ionewire (ionewire)
);
always @ (posedge clk) begin
if (cyc!=0) begin
cyc <= cyc + 1;
if (cyc==1) begin
ionewire <= 1'b1;
isizedwire <= 8'd8;
end
if (cyc==2) begin
if (low != 2'b00) $stop;
if (high != 2'b11) $stop;
if (oonewire !== 1'b1) $stop;
if (isizedwire !== 8'd8) $stop;
end
if (cyc==3) begin
ionewire <= 1'b0;
isizedwire <= 8'd7;
end
if (cyc==4) begin
if (oonewire !== 1'b0) $stop;
if (isizedwire !== 8'd7) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
end
end
endmodule
module t_inst
(
output reg [7:0] osizedreg,
output wire oonewire /*verilator public*/,
input [7:0] isizedwire,
input wire ionewire
);
assign oonewire = ionewire;
always @* begin
osizedreg = isizedwire;
end
endmodule