mirror of https://github.com/YosysHQ/yosys.git
sv: Switch parser to glr, prep for typedef
Signed-off-by: David Shah <dave@ds0.me>
This commit is contained in:
parent
e0a6742935
commit
f6b5e47e40
|
@ -164,6 +164,8 @@ std::string AST::type2str(AstNodeType type)
|
||||||
X(AST_MODPORT)
|
X(AST_MODPORT)
|
||||||
X(AST_MODPORTMEMBER)
|
X(AST_MODPORTMEMBER)
|
||||||
X(AST_PACKAGE)
|
X(AST_PACKAGE)
|
||||||
|
X(AST_WIRETYPE)
|
||||||
|
X(AST_TYPEDEF)
|
||||||
#undef X
|
#undef X
|
||||||
default:
|
default:
|
||||||
log_abort();
|
log_abort();
|
||||||
|
@ -206,6 +208,7 @@ AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2, AstNode *ch
|
||||||
was_checked = false;
|
was_checked = false;
|
||||||
range_valid = false;
|
range_valid = false;
|
||||||
range_swapped = false;
|
range_swapped = false;
|
||||||
|
is_custom_type = false;
|
||||||
port_id = 0;
|
port_id = 0;
|
||||||
range_left = -1;
|
range_left = -1;
|
||||||
range_right = 0;
|
range_right = 0;
|
||||||
|
|
|
@ -148,7 +148,10 @@ namespace AST
|
||||||
AST_INTERFACEPORTTYPE,
|
AST_INTERFACEPORTTYPE,
|
||||||
AST_MODPORT,
|
AST_MODPORT,
|
||||||
AST_MODPORTMEMBER,
|
AST_MODPORTMEMBER,
|
||||||
AST_PACKAGE
|
AST_PACKAGE,
|
||||||
|
|
||||||
|
AST_WIRETYPE,
|
||||||
|
AST_TYPEDEF
|
||||||
};
|
};
|
||||||
|
|
||||||
// convert an node type to a string (e.g. for debug output)
|
// convert an node type to a string (e.g. for debug output)
|
||||||
|
@ -174,7 +177,7 @@ namespace AST
|
||||||
// node content - most of it is unused in most node types
|
// node content - most of it is unused in most node types
|
||||||
std::string str;
|
std::string str;
|
||||||
std::vector<RTLIL::State> bits;
|
std::vector<RTLIL::State> bits;
|
||||||
bool is_input, is_output, is_reg, is_logic, is_signed, is_string, is_wand, is_wor, range_valid, range_swapped, was_checked, is_unsized;
|
bool is_input, is_output, is_reg, is_logic, is_signed, is_string, is_wand, is_wor, range_valid, range_swapped, was_checked, is_unsized, is_custom_type;
|
||||||
int port_id, range_left, range_right;
|
int port_id, range_left, range_right;
|
||||||
uint32_t integer;
|
uint32_t integer;
|
||||||
double realvalue;
|
double realvalue;
|
||||||
|
|
|
@ -863,6 +863,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
||||||
case AST_PACKAGE:
|
case AST_PACKAGE:
|
||||||
case AST_MODPORT:
|
case AST_MODPORT:
|
||||||
case AST_MODPORTMEMBER:
|
case AST_MODPORTMEMBER:
|
||||||
|
case AST_TYPEDEF:
|
||||||
break;
|
break;
|
||||||
case AST_INTERFACEPORT: {
|
case AST_INTERFACEPORT: {
|
||||||
// If a port in a module with unknown type is found, mark it with the attribute 'is_interface'
|
// If a port in a module with unknown type is found, mark it with the attribute 'is_interface'
|
||||||
|
|
|
@ -318,7 +318,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
||||||
}
|
}
|
||||||
|
|
||||||
// activate const folding if this is anything that must be evaluated statically (ranges, parameters, attributes, etc.)
|
// activate const folding if this is anything that must be evaluated statically (ranges, parameters, attributes, etc.)
|
||||||
if (type == AST_WIRE || type == AST_PARAMETER || type == AST_LOCALPARAM || type == AST_DEFPARAM || type == AST_PARASET || type == AST_RANGE || type == AST_PREFIX)
|
if (type == AST_WIRE || type == AST_PARAMETER || type == AST_LOCALPARAM || type == AST_DEFPARAM || type == AST_PARASET || type == AST_RANGE || type == AST_PREFIX || type == AST_TYPEDEF)
|
||||||
const_fold = true;
|
const_fold = true;
|
||||||
if (type == AST_IDENTIFIER && current_scope.count(str) > 0 && (current_scope[str]->type == AST_PARAMETER || current_scope[str]->type == AST_LOCALPARAM))
|
if (type == AST_IDENTIFIER && current_scope.count(str) > 0 && (current_scope[str]->type == AST_PARAMETER || current_scope[str]->type == AST_LOCALPARAM))
|
||||||
const_fold = true;
|
const_fold = true;
|
||||||
|
@ -336,6 +336,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
||||||
std::map<std::string, AstNode*> this_wire_scope;
|
std::map<std::string, AstNode*> this_wire_scope;
|
||||||
for (size_t i = 0; i < children.size(); i++) {
|
for (size_t i = 0; i < children.size(); i++) {
|
||||||
AstNode *node = children[i];
|
AstNode *node = children[i];
|
||||||
|
|
||||||
if (node->type == AST_WIRE) {
|
if (node->type == AST_WIRE) {
|
||||||
if (node->children.size() == 1 && node->children[0]->type == AST_RANGE) {
|
if (node->children.size() == 1 && node->children[0]->type == AST_RANGE) {
|
||||||
for (auto c : node->children[0]->children) {
|
for (auto c : node->children[0]->children) {
|
||||||
|
@ -405,14 +406,15 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
||||||
this_wire_scope[node->str] = node;
|
this_wire_scope[node->str] = node;
|
||||||
}
|
}
|
||||||
if (node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_WIRE || node->type == AST_AUTOWIRE || node->type == AST_GENVAR ||
|
if (node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_WIRE || node->type == AST_AUTOWIRE || node->type == AST_GENVAR ||
|
||||||
node->type == AST_MEMORY || node->type == AST_FUNCTION || node->type == AST_TASK || node->type == AST_DPI_FUNCTION || node->type == AST_CELL) {
|
node->type == AST_MEMORY || node->type == AST_FUNCTION || node->type == AST_TASK || node->type == AST_DPI_FUNCTION || node->type == AST_CELL ||
|
||||||
|
node->type == AST_TYPEDEF) {
|
||||||
backup_scope[node->str] = current_scope[node->str];
|
backup_scope[node->str] = current_scope[node->str];
|
||||||
current_scope[node->str] = node;
|
current_scope[node->str] = node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (size_t i = 0; i < children.size(); i++) {
|
for (size_t i = 0; i < children.size(); i++) {
|
||||||
AstNode *node = children[i];
|
AstNode *node = children[i];
|
||||||
if (node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_WIRE || node->type == AST_AUTOWIRE || node->type == AST_MEMORY)
|
if (node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_WIRE || node->type == AST_AUTOWIRE || node->type == AST_MEMORY || node->type == AST_TYPEDEF)
|
||||||
while (node->simplify(true, false, false, 1, -1, false, node->type == AST_PARAMETER || node->type == AST_LOCALPARAM))
|
while (node->simplify(true, false, false, 1, -1, false, node->type == AST_PARAMETER || node->type == AST_LOCALPARAM))
|
||||||
did_something = true;
|
did_something = true;
|
||||||
}
|
}
|
||||||
|
@ -780,6 +782,44 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
||||||
delete_children();
|
delete_children();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// resolve typedefs
|
||||||
|
if (type == AST_TYPEDEF) {
|
||||||
|
log_assert(children.size() == 1);
|
||||||
|
log_assert(children[0]->type == AST_WIRE);
|
||||||
|
while(children[0]->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) {};
|
||||||
|
log_assert(!children[0]->is_custom_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
// resolve types of wires and parameters
|
||||||
|
if (type == AST_WIRE || type == AST_LOCALPARAM || type == AST_PARAMETER) {
|
||||||
|
if (is_custom_type) {
|
||||||
|
log_assert(children.size() == 1);
|
||||||
|
log_assert(children[0]->type == AST_WIRETYPE);
|
||||||
|
if (!current_scope.count(children[0]->str))
|
||||||
|
log_file_error(filename, linenum, "Unknown identifier `%s' used as type name", children[0]->str.c_str());
|
||||||
|
AstNode *resolved_type = current_scope.at(children[0]->str);
|
||||||
|
if (resolved_type->type != AST_TYPEDEF)
|
||||||
|
log_file_error(filename, linenum, "`%s' does not name a type", children[0]->str.c_str());
|
||||||
|
log_assert(resolved_type->children.size() == 1);
|
||||||
|
AstNode *templ = resolved_type->children[0];
|
||||||
|
delete_children(); // type reference no longer needed
|
||||||
|
|
||||||
|
is_reg = templ->is_reg;
|
||||||
|
is_logic = templ->is_logic;
|
||||||
|
is_signed = templ->is_signed;
|
||||||
|
is_string = templ->is_string;
|
||||||
|
is_custom_type = templ->is_custom_type;
|
||||||
|
|
||||||
|
range_valid = templ->range_valid;
|
||||||
|
range_swapped = templ->range_swapped;
|
||||||
|
range_left = templ->range_left;
|
||||||
|
range_right = templ->range_right;
|
||||||
|
for (auto template_child : templ->children)
|
||||||
|
children.push_back(template_child->clone());
|
||||||
|
}
|
||||||
|
log_assert(!is_custom_type);
|
||||||
|
}
|
||||||
|
|
||||||
// resolve constant prefixes
|
// resolve constant prefixes
|
||||||
if (type == AST_PREFIX) {
|
if (type == AST_PREFIX) {
|
||||||
if (children[0]->type != AST_CONSTANT) {
|
if (children[0]->type != AST_CONSTANT) {
|
||||||
|
@ -1194,7 +1234,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
||||||
if (type == AST_BLOCK && str.empty())
|
if (type == AST_BLOCK && str.empty())
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < children.size(); i++)
|
for (size_t i = 0; i < children.size(); i++)
|
||||||
if (children[i]->type == AST_WIRE || children[i]->type == AST_MEMORY || children[i]->type == AST_PARAMETER || children[i]->type == AST_LOCALPARAM)
|
if (children[i]->type == AST_WIRE || children[i]->type == AST_MEMORY || children[i]->type == AST_PARAMETER || children[i]->type == AST_LOCALPARAM || children[i]->type == AST_TYPEDEF)
|
||||||
log_file_error(children[i]->filename, children[i]->linenum, "Local declaration in unnamed block is an unsupported SystemVerilog feature!\n");
|
log_file_error(children[i]->filename, children[i]->linenum, "Local declaration in unnamed block is an unsupported SystemVerilog feature!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1206,7 +1246,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
||||||
|
|
||||||
std::vector<AstNode*> new_children;
|
std::vector<AstNode*> new_children;
|
||||||
for (size_t i = 0; i < children.size(); i++)
|
for (size_t i = 0; i < children.size(); i++)
|
||||||
if (children[i]->type == AST_WIRE || children[i]->type == AST_MEMORY || children[i]->type == AST_PARAMETER || children[i]->type == AST_LOCALPARAM) {
|
if (children[i]->type == AST_WIRE || children[i]->type == AST_MEMORY || children[i]->type == AST_PARAMETER || children[i]->type == AST_LOCALPARAM || children[i]->type == AST_TYPEDEF) {
|
||||||
children[i]->simplify(false, false, false, stage, -1, false, false);
|
children[i]->simplify(false, false, false, stage, -1, false, false);
|
||||||
current_ast_mod->children.push_back(children[i]);
|
current_ast_mod->children.push_back(children[i]);
|
||||||
current_scope[children[i]->str] = children[i];
|
current_scope[children[i]->str] = children[i];
|
||||||
|
@ -2945,6 +2985,7 @@ void AstNode::expand_genblock(std::string index_var, std::string prefix, std::ma
|
||||||
child->expand_genblock(index_var, prefix, name_map);
|
child->expand_genblock(index_var, prefix, name_map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (backup_name_map.size() > 0)
|
if (backup_name_map.size() > 0)
|
||||||
name_map.swap(backup_name_map);
|
name_map.swap(backup_name_map);
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,6 +112,8 @@ struct specify_rise_fall {
|
||||||
|
|
||||||
%define api.prefix {frontend_verilog_yy}
|
%define api.prefix {frontend_verilog_yy}
|
||||||
|
|
||||||
|
%glr-parser
|
||||||
|
|
||||||
/* The union is defined in the header, so we need to provide all the
|
/* The union is defined in the header, so we need to provide all the
|
||||||
* includes it requires
|
* includes it requires
|
||||||
*/
|
*/
|
||||||
|
@ -180,7 +182,7 @@ struct specify_rise_fall {
|
||||||
%right UNARY_OPS
|
%right UNARY_OPS
|
||||||
|
|
||||||
%define parse.error verbose
|
%define parse.error verbose
|
||||||
%define parse.lac full
|
// %define parse.lac full
|
||||||
|
|
||||||
%nonassoc FAKE_THEN
|
%nonassoc FAKE_THEN
|
||||||
%nonassoc TOK_ELSE
|
%nonassoc TOK_ELSE
|
||||||
|
@ -206,6 +208,7 @@ design:
|
||||||
task_func_decl design |
|
task_func_decl design |
|
||||||
param_decl design |
|
param_decl design |
|
||||||
localparam_decl design |
|
localparam_decl design |
|
||||||
|
typedef_decl design |
|
||||||
package design |
|
package design |
|
||||||
interface design |
|
interface design |
|
||||||
/* empty */;
|
/* empty */;
|
||||||
|
@ -426,6 +429,7 @@ package_body:
|
||||||
package_body package_body_stmt |;
|
package_body package_body_stmt |;
|
||||||
|
|
||||||
package_body_stmt:
|
package_body_stmt:
|
||||||
|
typedef_decl |
|
||||||
localparam_decl;
|
localparam_decl;
|
||||||
|
|
||||||
interface:
|
interface:
|
||||||
|
@ -452,7 +456,7 @@ interface_body:
|
||||||
interface_body interface_body_stmt |;
|
interface_body interface_body_stmt |;
|
||||||
|
|
||||||
interface_body_stmt:
|
interface_body_stmt:
|
||||||
param_decl | localparam_decl | defparam_decl | wire_decl | always_stmt | assign_stmt |
|
param_decl | localparam_decl | typedef_decl | defparam_decl | wire_decl | always_stmt | assign_stmt |
|
||||||
modport_stmt;
|
modport_stmt;
|
||||||
|
|
||||||
non_opt_delay:
|
non_opt_delay:
|
||||||
|
@ -529,6 +533,11 @@ wire_type_token:
|
||||||
} |
|
} |
|
||||||
TOK_CONST {
|
TOK_CONST {
|
||||||
current_wire_const = true;
|
current_wire_const = true;
|
||||||
|
} |
|
||||||
|
hierarchical_id {
|
||||||
|
astbuf3->is_custom_type = true;
|
||||||
|
astbuf3->children.push_back(new AstNode(AST_WIRETYPE));
|
||||||
|
astbuf3->children.back()->str = *$1;
|
||||||
};
|
};
|
||||||
|
|
||||||
non_opt_range:
|
non_opt_range:
|
||||||
|
@ -591,7 +600,7 @@ module_body:
|
||||||
/* empty */;
|
/* empty */;
|
||||||
|
|
||||||
module_body_stmt:
|
module_body_stmt:
|
||||||
task_func_decl | specify_block |param_decl | localparam_decl | defparam_decl | specparam_declaration | wire_decl | assign_stmt | cell_stmt |
|
task_func_decl | specify_block |param_decl | localparam_decl | typedef_decl | defparam_decl | specparam_declaration | wire_decl | assign_stmt | cell_stmt |
|
||||||
always_stmt | TOK_GENERATE module_gen_body TOK_ENDGENERATE | defattr | assert_property | checker_decl | ignored_specify_block;
|
always_stmt | TOK_GENERATE module_gen_body TOK_ENDGENERATE | defattr | assert_property | checker_decl | ignored_specify_block;
|
||||||
|
|
||||||
checker_decl:
|
checker_decl:
|
||||||
|
@ -1377,6 +1386,27 @@ assign_expr:
|
||||||
ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, $1, $3));
|
ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, $1, $3));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef_decl:
|
||||||
|
TOK_TYPEDEF wire_type range TOK_ID ';' {
|
||||||
|
astbuf1 = $2;
|
||||||
|
astbuf2 = $3;
|
||||||
|
if (astbuf1->range_left >= 0 && astbuf1->range_right >= 0) {
|
||||||
|
if (astbuf2) {
|
||||||
|
frontend_verilog_yyerror("integer/genvar types cannot have packed dimensions.");
|
||||||
|
} else {
|
||||||
|
astbuf2 = new AstNode(AST_RANGE);
|
||||||
|
astbuf2->children.push_back(AstNode::mkconst_int(astbuf1->range_left, true));
|
||||||
|
astbuf2->children.push_back(AstNode::mkconst_int(astbuf1->range_right, true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (astbuf2 && astbuf2->children.size() != 2)
|
||||||
|
frontend_verilog_yyerror("wire/reg/logic packed dimension must be of the form: [<expr>:<expr>], [<expr>+:<expr>], or [<expr>-:<expr>]");
|
||||||
|
if (astbuf2)
|
||||||
|
astbuf1->children.push_back(astbuf2);
|
||||||
|
ast_stack.back()->children.push_back(new AstNode(AST_TYPEDEF, astbuf1));
|
||||||
|
ast_stack.back()->children.back()->str = *$4;
|
||||||
|
};
|
||||||
|
|
||||||
cell_stmt:
|
cell_stmt:
|
||||||
attr TOK_ID {
|
attr TOK_ID {
|
||||||
astbuf1 = new AstNode(AST_CELL);
|
astbuf1 = new AstNode(AST_CELL);
|
||||||
|
@ -1823,7 +1853,7 @@ simple_behavioral_stmt:
|
||||||
|
|
||||||
// this production creates the obligatory if-else shift/reduce conflict
|
// this production creates the obligatory if-else shift/reduce conflict
|
||||||
behavioral_stmt:
|
behavioral_stmt:
|
||||||
defattr | assert | wire_decl | param_decl | localparam_decl |
|
defattr | assert | wire_decl | param_decl | localparam_decl | typedef_decl |
|
||||||
non_opt_delay behavioral_stmt |
|
non_opt_delay behavioral_stmt |
|
||||||
simple_behavioral_stmt ';' | ';' |
|
simple_behavioral_stmt ';' | ';' |
|
||||||
hierarchical_id attr {
|
hierarchical_id attr {
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
`define STRINGIFY(x) `"x`"
|
||||||
|
`define STATIC_ASSERT(x) if(!(x)) $error({"assert failed: ", `STRINGIFY(x)})
|
||||||
|
|
||||||
|
module top;
|
||||||
|
|
||||||
|
typedef logic [1:0] uint2_t;
|
||||||
|
typedef logic signed [3:0] int4_t;
|
||||||
|
typedef logic signed [7:0] int8_t;
|
||||||
|
typedef int8_t char_t;
|
||||||
|
|
||||||
|
(* keep *) uint2_t int2 = 2'b10;
|
||||||
|
(* keep *) int4_t int4 = -1;
|
||||||
|
(* keep *) int8_t int8 = int4;
|
||||||
|
(* keep *) char_t ch = int8;
|
||||||
|
|
||||||
|
|
||||||
|
always @* assert(int2 == 2'b10);
|
||||||
|
always @* assert(int4 == 4'b1111);
|
||||||
|
always @* assert(int8 == 8'b11111111);
|
||||||
|
always @* assert(ch == 8'b11111111);
|
||||||
|
|
||||||
|
endmodule
|
Loading…
Reference in New Issue