Merge pull request #586 from larsclausen/struct-signed
Add support for signed packed structs/unions
This commit is contained in:
commit
f5f07d52b0
|
|
@ -180,6 +180,7 @@ netstruct_t* struct_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
|
||||||
netstruct_t*res = new netstruct_t;
|
netstruct_t*res = new netstruct_t;
|
||||||
|
|
||||||
res->packed(packed_flag);
|
res->packed(packed_flag);
|
||||||
|
res->set_signed(signed_flag);
|
||||||
|
|
||||||
if (union_flag)
|
if (union_flag)
|
||||||
res->union_flag(true);
|
res->union_flag(true);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
// Tests that packed structs can have signed/unsigned modifier and that signed
|
||||||
|
// packed structs when used as a primary behave correctly.
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
// Unsigned by default
|
||||||
|
struct packed {
|
||||||
|
logic [15:0] x;
|
||||||
|
} s1;
|
||||||
|
|
||||||
|
// Explicitly unsigned
|
||||||
|
struct packed unsigned {
|
||||||
|
logic [15:0] x;
|
||||||
|
} s2;
|
||||||
|
|
||||||
|
// Explicitly signed
|
||||||
|
struct packed signed {
|
||||||
|
logic [15:0] x;
|
||||||
|
} s3;
|
||||||
|
|
||||||
|
|
||||||
|
bit failed = 1'b0;
|
||||||
|
|
||||||
|
`define check(x) \
|
||||||
|
if (!(x)) begin \
|
||||||
|
$display("FAILED: ", `"x`"); \
|
||||||
|
failed = 1'b1; \
|
||||||
|
end
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
s1 = -1;
|
||||||
|
s2 = -1;
|
||||||
|
s3 = -1;
|
||||||
|
|
||||||
|
`check(!$is_signed(s1));
|
||||||
|
`check(!$is_signed(s2));
|
||||||
|
`check($is_signed(s3));
|
||||||
|
|
||||||
|
// These evaluate as signed
|
||||||
|
`check($signed(s1) < 0);
|
||||||
|
`check($signed(s2) < 0);
|
||||||
|
`check(s3 < 0);
|
||||||
|
|
||||||
|
// These all evaluate as unsigned
|
||||||
|
`check(s1 > 0);
|
||||||
|
`check(s2 > 0);
|
||||||
|
`check(s3.x > 0)
|
||||||
|
`check(s3[15:0] > 0)
|
||||||
|
`check({s3} > 0)
|
||||||
|
`check($unsigned(s3) > 0)
|
||||||
|
`check(s3 > 16'h0)
|
||||||
|
|
||||||
|
if (!failed) begin
|
||||||
|
$display("PASSED");
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -383,6 +383,7 @@ struct_packed_array2 normal,-g2009 ivltests
|
||||||
struct_packed_sysfunct normal,-g2009 ivltests
|
struct_packed_sysfunct normal,-g2009 ivltests
|
||||||
struct_packed_write_read2 normal,-g2009 ivltests
|
struct_packed_write_read2 normal,-g2009 ivltests
|
||||||
struct_invalid_member CE,-g2009 ivltests gold=struct_invalid_member.gold
|
struct_invalid_member CE,-g2009 ivltests gold=struct_invalid_member.gold
|
||||||
|
struct_signed normal,-g2009 ivltests
|
||||||
sv-constants normal,-g2005-sv ivltests
|
sv-constants normal,-g2005-sv ivltests
|
||||||
sv_array_assign_pattern2 normal,-g2009 ivltests
|
sv_array_assign_pattern2 normal,-g2009 ivltests
|
||||||
sv_cast_integer normal,-g2005-sv ivltests
|
sv_cast_integer normal,-g2005-sv ivltests
|
||||||
|
|
|
||||||
|
|
@ -838,6 +838,7 @@ size_cast3 normal,-g2009,-pallowsigned=1 ivltests
|
||||||
size_cast5 normal,-g2009,-pallowsigned=1 ivltests
|
size_cast5 normal,-g2009,-pallowsigned=1 ivltests
|
||||||
struct_packed_array normal,-g2009,-pallowsigned=1 ivltests
|
struct_packed_array normal,-g2009,-pallowsigned=1 ivltests
|
||||||
struct_packed_array2 normal,-g2009,-pallowsigned=1 ivltests
|
struct_packed_array2 normal,-g2009,-pallowsigned=1 ivltests
|
||||||
|
struct_signed normal,-g2009,-pallowsigned=1 ivltests
|
||||||
sv_for_variable normal,-g2009,-pallowsigned=1 ivltests
|
sv_for_variable normal,-g2009,-pallowsigned=1 ivltests
|
||||||
sv_foreach1 normal,-g2009,-pallowsigned=1 ivltests
|
sv_foreach1 normal,-g2009,-pallowsigned=1 ivltests
|
||||||
sv_foreach5 normal,-g2009,-pallowsigned=1 ivltests
|
sv_foreach5 normal,-g2009,-pallowsigned=1 ivltests
|
||||||
|
|
|
||||||
|
|
@ -2158,6 +2158,7 @@ test_mos_strength_reduction: Passed.
|
||||||
struct_packed_sysfunct: Passed.
|
struct_packed_sysfunct: Passed.
|
||||||
struct_packed_write_read2: Passed.
|
struct_packed_write_read2: Passed.
|
||||||
struct_invalid_member: Passed - CE.
|
struct_invalid_member: Passed - CE.
|
||||||
|
struct_signed: Passed.
|
||||||
sv-constants: Passed.
|
sv-constants: Passed.
|
||||||
sv_array_assign_pattern2: Passed.
|
sv_array_assign_pattern2: Passed.
|
||||||
sv_cast_integer: Passed.
|
sv_cast_integer: Passed.
|
||||||
|
|
@ -2565,4 +2566,4 @@ test_mos_strength_reduction: Passed.
|
||||||
ufuncsynth1: Passed.
|
ufuncsynth1: Passed.
|
||||||
============================================================================
|
============================================================================
|
||||||
Test results:
|
Test results:
|
||||||
Total=2563, Passed=2557, Failed=3, Not Implemented=0, Expected Fail=3
|
Total=2564, Passed=2558, Failed=3, Not Implemented=0, Expected Fail=3
|
||||||
|
|
|
||||||
|
|
@ -2165,6 +2165,7 @@ test_mos_strength_reduction: Passed.
|
||||||
struct_packed_sysfunct: Passed.
|
struct_packed_sysfunct: Passed.
|
||||||
struct_packed_write_read2: Passed.
|
struct_packed_write_read2: Passed.
|
||||||
struct_invalid_member: Passed - CE.
|
struct_invalid_member: Passed - CE.
|
||||||
|
struct_signed: Passed.
|
||||||
sv-constants: Passed.
|
sv-constants: Passed.
|
||||||
sv_array_assign_pattern2: Passed.
|
sv_array_assign_pattern2: Passed.
|
||||||
sv_cast_integer: Passed.
|
sv_cast_integer: Passed.
|
||||||
|
|
@ -2565,4 +2566,4 @@ test_mos_strength_reduction: Passed.
|
||||||
ufuncsynth1: Passed.
|
ufuncsynth1: Passed.
|
||||||
============================================================================
|
============================================================================
|
||||||
Test results:
|
Test results:
|
||||||
Total=2563, Passed=2543, Failed=17, Not Implemented=3, Expected Fail=0
|
Total=2564, Passed=2544, Failed=17, Not Implemented=3, Expected Fail=0
|
||||||
|
|
|
||||||
|
|
@ -2154,6 +2154,7 @@ test_mos_strength_reduction: Passed.
|
||||||
struct_packed_sysfunct: Passed.
|
struct_packed_sysfunct: Passed.
|
||||||
struct_packed_write_read2: Passed.
|
struct_packed_write_read2: Passed.
|
||||||
struct_invalid_member: Passed - CE.
|
struct_invalid_member: Passed - CE.
|
||||||
|
struct_signed: Passed.
|
||||||
sv-constants: Passed.
|
sv-constants: Passed.
|
||||||
sv_array_assign_pattern2: Passed.
|
sv_array_assign_pattern2: Passed.
|
||||||
sv_cast_integer: Passed.
|
sv_cast_integer: Passed.
|
||||||
|
|
@ -2562,4 +2563,4 @@ test_mos_strength_reduction: Passed.
|
||||||
ufuncsynth1: Passed.
|
ufuncsynth1: Passed.
|
||||||
============================================================================
|
============================================================================
|
||||||
Test results:
|
Test results:
|
||||||
Total=2560, Passed=2554, Failed=3, Not Implemented=0, Expected Fail=3
|
Total=2561, Passed=2555, Failed=3, Not Implemented=0, Expected Fail=3
|
||||||
|
|
|
||||||
|
|
@ -664,6 +664,7 @@ Running vlog95 compiler/VVP tests for Icarus Verilog version: 12.
|
||||||
size_cast5: Passed.
|
size_cast5: Passed.
|
||||||
struct_packed_array: Passed.
|
struct_packed_array: Passed.
|
||||||
struct_packed_array2: Passed.
|
struct_packed_array2: Passed.
|
||||||
|
struct_signed: Passed.
|
||||||
sv_for_variable: Passed.
|
sv_for_variable: Passed.
|
||||||
sv_foreach1: Passed.
|
sv_foreach1: Passed.
|
||||||
sv_foreach5: Passed.
|
sv_foreach5: Passed.
|
||||||
|
|
@ -2565,4 +2566,4 @@ test_mos_strength_reduction: Passed.
|
||||||
synth_if_no_else: Passed.
|
synth_if_no_else: Passed.
|
||||||
============================================================================
|
============================================================================
|
||||||
Test results:
|
Test results:
|
||||||
Total=2563, Passed=2524, Failed=2, Not Implemented=3, Expected Fail=34
|
Total=2564, Passed=2525, Failed=2, Not Implemented=3, Expected Fail=34
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,10 @@ class netstruct_t : public LineInfo, public ivl_type_s {
|
||||||
void packed(bool flag);
|
void packed(bool flag);
|
||||||
bool packed(void) const;
|
bool packed(void) const;
|
||||||
|
|
||||||
|
// When the struct is accessed as a primary it can be signed or unsigned
|
||||||
|
void set_signed(bool flag) { signed_ = flag; }
|
||||||
|
bool get_signed(void) const { return signed_; }
|
||||||
|
|
||||||
// Append a new member to the struct/union. This must be done
|
// Append a new member to the struct/union. This must be done
|
||||||
// after the union_flag and packed settings are set. This
|
// after the union_flag and packed settings are set. This
|
||||||
// function does error checking, and the "des" argument is
|
// function does error checking, and the "des" argument is
|
||||||
|
|
@ -74,6 +78,7 @@ class netstruct_t : public LineInfo, public ivl_type_s {
|
||||||
private:
|
private:
|
||||||
bool union_;
|
bool union_;
|
||||||
bool packed_;
|
bool packed_;
|
||||||
|
bool signed_;
|
||||||
std::vector<member_t>members_;
|
std::vector<member_t>members_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
43
parse.y
43
parse.y
|
|
@ -457,6 +457,11 @@ static void current_function_set_statement(const YYLTYPE&loc, std::vector<Statem
|
||||||
PExpr*expr;
|
PExpr*expr;
|
||||||
} genvar_iter;
|
} genvar_iter;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
bool packed_flag;
|
||||||
|
bool signed_flag;
|
||||||
|
} packed_signing;
|
||||||
|
|
||||||
verinum* number;
|
verinum* number;
|
||||||
|
|
||||||
verireal* realtime;
|
verireal* realtime;
|
||||||
|
|
@ -571,7 +576,7 @@ static void current_function_set_statement(const YYLTYPE&loc, std::vector<Statem
|
||||||
%type <number> number pos_neg_number
|
%type <number> number pos_neg_number
|
||||||
%type <flag> signing unsigned_signed_opt signed_unsigned_opt
|
%type <flag> signing unsigned_signed_opt signed_unsigned_opt
|
||||||
%type <flag> import_export
|
%type <flag> import_export
|
||||||
%type <flag> K_genvar_opt K_packed_opt K_reg_opt K_static_opt K_virtual_opt
|
%type <flag> K_genvar_opt K_reg_opt K_static_opt K_virtual_opt
|
||||||
%type <flag> udp_reg_opt edge_operator
|
%type <flag> udp_reg_opt edge_operator
|
||||||
%type <drive> drive_strength drive_strength_opt dr_strength0 dr_strength1
|
%type <drive> drive_strength drive_strength_opt dr_strength0 dr_strength1
|
||||||
%type <letter> udp_input_sym udp_output_sym
|
%type <letter> udp_input_sym udp_output_sym
|
||||||
|
|
@ -642,6 +647,7 @@ static void current_function_set_statement(const YYLTYPE&loc, std::vector<Statem
|
||||||
%type <struct_member> struct_union_member
|
%type <struct_member> struct_union_member
|
||||||
%type <struct_members> struct_union_member_list
|
%type <struct_members> struct_union_member_list
|
||||||
%type <struct_type> struct_data_type
|
%type <struct_type> struct_data_type
|
||||||
|
%type <packed_signing> packed_signing
|
||||||
|
|
||||||
%type <class_declaration_extends> class_declaration_extends_opt
|
%type <class_declaration_extends> class_declaration_extends_opt
|
||||||
|
|
||||||
|
|
@ -2988,38 +2994,54 @@ enum_name
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
struct_data_type
|
/* `signed` and `unsigned` are only valid if preceded by `packed` */
|
||||||
: K_struct K_packed_opt '{' struct_union_member_list '}'
|
packed_signing /* IEEE 1800-2012 A.2.2.1 */
|
||||||
|
: K_packed unsigned_signed_opt
|
||||||
|
{ $$.packed_flag = true;
|
||||||
|
$$.signed_flag = $2;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
{ $$.packed_flag = false;
|
||||||
|
$$.signed_flag = false;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
struct_data_type /* IEEE 1800-2012 A.2.2.1 */
|
||||||
|
: K_struct packed_signing '{' struct_union_member_list '}'
|
||||||
{ struct_type_t*tmp = new struct_type_t;
|
{ struct_type_t*tmp = new struct_type_t;
|
||||||
FILE_NAME(tmp, @1);
|
FILE_NAME(tmp, @1);
|
||||||
tmp->packed_flag = $2;
|
tmp->packed_flag = $2.packed_flag;
|
||||||
|
tmp->signed_flag = $2.signed_flag;
|
||||||
tmp->union_flag = false;
|
tmp->union_flag = false;
|
||||||
tmp->members .reset($4);
|
tmp->members .reset($4);
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
| K_union K_packed_opt '{' struct_union_member_list '}'
|
| K_union packed_signing '{' struct_union_member_list '}'
|
||||||
{ struct_type_t*tmp = new struct_type_t;
|
{ struct_type_t*tmp = new struct_type_t;
|
||||||
FILE_NAME(tmp, @1);
|
FILE_NAME(tmp, @1);
|
||||||
tmp->packed_flag = $2;
|
tmp->packed_flag = $2.packed_flag;
|
||||||
|
tmp->signed_flag = $2.signed_flag;
|
||||||
tmp->union_flag = true;
|
tmp->union_flag = true;
|
||||||
tmp->members .reset($4);
|
tmp->members .reset($4);
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
| K_struct K_packed_opt '{' error '}'
|
| K_struct packed_signing '{' error '}'
|
||||||
{ yyerror(@3, "error: Errors in struct member list.");
|
{ yyerror(@3, "error: Errors in struct member list.");
|
||||||
yyerrok;
|
yyerrok;
|
||||||
struct_type_t*tmp = new struct_type_t;
|
struct_type_t*tmp = new struct_type_t;
|
||||||
FILE_NAME(tmp, @1);
|
FILE_NAME(tmp, @1);
|
||||||
tmp->packed_flag = $2;
|
tmp->packed_flag = $2.packed_flag;
|
||||||
|
tmp->signed_flag = $2.signed_flag;
|
||||||
tmp->union_flag = false;
|
tmp->union_flag = false;
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
| K_union K_packed_opt '{' error '}'
|
| K_union packed_signing '{' error '}'
|
||||||
{ yyerror(@3, "error: Errors in union member list.");
|
{ yyerror(@3, "error: Errors in union member list.");
|
||||||
yyerrok;
|
yyerrok;
|
||||||
struct_type_t*tmp = new struct_type_t;
|
struct_type_t*tmp = new struct_type_t;
|
||||||
FILE_NAME(tmp, @1);
|
FILE_NAME(tmp, @1);
|
||||||
tmp->packed_flag = $2;
|
tmp->packed_flag = $2.packed_flag;
|
||||||
|
tmp->signed_flag = $2.signed_flag;
|
||||||
tmp->union_flag = true;
|
tmp->union_flag = true;
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
|
|
@ -7453,7 +7475,6 @@ unique_priority
|
||||||
collect those rules here. */
|
collect those rules here. */
|
||||||
|
|
||||||
K_genvar_opt : K_genvar { $$ = true; } | { $$ = false; } ;
|
K_genvar_opt : K_genvar { $$ = true; } | { $$ = false; } ;
|
||||||
K_packed_opt : K_packed { $$ = true; } | { $$ = false; } ;
|
|
||||||
K_reg_opt : K_reg { $$ = true; } | { $$ = false; } ;
|
K_reg_opt : K_reg { $$ = true; } | { $$ = false; } ;
|
||||||
K_static_opt : K_static { $$ = true; } | { $$ = false; } ;
|
K_static_opt : K_static { $$ = true; } | { $$ = false; } ;
|
||||||
K_virtual_opt : K_virtual { $$ = true; } | { $$ = false; } ;
|
K_virtual_opt : K_virtual { $$ = true; } | { $$ = false; } ;
|
||||||
|
|
|
||||||
|
|
@ -207,6 +207,7 @@ struct struct_type_t : public data_type_t {
|
||||||
|
|
||||||
bool packed_flag;
|
bool packed_flag;
|
||||||
bool union_flag;
|
bool union_flag;
|
||||||
|
bool signed_flag;
|
||||||
std::unique_ptr< std::list<struct_member_t*> > members;
|
std::unique_ptr< std::list<struct_member_t*> > members;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue