Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for const variables #975

Merged
merged 2 commits into from
Jul 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions PExpr.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,8 @@ class PExpr : public LineInfo {
virtual NetAssign_* elaborate_lval(Design*des,
NetScope*scope,
bool is_cassign,
bool is_force) const;
bool is_force,
bool is_init = false) const;

// This method returns true if the expression represents a
// structural net that can have multiple drivers. This is
Expand Down Expand Up @@ -262,7 +263,8 @@ class PEConcat : public PExpr {
virtual NetAssign_* elaborate_lval(Design*des,
NetScope*scope,
bool is_cassign,
bool is_force) const;
bool is_force,
bool is_init = false) const;
virtual bool is_collapsible_net(Design*des, NetScope*scope,
NetNet::PortType port_type) const;
private:
Expand Down Expand Up @@ -361,7 +363,8 @@ class PEIdent : public PExpr {
virtual NetAssign_* elaborate_lval(Design*des,
NetScope*scope,
bool is_cassign,
bool is_force) const;
bool is_force,
bool is_init = false) const;

virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
ivl_type_t type, unsigned flags) const;
Expand Down Expand Up @@ -647,7 +650,8 @@ class PENumber : public PExpr {
virtual NetAssign_* elaborate_lval(Design*des,
NetScope*scope,
bool is_cassign,
bool is_force) const;
bool is_force,
bool is_init = false) const;

private:
verinum*const value_;
Expand Down
6 changes: 6 additions & 0 deletions PWire.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ class PWire : public PNamedItem {
NetNet::PortType get_port_type() const;
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);
bool get_signed() const;

Expand Down Expand Up @@ -100,6 +103,9 @@ class PWire : public PNamedItem {
NetNet::PortType port_type_;
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
// wire. If they do not exist, the wire is 1 bit wide. If they
// do exist, they represent the packed dimensions of the
Expand Down
9 changes: 5 additions & 4 deletions Statement.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@ Statement::~Statement()
{
}

PAssign_::PAssign_(PExpr*lval__, PExpr*ex, bool is_constant)
: event_(0), count_(0), lval_(lval__), rval_(ex), is_constant_(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),
is_init_(is_init)
{
delay_ = 0;
}
Expand Down Expand Up @@ -73,8 +74,8 @@ PAssign::PAssign(PExpr*lval__, PExpr*cnt, PEventStatement*d, PExpr*ex)
{
}

PAssign::PAssign(PExpr*lval__, PExpr*ex, bool is_constant)
: PAssign_(lval__, ex, is_constant), op_(0)
PAssign::PAssign(PExpr*lval__, PExpr*ex, bool is_constant, bool is_init)
: PAssign_(lval__, ex, is_constant, is_init), op_(0)
{
}

Expand Down
7 changes: 5 additions & 2 deletions Statement.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@ class Statement : virtual public LineInfo {
*/
class PAssign_ : public Statement {
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*cnt, PEventStatement*de, PExpr*ex);
virtual ~PAssign_() =0;
Expand All @@ -122,6 +123,8 @@ class PAssign_ : public Statement {
PExpr* lval_;
PExpr* rval_;
bool is_constant_;
// Whether the assignment is a variable initializer expression
bool is_init_ = false;
};

class PAssign : public PAssign_ {
Expand All @@ -135,7 +138,7 @@ class PAssign : public PAssign_ {
explicit PAssign(PExpr*lval, char op, 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*ex, bool is_constant);
explicit PAssign(PExpr*lval, PExpr*ex, bool is_constant, bool is_init);
~PAssign();

virtual void dump(std::ostream&out, unsigned ind) const;
Expand Down
19 changes: 14 additions & 5 deletions elab_lval.cc
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ using namespace std;
* is to try to make a net elaboration, and see if the result is
* 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;
return 0;
Expand All @@ -98,7 +98,8 @@ NetAssign_* PExpr::elaborate_lval(Design*, NetScope*, bool, bool) const
NetAssign_* PEConcat::elaborate_lval(Design*des,
NetScope*scope,
bool is_cassign,
bool is_force) const
bool is_force,
bool is_init) const
{
if (repeat_) {
cerr << get_fileline() << ": error: Repeat concatenations make "
Expand All @@ -119,7 +120,7 @@ NetAssign_* PEConcat::elaborate_lval(Design*des,
}

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
already detected and printed. We just skip it and let
Expand Down Expand Up @@ -157,7 +158,8 @@ NetAssign_* PEConcat::elaborate_lval(Design*des,
NetAssign_* PEIdent::elaborate_lval(Design*des,
NetScope*scope,
bool is_cassign,
bool is_force) const
bool is_force,
bool is_init) const
{

if (debug_elaborate) {
Expand Down Expand Up @@ -213,6 +215,13 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
<< 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,
sr.type, member_path);
}
Expand Down Expand Up @@ -1535,7 +1544,7 @@ bool PEIdent::elaborate_lval_net_packed_member_(Design*des, NetScope*scope,
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 "
<< "in l-value expressions." << endl;
Expand Down
6 changes: 6 additions & 0 deletions elab_net.cc
Original file line number Diff line number Diff line change
Expand Up @@ -556,6 +556,12 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
<< 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
// assigned by anything, then convert it to an unresolved
Expand Down
2 changes: 2 additions & 0 deletions elab_sig.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1204,5 +1204,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
for (unsigned idx = 0 ; idx < nattrib ; idx += 1)
sig->attribute(attrib_list[idx].key, attrib_list[idx].val);

sig->set_const(is_const_);

return sig;
}
2 changes: 1 addition & 1 deletion elaborate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2378,7 +2378,7 @@ NetAssign_* PAssign_::elaborate_lval(Design*des, NetScope*scope) const
<< "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,
Expand Down
18 changes: 18 additions & 0 deletions ivtest/ivltests/sv_const1.v
Original file line number Diff line number Diff line change
@@ -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
29 changes: 29 additions & 0 deletions ivtest/ivltests/sv_const2.v
Original file line number Diff line number Diff line change
@@ -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
17 changes: 17 additions & 0 deletions ivtest/ivltests/sv_const3.v
Original file line number Diff line number Diff line change
@@ -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
18 changes: 18 additions & 0 deletions ivtest/ivltests/sv_const4.v
Original file line number Diff line number Diff line change
@@ -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
20 changes: 20 additions & 0 deletions ivtest/ivltests/sv_const5.v
Original file line number Diff line number Diff line change
@@ -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
13 changes: 13 additions & 0 deletions ivtest/ivltests/sv_const_fail1.v
Original file line number Diff line number Diff line change
@@ -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
12 changes: 12 additions & 0 deletions ivtest/ivltests/sv_const_fail2.v
Original file line number Diff line number Diff line change
@@ -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
12 changes: 12 additions & 0 deletions ivtest/ivltests/sv_const_fail3.v
Original file line number Diff line number Diff line change
@@ -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
12 changes: 12 additions & 0 deletions ivtest/ivltests/sv_const_fail4.v
Original file line number Diff line number Diff line change
@@ -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
12 changes: 12 additions & 0 deletions ivtest/ivltests/sv_const_fail5.v
Original file line number Diff line number Diff line change
@@ -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
16 changes: 16 additions & 0 deletions ivtest/ivltests/sv_const_fail6.v
Original file line number Diff line number Diff line change
@@ -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
Loading
Loading