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,
|
||||
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
|
||||
|
|
@ -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:
|
||||
|
|
@ -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;
|
||||
|
|
@ -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_;
|
||||
|
|
|
|||
6
PWire.h
6
PWire.h
|
|
@ -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;
|
||||
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -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_ {
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
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
|
||||
* 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;
|
||||
|
|
@ -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 "
|
||||
|
|
@ -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
|
||||
|
|
@ -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) {
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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_cassign6 vvp_tests/sv_array_cassign6.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_foreach10 vvp_tests/sv_foreach10.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. */
|
||||
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;
|
||||
|
||||
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;
|
||||
ivl_discipline_t discipline_;
|
||||
|
||||
// Whether the net is variable declared with the const keyword.
|
||||
bool is_const_ = false;
|
||||
|
||||
std::vector<netrange_t> unpacked_dims_;
|
||||
|
||||
// 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 <flag> signing unsigned_signed_opt signed_unsigned_opt
|
||||
%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 <drive> drive_strength drive_strength_opt dr_strength0 dr_strength1
|
||||
%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 */
|
||||
: attribute_list_opt data_type list_of_variable_decl_assignments ';'
|
||||
{ data_type_t*data_type = $2;
|
||||
if (data_type == 0) {
|
||||
: attribute_list_opt K_const_opt data_type list_of_variable_decl_assignments ';'
|
||||
{ data_type_t *data_type = $3;
|
||||
if (!data_type) {
|
||||
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 ';'
|
||||
{ data_type_t*data_type = $3;
|
||||
if (data_type == 0) {
|
||||
| attribute_list_opt K_const_opt K_var data_type_or_implicit list_of_variable_decl_assignments ';'
|
||||
{ data_type_t *data_type = $4;
|
||||
if (!data_type) {
|
||||
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 ';'
|
||||
{ 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
|
||||
recovering from an error. */
|
||||
|
||||
: K_var variable_lifetime_opt data_type_or_implicit list_of_variable_decl_assignments ';'
|
||||
{ data_type_t*data_type = $3;
|
||||
if (data_type == 0) {
|
||||
: K_const_opt K_var variable_lifetime_opt data_type_or_implicit list_of_variable_decl_assignments ';'
|
||||
{ data_type_t *data_type = $4;
|
||||
if (!data_type) {
|
||||
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;
|
||||
}
|
||||
|
||||
| variable_lifetime_opt data_type list_of_variable_decl_assignments ';'
|
||||
{ if ($2) pform_make_var(@2, $3, $2, attributes_in_context);
|
||||
| K_const_opt variable_lifetime_opt data_type list_of_variable_decl_assignments ';'
|
||||
{ if ($3) pform_make_var(@3, $4, $3, attributes_in_context, $1);
|
||||
var_lifetime = LexicalScope::INHERITED;
|
||||
}
|
||||
|
||||
/* 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 ';'
|
||||
{ if ($3) pform_make_var(@3, $4, $3, attributes_in_context);
|
||||
| K_const_opt variable_lifetime_opt K_reg data_type list_of_variable_decl_assignments ';'
|
||||
{ if ($4) pform_make_var(@4, $5, $4, attributes_in_context, $1);
|
||||
var_lifetime = LexicalScope::INHERITED;
|
||||
}
|
||||
|
||||
|
|
@ -2769,11 +2770,11 @@ block_item_decl
|
|||
/* Recover from errors that happen within variable lists. Use the
|
||||
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.");
|
||||
yyerrok;
|
||||
}
|
||||
| variable_lifetime_opt data_type error ';'
|
||||
| K_const_opt variable_lifetime_opt data_type error ';'
|
||||
{ yyerror(@1, "error: Syntax error in variable list.");
|
||||
yyerrok;
|
||||
}
|
||||
|
|
@ -7308,6 +7309,11 @@ unique_priority
|
|||
presence is significant. This is a fairly common pattern so
|
||||
collect those rules here. */
|
||||
|
||||
K_const_opt
|
||||
: K_const { $$ = true; }
|
||||
| { $$ = false; }
|
||||
;
|
||||
|
||||
K_genvar_opt
|
||||
: K_genvar { $$ = true; }
|
||||
| { $$ = 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,
|
||||
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 };
|
||||
|
||||
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,
|
||||
|
|
@ -2494,7 +2496,7 @@ void pform_make_var_init(const struct vlltype&li,
|
|||
|
||||
PEIdent*lval = new PEIdent(name);
|
||||
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);
|
||||
|
||||
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,
|
||||
NetNet::Type 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()) {
|
||||
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);
|
||||
}
|
||||
|
||||
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()) {
|
||||
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,
|
||||
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) {
|
||||
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);
|
||||
|
||||
wire->set_data_type(data_type);
|
||||
wire->set_const(is_const);
|
||||
|
||||
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,
|
||||
NetNet::Type 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,
|
||||
std::list<decl_assignment_t*>*assign_list,
|
||||
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,
|
||||
perm_string name, PExpr*expr);
|
||||
|
|
@ -374,7 +376,8 @@ extern void pform_set_data_type(const struct vlltype&li,
|
|||
data_type_t *data_type,
|
||||
std::vector<PWire*> *wires,
|
||||
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);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue