diff options
-rw-r--r-- | frontends/ast/genrtlil.cc | 49 | ||||
-rw-r--r-- | frontends/verilog/verilog_lexer.l | 1 | ||||
-rw-r--r-- | frontends/verilog/verilog_parser.y | 108 | ||||
-rw-r--r-- | tests/verilog/conflict_assert.ys | 8 | ||||
-rw-r--r-- | tests/verilog/conflict_cell_memory.ys | 9 | ||||
-rw-r--r-- | tests/verilog/conflict_interface_port.ys | 17 | ||||
-rw-r--r-- | tests/verilog/conflict_memory_wire.ys | 7 | ||||
-rw-r--r-- | tests/verilog/conflict_pwire.ys | 8 | ||||
-rw-r--r-- | tests/verilog/conflict_wire_memory.ys | 7 | ||||
-rw-r--r-- | tests/verilog/int_types.sv | 47 | ||||
-rw-r--r-- | tests/verilog/int_types.ys | 7 | ||||
-rw-r--r-- | tests/verilog/param_int_types.sv | 19 | ||||
-rw-r--r-- | tests/verilog/param_int_types.ys | 5 |
13 files changed, 241 insertions, 51 deletions
diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 449f8c38e..d4299bf69 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -1002,6 +1002,29 @@ void AstNode::detectSignWidth(int &width_hint, bool &sign_hint, bool *found_real detectSignWidthWorker(width_hint, sign_hint, found_real); } +static void check_unique_id(RTLIL::Module *module, RTLIL::IdString id, + const AstNode *node, const char *to_add_kind) +{ + auto already_exists = [&](const RTLIL::AttrObject *existing, const char *existing_kind) { + std::string src = existing->get_string_attribute(ID::src); + std::string location_str = "earlier"; + if (!src.empty()) + location_str = "at " + src; + log_file_error(node->filename, node->location.first_line, + "Cannot add %s `%s' because a %s with the same name was already created %s!\n", + to_add_kind, id.c_str(), existing_kind, location_str.c_str()); + }; + + if (const RTLIL::Wire *wire = module->wire(id)) + already_exists(wire, "signal"); + if (const RTLIL::Cell *cell = module->cell(id)) + already_exists(cell, "cell"); + if (module->processes.count(id)) + already_exists(module->processes.at(id), "process"); + if (module->memories.count(id)) + already_exists(module->memories.at(id), "memory"); +} + // create RTLIL from an AST node // all generated cells, wires and processes are added to the module pointed to by 'current_module' // when the AST node is an expression (AST_ADD, AST_BIT_XOR, etc.), the result signal is returned. @@ -1047,7 +1070,9 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) // If a port in a module with unknown type is found, mark it with the attribute 'is_interface' // This is used by the hierarchy pass to know when it can replace interface connection with the individual // signals. - RTLIL::Wire *wire = current_module->addWire(str, 1); + RTLIL::IdString id = str; + check_unique_id(current_module, id, this, "interface port"); + RTLIL::Wire *wire = current_module->addWire(id, 1); set_src_attr(wire, this); wire->start_offset = 0; wire->port_id = port_id; @@ -1085,7 +1110,9 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) log_file_error(filename, location.first_line, "Parameter `%s' with non-constant value!\n", str.c_str()); RTLIL::Const val = children[0]->bitsAsConst(); - RTLIL::Wire *wire = current_module->addWire(str, GetSize(val)); + RTLIL::IdString id = str; + check_unique_id(current_module, id, this, "pwire"); + RTLIL::Wire *wire = current_module->addWire(id, GetSize(val)); current_module->connect(wire, val); wire->is_signed = children[0]->is_signed; @@ -1102,15 +1129,15 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) // create an RTLIL::Wire for an AST_WIRE node case AST_WIRE: { - if (current_module->wires_.count(str) != 0) - log_file_error(filename, location.first_line, "Re-definition of signal `%s'!\n", str.c_str()); if (!range_valid) log_file_error(filename, location.first_line, "Signal `%s' with non-constant width!\n", str.c_str()); if (!(range_left + 1 >= range_right)) log_file_error(filename, location.first_line, "Signal `%s' with invalid width range %d!\n", str.c_str(), range_left - range_right + 1); - RTLIL::Wire *wire = current_module->addWire(str, range_left - range_right + 1); + RTLIL::IdString id = str; + check_unique_id(current_module, id, this, "signal"); + RTLIL::Wire *wire = current_module->addWire(id, range_left - range_right + 1); set_src_attr(wire, this); wire->start_offset = range_right; wire->port_id = port_id; @@ -1132,9 +1159,6 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) // create an RTLIL::Memory for an AST_MEMORY node case AST_MEMORY: { - if (current_module->memories.count(str) != 0) - log_file_error(filename, location.first_line, "Re-definition of memory `%s'!\n", str.c_str()); - log_assert(children.size() >= 2); log_assert(children[0]->type == AST_RANGE); log_assert(children[1]->type == AST_RANGE); @@ -1153,6 +1177,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) memory->start_offset = children[1]->range_left; memory->size = children[1]->range_right - children[1]->range_left + 1; } + check_unique_id(current_module, memory->name, this, "memory"); current_module->memories[memory->name] = memory; for (auto &attr : attributes) { @@ -1684,6 +1709,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) else cellname = str; + check_unique_id(current_module, cellname, this, "procedural assertion"); RTLIL::Cell *cell = current_module->addCell(cellname, celltype); set_src_attr(cell, this); @@ -1726,10 +1752,9 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) { int port_counter = 0, para_counter = 0; - if (current_module->count_id(str) != 0) - log_file_error(filename, location.first_line, "Re-definition of cell `%s'!\n", str.c_str()); - - RTLIL::Cell *cell = current_module->addCell(str, ""); + RTLIL::IdString id = str; + check_unique_id(current_module, id, this, "cell"); + RTLIL::Cell *cell = current_module->addCell(id, ""); set_src_attr(cell, this); // Set attribute 'module_not_derived' which will be cleared again after the hierarchy pass cell->set_bool_attribute(ID::module_not_derived); diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index eeb7440f8..66772a097 100644 --- a/frontends/verilog/verilog_lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -267,6 +267,7 @@ static bool isUserType(std::string &s) "int" { SV_KEYWORD(TOK_INT); } "byte" { SV_KEYWORD(TOK_BYTE); } "shortint" { SV_KEYWORD(TOK_SHORTINT); } +"longint" { SV_KEYWORD(TOK_LONGINT); } "eventually" { if (formal_mode) return TOK_EVENTUALLY; SV_KEYWORD(TOK_EVENTUALLY); } "s_eventually" { if (formal_mode) return TOK_EVENTUALLY; SV_KEYWORD(TOK_EVENTUALLY); } diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index dc7ec8348..476ee68ad 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -253,6 +253,7 @@ static void rewriteAsMemoryNode(AstNode *node, AstNode *rangeNode) struct specify_rise_fall *specify_rise_fall_ptr; bool boolean; char ch; + int integer; } %token <string> TOK_STRING TOK_ID TOK_CONSTVAL TOK_REALVAL TOK_PRIMITIVE @@ -278,15 +279,17 @@ static void rewriteAsMemoryNode(AstNode *node, AstNode *rangeNode) %token TOK_POS_INDEXED TOK_NEG_INDEXED TOK_PROPERTY TOK_ENUM TOK_TYPEDEF %token TOK_RAND TOK_CONST TOK_CHECKER TOK_ENDCHECKER TOK_EVENTUALLY %token TOK_INCREMENT TOK_DECREMENT TOK_UNIQUE TOK_UNIQUE0 TOK_PRIORITY -%token TOK_STRUCT TOK_PACKED TOK_UNSIGNED TOK_INT TOK_BYTE TOK_SHORTINT TOK_UNION +%token TOK_STRUCT TOK_PACKED TOK_UNSIGNED TOK_INT TOK_BYTE TOK_SHORTINT TOK_LONGINT TOK_UNION %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> range range_or_multirange non_opt_range non_opt_multirange %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 -%type <boolean> opt_signed opt_property always_comb_or_latch always_or_always_ff +%type <ast> opt_enum_init enum_type struct_type non_wire_data_type func_return_type +%type <boolean> opt_property always_comb_or_latch always_or_always_ff +%type <boolean> opt_signedness_default_signed opt_signedness_default_unsigned +%type <integer> integer_atom_type %type <al> attr case_attr %type <ast> struct_union @@ -716,12 +719,19 @@ wire_type_token: logic_type: TOK_LOGIC { } | - TOK_INTEGER { - astbuf3->range_left = 31; + integer_atom_type { + astbuf3->range_left = $1 - 1; astbuf3->range_right = 0; astbuf3->is_signed = true; }; +integer_atom_type: + TOK_INTEGER { $$ = 32; } | + TOK_INT { $$ = 32; } | + TOK_SHORTINT { $$ = 16; } | + TOK_LONGINT { $$ = 64; } | + TOK_BYTE { $$ = 8; } ; + non_opt_range: '[' expr ':' expr ']' { $$ = new AstNode(AST_RANGE); @@ -766,11 +776,6 @@ range_or_multirange: range { $$ = $1; } | non_opt_multirange { $$ = $1; }; -range_or_signed_int: - range { $$ = $1; } - | TOK_INTEGER { $$ = makeRange(); } - ; - module_body: module_body module_body_stmt | /* the following line makes the generate..endgenrate keywords optional */ @@ -841,29 +846,58 @@ task_func_decl: current_function_or_task = NULL; ast_stack.pop_back(); } | - attr TOK_FUNCTION opt_automatic opt_signed range_or_signed_int TOK_ID { + attr TOK_FUNCTION opt_automatic func_return_type TOK_ID { current_function_or_task = new AstNode(AST_FUNCTION); - current_function_or_task->str = *$6; + current_function_or_task->str = *$5; append_attr(current_function_or_task, $1); ast_stack.back()->children.push_back(current_function_or_task); ast_stack.push_back(current_function_or_task); AstNode *outreg = new AstNode(AST_WIRE); - outreg->str = *$6; - outreg->is_signed = $4; + outreg->str = *$5; + outreg->is_signed = false; outreg->is_reg = true; - if ($5 != NULL) { - outreg->children.push_back($5); - outreg->is_signed = $4 || $5->is_signed; - $5->is_signed = false; + if ($4 != NULL) { + outreg->children.push_back($4); + outreg->is_signed = $4->is_signed; + $4->is_signed = false; } current_function_or_task->children.push_back(outreg); current_function_or_task_port_id = 1; - delete $6; + delete $5; } task_func_args_opt ';' task_func_body TOK_ENDFUNCTION { current_function_or_task = NULL; ast_stack.pop_back(); }; +func_return_type: + opt_type_vec opt_signedness_default_unsigned { + $$ = makeRange(0, 0, $2); + } | + opt_type_vec opt_signedness_default_unsigned non_opt_range { + $$ = $3; + $$->is_signed = $2; + } | + integer_atom_type opt_signedness_default_signed { + $$ = makeRange($1 - 1, 0, $2); + }; + +opt_type_vec: + %empty + | TOK_REG + | TOK_LOGIC + ; + +opt_signedness_default_signed: + %empty { $$ = true; } + | TOK_SIGNED { $$ = true; } + | TOK_UNSIGNED { $$ = false; } + ; +opt_signedness_default_unsigned: + %empty { $$ = false; } + | TOK_SIGNED { $$ = true; } + | TOK_UNSIGNED { $$ = false; } + ; + dpi_function_arg: TOK_ID TOK_ID { current_function_or_task->children.push_back(AstNode::mkconst_str(*$1)); @@ -889,14 +923,6 @@ opt_automatic: TOK_AUTOMATIC | %empty; -opt_signed: - TOK_SIGNED { - $$ = true; - } | - %empty { - $$ = false; - }; - task_func_args_opt: '(' ')' | %empty | '(' { albuf = nullptr; @@ -1379,11 +1405,8 @@ param_signed: } | %empty; param_integer: - TOK_INTEGER { - astbuf1->children.push_back(new AstNode(AST_RANGE)); - astbuf1->children.back()->children.push_back(AstNode::mkconst_int(31, true)); - astbuf1->children.back()->children.push_back(AstNode::mkconst_int(0, true)); - astbuf1->is_signed = true; + type_atom { + astbuf1->is_reg = false; }; param_real: @@ -1399,7 +1422,13 @@ param_range: }; param_integer_type: param_integer param_signed; -param_range_type: type_vec param_signed param_range; +param_range_type: + type_vec param_signed { + addRange(astbuf1, 0, 0); + } | + type_vec param_signed non_opt_range { + astbuf1->children.push_back($3); + }; param_implicit_type: param_signed param_range; param_type: @@ -1496,11 +1525,12 @@ enum_base_type: type_atom type_signing | %empty { astbuf1->is_reg = true; addRange(astbuf1); } ; -type_atom: TOK_INTEGER { astbuf1->is_reg = true; astbuf1->is_signed = true; addRange(astbuf1); } // 4-state signed - | TOK_INT { astbuf1->is_reg = true; astbuf1->is_signed = true; addRange(astbuf1); } // 2-state signed - | TOK_SHORTINT { astbuf1->is_reg = true; astbuf1->is_signed = true; addRange(astbuf1, 15, 0); } // 2-state signed - | TOK_BYTE { astbuf1->is_reg = true; astbuf1->is_signed = true; addRange(astbuf1, 7, 0); } // 2-state signed - ; +type_atom: + integer_atom_type { + astbuf1->is_reg = true; + astbuf1->is_signed = true; + addRange(astbuf1, $1 - 1, 0); + }; type_vec: TOK_REG { astbuf1->is_reg = true; } // unsigned | TOK_LOGIC { astbuf1->is_logic = true; } // unsigned diff --git a/tests/verilog/conflict_assert.ys b/tests/verilog/conflict_assert.ys new file mode 100644 index 000000000..121a0cf51 --- /dev/null +++ b/tests/verilog/conflict_assert.ys @@ -0,0 +1,8 @@ +logger -expect error "Cannot add procedural assertion `\\x' because a signal with the same name was already created" 1 +read_verilog -sv <<EOT +module top; + wire x, y; + always @* + x: assert(y == 1); +endmodule +EOT diff --git a/tests/verilog/conflict_cell_memory.ys b/tests/verilog/conflict_cell_memory.ys new file mode 100644 index 000000000..ddc67596f --- /dev/null +++ b/tests/verilog/conflict_cell_memory.ys @@ -0,0 +1,9 @@ +logger -expect error "Cannot add cell `\\x' because a memory with the same name was already created" 1 +read_verilog <<EOT +module mod; +endmodule +module top; + reg [2:0] x [0:0]; + mod x(); +endmodule +EOT diff --git a/tests/verilog/conflict_interface_port.ys b/tests/verilog/conflict_interface_port.ys new file mode 100644 index 000000000..b97ec029e --- /dev/null +++ b/tests/verilog/conflict_interface_port.ys @@ -0,0 +1,17 @@ +logger -expect error "Cannot add interface port `\\i' because a signal with the same name was already created" 1 +read_verilog -sv <<EOT +interface intf; + logic x; + assign x = 1; + modport m(input x); +endinterface +module mod(intf.m i); + wire x; + assign x = i.x; + wire i; +endmodule +module top; + intf i(); + mod m(i); +endmodule +EOT diff --git a/tests/verilog/conflict_memory_wire.ys b/tests/verilog/conflict_memory_wire.ys new file mode 100644 index 000000000..5c296074f --- /dev/null +++ b/tests/verilog/conflict_memory_wire.ys @@ -0,0 +1,7 @@ +logger -expect error "Cannot add memory `\\x' because a signal with the same name was already created" 1 +read_verilog <<EOT +module top; + reg [2:0] x; + reg [2:0] x [0:0]; +endmodule +EOT diff --git a/tests/verilog/conflict_pwire.ys b/tests/verilog/conflict_pwire.ys new file mode 100644 index 000000000..ecc30d33a --- /dev/null +++ b/tests/verilog/conflict_pwire.ys @@ -0,0 +1,8 @@ +logger -expect error "Cannot add pwire `\\x' because a signal with the same name was already created" 1 +read_verilog -pwires <<EOT +module top; + wire x; + assign x = 1; + localparam x = 2; +endmodule +EOT diff --git a/tests/verilog/conflict_wire_memory.ys b/tests/verilog/conflict_wire_memory.ys new file mode 100644 index 000000000..77520fea9 --- /dev/null +++ b/tests/verilog/conflict_wire_memory.ys @@ -0,0 +1,7 @@ +logger -expect error "Cannot add signal `\\x' because a memory with the same name was already created" 1 +read_verilog <<EOT +module top; + reg [2:0] x [0:0]; + reg [2:0] x; +endmodule +EOT diff --git a/tests/verilog/int_types.sv b/tests/verilog/int_types.sv new file mode 100644 index 000000000..8133f8218 --- /dev/null +++ b/tests/verilog/int_types.sv @@ -0,0 +1,47 @@ +`define TEST(typ, width, is_signed) \ + if (1) begin \ + typ x = -1; \ + localparam typ y = -1; \ + logic [127:0] a = x; \ + logic [127:0] b = y; \ + if ($bits(x) != width) \ + $error(`"typ doesn't have expected size width`"); \ + if ($bits(x) != $bits(y)) \ + $error(`"localparam typ doesn't match size of typ`"); \ + function automatic typ f; \ + input integer x; \ + f = x; \ + endfunction \ + logic [127:0] c = f(-1); \ + always @* begin \ + assert (x == y); \ + assert (a == b); \ + assert (a == c); \ + assert ((a == -1) == is_signed); \ + end \ + end + +`define TEST_INTEGER_ATOM(typ, width) \ + `TEST(typ, width, 1) \ + `TEST(typ signed, width, 1) \ + `TEST(typ unsigned, width, 0) + +`define TEST_INTEGER_VECTOR(typ) \ + `TEST(typ, 1, 0) \ + `TEST(typ signed, 1, 1) \ + `TEST(typ unsigned, 1, 0) \ + `TEST(typ [1:0], 2, 0) \ + `TEST(typ signed [1:0], 2, 1) \ + `TEST(typ unsigned [1:0], 2, 0) + +module top; + `TEST_INTEGER_ATOM(integer, 32) + `TEST_INTEGER_ATOM(int, 32) + `TEST_INTEGER_ATOM(shortint, 16) + `TEST_INTEGER_ATOM(longint, 64) + `TEST_INTEGER_ATOM(byte, 8) + + `TEST_INTEGER_VECTOR(reg) + `TEST_INTEGER_VECTOR(logic) + `TEST_INTEGER_VECTOR(bit) +endmodule diff --git a/tests/verilog/int_types.ys b/tests/verilog/int_types.ys new file mode 100644 index 000000000..c17c44b4c --- /dev/null +++ b/tests/verilog/int_types.ys @@ -0,0 +1,7 @@ +read_verilog -sv int_types.sv +hierarchy +proc +flatten +opt -full +select -module top +sat -verify -seq 1 -tempinduct -prove-asserts -show-all diff --git a/tests/verilog/param_int_types.sv b/tests/verilog/param_int_types.sv new file mode 100644 index 000000000..3228369b8 --- /dev/null +++ b/tests/verilog/param_int_types.sv @@ -0,0 +1,19 @@ +module gate(out); + parameter integer a = -1; + parameter int b = -2; + parameter shortint c = -3; + parameter longint d = -4; + parameter byte e = -5; + output wire [1023:0] out; + assign out = {a, b, c, d, e}; +endmodule + +module gold(out); + integer a = -1; + int b = -2; + shortint c = -3; + longint d = -4; + byte e = -5; + output wire [1023:0] out; + assign out = {a, b, c, d, e}; +endmodule diff --git a/tests/verilog/param_int_types.ys b/tests/verilog/param_int_types.ys new file mode 100644 index 000000000..7727801cf --- /dev/null +++ b/tests/verilog/param_int_types.ys @@ -0,0 +1,5 @@ +read_verilog -sv param_int_types.sv +proc +equiv_make gold gate equiv +equiv_simple +equiv_status -assert |