mirror of
https://github.com/YosysHQ/yosys
synced 2025-04-13 04:28:18 +00:00
Support parameters using struct as a wiretype (#3050)
Signed-off-by: Kamil Rakoczy <krakoczy@antmicro.com>
This commit is contained in:
parent
06bddb5e49
commit
fdb19a5b3a
|
@ -1613,6 +1613,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
||||||
if (template_node->type == AST_STRUCT || template_node->type == AST_UNION) {
|
if (template_node->type == AST_STRUCT || template_node->type == AST_UNION) {
|
||||||
// replace with wire representing the packed structure
|
// replace with wire representing the packed structure
|
||||||
newNode = make_packed_struct(template_node, str);
|
newNode = make_packed_struct(template_node, str);
|
||||||
|
newNode->attributes[ID::wiretype] = mkconst_str(resolved_type_node->str);
|
||||||
// add original input/output attribute to resolved wire
|
// add original input/output attribute to resolved wire
|
||||||
newNode->is_input = this->is_input;
|
newNode->is_input = this->is_input;
|
||||||
newNode->is_output = this->is_output;
|
newNode->is_output = this->is_output;
|
||||||
|
@ -1661,18 +1662,33 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
||||||
if (is_custom_type) {
|
if (is_custom_type) {
|
||||||
log_assert(children.size() == 2);
|
log_assert(children.size() == 2);
|
||||||
log_assert(children[1]->type == AST_WIRETYPE);
|
log_assert(children[1]->type == AST_WIRETYPE);
|
||||||
if (!current_scope.count(children[1]->str))
|
auto type_name = children[1]->str;
|
||||||
log_file_error(filename, location.first_line, "Unknown identifier `%s' used as type name\n", children[1]->str.c_str());
|
if (!current_scope.count(type_name)) {
|
||||||
AstNode *resolved_type_node = current_scope.at(children[1]->str);
|
log_file_error(filename, location.first_line, "Unknown identifier `%s' used as type name\n", type_name.c_str());
|
||||||
|
}
|
||||||
|
AstNode *resolved_type_node = current_scope.at(type_name);
|
||||||
if (resolved_type_node->type != AST_TYPEDEF)
|
if (resolved_type_node->type != AST_TYPEDEF)
|
||||||
log_file_error(filename, location.first_line, "`%s' does not name a type\n", children[1]->str.c_str());
|
log_file_error(filename, location.first_line, "`%s' does not name a type\n", type_name.c_str());
|
||||||
log_assert(resolved_type_node->children.size() == 1);
|
log_assert(resolved_type_node->children.size() == 1);
|
||||||
AstNode *template_node = resolved_type_node->children[0];
|
AstNode *template_node = resolved_type_node->children[0];
|
||||||
delete children[1];
|
|
||||||
children.pop_back();
|
|
||||||
|
|
||||||
// Ensure typedef itself is fully simplified
|
// Ensure typedef itself is fully simplified
|
||||||
while(template_node->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) {};
|
while (template_node->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) {};
|
||||||
|
|
||||||
|
if (template_node->type == AST_STRUCT || template_node->type == AST_UNION) {
|
||||||
|
// replace with wire representing the packed structure
|
||||||
|
newNode = make_packed_struct(template_node, str);
|
||||||
|
newNode->attributes[ID::wiretype] = mkconst_str(resolved_type_node->str);
|
||||||
|
newNode->type = type;
|
||||||
|
current_scope[str] = this;
|
||||||
|
// copy param value, it needs to be 1st value
|
||||||
|
delete children[1];
|
||||||
|
children.pop_back();
|
||||||
|
newNode->children.insert(newNode->children.begin(), children[0]->clone());
|
||||||
|
goto apply_newNode;
|
||||||
|
}
|
||||||
|
delete children[1];
|
||||||
|
children.pop_back();
|
||||||
|
|
||||||
if (template_node->type == AST_MEMORY)
|
if (template_node->type == AST_MEMORY)
|
||||||
log_file_error(filename, location.first_line, "unpacked array type `%s' cannot be used for a parameter\n", children[1]->str.c_str());
|
log_file_error(filename, location.first_line, "unpacked array type `%s' cannot be used for a parameter\n", children[1]->str.c_str());
|
||||||
|
|
51
tests/various/param_struct.ys
Normal file
51
tests/various/param_struct.ys
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
read_verilog -sv << EOF
|
||||||
|
package p;
|
||||||
|
typedef struct packed {
|
||||||
|
logic a;
|
||||||
|
logic b;
|
||||||
|
} struct_t;
|
||||||
|
|
||||||
|
typedef struct packed {
|
||||||
|
struct_t g;
|
||||||
|
logic [2:0] h;
|
||||||
|
} nested_struct_t;
|
||||||
|
|
||||||
|
typedef union packed {
|
||||||
|
logic [4:0] x;
|
||||||
|
} nested_union_t;
|
||||||
|
|
||||||
|
parameter struct_t c = {1'b1, 1'b0};
|
||||||
|
parameter nested_struct_t x = {{1'b1, 1'b0}, 1'b1, 1'b1, 1'b1};
|
||||||
|
endpackage
|
||||||
|
|
||||||
|
module dut ();
|
||||||
|
parameter p::struct_t d = p::c;
|
||||||
|
parameter p::nested_struct_t i = p::x;
|
||||||
|
|
||||||
|
parameter p::nested_union_t u = {5'b11001};
|
||||||
|
|
||||||
|
localparam e = d.a;
|
||||||
|
localparam f = d.b;
|
||||||
|
|
||||||
|
localparam j = i.g.a;
|
||||||
|
localparam k = i.g.b;
|
||||||
|
localparam l = i.h;
|
||||||
|
localparam m = i.g;
|
||||||
|
|
||||||
|
localparam o = u.x;
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
assert(d == 2'b10);
|
||||||
|
assert(e == 1'b1);
|
||||||
|
assert(f == 1'b0);
|
||||||
|
assert(j == 1'b1);
|
||||||
|
assert(k == 1'b0);
|
||||||
|
assert(l == 3'b111);
|
||||||
|
// TODO: support access to whole sub-structs and unions
|
||||||
|
// assert(m == 2'b10);
|
||||||
|
assert(u == 5'b11001);
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
EOF
|
||||||
|
hierarchy; proc; opt
|
||||||
|
sat -verify -seq 1 -tempinduct -prove-asserts -show-all
|
Loading…
Reference in a new issue