diff --git a/elab_expr.cc b/elab_expr.cc index 4fe9dadf9..24a61469b 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -3163,10 +3163,10 @@ unsigned PENumber::test_width(Design*, NetScope*, width_mode_t&mode) { expr_type_ = IVL_VT_LOGIC; expr_width_ = value_->len(); - min_width_ = 1; + min_width_ = expr_width_; signed_flag_ = value_->has_sign(); - if ((mode < LOSSLESS) && !value_->has_len()) + if ((mode < LOSSLESS) && !value_->has_len() && !value_->is_single()) mode = LOSSLESS; return expr_width_; diff --git a/ivlpp/ivlpp.txt b/ivlpp/ivlpp.txt index d8b7d7506..38a0b39f2 100644 --- a/ivlpp/ivlpp.txt +++ b/ivlpp/ivlpp.txt @@ -49,7 +49,7 @@ valid options include: -f Read ivlpp input files from a file list. There can be no - more then one file list. + more than one file list. -I Add a directory to the include path. Normally, only "." is diff --git a/lexor.lex b/lexor.lex index 48ad58070..f254245ac 100644 --- a/lexor.lex +++ b/lexor.lex @@ -329,6 +329,14 @@ TU [munpf] return BASED_NUMBER; } \'[sS]?[hH][ \t]*[0-9a-fA-FxzXZ_\?]+ { yylval.number = make_unsized_hex(yytext); return BASED_NUMBER; } +\'[01xzXZ] { + if (generation_flag < GN_VER2005_SV) { + cerr << yylloc.text << ":" << yylloc.first_line << ": warning: " + << "Using SystemVerilog 'N bit vector. Use at least " + << "-g2005-sv to remove this warning." << endl; + } + yylval.number = make_unsized_binary(yytext); + return BASED_NUMBER; } [0-9][0-9_]* { yylval.number = make_unsized_dec(yytext); @@ -684,6 +692,7 @@ void lex_end_table() verinum*make_unsized_binary(const char*txt) { bool sign_flag = false; + bool single_flag = false; const char*ptr = txt; assert(*ptr == '\''); ptr += 1; @@ -693,8 +702,13 @@ verinum*make_unsized_binary(const char*txt) ptr += 1; } - assert(tolower(*ptr) == 'b'); - ptr += 1; + assert((tolower(*ptr) == 'b') || (generation_flag >= GN_VER2005_SV)); + if (tolower(*ptr) == 'b') { + ptr += 1; + } else { + assert(sign_flag == false); + single_flag = true; + } while (*ptr && ((*ptr == ' ') || (*ptr == '\t'))) ptr += 1; @@ -734,6 +748,7 @@ verinum*make_unsized_binary(const char*txt) verinum*out = new verinum(bits, size, false); out->has_sign(sign_flag); + out->is_single(single_flag); delete[]bits; return out; } diff --git a/netlist.h b/netlist.h index d10469d8c..042be10ae 100644 --- a/netlist.h +++ b/netlist.h @@ -1669,7 +1669,7 @@ class NetExpr : public LineInfo { // rise/fall/decay: Attach these delays to the driver for the // expression output. // - // drive0/drive1: Attach these strengths tp the driver for + // drive0/drive1: Attach these strengths to the driver for // the expression output. virtual NetNet*synthesize(Design*des, NetScope*scope, NetExpr*root); diff --git a/parse.y b/parse.y index a6bc54cf2..7bc27cee2 100644 --- a/parse.y +++ b/parse.y @@ -3463,6 +3463,19 @@ dimensions tmp->push_back(index); $$ = tmp; } + | '[' expression ']' + { if (generation_flag < GN_VER2005_SV) { + warn_count += 1; + cerr << @2 << ": warning: Use of SystemVerilog [size] dimension. " + << "Use at least -g2005-sv to remove this warning." << endl; + } + list *tmp = new list; + index_component_t index; + index.msb = new PENumber(new verinum((uint64_t)0, integer_width)); + index.lsb = new PEBinary('-', $2, new PENumber(new verinum((uint64_t)1, integer_width))); + tmp->push_back(index); + $$ = tmp; + } | dimensions '[' expression ':' expression ']' { list *tmp = $1; index_component_t index; @@ -3471,6 +3484,19 @@ dimensions tmp->push_back(index); $$ = tmp; } + | dimensions '[' expression ']' + { if (generation_flag < GN_VER2005_SV) { + warn_count += 1; + cerr << @2 << ": warning: Use of SystemVerilog [size] dimension. " + << "Use at least -g2005-sv to remove this warning." << endl; + } + list *tmp = $1; + index_component_t index; + index.msb = new PENumber(new verinum((uint64_t)0, integer_width)); + index.lsb = new PEBinary('-', $3, new PENumber(new verinum((uint64_t)1, integer_width))); + tmp->push_back(index); + $$ = tmp; + } /* This is used to express the return type of a function. */ function_range_or_type_opt diff --git a/pform.cc b/pform.cc index e800e1de7..0a23a4647 100644 --- a/pform.cc +++ b/pform.cc @@ -116,7 +116,7 @@ void parm_to_defparam_list(const string¶m) if (*value == '"') { // string type char *buf = strdup (value); char *buf_ptr = buf+1; - // Parse untill another '"' or '\0' + // Parse until another '"' or '\0' while (*buf_ptr != '"' && *buf_ptr != '\0') { buf_ptr++; // Check for escape, especially '\"', which does not mean the diff --git a/tgt-vhdl/stmt.cc b/tgt-vhdl/stmt.cc index de27ac749..1053ed00f 100644 --- a/tgt-vhdl/stmt.cc +++ b/tgt-vhdl/stmt.cc @@ -116,7 +116,7 @@ static int draw_stask_display(vhdl_procedural *proc, switch (*p) { case 'm': - // TOOD: we can get the module name via attributes + // TODO: we can get the module name via attributes cerr << "Warning: no VHDL translation for %m format code" << endl; break; @@ -1603,7 +1603,7 @@ int draw_utask(vhdl_procedural *proc, stmt_container *container, // TODO: adding some comments to the output would be helpful - // TOOD: this completely ignores parameters! + // TODO: this completely ignores parameters! draw_stmt(proc, container, ivl_scope_def(tscope), false); return 0; diff --git a/verinum.cc b/verinum.cc index 1b576c224..0c4629e4a 100644 --- a/verinum.cc +++ b/verinum.cc @@ -43,12 +43,12 @@ extern "C" long int lround(double x) static verinum::V add_with_carry(verinum::V l, verinum::V r, verinum::V&c); verinum::verinum() -: bits_(0), nbits_(0), has_len_(false), has_sign_(false), string_flag_(false) +: bits_(0), nbits_(0), has_len_(false), has_sign_(false), is_single_(false), string_flag_(false) { } verinum::verinum(const V*bits, unsigned nbits, bool has_len__) -: has_len_(has_len__), has_sign_(false), string_flag_(false) +: has_len_(has_len__), has_sign_(false), is_single_(false), string_flag_(false) { nbits_ = nbits; bits_ = new V [nbits]; @@ -111,7 +111,7 @@ static string process_verilog_string_quotes(const string&str) } verinum::verinum(const string&s) -: has_len_(true), has_sign_(false), string_flag_(true) +: has_len_(true), has_sign_(false), is_single_(false), string_flag_(true) { string str = process_verilog_string_quotes(s); nbits_ = str.length() * 8; @@ -149,7 +149,7 @@ verinum::verinum(const string&s) } verinum::verinum(verinum::V val, unsigned n, bool h) -: has_len_(h), has_sign_(false), string_flag_(false) +: has_len_(h), has_sign_(false), is_single_(false), string_flag_(false) { nbits_ = n; bits_ = new V[nbits_]; @@ -158,7 +158,7 @@ verinum::verinum(verinum::V val, unsigned n, bool h) } verinum::verinum(uint64_t val, unsigned n) -: has_len_(true), has_sign_(false), string_flag_(false) +: has_len_(true), has_sign_(false), is_single_(false), string_flag_(false) { nbits_ = n; bits_ = new V[nbits_]; @@ -171,7 +171,7 @@ verinum::verinum(uint64_t val, unsigned n) /* The second argument is not used! It is there to make this * constructor unique. */ verinum::verinum(double val, bool) -: has_len_(false), has_sign_(true), string_flag_(false) +: has_len_(false), has_sign_(true), is_single_(false), string_flag_(false) { bool is_neg = false; double fraction; @@ -281,6 +281,7 @@ verinum::verinum(const verinum&that) bits_ = new V[nbits_]; has_len_ = that.has_len_; has_sign_ = that.has_sign_; + is_single_ = that.is_single_; for (unsigned idx = 0 ; idx < nbits_ ; idx += 1) bits_[idx] = that.bits_[idx]; } @@ -292,6 +293,7 @@ verinum::verinum(const verinum&that, unsigned nbits) bits_ = new V[nbits_]; has_len_ = true; has_sign_ = that.has_sign_; + is_single_ = false; unsigned copy = nbits; if (copy > that.nbits_) @@ -300,7 +302,7 @@ verinum::verinum(const verinum&that, unsigned nbits) bits_[idx] = that.bits_[idx]; if (copy < nbits_) { - if (has_sign_) { + if (has_sign_ || that.is_single_) { for (unsigned idx = copy ; idx < nbits_ ; idx += 1) bits_[idx] = bits_[idx-1]; } else { @@ -311,7 +313,7 @@ verinum::verinum(const verinum&that, unsigned nbits) } verinum::verinum(int64_t that) -: has_len_(false), has_sign_(true), string_flag_(false) +: has_len_(false), has_sign_(true), is_single_(false), string_flag_(false) { int64_t tmp; @@ -348,6 +350,7 @@ verinum& verinum::operator= (const verinum&that) has_len_ = that.has_len_; has_sign_ = that.has_sign_; + is_single_ = that.is_single_; string_flag_ = that.string_flag_; return *this; } @@ -570,9 +573,9 @@ verinum pad_to_width(const verinum&that, unsigned width) } verinum::V pad = that[that.len()-1]; - if (pad==verinum::V1 && !that.has_sign()) + if (pad==verinum::V1 && !that.has_sign() && !that.is_single()) pad = verinum::V0; - if (that.has_len() && !that.has_sign()) { + if (that.has_len() && !that.has_sign() && !that.is_single()) { if (pad==verinum::Vx) pad = verinum::V0; if (pad==verinum::Vz) @@ -606,9 +609,9 @@ verinum cast_to_width(const verinum&that, unsigned width) } verinum::V pad = that[that.len()-1]; - if (pad==verinum::V1 && !that.has_sign()) + if (pad==verinum::V1 && !that.has_sign() && !that.is_single()) pad = verinum::V0; - if (that.has_len() && !that.has_sign()) { + if (that.has_len() && !that.has_sign() && !that.is_single()) { if (pad==verinum::Vx) pad = verinum::V0; if (pad==verinum::Vz) diff --git a/verinum.h b/verinum.h index acab1d673..24ea075d7 100644 --- a/verinum.h +++ b/verinum.h @@ -70,6 +70,10 @@ class verinum { bool has_sign(bool flag) { has_sign_ = flag; return has_sign_; } bool has_sign() const { return has_sign_; } + // A number "is single" if it comes from a SystemVerilog 'N bit vector + bool is_single(bool flag) { is_single_ = flag; return is_single_; } + bool is_single() const { return is_single_; } + // A number is "defined" if there are no x or z bits in its value. bool is_defined() const; bool is_zero() const; @@ -103,6 +107,7 @@ class verinum { unsigned nbits_; bool has_len_; bool has_sign_; + bool is_single_; // These are some convenience flags that help us do a better // job of pretty-printing values. diff --git a/vhdlpp/debug.cc b/vhdlpp/debug.cc index 5bcdb4cca..5357e8651 100644 --- a/vhdlpp/debug.cc +++ b/vhdlpp/debug.cc @@ -116,7 +116,7 @@ void Architecture::dump(ostream&out, perm_string of_entity) const void Architecture::Statement::dump(ostream&out) const { - out << " Architecutre::Statement at file=" << get_fileline() << endl; + out << " Architecture::Statement at file=" << get_fileline() << endl; } void Signal::dump(ostream&out) const diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index b62497c05..f58ec86ad 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -37,9 +37,9 @@ class Expression : public LineInfo { Expression(); virtual ~Expression() =0; - // The emit virtual method is called bu architecture emit to + // The emit virtual method is called by architecture emit to // output the generated code for the expression. The derived - // class fills in the details of what exactly happend. + // class fills in the details of what exactly happened. virtual int emit(ostream&out, Entity*ent, Architecture*arc) =0; // The evaluate virtual method tries to evaluate expressions @@ -49,9 +49,9 @@ class Expression : public LineInfo { virtual bool evaluate(int64_t&val) const; // This method returns true if the drawn Verilog for this - // expression is a primary. A containing expressin can use + // expression is a primary. A containing expression can use // this method to know if it needs to wrap parentheses. This - // is somewhile optional, so it is better to return false if + // is somewhat optional, so it is better to return false if // not certain. The default implementation does return false. virtual bool is_primary(void) const; diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index 1be4096e3..b9bd14f59 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -166,7 +166,7 @@ architecture_body FILE_NAME(tmp, @1); bind_architecture_to_entity($4, tmp); if ($11 && tmp->get_name() != $11) - errormsg(@2, "Architecture name doesn't match closing name\n"); + errormsg(@2, "Architecture name doesn't match closing name.\n"); delete[]$2; delete[]$4; delete $8; @@ -215,6 +215,31 @@ association_list | association_element ; +//TODO: this list is only a sketch +binding_indication + : K_use entity_aspect_opt + port_map_aspect_opt + generic_map_aspect_opt + ; + +binding_indication_semicolon_opt + : binding_indication ';' + | + ; + +block_configuration + : K_for IDENTIFIER + use_clauses_opt + configuration_items_opt + K_end K_for ';' + { delete[] $2; } + ; + +block_configuration_opt + : block_configuration + | + ; + block_declarative_item : K_signal identifier_list ':' subtype_indication ';' { /* Save the signal declaration in the block_signals map. */ @@ -231,16 +256,17 @@ block_declarative_item port_clause_opt K_end K_component identifier_opt ';' { perm_string name = lex_strings.make($2); - if ($7 && name != $7) { - errormsg(@7, "Identifier %s doesn't match component name %s\n", + if($7) { + if (name != $7) + errormsg(@7, "Identifier %s doesn't match component name %s.\n", $7, name.str()); - } + delete[] $7; + } ComponentBase*comp = new ComponentBase(name); if ($4) comp->set_interface($4); block_components[name] = comp; delete[]$2; - delete[]$7; } /* Various error handling rules for block_declarative_item... */ @@ -251,7 +277,12 @@ block_declarative_item { errormsg(@1, "Syntax error in block declarations.\n"); yyerrok; } | K_component IDENTIFIER K_is_opt error K_end K_component identifier_opt ';' - { errormsg(@4, "Syntax error in component declaration.\n"); yyerrok; } + { errormsg(@4, "Syntax error in component declaration.\n"); + delete[] $2; + if($7) { + delete[] $7; + } + yyerrok; } ; /* @@ -269,6 +300,13 @@ block_declarative_items_opt | ; +component_configuration + : K_for component_specification + binding_indication_semicolon_opt + block_configuration_opt + K_end K_for ';' + ; + component_instantiation_statement : IDENTIFIER ':' IDENTIFIER port_map_aspect_opt ';' { sorrymsg(@1, "Component instantiation statements are not supported.\n"); @@ -284,6 +322,28 @@ component_instantiation_statement } ; +component_specification + : instantiation_list ':' IDENTIFIER + { sorrymsg(@1, "Component specifications are not supported.\n"); + delete[] $3 + } + ; + +configuration_declaration + : K_configuration IDENTIFIER K_of IDENTIFIER K_is + configuration_declarative_part + block_configuration + K_end K_configuration_opt identifier_opt ';' + { + sorrymsg(@1, "Configuration declaration is not yet supported.\n"); + } + | K_configuration error K_end K_configuration_opt identifier_opt ';' + { errormsg(@2, "Too many errors, giving up on configuration declaration.\n"); + if($5) delete $5; + yyerrok; + } + ; + concurrent_signal_assignment_statement : name LEQ waveform ';' { ExpName*name = dynamic_cast ($1); @@ -306,6 +366,35 @@ concurrent_statement : component_instantiation_statement | concurrent_signal_assignment_statement ; +//TODO: this list is only a sketch. It must be filled out later +configuration_declarative_item + : use_clause + ; + +configuration_declarative_items + : configuration_declarative_items configuration_declarative_item + | configuration_declarative_item + ; + +configuration_declarative_part + : configuration_declarative_items + | + ; + +configuration_item + : block_configuration + | component_configuration + ; + +configuration_items + : configuration_items configuration_item + | configuration_item + ; + +configuration_items_opt + : configuration_items + | + ; context_clause : context_items | ; @@ -334,6 +423,17 @@ design_units direction : K_to { $$ = false; } | K_downto { $$ = true; } ; /* As an entity is declared, add it to the map of design entities. */ +entity_aspect + : K_entity IDENTIFIER {sorrymsg(@1, "Entity aspect not yet supported.\n"); delete $2;} + | K_configuration IDENTIFIER {sorrymsg(@1, "Instatiation lists not yet supported.\n"); delete $2;} + | K_open + ; + +entity_aspect_opt + : entity_aspect + | + ; + entity_declaration : K_entity IDENTIFIER K_is entity_header K_end K_entity_opt identifier_opt';' { Entity*tmp = new Entity(lex_strings.make($2)); @@ -348,6 +448,7 @@ entity_declaration if($7) { if(tmp->get_name() != $7) { errormsg(@1, "Syntax error in entity clause. Closing name doesn't match.\n"); + yyerrok; } delete $7; } @@ -485,6 +586,14 @@ factor $$ = tmp; } ; +generic_map_aspect_opt + : generic_map_aspect + | + ; + +generic_map_aspect + : K_generic K_map '(' association_list ')' + ; identifier_list : identifier_list ',' IDENTIFIER @@ -503,6 +612,20 @@ identifier_list identifier_opt : IDENTIFIER { $$ = $1; } | { $$ = 0; } ; + +instantiation_list + : identifier_list + { + sorrymsg(@1, "Instatiation lists not yet supported"); + delete $1; + } + | K_others + | K_all + { + sorrymsg(@1, "Instatiation lists not yet supported"); + } + ; + /* The interface_element is also an interface_declaration */ interface_element : identifier_list ':' mode subtype_indication @@ -546,8 +669,8 @@ library_clause /* Collapse the primary_unit and secondary_unit of the library_unit into this single set of rules. */ library_unit - : entity_declaration - | architecture_body + : primary_unit + | secondary_unit ; logical_name : IDENTIFIER { $$ = $1; } ; @@ -587,11 +710,71 @@ name } ; +package_declaration + : K_package IDENTIFIER K_is + package_declarative_part_opt + K_end K_package_opt identifier_opt ';' + { sorrymsg(@4, "Package declaration not supported yet.\n"); + if($7) { + if($2 != $7) { + errormsg(@1, "Syntax error in package clause. Closing name doesn't match.\n"); + yyerrok; + } + delete $7; + } + delete $2; + } + | K_package error K_end K_package_opt identifier_opt ';' + { errormsg(@2, "Syntax error in package clause.\n"); + yyerrok; + } + ; + +/* TODO: this list must be extended in the future + presently it is only a sketch */ +package_body_declarative_item + : use_clause + ; + +package_body_declarative_items + : package_body_declarative_items package_body_declarative_item + | package_body_declarative_item + ; +package_body_declarative_part_opt + : package_body_declarative_items + | + ; + +/* TODO: this list is only a sketch + it must be extended in the future */ +package_declarative_item + : use_clause + ; +package_declarative_items + : package_declarative_items package_declarative_item + | package_declarative_item + ; + +package_declarative_part_opt + : package_declarative_items + | + ; + +package_body + : K_package K_body IDENTIFIER K_is + package_body_declarative_part_opt + K_end K_package_opt identifier_opt ';' + { + delete[] $3; + if($8) delete[] $8; + } + ; + port_clause : K_port '(' interface_list ')' ';' { $$ = $3; } | K_port '(' error ')' ';' - { errormsg(@1, "Syntax error in port list\n"); + { errormsg(@1, "Syntax error in port list.\n"); yyerrok; $$ = 0; } @@ -620,8 +803,18 @@ primary { $$ = $2; } ; +primary_unit + : entity_declaration + | configuration_declaration + | package_declaration + ; + relation : shift_expression { $$ = $1; } ; +secondary_unit + : architecture_body + | package_body + ; /* The *_use variant of selected_name is used by the "use" clause. It is syntactically identical to other selected_name rules, but is a convenient place to attach use_clause actions. */ @@ -703,6 +896,16 @@ use_clause { errormsg(@1, "Syntax error in use clause.\n"); yyerrok; } ; +use_clauses + : use_clauses use_clause + | use_clause + ; + +use_clauses_opt + : use_clauses + | + ; + waveform : waveform_elements { $$ = $1; } @@ -733,7 +936,9 @@ waveform_element /* Some keywords are optional in some contexts. In all such cases, a similar rule is used, as described here. */ K_architecture_opt : K_architecture | ; +K_configuration_opt: K_configuration| ; K_entity_opt : K_entity | ; +K_package_opt : K_package | ; K_is_opt : K_is | ; %% diff --git a/vhdlpp/parse_api.h b/vhdlpp/parse_api.h index 73ce4201d..1193d8fb9 100644 --- a/vhdlpp/parse_api.h +++ b/vhdlpp/parse_api.h @@ -54,7 +54,7 @@ extern int yylex(void); extern int yyparse(void); /* - * Use this functio during parse to generate error messages. The "loc" + * Use this function during parse to generate error messages. The "loc" * is the location of the token that triggered the error, and the fmt * is printf-style format. */ diff --git a/vvp/README.txt b/vvp/README.txt index 7142941d8..a45854ded 100644 --- a/vvp/README.txt +++ b/vvp/README.txt @@ -282,7 +282,7 @@ general syntax of a variable is: