Merge pull request #2312 from antmicro/typedef-inout

Add support for user types in IOs
This commit is contained in:
whitequark 2021-01-18 20:20:52 +00:00 committed by GitHub
commit 056c12eb6f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 152 additions and 30 deletions

View File

@ -1330,6 +1330,9 @@ 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) {
// replace with wire representing the packed structure
newNode = make_packed_struct(template_node, str);
// add original input/output attribute to resolved wire
newNode->is_input = this->is_input;
newNode->is_output = this->is_output;
current_scope[str] = this;
goto apply_newNode;
}

View File

@ -282,7 +282,7 @@ static void rewriteAsMemoryNode(AstNode *node, AstNode *rangeNode)
%token TOK_OR_ASSIGN TOK_XOR_ASSIGN TOK_AND_ASSIGN TOK_SUB_ASSIGN
%type <ast> range range_or_multirange non_opt_range non_opt_multirange range_or_signed_int
%type <ast> wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list
%type <ast> wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list non_io_wire_type io_wire_type
%type <string> opt_label opt_sva_label tok_prim_wrapper hierarchical_id hierarchical_type_id integral_number
%type <string> type_name
%type <ast> opt_enum_init enum_type struct_type non_wire_data_type
@ -619,26 +619,19 @@ non_opt_delay:
delay:
non_opt_delay | %empty;
wire_type:
{
astbuf3 = new AstNode(AST_WIRE);
current_wire_rand = false;
current_wire_const = false;
} wire_type_token_list {
$$ = astbuf3;
SET_RULE_LOC(@$, @2, @$);
};
io_wire_type:
{ astbuf3 = new AstNode(AST_WIRE); current_wire_rand = false; current_wire_const = false; }
wire_type_token_io wire_type_const_rand opt_wire_type_token wire_type_signedness
{ $$ = astbuf3; SET_RULE_LOC(@$, @2, @$); };
wire_type_token_list:
wire_type_token |
wire_type_token_list wire_type_token |
wire_type_token_io |
hierarchical_type_id {
astbuf3->is_custom_type = true;
astbuf3->children.push_back(new AstNode(AST_WIRETYPE));
astbuf3->children.back()->str = *$1;
delete $1;
};
non_io_wire_type:
{ astbuf3 = new AstNode(AST_WIRE); current_wire_rand = false; current_wire_const = false; }
wire_type_const_rand wire_type_token wire_type_signedness
{ $$ = astbuf3; SET_RULE_LOC(@$, @2, @$); };
wire_type:
io_wire_type |
non_io_wire_type;
wire_type_token_io:
TOK_INPUT {
@ -652,7 +645,25 @@ wire_type_token_io:
astbuf3->is_output = true;
};
wire_type_signedness:
TOK_SIGNED { astbuf3->is_signed = true; } |
TOK_UNSIGNED { astbuf3->is_signed = false; } |
%empty;
wire_type_const_rand:
TOK_CONST { current_wire_const = true; } |
TOK_RAND { current_wire_rand = true; } |
%empty;
opt_wire_type_token:
wire_type_token | %empty;
wire_type_token:
hierarchical_type_id {
astbuf3->is_custom_type = true;
astbuf3->children.push_back(new AstNode(AST_WIRETYPE));
astbuf3->children.back()->str = *$1;
} |
TOK_WIRE {
} |
TOK_WOR {
@ -682,15 +693,6 @@ wire_type_token:
astbuf3->is_signed = true;
astbuf3->range_left = 31;
astbuf3->range_right = 0;
} |
TOK_SIGNED {
astbuf3->is_signed = true;
} |
TOK_RAND {
current_wire_rand = true;
} |
TOK_CONST {
current_wire_const = true;
};
non_opt_range:
@ -1803,7 +1805,7 @@ type_name: TOK_ID // first time seen
;
typedef_decl:
TOK_TYPEDEF wire_type range type_name range_or_multirange ';' {
TOK_TYPEDEF non_io_wire_type range type_name range_or_multirange ';' {
astbuf1 = $2;
astbuf2 = checkRange(astbuf1, $3);
if (astbuf2)

View File

@ -0,0 +1,111 @@
package p;
typedef struct packed {
byte a;
byte b;
} p_t;
typedef logic [31:0] l_t;
endpackage
module foo1(
input p::p_t p,
output p::p_t o
);
assign o = p;
endmodule
module foo2(p, o);
input p::p_t p;
output p::p_t o;
assign o = p;
endmodule
module foo3(input p::l_t p, input p::l_t o);
assign o = p;
endmodule
module foo4(input logic [15:0] p, input logic [15:0] o);
assign o = p;
endmodule
module test_parser(a,b,c,d,e,f,g,h,i);
input [7:0] a; // no explicit net declaration - net is unsigned
input [7:0] b;
input signed [7:0] c;
input signed [7:0] d; // no explicit net declaration - net is signed
output [7:0] e; // no explicit net declaration - net is unsigned
output [7:0] f;
output signed [7:0] g;
output signed [7:0] h; // no explicit net declaration - net is signed
output unsigned [7:0] i;
wire signed [7:0] b; // port b inherits signed attribute from net decl.
wire [7:0] c; // net c inherits signed attribute from port
logic signed [7:0] f;// port f inherits signed attribute from logic decl.
logic [7:0] g; // logic g inherits signed attribute from port
assign a = 8'b10001111;
assign b = 8'b10001111;
assign c = 8'b10001111;
assign d = 8'b10001111;
assign e = 8'b10001111;
assign f = 8'b10001111;
assign g = 8'b10001111;
assign h = 8'b10001111;
assign i = 8'b10001111;
always_comb begin
assert($unsigned(143) == a);
assert($signed(-113) == b);
assert($signed(-113) == c);
assert($signed(-113) == d);
assert($unsigned(143) == e);
assert($unsigned(143) == f);
assert($signed(-113) == g);
assert($signed(-113) == h);
assert($unsigned(143) == i);
end
endmodule
module top;
p::p_t ps;
assign ps.a = 8'hAA;
assign ps.b = 8'h55;
foo1 foo(.p(ps));
p::p_t body;
assign body.a = 8'hBB;
assign body.b = 8'h66;
foo2 foo_b(.p(body));
typedef p::l_t local_alias;
local_alias l_s;
assign l_s = 32'hAAAAAAAA;
foo3 foo_l(.p(l_s));
typedef logic [15:0] sl_t;
sl_t sl_s;
assign sl_s = 16'hBBBB;
foo4 foo_sl(.p(sl_s));
typedef sl_t local_alias_st;
local_alias_st lsl_s;
assign lsl_s = 16'hCCCC;
foo4 foo_lsl(.p(lsl_s));
const logic j = 1'b1;
always_comb begin
assert(8'hAA == ps.a);
assert(8'h55 == ps.b);
assert(8'hBB == body.a);
assert(8'h66 == body.b);
assert(32'hAAAAAAAA == l_s);
assert(16'hBBBB == sl_s);
assert(16'hCCCC == lsl_s);
assert(1'b1 == j);
end
endmodule

View File

@ -0,0 +1,6 @@
read_verilog -sv typedef_struct_port.sv
hierarchy; proc; opt
select -module top
sat -verify -seq 1 -tempinduct -prove-asserts -show-all
select -module test_parser
sat -verify -seq 1 -tempinduct -prove-asserts -show-all