Merge pull request #1366 from larsclausen/sv2023-type-param-restrictions
Add support for restricted type parameters
This commit is contained in:
commit
8229ce1b49
4
PScope.h
4
PScope.h
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef IVL_PScope_H
|
||||
#define IVL_PScope_H
|
||||
/*
|
||||
* Copyright (c) 2008-2025 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2008-2026 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -121,6 +121,8 @@ class LexicalScope {
|
|||
bool overridable;
|
||||
// Whether the parameter is a type parameter
|
||||
bool type_flag = false;
|
||||
// Type restriction for a type parameter
|
||||
type_restrict_t type_restrict;
|
||||
// The lexical position of the declaration
|
||||
unsigned lexical_pos = 0;
|
||||
|
||||
|
|
|
|||
22
elab_type.cc
22
elab_type.cc
|
|
@ -452,27 +452,7 @@ ivl_type_t typedef_t::elaborate_type(Design *des, NetScope *scope)
|
|||
if (!elab_type)
|
||||
return netvector_t::integer_type();
|
||||
|
||||
bool type_ok = true;
|
||||
switch (basic_type) {
|
||||
case ENUM:
|
||||
type_ok = dynamic_cast<const netenum_t *>(elab_type);
|
||||
break;
|
||||
case STRUCT: {
|
||||
const netstruct_t *struct_type = dynamic_cast<const netstruct_t *>(elab_type);
|
||||
type_ok = struct_type && !struct_type->union_flag();
|
||||
break;
|
||||
}
|
||||
case UNION: {
|
||||
const netstruct_t *struct_type = dynamic_cast<const netstruct_t *>(elab_type);
|
||||
type_ok = struct_type && struct_type->union_flag();
|
||||
break;
|
||||
}
|
||||
case CLASS:
|
||||
type_ok = dynamic_cast<const netclass_t *>(elab_type);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
bool type_ok = basic_type.matches(elab_type);
|
||||
|
||||
if (!type_ok) {
|
||||
cerr << data_type->get_fileline() << " error: "
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
// Check that restricted class type parameter defaults are supported.
|
||||
|
||||
class C0;
|
||||
bit [7:0] value;
|
||||
endclass
|
||||
|
||||
module M #(
|
||||
parameter type class T = C0
|
||||
);
|
||||
T x;
|
||||
endmodule
|
||||
|
||||
module test;
|
||||
|
||||
`define check(val, exp) \
|
||||
if (val !== exp) begin \
|
||||
$display("FAILED(%0d). '%s' expected %0d, got %0d", `__LINE__, `"val`", exp, val); \
|
||||
failed = 1'b1; \
|
||||
end
|
||||
|
||||
bit failed = 1'b0;
|
||||
|
||||
M i_m();
|
||||
|
||||
initial begin
|
||||
i_m.x = new;
|
||||
|
||||
`check($bits(i_m.x.value), 8)
|
||||
|
||||
if (!failed) begin
|
||||
$display("PASSED");
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
// Check that restricted class type parameter overrides are supported.
|
||||
|
||||
class C0;
|
||||
bit [7:0] value;
|
||||
endclass
|
||||
|
||||
class C1;
|
||||
bit [15:0] value;
|
||||
endclass
|
||||
|
||||
module M #(
|
||||
parameter type class T = C0
|
||||
);
|
||||
T x;
|
||||
endmodule
|
||||
|
||||
module test;
|
||||
|
||||
`define check(val, exp) \
|
||||
if (val !== exp) begin \
|
||||
$display("FAILED(%0d). '%s' expected %0d, got %0d", `__LINE__, `"val`", exp, val); \
|
||||
failed = 1'b1; \
|
||||
end
|
||||
|
||||
bit failed = 1'b0;
|
||||
|
||||
M #(
|
||||
.T(C1)
|
||||
) i_m();
|
||||
|
||||
initial begin
|
||||
i_m.x = new;
|
||||
|
||||
`check($bits(i_m.x.value), 16)
|
||||
|
||||
if (!failed) begin
|
||||
$display("PASSED");
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
// Check that a class restricted type parameter rejects non-class defaults.
|
||||
|
||||
module test #(
|
||||
parameter type class T = int
|
||||
);
|
||||
|
||||
initial begin
|
||||
$display("FAILED");
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
// Check that a class restricted type parameter rejects non-class overrides.
|
||||
|
||||
class class_t;
|
||||
endclass
|
||||
|
||||
module M #(
|
||||
parameter type class T = class_t
|
||||
);
|
||||
endmodule
|
||||
|
||||
module test;
|
||||
|
||||
M #(
|
||||
.T(int)
|
||||
) i_m();
|
||||
|
||||
initial begin
|
||||
$display("FAILED");
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
// Check that restricted enum type parameter defaults are supported.
|
||||
|
||||
typedef enum bit [2:0] {
|
||||
A0, B0
|
||||
} T0;
|
||||
|
||||
module M #(
|
||||
parameter type enum T = T0
|
||||
);
|
||||
T x;
|
||||
endmodule
|
||||
|
||||
module test;
|
||||
|
||||
`define check(val, exp) \
|
||||
if (val !== exp) begin \
|
||||
$display("FAILED(%0d). '%s' expected %0d, got %0d", `__LINE__, `"val`", exp, val); \
|
||||
failed = 1'b1; \
|
||||
end
|
||||
|
||||
bit failed = 1'b0;
|
||||
|
||||
M i_m();
|
||||
|
||||
initial begin
|
||||
`check($bits(i_m.x), $bits(T0))
|
||||
|
||||
if (!failed) begin
|
||||
$display("PASSED");
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
// Check that restricted enum type parameter overrides are supported.
|
||||
|
||||
typedef enum bit [2:0] {
|
||||
A0, B0
|
||||
} T0;
|
||||
|
||||
typedef enum bit [3:0] {
|
||||
A1, B1
|
||||
} T1;
|
||||
|
||||
module M #(
|
||||
parameter type enum T = T0
|
||||
);
|
||||
T x;
|
||||
endmodule
|
||||
|
||||
module test;
|
||||
|
||||
`define check(val, exp) \
|
||||
if (val !== exp) begin \
|
||||
$display("FAILED(%0d). '%s' expected %0d, got %0d", `__LINE__, `"val`", exp, val); \
|
||||
failed = 1'b1; \
|
||||
end
|
||||
|
||||
bit failed = 1'b0;
|
||||
|
||||
M #(
|
||||
.T(T1)
|
||||
) i_m();
|
||||
|
||||
initial begin
|
||||
`check($bits(i_m.x), $bits(T1))
|
||||
|
||||
if (!failed) begin
|
||||
$display("PASSED");
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
// Check that an enum restricted type parameter rejects non-enum defaults.
|
||||
|
||||
module test #(
|
||||
parameter type enum T = int
|
||||
);
|
||||
|
||||
initial begin
|
||||
$display("FAILED");
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
// Check that an enum restricted type parameter rejects non-enum overrides.
|
||||
|
||||
typedef enum bit {
|
||||
ENUM_VALUE
|
||||
} enum_t;
|
||||
|
||||
module M #(
|
||||
parameter type enum T = enum_t
|
||||
);
|
||||
endmodule
|
||||
|
||||
module test;
|
||||
|
||||
M #(
|
||||
.T(int)
|
||||
) i_m();
|
||||
|
||||
initial begin
|
||||
$display("FAILED");
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
// Check that restricted struct type parameter defaults are supported.
|
||||
|
||||
typedef struct packed {
|
||||
logic [3:0] x;
|
||||
} T0;
|
||||
|
||||
module M #(
|
||||
parameter type struct T = T0
|
||||
);
|
||||
T x;
|
||||
endmodule
|
||||
|
||||
module test;
|
||||
|
||||
`define check(val, exp) \
|
||||
if (val !== exp) begin \
|
||||
$display("FAILED(%0d). '%s' expected %0d, got %0d", `__LINE__, `"val`", exp, val); \
|
||||
failed = 1'b1; \
|
||||
end
|
||||
|
||||
bit failed = 1'b0;
|
||||
|
||||
M i_m();
|
||||
|
||||
initial begin
|
||||
`check($bits(i_m.x), $bits(T0))
|
||||
|
||||
if (!failed) begin
|
||||
$display("PASSED");
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
// Check that restricted struct type parameter overrides are supported.
|
||||
|
||||
typedef struct packed {
|
||||
logic [3:0] x;
|
||||
} T0;
|
||||
|
||||
typedef struct packed {
|
||||
logic [7:0] x;
|
||||
} T1;
|
||||
|
||||
module M #(
|
||||
parameter type struct T = T0
|
||||
);
|
||||
T x;
|
||||
endmodule
|
||||
|
||||
module test;
|
||||
|
||||
`define check(val, exp) \
|
||||
if (val !== exp) begin \
|
||||
$display("FAILED(%0d). '%s' expected %0d, got %0d", `__LINE__, `"val`", exp, val); \
|
||||
failed = 1'b1; \
|
||||
end
|
||||
|
||||
bit failed = 1'b0;
|
||||
|
||||
M #(
|
||||
.T(T1)
|
||||
) i_m();
|
||||
|
||||
initial begin
|
||||
`check($bits(i_m.x), $bits(T1))
|
||||
|
||||
if (!failed) begin
|
||||
$display("PASSED");
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
// Check that a struct restricted type parameter rejects non-struct defaults.
|
||||
|
||||
typedef union packed {
|
||||
logic [3:0] value;
|
||||
logic [3:0] other;
|
||||
} union_t;
|
||||
|
||||
module test #(
|
||||
parameter type struct T = union_t
|
||||
);
|
||||
|
||||
initial begin
|
||||
$display("FAILED");
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
// Check that a struct restricted type parameter rejects non-struct overrides.
|
||||
|
||||
typedef struct packed {
|
||||
logic [3:0] value;
|
||||
} struct_t;
|
||||
|
||||
typedef union packed {
|
||||
logic [3:0] value;
|
||||
logic [3:0] other;
|
||||
} union_t;
|
||||
|
||||
module M #(
|
||||
parameter type struct T = struct_t
|
||||
);
|
||||
endmodule
|
||||
|
||||
module test;
|
||||
|
||||
M #(
|
||||
.T(union_t)
|
||||
) i_m();
|
||||
|
||||
initial begin
|
||||
$display("FAILED");
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
// Check that restricted union type parameter defaults are supported.
|
||||
|
||||
typedef union packed {
|
||||
logic [3:0] x;
|
||||
logic [3:0] y;
|
||||
} T0;
|
||||
|
||||
module M #(
|
||||
parameter type union T = T0
|
||||
);
|
||||
T x;
|
||||
endmodule
|
||||
|
||||
module test;
|
||||
|
||||
`define check(val, exp) \
|
||||
if (val !== exp) begin \
|
||||
$display("FAILED(%0d). '%s' expected %0d, got %0d", `__LINE__, `"val`", exp, val); \
|
||||
failed = 1'b1; \
|
||||
end
|
||||
|
||||
bit failed = 1'b0;
|
||||
|
||||
M i_m();
|
||||
|
||||
initial begin
|
||||
`check($bits(i_m.x), $bits(T0))
|
||||
|
||||
if (!failed) begin
|
||||
$display("PASSED");
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
// Check that restricted union type parameter overrides are supported.
|
||||
|
||||
typedef union packed {
|
||||
logic [3:0] x;
|
||||
logic [3:0] y;
|
||||
} T0;
|
||||
|
||||
typedef union packed {
|
||||
logic [7:0] x;
|
||||
logic [7:0] y;
|
||||
} T1;
|
||||
|
||||
module M #(
|
||||
parameter type union T = T0
|
||||
);
|
||||
T x;
|
||||
endmodule
|
||||
|
||||
module test;
|
||||
|
||||
`define check(val, exp) \
|
||||
if (val !== exp) begin \
|
||||
$display("FAILED(%0d). '%s' expected %0d, got %0d", `__LINE__, `"val`", exp, val); \
|
||||
failed = 1'b1; \
|
||||
end
|
||||
|
||||
bit failed = 1'b0;
|
||||
|
||||
M #(
|
||||
.T(T1)
|
||||
) i_m();
|
||||
|
||||
initial begin
|
||||
`check($bits(i_m.x), $bits(T1))
|
||||
|
||||
if (!failed) begin
|
||||
$display("PASSED");
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
// Check that a union restricted type parameter rejects non-union defaults.
|
||||
|
||||
typedef struct packed {
|
||||
logic [3:0] value;
|
||||
} struct_t;
|
||||
|
||||
module test #(
|
||||
parameter type union T = struct_t
|
||||
);
|
||||
|
||||
initial begin
|
||||
$display("FAILED");
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
// Check that a union restricted type parameter rejects non-union overrides.
|
||||
|
||||
typedef struct packed {
|
||||
logic [3:0] value;
|
||||
} struct_t;
|
||||
|
||||
typedef union packed {
|
||||
logic [3:0] value;
|
||||
logic [3:0] other;
|
||||
} union_t;
|
||||
|
||||
module M #(
|
||||
parameter type union T = union_t
|
||||
);
|
||||
endmodule
|
||||
|
||||
module test;
|
||||
|
||||
M #(
|
||||
.T(struct_t)
|
||||
) i_m();
|
||||
|
||||
initial begin
|
||||
$display("FAILED");
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
@ -342,6 +342,22 @@ sv_queue_assign_op vvp_tests/sv_queue_assign_op.json
|
|||
sv_soft_packed_union vvp_tests/sv_soft_packed_union.json
|
||||
sv_soft_packed_union_fail1 vvp_tests/sv_soft_packed_union_fail1.json
|
||||
sv_super_member_fail vvp_tests/sv_super_member_fail.json
|
||||
sv_type_param_restrict_class1 vvp_tests/sv_type_param_restrict_class1.json
|
||||
sv_type_param_restrict_class2 vvp_tests/sv_type_param_restrict_class2.json
|
||||
sv_type_param_restrict_class_fail1 vvp_tests/sv_type_param_restrict_class_fail1.json
|
||||
sv_type_param_restrict_class_fail2 vvp_tests/sv_type_param_restrict_class_fail2.json
|
||||
sv_type_param_restrict_enum1 vvp_tests/sv_type_param_restrict_enum1.json
|
||||
sv_type_param_restrict_enum2 vvp_tests/sv_type_param_restrict_enum2.json
|
||||
sv_type_param_restrict_enum_fail1 vvp_tests/sv_type_param_restrict_enum_fail1.json
|
||||
sv_type_param_restrict_enum_fail2 vvp_tests/sv_type_param_restrict_enum_fail2.json
|
||||
sv_type_param_restrict_struct1 vvp_tests/sv_type_param_restrict_struct1.json
|
||||
sv_type_param_restrict_struct2 vvp_tests/sv_type_param_restrict_struct2.json
|
||||
sv_type_param_restrict_struct_fail1 vvp_tests/sv_type_param_restrict_struct_fail1.json
|
||||
sv_type_param_restrict_struct_fail2 vvp_tests/sv_type_param_restrict_struct_fail2.json
|
||||
sv_type_param_restrict_union1 vvp_tests/sv_type_param_restrict_union1.json
|
||||
sv_type_param_restrict_union2 vvp_tests/sv_type_param_restrict_union2.json
|
||||
sv_type_param_restrict_union_fail1 vvp_tests/sv_type_param_restrict_union_fail1.json
|
||||
sv_type_param_restrict_union_fail2 vvp_tests/sv_type_param_restrict_union_fail2.json
|
||||
sv_wildcard_import8 vvp_tests/sv_wildcard_import8.json
|
||||
sdf_header vvp_tests/sdf_header.json
|
||||
task_return1 vvp_tests/task_return1.json
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"type" : "normal",
|
||||
"source" : "sv_type_param_restrict_class1.v",
|
||||
"iverilog-args" : [ "-g2023" ],
|
||||
"vlog95" : {
|
||||
"__comment" : "Classes are not supported",
|
||||
"type" : "CE"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"type" : "normal",
|
||||
"source" : "sv_type_param_restrict_class2.v",
|
||||
"iverilog-args" : [ "-g2023" ],
|
||||
"vlog95" : {
|
||||
"__comment" : "Classes are not supported",
|
||||
"type" : "CE"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"type" : "CE",
|
||||
"source" : "sv_type_param_restrict_class_fail1.v",
|
||||
"iverilog-args" : [ "-g2023" ]
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"type" : "CE",
|
||||
"source" : "sv_type_param_restrict_class_fail2.v",
|
||||
"iverilog-args" : [ "-g2023" ]
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"type" : "normal",
|
||||
"source" : "sv_type_param_restrict_enum1.v",
|
||||
"iverilog-args" : [ "-g2023" ]
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"type" : "normal",
|
||||
"source" : "sv_type_param_restrict_enum2.v",
|
||||
"iverilog-args" : [ "-g2023" ]
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"type" : "CE",
|
||||
"source" : "sv_type_param_restrict_enum_fail1.v",
|
||||
"iverilog-args" : [ "-g2023" ]
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"type" : "CE",
|
||||
"source" : "sv_type_param_restrict_enum_fail2.v",
|
||||
"iverilog-args" : [ "-g2023" ]
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"type" : "normal",
|
||||
"source" : "sv_type_param_restrict_struct1.v",
|
||||
"iverilog-args" : [ "-g2023" ]
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"type" : "normal",
|
||||
"source" : "sv_type_param_restrict_struct2.v",
|
||||
"iverilog-args" : [ "-g2023" ]
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"type" : "CE",
|
||||
"source" : "sv_type_param_restrict_struct_fail1.v",
|
||||
"iverilog-args" : [ "-g2023" ]
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"type" : "CE",
|
||||
"source" : "sv_type_param_restrict_struct_fail2.v",
|
||||
"iverilog-args" : [ "-g2023" ]
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"type" : "normal",
|
||||
"source" : "sv_type_param_restrict_union1.v",
|
||||
"iverilog-args" : [ "-g2023" ]
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"type" : "normal",
|
||||
"source" : "sv_type_param_restrict_union2.v",
|
||||
"iverilog-args" : [ "-g2023" ]
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"type" : "CE",
|
||||
"source" : "sv_type_param_restrict_union_fail1.v",
|
||||
"iverilog-args" : [ "-g2023" ]
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"type" : "CE",
|
||||
"source" : "sv_type_param_restrict_union_fail2.v",
|
||||
"iverilog-args" : [ "-g2023" ]
|
||||
}
|
||||
|
|
@ -838,6 +838,16 @@ void NetScope::evaluate_type_parameter_(Design *des, param_ref_t cur)
|
|||
data_type_t *ptype = type_expr->get_type();
|
||||
NetScope *type_scope = cur->second.val_scope;
|
||||
cur->second.ivl_type = ptype->elaborate_type(des, type_scope);
|
||||
if (!cur->second.ivl_type)
|
||||
return;
|
||||
|
||||
if (!cur->second.type_restrict.matches(cur->second.ivl_type)) {
|
||||
cerr << type_expr->get_fileline() << ": error: "
|
||||
<< "Type parameter `" << cur->first << "` expects a `"
|
||||
<< cur->second.type_restrict << "` type, got `"
|
||||
<< *cur->second.ivl_type << "`." << endl;
|
||||
des->errors++;
|
||||
}
|
||||
}
|
||||
|
||||
void NetScope::evaluate_parameter_(Design*des, param_ref_t cur)
|
||||
|
|
|
|||
|
|
@ -281,6 +281,7 @@ void NetScope::set_parameter(perm_string key, bool is_annotatable,
|
|||
ref.local_flag = param.local_flag;
|
||||
ref.overridable = param.overridable;
|
||||
ref.type_flag = param.type_flag;
|
||||
ref.type_restrict = param.type_restrict;
|
||||
ref.lexical_pos = param.lexical_pos;
|
||||
ivl_assert(param, !ref.range);
|
||||
ref.range = range_list;
|
||||
|
|
|
|||
|
|
@ -1279,6 +1279,8 @@ class NetScope : public Definitions, public Attrib {
|
|||
bool overridable = false;
|
||||
// Is it a type parameter
|
||||
bool type_flag = false;
|
||||
// Type restriction for a type parameter
|
||||
type_restrict_t type_restrict;
|
||||
// The lexical position of the declaration
|
||||
unsigned lexical_pos = 0;
|
||||
// range constraints
|
||||
|
|
|
|||
43
parse.y
43
parse.y
|
|
@ -45,6 +45,7 @@ extern void lex_end_table();
|
|||
static data_type_t* param_data_type = 0;
|
||||
static bool param_is_local = false;
|
||||
static bool param_is_type = false;
|
||||
static type_restrict_t param_type_restrict;
|
||||
static bool in_gen_region = false;
|
||||
static std::list<pform_range_t>* specparam_active_range = 0;
|
||||
|
||||
|
|
@ -598,7 +599,7 @@ Module::port_t *module_declare_interface_port(const YYLTYPE&loc, char *type,
|
|||
|
||||
LexicalScope::lifetime_t lifetime;
|
||||
|
||||
enum typedef_t::basic_type typedef_basic_type;
|
||||
enum type_restrict_t::type_t type_restrict;
|
||||
};
|
||||
|
||||
%token <text> IDENTIFIER INTERFACE_IDENTIFIER SYSTEM_IDENTIFIER STRING TIME_LITERAL
|
||||
|
|
@ -858,7 +859,7 @@ Module::port_t *module_declare_interface_port(const YYLTYPE&loc, char *type,
|
|||
|
||||
%type <letter> compressed_operator
|
||||
|
||||
%type <typedef_basic_type> typedef_basic_type
|
||||
%type <type_restrict> forward_type forward_type_without_enum
|
||||
|
||||
%token K_TAND
|
||||
%nonassoc K_PLUS_EQ K_MINUS_EQ K_MUL_EQ K_DIV_EQ K_MOD_EQ K_AND_EQ K_OR_EQ
|
||||
|
|
@ -2882,11 +2883,16 @@ block_item_decls_opt
|
|||
* `typedef enum <TYPE_IDENTIFIER>` can either be the start of a enum forward
|
||||
* declaration or a enum type declaration with a type identifier as its base
|
||||
* type. And this abmiguity can not be resolved if we reduce the K_enum to
|
||||
* typedef_basic_type. */
|
||||
typedef_basic_type
|
||||
: K_struct { $$ = typedef_t::STRUCT; }
|
||||
| K_union { $$ = typedef_t::UNION; }
|
||||
| K_class { $$ = typedef_t::CLASS; }
|
||||
* forward_type_without_enum. */
|
||||
forward_type_without_enum
|
||||
: K_struct { $$ = type_restrict_t::STRUCT; }
|
||||
| K_union { $$ = type_restrict_t::UNION; }
|
||||
| K_class { $$ = type_restrict_t::CLASS; }
|
||||
;
|
||||
|
||||
forward_type
|
||||
: K_enum { $$ = type_restrict_t::ENUM; }
|
||||
| forward_type_without_enum
|
||||
;
|
||||
|
||||
/* Type declarations are parsed here. The rule actions call pform
|
||||
|
|
@ -2902,17 +2908,17 @@ type_declaration
|
|||
|
||||
| K_typedef identifier_name ';'
|
||||
{ perm_string name = lex_strings.make($2);
|
||||
pform_forward_typedef(@2, name, typedef_t::ANY);
|
||||
pform_forward_typedef(@2, name, type_restrict_t::ANY);
|
||||
delete[]$2;
|
||||
}
|
||||
| K_typedef typedef_basic_type identifier_name ';'
|
||||
| K_typedef forward_type_without_enum identifier_name ';'
|
||||
{ perm_string name = lex_strings.make($3);
|
||||
pform_forward_typedef(@3, name, $2);
|
||||
delete[]$3;
|
||||
}
|
||||
| K_typedef K_enum identifier_name ';'
|
||||
{ perm_string name = lex_strings.make($3);
|
||||
pform_forward_typedef(@3, name, typedef_t::ENUM);
|
||||
pform_forward_typedef(@3, name, type_restrict_t::ENUM);
|
||||
delete[]$3;
|
||||
}
|
||||
| K_typedef error ';'
|
||||
|
|
@ -4924,7 +4930,16 @@ module_parameter_port_list_opt
|
|||
;
|
||||
|
||||
type_param
|
||||
: K_type { param_is_type = true; }
|
||||
: K_type
|
||||
{ param_is_type = true;
|
||||
param_type_restrict = {};
|
||||
}
|
||||
| K_type forward_type
|
||||
{ if (generation_flag < GN_VER2023)
|
||||
yyerror(@1, "error: Restricted type parameters require SystemVerilog 2023 or later.");
|
||||
param_is_type = true;
|
||||
param_type_restrict = $2;
|
||||
}
|
||||
;
|
||||
|
||||
module_parameter
|
||||
|
|
@ -4940,6 +4955,7 @@ module_parameter_port_list
|
|||
{ param_data_type = $1;
|
||||
param_is_local = false;
|
||||
param_is_type = false;
|
||||
param_type_restrict = {};
|
||||
}
|
||||
parameter_assign
|
||||
{ pform_requires_sv(@3, "Omitting initial `parameter` in parameter port "
|
||||
|
|
@ -4955,6 +4971,7 @@ module_parameter_port_list
|
|||
"data type in parameter port list");
|
||||
param_data_type = $3;
|
||||
param_is_type = false;
|
||||
param_type_restrict = {};
|
||||
}
|
||||
}
|
||||
parameter_assign
|
||||
|
|
@ -5598,6 +5615,7 @@ param_type
|
|||
: data_type_or_implicit
|
||||
{ param_is_type = false;
|
||||
param_data_type = $1;
|
||||
param_type_restrict = {};
|
||||
}
|
||||
| type_param
|
||||
|
||||
|
|
@ -5632,7 +5650,8 @@ parameter_assign_list
|
|||
parameter_assign
|
||||
: IDENTIFIER dimensions_opt initializer_opt parameter_value_ranges_opt
|
||||
{ pform_set_parameter(@1, lex_strings.make($1), param_is_local,
|
||||
param_is_type, param_data_type, $2, $3, $4);
|
||||
param_is_type, param_type_restrict,
|
||||
param_data_type, $2, $3, $4);
|
||||
delete[]$1;
|
||||
}
|
||||
;
|
||||
|
|
|
|||
4
pform.cc
4
pform.cc
|
|
@ -841,7 +841,7 @@ static typedef_t *pform_get_typedef(const struct vlltype&loc, perm_string name)
|
|||
}
|
||||
|
||||
void pform_forward_typedef(const struct vlltype&loc, perm_string name,
|
||||
enum typedef_t::basic_type basic_type)
|
||||
type_restrict_t basic_type)
|
||||
{
|
||||
typedef_t *td = pform_get_typedef(loc, name);
|
||||
|
||||
|
|
@ -2948,6 +2948,7 @@ static void pform_set_type_parameter(const struct vlltype&loc, perm_string name,
|
|||
|
||||
void pform_set_parameter(const struct vlltype&loc,
|
||||
perm_string name, bool is_local, bool is_type,
|
||||
type_restrict_t type_restrict,
|
||||
data_type_t*data_type, const list<pform_range_t>*udims,
|
||||
PExpr*expr, LexicalScope::range_t*value_range)
|
||||
{
|
||||
|
|
@ -3020,6 +3021,7 @@ void pform_set_parameter(const struct vlltype&loc,
|
|||
parm->local_flag = is_local;
|
||||
parm->overridable = overridable;
|
||||
parm->type_flag = is_type;
|
||||
parm->type_restrict = type_restrict;
|
||||
parm->lexical_pos = loc.lexical_pos;
|
||||
|
||||
scope->parameters[name] = parm;
|
||||
|
|
|
|||
3
pform.h
3
pform.h
|
|
@ -323,7 +323,7 @@ extern void pform_set_typedef(const struct vlltype&loc, perm_string name,
|
|||
data_type_t*data_type,
|
||||
std::list<pform_range_t>*unp_ranges = nullptr);
|
||||
extern void pform_forward_typedef(const struct vlltype&loc, perm_string name,
|
||||
enum typedef_t::basic_type basic_type);
|
||||
type_restrict_t basic_type);
|
||||
|
||||
extern void pform_set_type_referenced(const struct vlltype&loc, const char*name);
|
||||
|
||||
|
|
@ -412,6 +412,7 @@ extern LexicalScope::range_t* pform_parameter_value_range(bool exclude_flag,
|
|||
extern void pform_set_parameter(const struct vlltype&loc,
|
||||
perm_string name,
|
||||
bool is_local, bool is_type,
|
||||
type_restrict_t type_restrict,
|
||||
data_type_t*data_type, const std::list<pform_range_t>*udims,
|
||||
PExpr*expr, LexicalScope::range_t*value_range);
|
||||
extern void pform_set_specparam(const struct vlltype&loc,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2007-2019 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2007-2026 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
|
||||
# include "pform_types.h"
|
||||
# include "netclass.h"
|
||||
# include "netenum.h"
|
||||
|
||||
data_type_t::~data_type_t()
|
||||
{
|
||||
|
|
@ -55,34 +57,59 @@ bool typedef_t::set_data_type(data_type_t *t)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool typedef_t::set_basic_type(enum basic_type bt)
|
||||
bool typedef_t::set_basic_type(type_restrict_t type)
|
||||
{
|
||||
if (bt == ANY)
|
||||
return basic_type.merge(type);
|
||||
}
|
||||
|
||||
bool type_restrict_t::merge(type_restrict_t other)
|
||||
{
|
||||
if (other.type == ANY)
|
||||
return true;
|
||||
if (basic_type != ANY && bt != basic_type)
|
||||
if (this->type != ANY && other.type != this->type)
|
||||
return false;
|
||||
|
||||
basic_type = bt;
|
||||
this->type = other.type;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::ostream& operator<< (std::ostream&out, enum typedef_t::basic_type bt)
|
||||
bool type_restrict_t::matches(ivl_type_t ivl_type) const
|
||||
{
|
||||
switch (bt) {
|
||||
case typedef_t::ANY:
|
||||
switch (this->type) {
|
||||
case ENUM:
|
||||
return dynamic_cast<const netenum_t *>(ivl_type);
|
||||
case STRUCT: {
|
||||
const netstruct_t *struct_type = dynamic_cast<const netstruct_t *>(ivl_type);
|
||||
return struct_type && !struct_type->union_flag();
|
||||
}
|
||||
case UNION: {
|
||||
const netstruct_t *struct_type = dynamic_cast<const netstruct_t *>(ivl_type);
|
||||
return struct_type && struct_type->union_flag();
|
||||
}
|
||||
case CLASS:
|
||||
return dynamic_cast<const netclass_t *>(ivl_type);
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream& operator<< (std::ostream&out, const type_restrict_t& type)
|
||||
{
|
||||
switch (type.type) {
|
||||
case type_restrict_t::ANY:
|
||||
out << "any";
|
||||
break;
|
||||
case typedef_t::ENUM:
|
||||
case type_restrict_t::ENUM:
|
||||
out << "enum";
|
||||
break;
|
||||
case typedef_t::STRUCT:
|
||||
case type_restrict_t::STRUCT:
|
||||
out << "struct";
|
||||
break;
|
||||
case typedef_t::UNION:
|
||||
case type_restrict_t::UNION:
|
||||
out << "union";
|
||||
break;
|
||||
case typedef_t::CLASS:
|
||||
case type_restrict_t::CLASS:
|
||||
out << "class";
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,6 +49,24 @@ class netclass_t;
|
|||
class netenum_t;
|
||||
typedef named<PExpr*> named_pexpr_t;
|
||||
|
||||
struct type_restrict_t {
|
||||
enum type_t {
|
||||
ANY,
|
||||
ENUM,
|
||||
STRUCT,
|
||||
UNION,
|
||||
CLASS
|
||||
};
|
||||
|
||||
type_restrict_t() = default;
|
||||
type_restrict_t(type_t kind) : type(kind) { }
|
||||
|
||||
bool merge(type_restrict_t other);
|
||||
bool matches(ivl_type_t type) const;
|
||||
|
||||
enum type_t type = ANY;
|
||||
};
|
||||
|
||||
/*
|
||||
* The pform_ident_t holds the identifier name and its lexical position
|
||||
* (the lexical_pos supplied by the scanner).
|
||||
|
|
@ -180,26 +198,18 @@ class data_type_t : public PNamedItem {
|
|||
};
|
||||
|
||||
struct typedef_t : public PNamedItem {
|
||||
explicit typedef_t(perm_string n) : basic_type(ANY), name(n) { };
|
||||
explicit typedef_t(perm_string n) : name(n) { };
|
||||
|
||||
ivl_type_t elaborate_type(Design*des, NetScope*scope);
|
||||
|
||||
enum basic_type {
|
||||
ANY,
|
||||
ENUM,
|
||||
STRUCT,
|
||||
UNION,
|
||||
CLASS
|
||||
};
|
||||
|
||||
bool set_data_type(data_type_t *t);
|
||||
const data_type_t *get_data_type() const { return data_type.get(); }
|
||||
|
||||
bool set_basic_type(basic_type bt);
|
||||
enum basic_type get_basic_type() const { return basic_type; }
|
||||
bool set_basic_type(type_restrict_t type);
|
||||
type_restrict_t get_basic_type() const { return basic_type; }
|
||||
|
||||
protected:
|
||||
enum basic_type basic_type;
|
||||
type_restrict_t basic_type;
|
||||
std::unique_ptr<data_type_t> data_type;
|
||||
public:
|
||||
perm_string name;
|
||||
|
|
@ -498,6 +508,6 @@ extern std::ostream& operator<< (std::ostream&out, const pform_name_t&);
|
|||
extern std::ostream& operator<< (std::ostream&out, const pform_scoped_name_t&);
|
||||
extern std::ostream& operator<< (std::ostream&out, const name_component_t&that);
|
||||
extern std::ostream& operator<< (std::ostream&out, const index_component_t&that);
|
||||
extern std::ostream& operator<< (std::ostream&out, enum typedef_t::basic_type bt);
|
||||
extern std::ostream& operator<< (std::ostream&out, const type_restrict_t& type);
|
||||
|
||||
#endif /* IVL_pform_types_H */
|
||||
|
|
|
|||
Loading…
Reference in New Issue