aboutsummaryrefslogtreecommitdiffstats
path: root/frontends
diff options
context:
space:
mode:
Diffstat (limited to 'frontends')
-rw-r--r--frontends/ast/genrtlil.cc49
-rw-r--r--frontends/verilog/verilog_lexer.l1
-rw-r--r--frontends/verilog/verilog_parser.y108
3 files changed, 107 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