Support bind, to module names only, bug602.
This commit is contained in:
parent
aae0615ffd
commit
795e66eac9
2
Changes
2
Changes
|
|
@ -10,6 +10,8 @@ indicates the contributor was also the author of the fix; Thanks!
|
||||||
Verilated models. This may affect packed arrays that are public or
|
Verilated models. This may affect packed arrays that are public or
|
||||||
accessed via the VPI.
|
accessed via the VPI.
|
||||||
|
|
||||||
|
*** Support bind, to module names only, bug602. [Ed Lander]
|
||||||
|
|
||||||
* Verilator 3.844 2013/01/09
|
* Verilator 3.844 2013/01/09
|
||||||
|
|
||||||
*** Support "unsigned int" DPI import functions, msg966. [Alex Lee]
|
*** Support "unsigned int" DPI import functions, msg966. [Alex Lee]
|
||||||
|
|
|
||||||
|
|
@ -2327,6 +2327,11 @@ always @* to reduce missing activity items. Avoid putting $displays in
|
||||||
combo blocks, as they may print multiple times when not desired, even on
|
combo blocks, as they may print multiple times when not desired, even on
|
||||||
compliant simulators as event ordering is not specified.
|
compliant simulators as event ordering is not specified.
|
||||||
|
|
||||||
|
=head2 Bind
|
||||||
|
|
||||||
|
Verilator only supports "bind" to a target module name, not an instance
|
||||||
|
path.
|
||||||
|
|
||||||
=head2 Dotted cross-hierarchy references
|
=head2 Dotted cross-hierarchy references
|
||||||
|
|
||||||
Verilator supports dotted references to variables, functions and tasks in
|
Verilator supports dotted references to variables, functions and tasks in
|
||||||
|
|
|
||||||
|
|
@ -1331,6 +1331,25 @@ public:
|
||||||
virtual void name(const string& name) { m_name = name; }
|
virtual void name(const string& name) { m_name = name; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct AstBind : public AstNode {
|
||||||
|
// Parents: MODULE
|
||||||
|
// Children: CELL
|
||||||
|
private:
|
||||||
|
string m_name; // Binding to name
|
||||||
|
public:
|
||||||
|
AstBind(FileLine* fl, const string& name, AstNode* cellsp)
|
||||||
|
: AstNode(fl)
|
||||||
|
, m_name(name) {
|
||||||
|
if (!cellsp->castCell()) cellsp->v3fatalSrc("Only cells allowed to be bound");
|
||||||
|
addNOp1p(cellsp);
|
||||||
|
}
|
||||||
|
ASTNODE_NODE_FUNCS(Bind, BIND)
|
||||||
|
// ACCESSORS
|
||||||
|
virtual string name() const { return m_name; } // * = Bind Target name
|
||||||
|
virtual void name(const string& name) { m_name = name; }
|
||||||
|
AstNode* cellsp() const { return op1p(); } // op1= cells
|
||||||
|
};
|
||||||
|
|
||||||
struct AstPort : public AstNode {
|
struct AstPort : public AstNode {
|
||||||
// A port (in/out/inout) on a module
|
// A port (in/out/inout) on a module
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -90,6 +90,7 @@ private:
|
||||||
// NODE STATE
|
// NODE STATE
|
||||||
// Entire netlist:
|
// Entire netlist:
|
||||||
// AstNodeModule::user1p() // V3GraphVertex* Vertex describing this module
|
// AstNodeModule::user1p() // V3GraphVertex* Vertex describing this module
|
||||||
|
// AstCell::user1() // bool Did it.
|
||||||
// Allocated across all readFiles in V3Global::readFiles:
|
// Allocated across all readFiles in V3Global::readFiles:
|
||||||
// AstNode::user4p() // VSymEnt* Package and typedef symbol names
|
// AstNode::user4p() // VSymEnt* Package and typedef symbol names
|
||||||
AstUser1InUse m_inuser1;
|
AstUser1InUse m_inuser1;
|
||||||
|
|
@ -121,6 +122,26 @@ private:
|
||||||
return (nodep->user1p()->castGraphVertex());
|
return (nodep->user1p()->castGraphVertex());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AstNodeModule* resolveModule(AstNode* nodep, const string& modName) {
|
||||||
|
AstNodeModule* modp = m_mods.rootp()->findIdFallback(modName)->nodep()->castNodeModule();
|
||||||
|
if (!modp) {
|
||||||
|
// Read-subfile
|
||||||
|
// If file not found, make AstNotFoundModule, rather than error out.
|
||||||
|
// We'll throw the error when we know the module will really be needed.
|
||||||
|
V3Parse parser (v3Global.rootp(), m_filterp, m_parseSymp);
|
||||||
|
parser.parseFile(nodep->fileline(), modName, false, "");
|
||||||
|
V3Error::abortIfErrors();
|
||||||
|
// We've read new modules, grab new pointers to their names
|
||||||
|
readModNames();
|
||||||
|
// Check again
|
||||||
|
modp = m_mods.rootp()->findIdFallback(modName)->nodep()->castNodeModule();
|
||||||
|
if (!modp) {
|
||||||
|
nodep->v3error("Can't resolve module reference: "<<modName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return modp;
|
||||||
|
}
|
||||||
|
|
||||||
// VISITs
|
// VISITs
|
||||||
virtual void visit(AstNetlist* nodep, AstNUser*) {
|
virtual void visit(AstNetlist* nodep, AstNUser*) {
|
||||||
AstNode::user1ClearTree();
|
AstNode::user1ClearTree();
|
||||||
|
|
@ -180,6 +201,7 @@ private:
|
||||||
if (!m_libVertexp) m_libVertexp = new LibraryVertex(&m_graph);
|
if (!m_libVertexp) m_libVertexp = new LibraryVertex(&m_graph);
|
||||||
new V3GraphEdge(&m_graph, m_libVertexp, vertex(nodep), 1, false);
|
new V3GraphEdge(&m_graph, m_libVertexp, vertex(nodep), 1, false);
|
||||||
}
|
}
|
||||||
|
// Note AstBind also has iteration on cells
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
nodep->checkTree();
|
nodep->checkTree();
|
||||||
m_modp = NULL;
|
m_modp = NULL;
|
||||||
|
|
@ -192,28 +214,35 @@ private:
|
||||||
new V3GraphEdge(&m_graph, vertex(m_modp), vertex(nodep->packagep()), 1, false);
|
new V3GraphEdge(&m_graph, vertex(m_modp), vertex(nodep->packagep()), 1, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void visit(AstBind* nodep, AstNUser*) {
|
||||||
|
// Bind: Has cells underneath that need to be put into the new module, and cells which need resolution
|
||||||
|
// TODO this doesn't allow bind to dotted hier names, that would require
|
||||||
|
// this move to post param, which would mean we do not auto-read modules
|
||||||
|
// and means we cannot compute module levels until later.
|
||||||
|
UINFO(4,"Link Bind: "<<nodep<<endl);
|
||||||
|
AstNodeModule* modp = resolveModule(nodep,nodep->name());
|
||||||
|
if (modp) {
|
||||||
|
AstNode* cellsp = nodep->cellsp()->unlinkFrBackWithNext();
|
||||||
|
// Module may have already linked, so need to pick up these new cells
|
||||||
|
AstNodeModule* oldModp = m_modp;
|
||||||
|
{
|
||||||
|
m_modp = modp;
|
||||||
|
modp->addStmtp(cellsp); // Important that this adds to end, as next iterate assumes does all cells
|
||||||
|
cellsp->iterateAndNext(*this);
|
||||||
|
}
|
||||||
|
m_modp = oldModp;
|
||||||
|
}
|
||||||
|
pushDeletep(nodep->unlinkFrBack());
|
||||||
|
}
|
||||||
|
|
||||||
virtual void visit(AstCell* nodep, AstNUser*) {
|
virtual void visit(AstCell* nodep, AstNUser*) {
|
||||||
// Cell: Resolve its filename. If necessary, parse it.
|
// Cell: Resolve its filename. If necessary, parse it.
|
||||||
|
if (nodep->user1SetOnce()) return; // AstBind and AstNodeModule may call a cell twice
|
||||||
if (!nodep->modp()) {
|
if (!nodep->modp()) {
|
||||||
UINFO(4,"Link Cell: "<<nodep<<endl);
|
UINFO(4,"Link Cell: "<<nodep<<endl);
|
||||||
// Use findIdFallback instead of findIdFlat; it doesn't matter for now
|
// Use findIdFallback instead of findIdFlat; it doesn't matter for now
|
||||||
// but we might support modules-under-modules someday.
|
// but we might support modules-under-modules someday.
|
||||||
AstNodeModule* modp = m_mods.rootp()->findIdFallback(nodep->modName())->nodep()->castNodeModule();
|
AstNodeModule* modp = resolveModule(nodep,nodep->modName());
|
||||||
if (!modp) {
|
|
||||||
// Read-subfile
|
|
||||||
// If file not found, make AstNotFoundModule, rather than error out.
|
|
||||||
// We'll throw the error when we know the module will really be needed.
|
|
||||||
V3Parse parser (v3Global.rootp(), m_filterp, m_parseSymp);
|
|
||||||
parser.parseFile(nodep->fileline(), nodep->modName(), false, "");
|
|
||||||
V3Error::abortIfErrors();
|
|
||||||
// We've read new modules, grab new pointers to their names
|
|
||||||
readModNames();
|
|
||||||
// Check again
|
|
||||||
modp = m_mods.rootp()->findIdFallback(nodep->modName())->nodep()->castNodeModule();
|
|
||||||
if (!modp) {
|
|
||||||
nodep->v3error("Can't resolve module reference: "<<nodep->modName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (modp) {
|
if (modp) {
|
||||||
nodep->modp(modp);
|
nodep->modp(modp);
|
||||||
// Track module depths, so can sort list from parent down to children
|
// Track module depths, so can sort list from parent down to children
|
||||||
|
|
|
||||||
|
|
@ -398,6 +398,7 @@ word [a-zA-Z0-9_]+
|
||||||
"always_comb" { FL; return yALWAYS; }
|
"always_comb" { FL; return yALWAYS; }
|
||||||
"always_ff" { FL; return yALWAYS; }
|
"always_ff" { FL; return yALWAYS; }
|
||||||
"always_latch" { FL; return yALWAYS; }
|
"always_latch" { FL; return yALWAYS; }
|
||||||
|
"bind" { FL; return yBIND; }
|
||||||
"bit" { FL; return yBIT; }
|
"bit" { FL; return yBIT; }
|
||||||
"break" { FL; return yBREAK; }
|
"break" { FL; return yBREAK; }
|
||||||
"byte" { FL; return yBYTE; }
|
"byte" { FL; return yBYTE; }
|
||||||
|
|
@ -440,7 +441,6 @@ word [a-zA-Z0-9_]+
|
||||||
/* Note assert_strobe was in SystemVerilog 3.1, but removed for SystemVerilog 2005 */
|
/* Note assert_strobe was in SystemVerilog 3.1, but removed for SystemVerilog 2005 */
|
||||||
"$root" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
"$root" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||||
"alias" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
"alias" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||||
"bind" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
|
||||||
"bins" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
"bins" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||||
"binsof" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
"binsof" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||||
"class" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
"class" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||||
|
|
|
||||||
|
|
@ -282,6 +282,7 @@ class AstSenTree;
|
||||||
%token<fl> yASSIGN "assign"
|
%token<fl> yASSIGN "assign"
|
||||||
%token<fl> yAUTOMATIC "automatic"
|
%token<fl> yAUTOMATIC "automatic"
|
||||||
%token<fl> yBEGIN "begin"
|
%token<fl> yBEGIN "begin"
|
||||||
|
%token<fl> yBIND "bind"
|
||||||
%token<fl> yBIT "bit"
|
%token<fl> yBIT "bit"
|
||||||
%token<fl> yBREAK "break"
|
%token<fl> yBREAK "break"
|
||||||
%token<fl> yBUF "buf"
|
%token<fl> yBUF "buf"
|
||||||
|
|
@ -1512,7 +1513,7 @@ module_common_item<nodep>: // ==IEEE: module_common_item
|
||||||
// // + module_instantiation from module_or_generate_item
|
// // + module_instantiation from module_or_generate_item
|
||||||
| etcInst { $$ = $1; }
|
| etcInst { $$ = $1; }
|
||||||
| concurrent_assertion_item { $$ = $1; }
|
| concurrent_assertion_item { $$ = $1; }
|
||||||
//UNSUP bind_directive { $$ = $1; }
|
| bind_directive { $$ = $1; }
|
||||||
| continuous_assign { $$ = $1; }
|
| continuous_assign { $$ = $1; }
|
||||||
// // IEEE: net_alias
|
// // IEEE: net_alias
|
||||||
//UNSUP yALIAS variable_lvalue aliasEqList ';' { UNSUP }
|
//UNSUP yALIAS variable_lvalue aliasEqList ';' { UNSUP }
|
||||||
|
|
@ -1549,6 +1550,31 @@ module_or_generate_item_declaration<nodep>: // ==IEEE: module_or_generate_item_d
|
||||||
//UNSUP yDEFAULT yCLOCKING idAny/*new-clocking_identifier*/ ';' { $$ = $1; }
|
//UNSUP yDEFAULT yCLOCKING idAny/*new-clocking_identifier*/ ';' { $$ = $1; }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
bind_directive<nodep>: // ==IEEE: bind_directive + bind_target_scope
|
||||||
|
// // ';' - Note IEEE grammar is wrong, includes extra ';' - it's already in module_instantiation
|
||||||
|
// // We merged the rules - id may be a bind_target_instance or module_identifier or interface_identifier
|
||||||
|
yBIND bind_target_instance bind_instantiation { $$ = new AstBind($<fl>1,*$2,$3); }
|
||||||
|
| yBIND bind_target_instance ':' bind_target_instance_list bind_instantiation { $$=NULL; $1->v3error("Unsupported: Bind with instance list"); }
|
||||||
|
;
|
||||||
|
|
||||||
|
bind_target_instance_list: // ==IEEE: bind_target_instance_list
|
||||||
|
bind_target_instance { }
|
||||||
|
| bind_target_instance_list ',' bind_target_instance { }
|
||||||
|
;
|
||||||
|
|
||||||
|
bind_target_instance<strp>: // ==IEEE: bind_target_instance
|
||||||
|
//UNSUP hierarchical_identifierBit { }
|
||||||
|
idAny { $$ = $1; }
|
||||||
|
;
|
||||||
|
|
||||||
|
bind_instantiation<nodep>: // ==IEEE: bind_instantiation
|
||||||
|
// // IEEE: program_instantiation
|
||||||
|
// // IEEE: + module_instantiation
|
||||||
|
// // IEEE: + interface_instantiation
|
||||||
|
// // Need to get an AstBind instead of AstCell, so have special rules
|
||||||
|
instDecl { $$ = $1; }
|
||||||
|
;
|
||||||
|
|
||||||
//************************************************
|
//************************************************
|
||||||
// Generates
|
// Generates
|
||||||
//
|
//
|
||||||
|
|
|
||||||
|
|
@ -7,14 +7,12 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
|
||||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
# Version 2.0.
|
# Version 2.0.
|
||||||
|
|
||||||
$Self->{vlt} and $Self->unsupported("Verilator unsupported, bind");
|
|
||||||
|
|
||||||
compile (
|
compile (
|
||||||
);
|
);
|
||||||
|
|
||||||
execute (
|
execute (
|
||||||
check_finished=>1,
|
check_finished=>1,
|
||||||
);
|
);
|
||||||
|
|
||||||
ok(1);
|
ok(1);
|
||||||
1;
|
1;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# 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
|
||||||
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
|
# Version 2.0.
|
||||||
|
|
||||||
|
$Self->{vlt} and $Self->unsupported("Verilator unsupported, bug602");
|
||||||
|
|
||||||
|
compile (
|
||||||
|
);
|
||||||
|
|
||||||
|
execute (
|
||||||
|
check_finished=>1,
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
|
|
@ -0,0 +1,89 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2013 by Ed Lander.
|
||||||
|
|
||||||
|
`define check(got,expec) do if ((got) != (expec)) begin $display("Line%0d: Got 0x%0x Exp 0x%0x\n", `__LINE__, (got), (expec)); $stop; end while(0);
|
||||||
|
|
||||||
|
module t (/*AUTOARG*/
|
||||||
|
// Inputs
|
||||||
|
clk
|
||||||
|
);
|
||||||
|
input clk;
|
||||||
|
reg [7:0] p1;
|
||||||
|
reg [7:0] p2;
|
||||||
|
reg [7:0] p3;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
p1 = 8'h01;
|
||||||
|
p2 = 8'h02;
|
||||||
|
p3 = 8'h03;
|
||||||
|
end
|
||||||
|
|
||||||
|
parameter int param1 = 8'h11;
|
||||||
|
parameter int param2 = 8'h12;
|
||||||
|
parameter int param3 = 8'h13;
|
||||||
|
|
||||||
|
targetmod i_targetmod (/*AUTOINST*/
|
||||||
|
// Inputs
|
||||||
|
.clk (clk));
|
||||||
|
|
||||||
|
//Binding i_targetmod to mycheck --instantiates i_mycheck inside i_targetmod
|
||||||
|
//param1 not over-riden (as mycheck) (=> 0x31)
|
||||||
|
//param2 explicitly bound to targetmod value (=> 0x22)
|
||||||
|
//param3 explicitly bound to top value (=> 0x13)
|
||||||
|
//p1 implictly bound (.*), takes value from targetmod (=> 0x04)
|
||||||
|
//p2 explictly bound to targetmod (=> 0x05)
|
||||||
|
//p3 explictly bound to top (=> 0x03)
|
||||||
|
|
||||||
|
bind i_targetmod mycheck
|
||||||
|
#(
|
||||||
|
.param2(param2),
|
||||||
|
.param3(param3)
|
||||||
|
)
|
||||||
|
i_mycheck (.p2(p2), .p3(p3), .*);
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module targetmod (input clk);
|
||||||
|
reg [7:0] p1;
|
||||||
|
reg [7:0] p2;
|
||||||
|
reg [7:0] p3;
|
||||||
|
|
||||||
|
parameter int param1 = 8'h21;
|
||||||
|
parameter int param2 = 8'h22;
|
||||||
|
parameter int param3 = 8'h23;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
p1 = 8'h04;
|
||||||
|
p2 = 8'h05;
|
||||||
|
p3 = 8'h06;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module mycheck (/*AUTOARG*/
|
||||||
|
// Inputs
|
||||||
|
clk, p1, p2, p3
|
||||||
|
);
|
||||||
|
|
||||||
|
input clk;
|
||||||
|
input [7:0] p1;
|
||||||
|
input [7:0] p2;
|
||||||
|
input [7:0] p3;
|
||||||
|
|
||||||
|
parameter int param1 = 8'h31;
|
||||||
|
parameter int param2 = 8'h32;
|
||||||
|
parameter int param3 = 8'h33;
|
||||||
|
|
||||||
|
always @ (posedge clk) begin
|
||||||
|
`check(param1,8'h31);
|
||||||
|
`check(param2,8'h22);
|
||||||
|
`check(param3,8'h23);
|
||||||
|
`check(p1,8'h04);
|
||||||
|
`check(p2,8'h05);
|
||||||
|
`check(p3,8'h06);
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
|
@ -14,7 +14,7 @@ module t (/*AUTOARG*/);
|
||||||
c_t [17:16] d;
|
c_t [17:16] d;
|
||||||
} e_t;
|
} e_t;
|
||||||
|
|
||||||
`define check(got,expec) do if ((got) != (expec)) begin $display("Line%d: Got %b Exp %b\n", `__LINE__, (got), (expec)); $stop; end while(0);
|
`define check(got,expec) do if ((got) != (expec)) begin $display("Line%0d: Got %b Exp %b\n", `__LINE__, (got), (expec)); $stop; end while(0);
|
||||||
|
|
||||||
initial begin
|
initial begin
|
||||||
e_t e;
|
e_t e;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue