Merge pull request #975 from larsclausen/sv_const_var
Add support for `const` variables
This commit is contained in:
commit
999bcb6935
12
PExpr.h
12
PExpr.h
|
|
@ -172,7 +172,8 @@ class PExpr : public LineInfo {
|
||||||
virtual NetAssign_* elaborate_lval(Design*des,
|
virtual NetAssign_* elaborate_lval(Design*des,
|
||||||
NetScope*scope,
|
NetScope*scope,
|
||||||
bool is_cassign,
|
bool is_cassign,
|
||||||
bool is_force) const;
|
bool is_force,
|
||||||
|
bool is_init = false) const;
|
||||||
|
|
||||||
// This method returns true if the expression represents a
|
// This method returns true if the expression represents a
|
||||||
// structural net that can have multiple drivers. This is
|
// structural net that can have multiple drivers. This is
|
||||||
|
|
@ -262,7 +263,8 @@ class PEConcat : public PExpr {
|
||||||
virtual NetAssign_* elaborate_lval(Design*des,
|
virtual NetAssign_* elaborate_lval(Design*des,
|
||||||
NetScope*scope,
|
NetScope*scope,
|
||||||
bool is_cassign,
|
bool is_cassign,
|
||||||
bool is_force) const;
|
bool is_force,
|
||||||
|
bool is_init = false) const;
|
||||||
virtual bool is_collapsible_net(Design*des, NetScope*scope,
|
virtual bool is_collapsible_net(Design*des, NetScope*scope,
|
||||||
NetNet::PortType port_type) const;
|
NetNet::PortType port_type) const;
|
||||||
private:
|
private:
|
||||||
|
|
@ -361,7 +363,8 @@ class PEIdent : public PExpr {
|
||||||
virtual NetAssign_* elaborate_lval(Design*des,
|
virtual NetAssign_* elaborate_lval(Design*des,
|
||||||
NetScope*scope,
|
NetScope*scope,
|
||||||
bool is_cassign,
|
bool is_cassign,
|
||||||
bool is_force) const;
|
bool is_force,
|
||||||
|
bool is_init = false) const;
|
||||||
|
|
||||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||||
ivl_type_t type, unsigned flags) const;
|
ivl_type_t type, unsigned flags) const;
|
||||||
|
|
@ -647,7 +650,8 @@ class PENumber : public PExpr {
|
||||||
virtual NetAssign_* elaborate_lval(Design*des,
|
virtual NetAssign_* elaborate_lval(Design*des,
|
||||||
NetScope*scope,
|
NetScope*scope,
|
||||||
bool is_cassign,
|
bool is_cassign,
|
||||||
bool is_force) const;
|
bool is_force,
|
||||||
|
bool is_init = false) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
verinum*const value_;
|
verinum*const value_;
|
||||||
|
|
|
||||||
6
PWire.h
6
PWire.h
|
|
@ -68,6 +68,9 @@ class PWire : public PNamedItem {
|
||||||
NetNet::PortType get_port_type() const;
|
NetNet::PortType get_port_type() const;
|
||||||
bool set_port_type(NetNet::PortType);
|
bool set_port_type(NetNet::PortType);
|
||||||
|
|
||||||
|
void set_const(bool is_const) { is_const_ = is_const; };
|
||||||
|
bool get_const() const { return is_const_; };
|
||||||
|
|
||||||
void set_signed(bool flag);
|
void set_signed(bool flag);
|
||||||
bool get_signed() const;
|
bool get_signed() const;
|
||||||
|
|
||||||
|
|
@ -100,6 +103,9 @@ class PWire : public PNamedItem {
|
||||||
NetNet::PortType port_type_;
|
NetNet::PortType port_type_;
|
||||||
bool signed_;
|
bool signed_;
|
||||||
|
|
||||||
|
// Whether the wire is variable declared with the const keyword.
|
||||||
|
bool is_const_ = false;
|
||||||
|
|
||||||
// These members hold expressions for the bit width of the
|
// These members hold expressions for the bit width of the
|
||||||
// wire. If they do not exist, the wire is 1 bit wide. If they
|
// wire. If they do not exist, the wire is 1 bit wide. If they
|
||||||
// do exist, they represent the packed dimensions of the
|
// do exist, they represent the packed dimensions of the
|
||||||
|
|
|
||||||
|
|
@ -29,8 +29,9 @@ Statement::~Statement()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
PAssign_::PAssign_(PExpr*lval__, PExpr*ex, bool is_constant)
|
PAssign_::PAssign_(PExpr*lval__, PExpr*ex, bool is_constant, bool is_init)
|
||||||
: event_(0), count_(0), lval_(lval__), rval_(ex), is_constant_(is_constant)
|
: event_(0), count_(0), lval_(lval__), rval_(ex), is_constant_(is_constant),
|
||||||
|
is_init_(is_init)
|
||||||
{
|
{
|
||||||
delay_ = 0;
|
delay_ = 0;
|
||||||
}
|
}
|
||||||
|
|
@ -73,8 +74,8 @@ PAssign::PAssign(PExpr*lval__, PExpr*cnt, PEventStatement*d, PExpr*ex)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
PAssign::PAssign(PExpr*lval__, PExpr*ex, bool is_constant)
|
PAssign::PAssign(PExpr*lval__, PExpr*ex, bool is_constant, bool is_init)
|
||||||
: PAssign_(lval__, ex, is_constant), op_(0)
|
: PAssign_(lval__, ex, is_constant, is_init), op_(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,8 @@ class Statement : virtual public LineInfo {
|
||||||
*/
|
*/
|
||||||
class PAssign_ : public Statement {
|
class PAssign_ : public Statement {
|
||||||
public:
|
public:
|
||||||
explicit PAssign_(PExpr*lval, PExpr*ex, bool is_constant);
|
explicit PAssign_(PExpr*lval, PExpr*ex, bool is_constant,
|
||||||
|
bool is_init = false);
|
||||||
explicit PAssign_(PExpr*lval, PExpr*de, PExpr*ex);
|
explicit PAssign_(PExpr*lval, PExpr*de, PExpr*ex);
|
||||||
explicit PAssign_(PExpr*lval, PExpr*cnt, PEventStatement*de, PExpr*ex);
|
explicit PAssign_(PExpr*lval, PExpr*cnt, PEventStatement*de, PExpr*ex);
|
||||||
virtual ~PAssign_() =0;
|
virtual ~PAssign_() =0;
|
||||||
|
|
@ -122,6 +123,8 @@ class PAssign_ : public Statement {
|
||||||
PExpr* lval_;
|
PExpr* lval_;
|
||||||
PExpr* rval_;
|
PExpr* rval_;
|
||||||
bool is_constant_;
|
bool is_constant_;
|
||||||
|
// Whether the assignment is a variable initializer expression
|
||||||
|
bool is_init_ = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PAssign : public PAssign_ {
|
class PAssign : public PAssign_ {
|
||||||
|
|
@ -135,7 +138,7 @@ class PAssign : public PAssign_ {
|
||||||
explicit PAssign(PExpr*lval, char op, PExpr*ex);
|
explicit PAssign(PExpr*lval, char op, PExpr*ex);
|
||||||
explicit PAssign(PExpr*lval, PExpr*de, PExpr*ex);
|
explicit PAssign(PExpr*lval, PExpr*de, PExpr*ex);
|
||||||
explicit PAssign(PExpr*lval, PExpr*cnt, PEventStatement*de, PExpr*ex);
|
explicit PAssign(PExpr*lval, PExpr*cnt, PEventStatement*de, PExpr*ex);
|
||||||
explicit PAssign(PExpr*lval, PExpr*ex, bool is_constant);
|
explicit PAssign(PExpr*lval, PExpr*ex, bool is_constant, bool is_init);
|
||||||
~PAssign();
|
~PAssign();
|
||||||
|
|
||||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||||
|
|
|
||||||
19
elab_lval.cc
19
elab_lval.cc
|
|
@ -76,7 +76,7 @@ using namespace std;
|
||||||
* is to try to make a net elaboration, and see if the result is
|
* is to try to make a net elaboration, and see if the result is
|
||||||
* suitable for assignment.
|
* suitable for assignment.
|
||||||
*/
|
*/
|
||||||
NetAssign_* PExpr::elaborate_lval(Design*, NetScope*, bool, bool) const
|
NetAssign_* PExpr::elaborate_lval(Design*, NetScope*, bool, bool, bool) const
|
||||||
{
|
{
|
||||||
cerr << get_fileline() << ": Assignment l-value too complex." << endl;
|
cerr << get_fileline() << ": Assignment l-value too complex." << endl;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -98,7 +98,8 @@ NetAssign_* PExpr::elaborate_lval(Design*, NetScope*, bool, bool) const
|
||||||
NetAssign_* PEConcat::elaborate_lval(Design*des,
|
NetAssign_* PEConcat::elaborate_lval(Design*des,
|
||||||
NetScope*scope,
|
NetScope*scope,
|
||||||
bool is_cassign,
|
bool is_cassign,
|
||||||
bool is_force) const
|
bool is_force,
|
||||||
|
bool is_init) const
|
||||||
{
|
{
|
||||||
if (repeat_) {
|
if (repeat_) {
|
||||||
cerr << get_fileline() << ": error: Repeat concatenations make "
|
cerr << get_fileline() << ": error: Repeat concatenations make "
|
||||||
|
|
@ -119,7 +120,7 @@ NetAssign_* PEConcat::elaborate_lval(Design*des,
|
||||||
}
|
}
|
||||||
|
|
||||||
NetAssign_*tmp = parms_[idx]->elaborate_lval(des, scope,
|
NetAssign_*tmp = parms_[idx]->elaborate_lval(des, scope,
|
||||||
is_cassign, is_force);
|
is_cassign, is_force, is_init);
|
||||||
|
|
||||||
/* If the l-value doesn't elaborate, the error was
|
/* If the l-value doesn't elaborate, the error was
|
||||||
already detected and printed. We just skip it and let
|
already detected and printed. We just skip it and let
|
||||||
|
|
@ -157,7 +158,8 @@ NetAssign_* PEConcat::elaborate_lval(Design*des,
|
||||||
NetAssign_* PEIdent::elaborate_lval(Design*des,
|
NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||||
NetScope*scope,
|
NetScope*scope,
|
||||||
bool is_cassign,
|
bool is_cassign,
|
||||||
bool is_force) const
|
bool is_force,
|
||||||
|
bool is_init) const
|
||||||
{
|
{
|
||||||
|
|
||||||
if (debug_elaborate) {
|
if (debug_elaborate) {
|
||||||
|
|
@ -213,6 +215,13 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||||
<< endl;
|
<< endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (reg->get_const() && !is_init) {
|
||||||
|
cerr << get_fileline() << ": error: Assignment to const signal `"
|
||||||
|
<< reg->name() << "` is not allowed." << endl;
|
||||||
|
des->errors++;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
return elaborate_lval_var_(des, scope, is_force, is_cassign, reg,
|
return elaborate_lval_var_(des, scope, is_force, is_cassign, reg,
|
||||||
sr.type, member_path);
|
sr.type, member_path);
|
||||||
}
|
}
|
||||||
|
|
@ -1535,7 +1544,7 @@ bool PEIdent::elaborate_lval_net_packed_member_(Design*des, NetScope*scope,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*, bool, bool) const
|
NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*, bool, bool, bool) const
|
||||||
{
|
{
|
||||||
cerr << get_fileline() << ": error: Constant values not allowed "
|
cerr << get_fileline() << ": error: Constant values not allowed "
|
||||||
<< "in l-value expressions." << endl;
|
<< "in l-value expressions." << endl;
|
||||||
|
|
|
||||||
|
|
@ -556,6 +556,12 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||||
<< endl;
|
<< endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sig->get_const()) {
|
||||||
|
cerr << get_fileline() << ": error: Continuous assignment to const"
|
||||||
|
<< " signal `" << sig->name() << "` is not allowed." << endl;
|
||||||
|
des->errors++;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
// If this is SystemVerilog and the variable is not yet
|
// If this is SystemVerilog and the variable is not yet
|
||||||
// assigned by anything, then convert it to an unresolved
|
// assigned by anything, then convert it to an unresolved
|
||||||
|
|
|
||||||
|
|
@ -1204,5 +1204,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||||
for (unsigned idx = 0 ; idx < nattrib ; idx += 1)
|
for (unsigned idx = 0 ; idx < nattrib ; idx += 1)
|
||||||
sig->attribute(attrib_list[idx].key, attrib_list[idx].val);
|
sig->attribute(attrib_list[idx].key, attrib_list[idx].val);
|
||||||
|
|
||||||
|
sig->set_const(is_const_);
|
||||||
|
|
||||||
return sig;
|
return sig;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2378,7 +2378,7 @@ NetAssign_* PAssign_::elaborate_lval(Design*des, NetScope*scope) const
|
||||||
<< "lval_ expr type = " << typeid(*lval_).name() << endl;
|
<< "lval_ expr type = " << typeid(*lval_).name() << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
return lval_->elaborate_lval(des, scope, false, false);
|
return lval_->elaborate_lval(des, scope, false, false, is_init_);
|
||||||
}
|
}
|
||||||
|
|
||||||
NetExpr* PAssign_::elaborate_rval_(Design*des, NetScope*scope,
|
NetExpr* PAssign_::elaborate_rval_(Design*des, NetScope*scope,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
// Check that const variables in module scope are supported.
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
const integer x = 10;
|
||||||
|
|
||||||
|
// The initializer expression is allowed to reference other const variables.
|
||||||
|
const integer y = 20 + x;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
if (x === 10 && y === 30) begin
|
||||||
|
$display("PASSED");
|
||||||
|
end else begin
|
||||||
|
$display("FAILED");
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
// Check that const variables are supported in function and task scope.
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
function automatic integer f(integer x);
|
||||||
|
// Automatic const variables can have a non-const initializer epxression
|
||||||
|
const integer y = 2 * x;
|
||||||
|
return y;
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
task automatic t(input integer x, output integer y);
|
||||||
|
// Automatic const variables can have a non-const initializer epxression
|
||||||
|
const integer z = 2 * x;
|
||||||
|
y = z;
|
||||||
|
endtask
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
integer y;
|
||||||
|
|
||||||
|
t(15, y);
|
||||||
|
|
||||||
|
if (f(10) === 20 && y === 30) begin
|
||||||
|
$display("PASSED");
|
||||||
|
end else begin
|
||||||
|
$display("FAILED");
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
// Check that const variables in block scope are supported.
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
const static integer x = 10;
|
||||||
|
// The initializer expression is allowed to reference other const variables.
|
||||||
|
const static integer y = 20 + x;
|
||||||
|
|
||||||
|
if (x === 10 && y === 30) begin
|
||||||
|
$display("PASSED");
|
||||||
|
end else begin
|
||||||
|
$display("FAILED");
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
// Check that const variables are supported in the unit scope.
|
||||||
|
|
||||||
|
const integer x = 10;
|
||||||
|
|
||||||
|
// The initializer expression is allowed to reference other const variables.
|
||||||
|
const integer y = 20 + x;
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
if (x === 10 && y === 30) begin
|
||||||
|
$display("PASSED");
|
||||||
|
end else begin
|
||||||
|
$display("FAILED");
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
// Check that const variables are supported in a package scope.
|
||||||
|
|
||||||
|
package P;
|
||||||
|
const integer x = 10;
|
||||||
|
|
||||||
|
// The initializer expression is allowed to reference other const variables.
|
||||||
|
const integer y = 20 + x;
|
||||||
|
endpackage
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
if (P::x === 10 && P::y === 30) begin
|
||||||
|
$display("PASSED");
|
||||||
|
end else begin
|
||||||
|
$display("FAILED");
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
// Check that continuous assignment to a const variable fails.
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
const integer x = 10;
|
||||||
|
|
||||||
|
assign x = 20; // Error: Assignment to const variable
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
$display("FAILED");
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
// Check that blocking assignment to a const variable fails.
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
const integer x = 10;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
x = 20; // Error: Assignment to const variable
|
||||||
|
$display("FAILED");
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
// Check that non-blocking assignment to a const variable fails.
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
const integer x = 10;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
x <= 20; // Error: Assignment to const variable
|
||||||
|
$display("FAILED");
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
// Check that force assignment to a const variable fails.
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
const integer x = 10;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
force x = 20; // Error: Assignment to const variable
|
||||||
|
$display("FAILED");
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
// Check that procedural continuous assignment to a const variable fails.
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
const integer x = 10;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
assign x = 20; // Error: Assignment to const variable
|
||||||
|
$display("FAILED");
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
// Check that binding a const variable to a task output port fails.
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
const integer x = 10;
|
||||||
|
|
||||||
|
task t(output integer x);
|
||||||
|
x = 20;
|
||||||
|
endtask
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
t(x);
|
||||||
|
$display("FAILED");
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
// Check that binding a const variable to a module output port fails.
|
||||||
|
|
||||||
|
module M(
|
||||||
|
output integer x
|
||||||
|
);
|
||||||
|
assign x = 20;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
const integer x = 10;
|
||||||
|
|
||||||
|
M i_m (
|
||||||
|
.x (x)
|
||||||
|
);
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
$display("FAILED");
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
// Check that binding a const variable to a module inout port fails.
|
||||||
|
|
||||||
|
module M(
|
||||||
|
inout integer x
|
||||||
|
);
|
||||||
|
assign x = 20;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
const integer x = 10;
|
||||||
|
|
||||||
|
M i_m (
|
||||||
|
.x (x)
|
||||||
|
);
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
$display("FAILED");
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -60,6 +60,19 @@ sv_array_assign_fail1 vvp_tests/sv_array_assign_fail1.json
|
||||||
sv_array_assign_fail2 vvp_tests/sv_array_assign_fail2.json
|
sv_array_assign_fail2 vvp_tests/sv_array_assign_fail2.json
|
||||||
sv_array_cassign6 vvp_tests/sv_array_cassign6.json
|
sv_array_cassign6 vvp_tests/sv_array_cassign6.json
|
||||||
sv_array_cassign7 vvp_tests/sv_array_cassign7.json
|
sv_array_cassign7 vvp_tests/sv_array_cassign7.json
|
||||||
|
sv_const1 vvp_tests/sv_const1.json
|
||||||
|
sv_const2 vvp_tests/sv_const2.json
|
||||||
|
sv_const3 vvp_tests/sv_const3.json
|
||||||
|
sv_const4 vvp_tests/sv_const4.json
|
||||||
|
sv_const5 vvp_tests/sv_const5.json
|
||||||
|
sv_const_fail1 vvp_tests/sv_const_fail1.json
|
||||||
|
sv_const_fail2 vvp_tests/sv_const_fail2.json
|
||||||
|
sv_const_fail3 vvp_tests/sv_const_fail3.json
|
||||||
|
sv_const_fail4 vvp_tests/sv_const_fail4.json
|
||||||
|
sv_const_fail5 vvp_tests/sv_const_fail5.json
|
||||||
|
sv_const_fail6 vvp_tests/sv_const_fail6.json
|
||||||
|
sv_const_fail7 vvp_tests/sv_const_fail7.json
|
||||||
|
sv_const_fail8 vvp_tests/sv_const_fail8.json
|
||||||
sv_foreach9 vvp_tests/sv_foreach9.json
|
sv_foreach9 vvp_tests/sv_foreach9.json
|
||||||
sv_foreach10 vvp_tests/sv_foreach10.json
|
sv_foreach10 vvp_tests/sv_foreach10.json
|
||||||
sv_module_port1 vvp_tests/sv_module_port1.json
|
sv_module_port1 vvp_tests/sv_module_port1.json
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"type" : "normal",
|
||||||
|
"source" : "sv_const1.v",
|
||||||
|
"iverilog-args" : [ "-g2005-sv" ]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"type" : "normal",
|
||||||
|
"source" : "sv_const2.v",
|
||||||
|
"iverilog-args" : [ "-g2005-sv" ]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"type" : "normal",
|
||||||
|
"source" : "sv_const3.v",
|
||||||
|
"iverilog-args" : [ "-g2005-sv" ]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"type" : "normal",
|
||||||
|
"source" : "sv_const4.v",
|
||||||
|
"iverilog-args" : [ "-g2005-sv" ]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"type" : "normal",
|
||||||
|
"source" : "sv_const5.v",
|
||||||
|
"iverilog-args" : [ "-g2005-sv" ]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"type" : "CE",
|
||||||
|
"source" : "sv_const_fail1.v",
|
||||||
|
"iverilog-args" : [ "-g2005-sv" ]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"type" : "CE",
|
||||||
|
"source" : "sv_const_fail2.v",
|
||||||
|
"iverilog-args" : [ "-g2005-sv" ]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"type" : "CE",
|
||||||
|
"source" : "sv_const_fail3.v",
|
||||||
|
"iverilog-args" : [ "-g2005-sv" ]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"type" : "CE",
|
||||||
|
"source" : "sv_const_fail4.v",
|
||||||
|
"iverilog-args" : [ "-g2005-sv" ]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"type" : "CE",
|
||||||
|
"source" : "sv_const_fail5.v",
|
||||||
|
"iverilog-args" : [ "-g2005-sv" ]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"type" : "CE",
|
||||||
|
"source" : "sv_const_fail6.v",
|
||||||
|
"iverilog-args" : [ "-g2005-sv" ]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"type" : "CE",
|
||||||
|
"source" : "sv_const_fail7.v",
|
||||||
|
"iverilog-args" : [ "-g2005-sv" ]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"type" : "CE",
|
||||||
|
"source" : "sv_const_fail8.v",
|
||||||
|
"iverilog-args" : [ "-g2005-sv" ]
|
||||||
|
}
|
||||||
|
|
@ -702,6 +702,9 @@ class NetNet : public NetObj, public PortType {
|
||||||
signed. Otherwise, it is unsigned. */
|
signed. Otherwise, it is unsigned. */
|
||||||
bool get_signed() const;
|
bool get_signed() const;
|
||||||
|
|
||||||
|
void set_const(bool is_const) { is_const_ = is_const; }
|
||||||
|
bool get_const() const { return is_const_; }
|
||||||
|
|
||||||
bool get_scalar() const;
|
bool get_scalar() const;
|
||||||
|
|
||||||
inline const ivl_type_s* net_type(void) const { return net_type_; }
|
inline const ivl_type_s* net_type(void) const { return net_type_; }
|
||||||
|
|
@ -808,6 +811,9 @@ class NetNet : public NetObj, public PortType {
|
||||||
netuarray_t *array_type_ = nullptr;
|
netuarray_t *array_type_ = nullptr;
|
||||||
ivl_discipline_t discipline_;
|
ivl_discipline_t discipline_;
|
||||||
|
|
||||||
|
// Whether the net is variable declared with the const keyword.
|
||||||
|
bool is_const_ = false;
|
||||||
|
|
||||||
std::vector<netrange_t> unpacked_dims_;
|
std::vector<netrange_t> unpacked_dims_;
|
||||||
|
|
||||||
// These are the widths of the various slice depths. There is
|
// These are the widths of the various slice depths. There is
|
||||||
|
|
|
||||||
50
parse.y
50
parse.y
|
|
@ -639,7 +639,7 @@ Module::port_t *module_declare_port(const YYLTYPE&loc, char *id,
|
||||||
%type <number> number pos_neg_number
|
%type <number> number pos_neg_number
|
||||||
%type <flag> signing unsigned_signed_opt signed_unsigned_opt
|
%type <flag> signing unsigned_signed_opt signed_unsigned_opt
|
||||||
%type <flag> import_export
|
%type <flag> import_export
|
||||||
%type <flag> K_genvar_opt K_static_opt K_virtual_opt
|
%type <flag> K_genvar_opt K_static_opt K_virtual_opt K_const_opt
|
||||||
%type <flag> udp_reg_opt edge_operator
|
%type <flag> udp_reg_opt edge_operator
|
||||||
%type <drive> drive_strength drive_strength_opt dr_strength0 dr_strength1
|
%type <drive> drive_strength drive_strength_opt dr_strength0 dr_strength1
|
||||||
%type <letter> udp_input_sym udp_output_sym
|
%type <letter> udp_input_sym udp_output_sym
|
||||||
|
|
@ -1231,21 +1231,22 @@ constraint_set /* IEEE1800-2005 A.1.9 */
|
||||||
;
|
;
|
||||||
|
|
||||||
data_declaration /* IEEE1800-2005: A.2.1.3 */
|
data_declaration /* IEEE1800-2005: A.2.1.3 */
|
||||||
: attribute_list_opt data_type list_of_variable_decl_assignments ';'
|
: attribute_list_opt K_const_opt data_type list_of_variable_decl_assignments ';'
|
||||||
{ data_type_t*data_type = $2;
|
{ data_type_t *data_type = $3;
|
||||||
if (data_type == 0) {
|
if (!data_type) {
|
||||||
data_type = new vector_type_t(IVL_VT_LOGIC, false, 0);
|
data_type = new vector_type_t(IVL_VT_LOGIC, false, 0);
|
||||||
FILE_NAME(data_type, @2);
|
FILE_NAME(data_type, @3);
|
||||||
}
|
}
|
||||||
pform_makewire(@2, 0, str_strength, $3, NetNet::IMPLICIT_REG, data_type, $1);
|
pform_makewire(@3, 0, str_strength, $4, NetNet::IMPLICIT_REG, data_type,
|
||||||
|
$1, $2);
|
||||||
}
|
}
|
||||||
| attribute_list_opt K_var data_type_or_implicit list_of_variable_decl_assignments ';'
|
| attribute_list_opt K_const_opt K_var data_type_or_implicit list_of_variable_decl_assignments ';'
|
||||||
{ data_type_t*data_type = $3;
|
{ data_type_t *data_type = $4;
|
||||||
if (data_type == 0) {
|
if (!data_type) {
|
||||||
data_type = new vector_type_t(IVL_VT_LOGIC, false, 0);
|
data_type = new vector_type_t(IVL_VT_LOGIC, false, 0);
|
||||||
FILE_NAME(data_type, @2);
|
FILE_NAME(data_type, @3);
|
||||||
}
|
}
|
||||||
pform_make_var(@2, $4, data_type, $1);
|
pform_make_var(@3, $5, data_type, $1, $2);
|
||||||
}
|
}
|
||||||
| attribute_list_opt K_event event_variable_list ';'
|
| attribute_list_opt K_event event_variable_list ';'
|
||||||
{ if ($3) pform_make_events(@2, $3);
|
{ if ($3) pform_make_events(@2, $3);
|
||||||
|
|
@ -2731,24 +2732,24 @@ block_item_decl
|
||||||
/* variable declarations. Note that data_type can be 0 if we are
|
/* variable declarations. Note that data_type can be 0 if we are
|
||||||
recovering from an error. */
|
recovering from an error. */
|
||||||
|
|
||||||
: K_var variable_lifetime_opt data_type_or_implicit list_of_variable_decl_assignments ';'
|
: K_const_opt K_var variable_lifetime_opt data_type_or_implicit list_of_variable_decl_assignments ';'
|
||||||
{ data_type_t*data_type = $3;
|
{ data_type_t *data_type = $4;
|
||||||
if (data_type == 0) {
|
if (!data_type) {
|
||||||
data_type = new vector_type_t(IVL_VT_LOGIC, false, 0);
|
data_type = new vector_type_t(IVL_VT_LOGIC, false, 0);
|
||||||
FILE_NAME(data_type, @1);
|
FILE_NAME(data_type, @2);
|
||||||
}
|
}
|
||||||
pform_make_var(@1, $4, data_type, attributes_in_context);
|
pform_make_var(@2, $5, data_type, attributes_in_context);
|
||||||
var_lifetime = LexicalScope::INHERITED;
|
var_lifetime = LexicalScope::INHERITED;
|
||||||
}
|
}
|
||||||
|
|
||||||
| variable_lifetime_opt data_type list_of_variable_decl_assignments ';'
|
| K_const_opt variable_lifetime_opt data_type list_of_variable_decl_assignments ';'
|
||||||
{ if ($2) pform_make_var(@2, $3, $2, attributes_in_context);
|
{ if ($3) pform_make_var(@3, $4, $3, attributes_in_context, $1);
|
||||||
var_lifetime = LexicalScope::INHERITED;
|
var_lifetime = LexicalScope::INHERITED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The extra `reg` is not valid (System)Verilog, this is a iverilog extension. */
|
/* The extra `reg` is not valid (System)Verilog, this is a iverilog extension. */
|
||||||
| variable_lifetime_opt K_reg data_type list_of_variable_decl_assignments ';'
|
| K_const_opt variable_lifetime_opt K_reg data_type list_of_variable_decl_assignments ';'
|
||||||
{ if ($3) pform_make_var(@3, $4, $3, attributes_in_context);
|
{ if ($4) pform_make_var(@4, $5, $4, attributes_in_context, $1);
|
||||||
var_lifetime = LexicalScope::INHERITED;
|
var_lifetime = LexicalScope::INHERITED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2769,11 +2770,11 @@ block_item_decl
|
||||||
/* Recover from errors that happen within variable lists. Use the
|
/* Recover from errors that happen within variable lists. Use the
|
||||||
trailing semi-colon to resync the parser. */
|
trailing semi-colon to resync the parser. */
|
||||||
|
|
||||||
| K_var variable_lifetime_opt data_type_or_implicit error ';'
|
| K_const_opt K_var variable_lifetime_opt data_type_or_implicit error ';'
|
||||||
{ yyerror(@1, "error: Syntax error in variable list.");
|
{ yyerror(@1, "error: Syntax error in variable list.");
|
||||||
yyerrok;
|
yyerrok;
|
||||||
}
|
}
|
||||||
| variable_lifetime_opt data_type error ';'
|
| K_const_opt variable_lifetime_opt data_type error ';'
|
||||||
{ yyerror(@1, "error: Syntax error in variable list.");
|
{ yyerror(@1, "error: Syntax error in variable list.");
|
||||||
yyerrok;
|
yyerrok;
|
||||||
}
|
}
|
||||||
|
|
@ -7308,6 +7309,11 @@ unique_priority
|
||||||
presence is significant. This is a fairly common pattern so
|
presence is significant. This is a fairly common pattern so
|
||||||
collect those rules here. */
|
collect those rules here. */
|
||||||
|
|
||||||
|
K_const_opt
|
||||||
|
: K_const { $$ = true; }
|
||||||
|
| { $$ = false; }
|
||||||
|
;
|
||||||
|
|
||||||
K_genvar_opt
|
K_genvar_opt
|
||||||
: K_genvar { $$ = true; }
|
: K_genvar { $$ = true; }
|
||||||
| { $$ = false; }
|
| { $$ = false; }
|
||||||
|
|
|
||||||
16
pform.cc
16
pform.cc
|
|
@ -951,11 +951,13 @@ PCallTask* pform_make_call_task(const struct vlltype&loc,
|
||||||
|
|
||||||
void pform_make_var(const struct vlltype&loc,
|
void pform_make_var(const struct vlltype&loc,
|
||||||
std::list<decl_assignment_t*>*assign_list,
|
std::list<decl_assignment_t*>*assign_list,
|
||||||
data_type_t*data_type, std::list<named_pexpr_t>*attr)
|
data_type_t*data_type, std::list<named_pexpr_t>*attr,
|
||||||
|
bool is_const)
|
||||||
{
|
{
|
||||||
static const struct str_pair_t str = { IVL_DR_STRONG, IVL_DR_STRONG };
|
static const struct str_pair_t str = { IVL_DR_STRONG, IVL_DR_STRONG };
|
||||||
|
|
||||||
pform_makewire(loc, 0, str, assign_list, NetNet::REG, data_type, attr);
|
pform_makewire(loc, 0, str, assign_list, NetNet::REG, data_type, attr,
|
||||||
|
is_const);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pform_make_foreach_declarations(const struct vlltype&loc,
|
void pform_make_foreach_declarations(const struct vlltype&loc,
|
||||||
|
|
@ -2494,7 +2496,7 @@ void pform_make_var_init(const struct vlltype&li,
|
||||||
|
|
||||||
PEIdent*lval = new PEIdent(name);
|
PEIdent*lval = new PEIdent(name);
|
||||||
FILE_NAME(lval, li);
|
FILE_NAME(lval, li);
|
||||||
PAssign*ass = new PAssign(lval, expr, !gn_system_verilog());
|
PAssign*ass = new PAssign(lval, expr, !gn_system_verilog(), true);
|
||||||
FILE_NAME(ass, li);
|
FILE_NAME(ass, li);
|
||||||
|
|
||||||
lexical_scope->var_inits.push_back(ass);
|
lexical_scope->var_inits.push_back(ass);
|
||||||
|
|
@ -2646,7 +2648,8 @@ void pform_makewire(const struct vlltype&li,
|
||||||
std::list<decl_assignment_t*>*assign_list,
|
std::list<decl_assignment_t*>*assign_list,
|
||||||
NetNet::Type type,
|
NetNet::Type type,
|
||||||
data_type_t*data_type,
|
data_type_t*data_type,
|
||||||
list<named_pexpr_t>*attr)
|
list<named_pexpr_t>*attr,
|
||||||
|
bool is_const)
|
||||||
{
|
{
|
||||||
if (is_compilation_unit(lexical_scope) && !gn_system_verilog()) {
|
if (is_compilation_unit(lexical_scope) && !gn_system_verilog()) {
|
||||||
VLerror(li, "error: Variable declarations must be contained within a module.");
|
VLerror(li, "error: Variable declarations must be contained within a module.");
|
||||||
|
|
@ -2662,7 +2665,7 @@ void pform_makewire(const struct vlltype&li,
|
||||||
wires->push_back(wire);
|
wires->push_back(wire);
|
||||||
}
|
}
|
||||||
|
|
||||||
pform_set_data_type(li, data_type, wires, type, attr);
|
pform_set_data_type(li, data_type, wires, type, attr, is_const);
|
||||||
|
|
||||||
while (! assign_list->empty()) {
|
while (! assign_list->empty()) {
|
||||||
decl_assignment_t*first = assign_list->front();
|
decl_assignment_t*first = assign_list->front();
|
||||||
|
|
@ -3224,7 +3227,7 @@ void pform_set_port_type(const struct vlltype&li,
|
||||||
*/
|
*/
|
||||||
void pform_set_data_type(const struct vlltype&li, data_type_t*data_type,
|
void pform_set_data_type(const struct vlltype&li, data_type_t*data_type,
|
||||||
std::vector<PWire*> *wires, NetNet::Type net_type,
|
std::vector<PWire*> *wires, NetNet::Type net_type,
|
||||||
list<named_pexpr_t>*attr)
|
list<named_pexpr_t>*attr, bool is_const)
|
||||||
{
|
{
|
||||||
if (data_type == 0) {
|
if (data_type == 0) {
|
||||||
VLerror(li, "internal error: data_type==0.");
|
VLerror(li, "internal error: data_type==0.");
|
||||||
|
|
@ -3245,6 +3248,7 @@ void pform_set_data_type(const struct vlltype&li, data_type_t*data_type,
|
||||||
ivl_assert(li, rc);
|
ivl_assert(li, rc);
|
||||||
|
|
||||||
wire->set_data_type(data_type);
|
wire->set_data_type(data_type);
|
||||||
|
wire->set_const(is_const);
|
||||||
|
|
||||||
pform_bind_attributes(wire->attributes, attr, true);
|
pform_bind_attributes(wire->attributes, attr, true);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
9
pform.h
9
pform.h
|
|
@ -350,12 +350,14 @@ extern void pform_makewire(const struct vlltype&li,
|
||||||
std::list<decl_assignment_t*>*assign_list,
|
std::list<decl_assignment_t*>*assign_list,
|
||||||
NetNet::Type type,
|
NetNet::Type type,
|
||||||
data_type_t*data_type,
|
data_type_t*data_type,
|
||||||
std::list<named_pexpr_t>*attr = 0);
|
std::list<named_pexpr_t>*attr = 0,
|
||||||
|
bool is_const = false);
|
||||||
|
|
||||||
extern void pform_make_var(const struct vlltype&loc,
|
extern void pform_make_var(const struct vlltype&loc,
|
||||||
std::list<decl_assignment_t*>*assign_list,
|
std::list<decl_assignment_t*>*assign_list,
|
||||||
data_type_t*data_type,
|
data_type_t*data_type,
|
||||||
std::list<named_pexpr_t>*attr = 0);
|
std::list<named_pexpr_t>*attr = 0,
|
||||||
|
bool is_const = false);
|
||||||
|
|
||||||
extern void pform_make_var_init(const struct vlltype&li,
|
extern void pform_make_var_init(const struct vlltype&li,
|
||||||
perm_string name, PExpr*expr);
|
perm_string name, PExpr*expr);
|
||||||
|
|
@ -374,7 +376,8 @@ extern void pform_set_data_type(const struct vlltype&li,
|
||||||
data_type_t *data_type,
|
data_type_t *data_type,
|
||||||
std::vector<PWire*> *wires,
|
std::vector<PWire*> *wires,
|
||||||
NetNet::Type net_type,
|
NetNet::Type net_type,
|
||||||
std::list<named_pexpr_t>*attr);
|
std::list<named_pexpr_t>*attr,
|
||||||
|
bool is_const = false);
|
||||||
|
|
||||||
extern void pform_set_string_type(const struct vlltype&li, const string_type_t*string_type, std::list<perm_string>*names, NetNet::Type net_type, std::list<named_pexpr_t>*attr);
|
extern void pform_set_string_type(const struct vlltype&li, const string_type_t*string_type, std::list<perm_string>*names, NetNet::Type net_type, std::list<named_pexpr_t>*attr);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue