mirror of
https://github.com/YosysHQ/yosys
synced 2025-06-07 14:43:23 +00:00
Merge pull request #1803 from Grazfather/typedef
Support standard typedef grammar (Fixed)
This commit is contained in:
commit
b86905d952
12 changed files with 124 additions and 40 deletions
|
@ -1179,12 +1179,13 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump
|
||||||
for (auto n : design->verilog_globals)
|
for (auto n : design->verilog_globals)
|
||||||
(*it)->children.push_back(n->clone());
|
(*it)->children.push_back(n->clone());
|
||||||
|
|
||||||
for (auto n : design->verilog_packages){
|
// append nodes from previous packages using package-qualified names
|
||||||
for (auto o : n->children) {
|
for (auto &n : design->verilog_packages) {
|
||||||
|
for (auto &o : n->children) {
|
||||||
AstNode *cloned_node = o->clone();
|
AstNode *cloned_node = o->clone();
|
||||||
log("cloned node %s\n", type2str(cloned_node->type).c_str());
|
// log("cloned node %s\n", type2str(cloned_node->type).c_str());
|
||||||
if (cloned_node->type == AST_ENUM){
|
if (cloned_node->type == AST_ENUM) {
|
||||||
for (auto e : cloned_node->children){
|
for (auto &e : cloned_node->children) {
|
||||||
log_assert(e->type == AST_ENUM_ITEM);
|
log_assert(e->type == AST_ENUM_ITEM);
|
||||||
e->str = n->str + std::string("::") + e->str.substr(1);
|
e->str = n->str + std::string("::") + e->str.substr(1);
|
||||||
}
|
}
|
||||||
|
@ -1220,6 +1221,8 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump
|
||||||
design->add(process_module(*it, defer));
|
design->add(process_module(*it, defer));
|
||||||
}
|
}
|
||||||
else if ((*it)->type == AST_PACKAGE) {
|
else if ((*it)->type == AST_PACKAGE) {
|
||||||
|
// process enum/other declarations
|
||||||
|
(*it)->simplify(true, false, false, 1, -1, false, false);
|
||||||
design->verilog_packages.push_back((*it)->clone());
|
design->verilog_packages.push_back((*it)->clone());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -47,6 +47,22 @@ static void error_on_dpi_function(AST::AstNode *node)
|
||||||
error_on_dpi_function(child);
|
error_on_dpi_function(child);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void add_package_types(std::map<std::string, AST::AstNode *> &user_types, std::vector<AST::AstNode *> &package_list)
|
||||||
|
{
|
||||||
|
// prime the parser's user type lookup table with the package qualified names
|
||||||
|
// of typedefed names in the packages seen so far.
|
||||||
|
user_types.clear();
|
||||||
|
for (const auto &pkg : package_list) {
|
||||||
|
log_assert(pkg->type==AST::AST_PACKAGE);
|
||||||
|
for (const auto &node: pkg->children) {
|
||||||
|
if (node->type == AST::AST_TYPEDEF) {
|
||||||
|
std::string s = pkg->str + "::" + node->str.substr(1);
|
||||||
|
user_types[s] = node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct VerilogFrontend : public Frontend {
|
struct VerilogFrontend : public Frontend {
|
||||||
VerilogFrontend() : Frontend("verilog", "read modules from Verilog file") { }
|
VerilogFrontend() : Frontend("verilog", "read modules from Verilog file") { }
|
||||||
void help() YS_OVERRIDE
|
void help() YS_OVERRIDE
|
||||||
|
@ -450,6 +466,9 @@ struct VerilogFrontend : public Frontend {
|
||||||
lexin = new std::istringstream(code_after_preproc);
|
lexin = new std::istringstream(code_after_preproc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// make package typedefs available to parser
|
||||||
|
add_package_types(pkg_user_types, design->verilog_packages);
|
||||||
|
|
||||||
frontend_verilog_yyset_lineno(1);
|
frontend_verilog_yyset_lineno(1);
|
||||||
frontend_verilog_yyrestart(NULL);
|
frontend_verilog_yyrestart(NULL);
|
||||||
frontend_verilog_yyparse();
|
frontend_verilog_yyparse();
|
||||||
|
@ -468,6 +487,7 @@ struct VerilogFrontend : public Frontend {
|
||||||
AST::process(design, current_ast, flag_dump_ast1, flag_dump_ast2, flag_no_dump_ptr, flag_dump_vlog1, flag_dump_vlog2, flag_dump_rtlil, flag_nolatches,
|
AST::process(design, current_ast, flag_dump_ast1, flag_dump_ast2, flag_no_dump_ptr, flag_dump_vlog1, flag_dump_vlog2, flag_dump_rtlil, flag_nolatches,
|
||||||
flag_nomeminit, flag_nomem2reg, flag_mem2reg, flag_noblackbox, lib_mode, flag_nowb, flag_noopt, flag_icells, flag_pwires, flag_nooverwrite, flag_overwrite, flag_defer, default_nettype_wire);
|
flag_nomeminit, flag_nomem2reg, flag_mem2reg, flag_noblackbox, lib_mode, flag_nowb, flag_noopt, flag_icells, flag_pwires, flag_nooverwrite, flag_overwrite, flag_defer, default_nettype_wire);
|
||||||
|
|
||||||
|
|
||||||
if (!flag_nopp)
|
if (!flag_nopp)
|
||||||
delete lexin;
|
delete lexin;
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,12 @@ namespace VERILOG_FRONTEND
|
||||||
// this function converts a Verilog constant to an AST_CONSTANT node
|
// this function converts a Verilog constant to an AST_CONSTANT node
|
||||||
AST::AstNode *const2ast(std::string code, char case_type = 0, bool warn_z = false);
|
AST::AstNode *const2ast(std::string code, char case_type = 0, bool warn_z = false);
|
||||||
|
|
||||||
|
// names of locally typedef'ed types
|
||||||
|
extern std::map<std::string, AST::AstNode*> user_types;
|
||||||
|
|
||||||
|
// names of package typedef'ed types
|
||||||
|
extern std::map<std::string, AST::AstNode*> pkg_user_types;
|
||||||
|
|
||||||
// state of `default_nettype
|
// state of `default_nettype
|
||||||
extern bool default_nettype_wire;
|
extern bool default_nettype_wire;
|
||||||
|
|
||||||
|
|
|
@ -372,9 +372,33 @@ supply1 { return TOK_SUPPLY1; }
|
||||||
"$signed" { return TOK_TO_SIGNED; }
|
"$signed" { return TOK_TO_SIGNED; }
|
||||||
"$unsigned" { return TOK_TO_UNSIGNED; }
|
"$unsigned" { return TOK_TO_UNSIGNED; }
|
||||||
|
|
||||||
[a-zA-Z_$][a-zA-Z0-9_$]* {
|
[a-zA-Z_][a-zA-Z0-9_]*::[a-zA-Z_$][a-zA-Z0-9_$]* {
|
||||||
|
// package qualifier
|
||||||
|
auto s = std::string("\\") + yytext;
|
||||||
|
if (pkg_user_types.count(s) > 0) {
|
||||||
|
// found it
|
||||||
|
yylval->string = new std::string(s);
|
||||||
|
return TOK_USER_TYPE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// backup before :: just return first part
|
||||||
|
size_t len = strchr(yytext, ':') - yytext;
|
||||||
|
yyless(len);
|
||||||
yylval->string = new std::string(std::string("\\") + yytext);
|
yylval->string = new std::string(std::string("\\") + yytext);
|
||||||
return TOK_ID;
|
return TOK_ID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[a-zA-Z_$][a-zA-Z0-9_$]* {
|
||||||
|
auto s = std::string("\\") + yytext;
|
||||||
|
if (user_types.count(s) > 0) {
|
||||||
|
yylval->string = new std::string(s);
|
||||||
|
return TOK_USER_TYPE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
yylval->string = new std::string(std::string("\\") + yytext);
|
||||||
|
return TOK_ID;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[a-zA-Z_$][a-zA-Z0-9_$\.]* {
|
[a-zA-Z_$][a-zA-Z0-9_$\.]* {
|
||||||
|
|
|
@ -54,6 +54,8 @@ namespace VERILOG_FRONTEND {
|
||||||
std::map<std::string, AstNode*> *attr_list, default_attr_list;
|
std::map<std::string, AstNode*> *attr_list, default_attr_list;
|
||||||
std::stack<std::map<std::string, AstNode*> *> attr_list_stack;
|
std::stack<std::map<std::string, AstNode*> *> attr_list_stack;
|
||||||
std::map<std::string, AstNode*> *albuf;
|
std::map<std::string, AstNode*> *albuf;
|
||||||
|
std::map<std::string, AstNode*> user_types;
|
||||||
|
std::map<std::string, AstNode*> pkg_user_types;
|
||||||
std::vector<AstNode*> ast_stack;
|
std::vector<AstNode*> ast_stack;
|
||||||
struct AstNode *astbuf1, *astbuf2, *astbuf3;
|
struct AstNode *astbuf1, *astbuf2, *astbuf3;
|
||||||
struct AstNode *current_function_or_task;
|
struct AstNode *current_function_or_task;
|
||||||
|
@ -125,6 +127,26 @@ struct specify_rise_fall {
|
||||||
specify_triple fall;
|
specify_triple fall;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void addTypedefNode(std::string *name, AstNode *node)
|
||||||
|
{
|
||||||
|
log_assert(node);
|
||||||
|
// seems to be support for local scoped typedefs in simplify()
|
||||||
|
// and tests redefine types.
|
||||||
|
//if (user_types.count(*name) > 0) {
|
||||||
|
// frontend_verilog_yyerror("Type already defined.");
|
||||||
|
//}
|
||||||
|
auto *tnode = new AstNode(AST_TYPEDEF, node);
|
||||||
|
tnode->str = *name;
|
||||||
|
user_types[*name] = tnode;
|
||||||
|
if (current_ast_mod && current_ast_mod->type == AST_PACKAGE) {
|
||||||
|
// typedef inside a package so we need the qualified name
|
||||||
|
auto qname = current_ast_mod->str + "::" + (*name).substr(1);
|
||||||
|
pkg_user_types[qname] = tnode;
|
||||||
|
}
|
||||||
|
delete name;
|
||||||
|
ast_stack.back()->children.push_back(tnode);
|
||||||
|
}
|
||||||
|
|
||||||
static AstNode *makeRange(int msb = 31, int lsb = 0, bool isSigned = true)
|
static AstNode *makeRange(int msb = 31, int lsb = 0, bool isSigned = true)
|
||||||
{
|
{
|
||||||
auto range = new AstNode(AST_RANGE);
|
auto range = new AstNode(AST_RANGE);
|
||||||
|
@ -167,6 +189,7 @@ static void addRange(AstNode *parent, int msb = 31, int lsb = 0, bool isSigned =
|
||||||
%token <string> TOK_STRING TOK_ID TOK_CONSTVAL TOK_REALVAL TOK_PRIMITIVE
|
%token <string> TOK_STRING TOK_ID TOK_CONSTVAL TOK_REALVAL TOK_PRIMITIVE
|
||||||
%token <string> TOK_SVA_LABEL TOK_SPECIFY_OPER TOK_MSG_TASKS
|
%token <string> TOK_SVA_LABEL TOK_SPECIFY_OPER TOK_MSG_TASKS
|
||||||
%token <string> TOK_BASE TOK_BASED_CONSTVAL TOK_UNBASED_UNSIZED_CONSTVAL
|
%token <string> TOK_BASE TOK_BASED_CONSTVAL TOK_UNBASED_UNSIZED_CONSTVAL
|
||||||
|
%token <string> TOK_USER_TYPE
|
||||||
%token TOK_ASSERT TOK_ASSUME TOK_RESTRICT TOK_COVER TOK_FINAL
|
%token TOK_ASSERT TOK_ASSUME TOK_RESTRICT TOK_COVER TOK_FINAL
|
||||||
%token ATTR_BEGIN ATTR_END DEFATTR_BEGIN DEFATTR_END
|
%token ATTR_BEGIN ATTR_END DEFATTR_BEGIN DEFATTR_END
|
||||||
%token TOK_MODULE TOK_ENDMODULE TOK_PARAMETER TOK_LOCALPARAM TOK_DEFPARAM
|
%token TOK_MODULE TOK_ENDMODULE TOK_PARAMETER TOK_LOCALPARAM TOK_DEFPARAM
|
||||||
|
@ -190,6 +213,7 @@ static void addRange(AstNode *parent, int msb = 31, int lsb = 0, bool isSigned =
|
||||||
%type <ast> range range_or_multirange non_opt_range non_opt_multirange range_or_signed_int
|
%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
|
||||||
%type <string> opt_label opt_sva_label tok_prim_wrapper hierarchical_id hierarchical_type_id integral_number
|
%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
|
%type <ast> opt_enum_init
|
||||||
%type <boolean> opt_signed opt_property unique_case_attr always_comb_or_latch always_or_always_ff
|
%type <boolean> opt_signed opt_property unique_case_attr always_comb_or_latch always_or_always_ff
|
||||||
%type <al> attr case_attr
|
%type <al> attr case_attr
|
||||||
|
@ -330,7 +354,9 @@ hierarchical_id:
|
||||||
};
|
};
|
||||||
|
|
||||||
hierarchical_type_id:
|
hierarchical_type_id:
|
||||||
'(' hierarchical_id ')' { $$ = $2; };
|
TOK_USER_TYPE
|
||||||
|
| '(' TOK_USER_TYPE ')' { $$ = $2; } // non-standard grammar
|
||||||
|
;
|
||||||
|
|
||||||
module:
|
module:
|
||||||
attr TOK_MODULE TOK_ID {
|
attr TOK_MODULE TOK_ID {
|
||||||
|
@ -352,6 +378,7 @@ module:
|
||||||
ast_stack.pop_back();
|
ast_stack.pop_back();
|
||||||
log_assert(ast_stack.size() == 1);
|
log_assert(ast_stack.size() == 1);
|
||||||
current_ast_mod = NULL;
|
current_ast_mod = NULL;
|
||||||
|
user_types.clear();
|
||||||
};
|
};
|
||||||
|
|
||||||
module_para_opt:
|
module_para_opt:
|
||||||
|
@ -465,6 +492,7 @@ package:
|
||||||
} ';' package_body TOK_ENDPACKAGE {
|
} ';' package_body TOK_ENDPACKAGE {
|
||||||
ast_stack.pop_back();
|
ast_stack.pop_back();
|
||||||
current_ast_mod = NULL;
|
current_ast_mod = NULL;
|
||||||
|
user_types.clear();
|
||||||
};
|
};
|
||||||
|
|
||||||
package_body:
|
package_body:
|
||||||
|
@ -494,6 +522,7 @@ interface:
|
||||||
ast_stack.pop_back();
|
ast_stack.pop_back();
|
||||||
log_assert(ast_stack.size() == 1);
|
log_assert(ast_stack.size() == 1);
|
||||||
current_ast_mod = NULL;
|
current_ast_mod = NULL;
|
||||||
|
user_types.clear();
|
||||||
};
|
};
|
||||||
|
|
||||||
interface_body:
|
interface_body:
|
||||||
|
@ -1591,8 +1620,12 @@ assign_expr:
|
||||||
ast_stack.back()->children.push_back(node);
|
ast_stack.back()->children.push_back(node);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type_name: TOK_ID // first time seen
|
||||||
|
| TOK_USER_TYPE // redefinition
|
||||||
|
;
|
||||||
|
|
||||||
typedef_decl:
|
typedef_decl:
|
||||||
TOK_TYPEDEF wire_type range TOK_ID range_or_multirange ';' {
|
TOK_TYPEDEF wire_type range type_name range_or_multirange ';' {
|
||||||
astbuf1 = $2;
|
astbuf1 = $2;
|
||||||
astbuf2 = $3;
|
astbuf2 = $3;
|
||||||
if (astbuf1->range_left >= 0 && astbuf1->range_right >= 0) {
|
if (astbuf1->range_left >= 0 && astbuf1->range_right >= 0) {
|
||||||
|
@ -1625,13 +1658,10 @@ typedef_decl:
|
||||||
}
|
}
|
||||||
astbuf1->children.push_back(rangeNode);
|
astbuf1->children.push_back(rangeNode);
|
||||||
}
|
}
|
||||||
|
addTypedefNode($4, astbuf1);
|
||||||
ast_stack.back()->children.push_back(new AstNode(AST_TYPEDEF, astbuf1));
|
|
||||||
ast_stack.back()->children.back()->str = *$4;
|
|
||||||
} |
|
} |
|
||||||
TOK_TYPEDEF enum_type TOK_ID ';' {
|
TOK_TYPEDEF enum_type type_name ';' {
|
||||||
ast_stack.back()->children.push_back(new AstNode(AST_TYPEDEF, astbuf1));
|
addTypedefNode($3, astbuf1);
|
||||||
ast_stack.back()->children.back()->str = *$3;
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,9 @@ module enum_simple(input clk, input rst);
|
||||||
typedef enum logic [1:0] {
|
typedef enum logic [1:0] {
|
||||||
ts0, ts1, ts2, ts3
|
ts0, ts1, ts2, ts3
|
||||||
} states_t;
|
} states_t;
|
||||||
(states_t) state;
|
states_t state;
|
||||||
(states_t) enum_const = ts1;
|
(states_t) state1;
|
||||||
|
states_t enum_const = ts1;
|
||||||
|
|
||||||
always @(posedge clk) begin
|
always @(posedge clk) begin
|
||||||
if (rst) begin
|
if (rst) begin
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
module top(input [3:0] addr, wdata, input clk, wen, output reg [3:0] rdata);
|
module top(input [3:0] addr, wdata, input clk, wen, output reg [3:0] rdata);
|
||||||
typedef logic [3:0] ram16x4_t[0:15];
|
typedef logic [3:0] ram16x4_t[0:15];
|
||||||
|
|
||||||
(ram16x4_t) mem;
|
ram16x4_t mem;
|
||||||
|
|
||||||
always @(posedge clk) begin
|
always @(posedge clk) begin
|
||||||
if (wen) mem[addr] <= wdata;
|
if (wen) mem[addr] <= wdata;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
module top(input [3:0] addr, wdata, input clk, wen, output reg [3:0] rdata);
|
module top(input [3:0] addr, wdata, input clk, wen, output reg [3:0] rdata);
|
||||||
typedef logic [3:0] nibble;
|
typedef logic [3:0] nibble;
|
||||||
|
|
||||||
(nibble) mem[0:15];
|
nibble mem[0:15];
|
||||||
|
|
||||||
always @(posedge clk) begin
|
always @(posedge clk) begin
|
||||||
if (wen) mem[addr] <= wdata;
|
if (wen) mem[addr] <= wdata;
|
||||||
|
|
|
@ -5,8 +5,8 @@ endpackage
|
||||||
|
|
||||||
module top;
|
module top;
|
||||||
|
|
||||||
(* keep *) (pkg::uint8_t) a = 8'hAA;
|
(* keep *) pkg::uint8_t a = 8'hAA;
|
||||||
(* keep *) (pkg::enum8_t) b_enum = pkg::bb;
|
(* keep *) pkg::enum8_t b_enum = pkg::bb;
|
||||||
|
|
||||||
always @* assert(a == 8'hAA);
|
always @* assert(a == 8'hAA);
|
||||||
always @* assert(b_enum == 8'hBB);
|
always @* assert(b_enum == 8'hBB);
|
||||||
|
|
|
@ -6,12 +6,12 @@ module top;
|
||||||
typedef logic [1:0] uint2_t;
|
typedef logic [1:0] uint2_t;
|
||||||
typedef logic signed [3:0] int4_t;
|
typedef logic signed [3:0] int4_t;
|
||||||
typedef logic signed [7:0] int8_t;
|
typedef logic signed [7:0] int8_t;
|
||||||
typedef (int8_t) char_t;
|
typedef int8_t char_t;
|
||||||
|
|
||||||
parameter (uint2_t) int2 = 2'b10;
|
parameter uint2_t int2 = 2'b10;
|
||||||
localparam (int4_t) int4 = -1;
|
localparam int4_t int4 = -1;
|
||||||
localparam (int8_t) int8 = int4;
|
localparam int8_t int8 = int4;
|
||||||
localparam (char_t) ch = int8;
|
localparam char_t ch = int8;
|
||||||
|
|
||||||
|
|
||||||
`STATIC_ASSERT(int2 == 2'b10);
|
`STATIC_ASSERT(int2 == 2'b10);
|
||||||
|
|
|
@ -4,30 +4,30 @@ typedef enum logic {s0, s1} outer_enum_t;
|
||||||
|
|
||||||
module top;
|
module top;
|
||||||
|
|
||||||
(outer_uint4_t) u4_i = 8'hA5;
|
outer_uint4_t u4_i = 8'hA5;
|
||||||
(outer_enum_t) enum4_i = s0;
|
outer_enum_t enum4_i = s0;
|
||||||
always @(*) assert(u4_i == 4'h5);
|
always @(*) assert(u4_i == 4'h5);
|
||||||
always @(*) assert(enum4_i == 1'b0);
|
always @(*) assert(enum4_i == 1'b0);
|
||||||
|
|
||||||
typedef logic [3:0] inner_type;
|
typedef logic [3:0] inner_type;
|
||||||
typedef enum logic [2:0] {s2=2, s3, s4} inner_enum_t;
|
typedef enum logic [2:0] {s2=2, s3, s4} inner_enum_t;
|
||||||
(inner_type) inner_i1 = 8'h5A;
|
inner_type inner_i1 = 8'h5A;
|
||||||
(inner_enum_t) inner_enum1 = s3;
|
inner_enum_t inner_enum1 = s3;
|
||||||
always @(*) assert(inner_i1 == 4'hA);
|
always @(*) assert(inner_i1 == 4'hA);
|
||||||
always @(*) assert(inner_enum1 == 3'h3);
|
always @(*) assert(inner_enum1 == 3'h3);
|
||||||
|
|
||||||
if (1) begin: genblock
|
if (1) begin: genblock
|
||||||
typedef logic [7:0] inner_type;
|
typedef logic [7:0] inner_type;
|
||||||
parameter (inner_type) inner_const = 8'hA5;
|
parameter inner_type inner_const = 8'hA5;
|
||||||
typedef enum logic [2:0] {s5=5, s6, s7} inner_enum_t;
|
typedef enum logic [2:0] {s5=5, s6, s7} inner_enum_t;
|
||||||
(inner_type) inner_gb_i = inner_const; //8'hA5;
|
inner_type inner_gb_i = inner_const; //8'hA5;
|
||||||
(inner_enum_t) inner_gb_enum1 = s7;
|
inner_enum_t inner_gb_enum1 = s7;
|
||||||
always @(*) assert(inner_gb_i == 8'hA5);
|
always @(*) assert(inner_gb_i == 8'hA5);
|
||||||
always @(*) assert(inner_gb_enum1 == 3'h7);
|
always @(*) assert(inner_gb_enum1 == 3'h7);
|
||||||
end
|
end
|
||||||
|
|
||||||
(inner_type) inner_i2 = 8'h42;
|
inner_type inner_i2 = 8'h42;
|
||||||
(inner_enum_t) inner_enum2 = s4;
|
inner_enum_t inner_enum2 = s4;
|
||||||
always @(*) assert(inner_i2 == 4'h2);
|
always @(*) assert(inner_i2 == 4'h2);
|
||||||
always @(*) assert(inner_enum2 == 3'h4);
|
always @(*) assert(inner_enum2 == 3'h4);
|
||||||
|
|
||||||
|
|
|
@ -3,12 +3,12 @@ module top;
|
||||||
typedef logic [1:0] uint2_t;
|
typedef logic [1:0] uint2_t;
|
||||||
typedef logic signed [3:0] int4_t;
|
typedef logic signed [3:0] int4_t;
|
||||||
typedef logic signed [7:0] int8_t;
|
typedef logic signed [7:0] int8_t;
|
||||||
typedef (int8_t) char_t;
|
typedef int8_t char_t;
|
||||||
|
|
||||||
(* keep *) (uint2_t) int2 = 2'b10;
|
(* keep *) uint2_t int2 = 2'b10;
|
||||||
(* keep *) (int4_t) int4 = -1;
|
(* keep *) int4_t int4 = -1;
|
||||||
(* keep *) (int8_t) int8 = int4;
|
(* keep *) int8_t int8 = int4;
|
||||||
(* keep *) (char_t) ch = int8;
|
(* keep *) char_t ch = int8;
|
||||||
|
|
||||||
|
|
||||||
always @* assert(int2 == 2'b10);
|
always @* assert(int2 == 2'b10);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue