Merge pull request #1 from steveicarus/master

update
This commit is contained in:
nbrereton 2019-10-05 21:04:03 -04:00 committed by GitHub
commit cce30e89bb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 434 additions and 124 deletions

View File

@ -126,9 +126,8 @@ PEBinary::~PEBinary()
void PEBinary::declare_implicit_nets(LexicalScope*scope, NetNet::Type type) void PEBinary::declare_implicit_nets(LexicalScope*scope, NetNet::Type type)
{ {
assert(left_ && right_); if (left_) left_->declare_implicit_nets(scope, type);
left_->declare_implicit_nets(scope, type); if (right_) right_->declare_implicit_nets(scope, type);
right_->declare_implicit_nets(scope, type);
} }
bool PEBinary::has_aa_term(Design*des, NetScope*scope) const bool PEBinary::has_aa_term(Design*des, NetScope*scope) const

View File

@ -206,8 +206,8 @@ const pform_name_t& PCallTask::path() const
return path_; return path_;
} }
PCase::PCase(NetCase::TYPE t, PExpr*ex, svector<PCase::Item*>*l) PCase::PCase(ivl_case_quality_t q, NetCase::TYPE t, PExpr*ex, svector<PCase::Item*>*l)
: type_(t), expr_(ex), items_(l) : quality_(q), type_(t), expr_(ex), items_(l)
{ {
} }

View File

@ -254,7 +254,7 @@ class PCase : public Statement {
Statement*stat; Statement*stat;
}; };
PCase(NetCase::TYPE, PExpr*ex, svector<Item*>*); PCase(ivl_case_quality_t, NetCase::TYPE, PExpr*ex, svector<Item*>*);
~PCase(); ~PCase();
virtual NetProc* elaborate(Design*des, NetScope*scope) const; virtual NetProc* elaborate(Design*des, NetScope*scope) const;
@ -263,6 +263,7 @@ class PCase : public Statement {
virtual void dump(ostream&out, unsigned ind) const; virtual void dump(ostream&out, unsigned ind) const;
private: private:
ivl_case_quality_t quality_;
NetCase::TYPE type_; NetCase::TYPE type_;
PExpr*expr_; PExpr*expr_;

View File

@ -1,7 +1,7 @@
#ifndef IVL_compiler_H #ifndef IVL_compiler_H
#define IVL_compiler_H #define IVL_compiler_H
/* /*
* Copyright (c) 1999-2017 Stephen Williams (steve@icarus.com) * Copyright (c) 1999-2019 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -177,9 +177,12 @@ extern bool gn_icarus_misc_flag;
is false, then skip elaboration of specify behavior. */ is false, then skip elaboration of specify behavior. */
extern bool gn_specify_blocks_flag; extern bool gn_specify_blocks_flag;
/* If this flag is true, then elaborate assertions. If this flag is /* If this flag is true, then elaborate supported assertion statements. If
false, then stub out assertion statements. */ this flag is false, then stub out supported assertion statements. */
extern bool gn_assertions_flag; extern bool gn_supported_assertions_flag;
/* If this flag is true, then error on unsupported assertion statements. If
this flag is false, then stub out unsupported assertion statements. */
extern bool gn_unsupported_assertions_flag;
/* If this flag is true, then support/elaborate Verilog-AMS. */ /* If this flag is true, then support/elaborate Verilog-AMS. */
extern bool gn_verilog_ams_flag; extern bool gn_verilog_ams_flag;

View File

@ -1150,15 +1150,29 @@ void NetBlock::dump(ostream&o, unsigned ind) const
void NetCase::dump(ostream&o, unsigned ind) const void NetCase::dump(ostream&o, unsigned ind) const
{ {
o << setw(ind) << "";
switch (quality_) {
case IVL_CASE_QUALITY_BASIC:
break;
case IVL_CASE_QUALITY_UNIQUE:
o << "unique ";
break;
case IVL_CASE_QUALITY_UNIQUE0:
o << "unique0 ";
break;
case IVL_CASE_QUALITY_PRIORITY:
o << "priority ";
break;
}
switch (type_) { switch (type_) {
case EQ: case EQ:
o << setw(ind) << "" << "case (" << *expr_ << ")" << endl; o << "case (" << *expr_ << ")" << endl;
break; break;
case EQX: case EQX:
o << setw(ind) << "" << "casex (" << *expr_ << ")" << endl; o << "casex (" << *expr_ << ")" << endl;
break; break;
case EQZ: case EQZ:
o << setw(ind) << "" << "casez (" << *expr_ << ")" << endl; o << "casez (" << *expr_ << ")" << endl;
break; break;
} }

View File

@ -1,4 +1,4 @@
.TH iverilog 1 "Sep 20th, 2019" "" "Version %M.%n%E" .TH iverilog 1 "Oct 5th, 2019" "" "Version %M.%n%E"
.SH NAME .SH NAME
iverilog - Icarus Verilog compiler iverilog - Icarus Verilog compiler
@ -80,10 +80,11 @@ use any of the new \fIIEEE1800\fP keywords.
Enable or disable (default) support for Verilog\-AMS. Enable or disable (default) support for Verilog\-AMS.
Very little Verilog\-AMS specific functionality is currently supported. Very little Verilog\-AMS specific functionality is currently supported.
.TP 8 .TP 8
.B -gassertions\fI|\fP-gno-assertions .B -gassertions\fI|\fP-gsupported-assertions\fI|\fP-gno-assertions
Enable (default) or disable SystemVerilog assertions. When enabled, Enable (default) or disable SystemVerilog assertions. When enabled,
assertion statements are elaborated. When disabled, assertion statements assertion statements are elaborated. When disabled, assertion statements
are parsed but ignored. are parsed but ignored. The \fB\-gsupported-assertions\fP option only
enables assertions that are currently supported by the compiler.
.TP 8 .TP 8
.B -gspecify\fI|\fP-gno-specify .B -gspecify\fI|\fP-gno-specify
Enable or disable (default) specify block support. When enabled, Enable or disable (default) specify block support. When enabled,
@ -129,7 +130,7 @@ default, parts of the expression that do not depend on the changed
input value(s) are not re-evaluated. If an expression contains a call input value(s) are not re-evaluated. If an expression contains a call
to a function that doesn't depend solely on its input values or that to a function that doesn't depend solely on its input values or that
has side effects, the resulting behavior will differ from that has side effects, the resulting behavior will differ from that
required by the standard. Using \fI\-gstrict\-ca\-eval\fP will force required by the standard. Using \fB\-gstrict\-ca\-eval\fP will force
standard compliant behavior (with some loss in performance). standard compliant behavior (with some loss in performance).
.TP 8 .TP 8
.B -gstrict-expr-width\fI|\fP-gno-strict-expr-width .B -gstrict-expr-width\fI|\fP-gno-strict-expr-width

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2000-2017 Stephen Williams (steve@icarus.com) * Copyright (c) 2000-2019 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -748,6 +748,9 @@ static int process_generation(const char*name)
else if (strcmp(name,"assertions") == 0) else if (strcmp(name,"assertions") == 0)
gen_assertions = "assertions"; gen_assertions = "assertions";
else if (strcmp(name,"supported-assertions") == 0)
gen_assertions = "supported-assertions";
else if (strcmp(name,"no-assertions") == 0) else if (strcmp(name,"no-assertions") == 0)
gen_assertions = "no-assertions"; gen_assertions = "no-assertions";
@ -804,6 +807,7 @@ static int process_generation(const char*name)
" 2009 -- IEEE1800-2009\n" " 2009 -- IEEE1800-2009\n"
" 2012 -- IEEE1800-2012\n" " 2012 -- IEEE1800-2012\n"
"Other generation flags:\n" "Other generation flags:\n"
" assertions | supported-assertions | no-assertions\n"
" specify | no-specify\n" " specify | no-specify\n"
" verilog-ams | no-verilog-ams\n" " verilog-ams | no-verilog-ams\n"
" std-include | no-std-include\n" " std-include | no-std-include\n"
@ -1176,7 +1180,7 @@ int main(int argc, char **argv)
if (version_flag || verbose_flag) { if (version_flag || verbose_flag) {
printf("Icarus Verilog version " VERSION " (" VERSION_TAG ")\n\n"); printf("Icarus Verilog version " VERSION " (" VERSION_TAG ")\n\n");
printf("Copyright 1998-2017 Stephen Williams\n\n"); printf("Copyright 1998-2019 Stephen Williams\n\n");
puts(NOTICE); puts(NOTICE);
} }

View File

@ -2321,8 +2321,6 @@ NetExpr* PAssign_::elaborate_rval_(Design*des, NetScope*scope,
if (!is_constant_ || !rv) return rv; if (!is_constant_ || !rv) return rv;
if (dynamic_cast<NetENew*>(rv)) return rv;
cerr << get_fileline() << ": error: " cerr << get_fileline() << ": error: "
"The RHS expression must be constant." << endl; "The RHS expression must be constant." << endl;
cerr << get_fileline() << " : " cerr << get_fileline() << " : "
@ -3129,7 +3127,7 @@ NetProc* PCase::elaborate(Design*des, NetScope*scope) const
icount += cur->expr.size(); icount += cur->expr.size();
} }
NetCase*res = new NetCase(type_, expr, icount); NetCase*res = new NetCase(quality_, type_, expr, icount);
res->set_line(*this); res->set_line(*this);
/* Iterate over all the case items (guard/statement pairs) /* Iterate over all the case items (guard/statement pairs)

View File

@ -434,6 +434,14 @@ typedef enum ivl_statement_type_e {
IVL_ST_WHILE = 23 IVL_ST_WHILE = 23
} ivl_statement_type_t; } ivl_statement_type_t;
/* Case statements can be tagged as unique/unique0/priority. */
typedef enum ivl_case_quality_t {
IVL_CASE_QUALITY_BASIC = 0, /* no quality flags */
IVL_CASE_QUALITY_UNIQUE = 1,
IVL_CASE_QUALITY_UNIQUE0 = 2,
IVL_CASE_QUALITY_PRIORITY = 3
} ivl_case_quality_t;
/* SystemVerilog allows a system function to be called as a task. */ /* SystemVerilog allows a system function to be called as a task. */
typedef enum ivl_sfunc_as_task_e { typedef enum ivl_sfunc_as_task_e {
IVL_SFUNC_AS_TASK_ERROR = 0, IVL_SFUNC_AS_TASK_ERROR = 0,
@ -2222,6 +2230,8 @@ extern ivl_scope_t ivl_stmt_call(ivl_statement_t net);
extern unsigned ivl_stmt_case_count(ivl_statement_t net); extern unsigned ivl_stmt_case_count(ivl_statement_t net);
/* IVL_ST_CASE,IVL_ST_CASER,IVL_ST_CASEX,IVL_ST_CASEZ */ /* IVL_ST_CASE,IVL_ST_CASER,IVL_ST_CASEX,IVL_ST_CASEZ */
extern ivl_expr_t ivl_stmt_case_expr(ivl_statement_t net, unsigned i); extern ivl_expr_t ivl_stmt_case_expr(ivl_statement_t net, unsigned i);
/* IVL+ST_CASE,IVL_ST_CASER,IVL_ST_CASEX,IVL_ST_CASEZ */
extern ivl_case_quality_t ivl_stmt_case_quality(ivl_statement_t net);
/* IVL_ST_CASE,IVL_ST_CASER,IVL_ST_CASEX,IVL_ST_CASEZ */ /* IVL_ST_CASE,IVL_ST_CASER,IVL_ST_CASEX,IVL_ST_CASEZ */
extern ivl_statement_t ivl_stmt_case_stmt(ivl_statement_t net, unsigned i); extern ivl_statement_t ivl_stmt_case_stmt(ivl_statement_t net, unsigned i);
/* IVL_ST_CONDIT IVL_ST_CASE IVL_ST_REPEAT IVL_ST_WHILE */ /* IVL_ST_CONDIT IVL_ST_CASE IVL_ST_REPEAT IVL_ST_WHILE */

15
main.cc
View File

@ -1,5 +1,5 @@
const char COPYRIGHT[] = const char COPYRIGHT[] =
"Copyright (c) 1998-2017 Stephen Williams (steve@icarus.com)"; "Copyright (c) 1998-2019 Stephen Williams (steve@icarus.com)";
/* /*
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
@ -104,7 +104,8 @@ generation_t generation_flag = GN_DEFAULT;
bool gn_icarus_misc_flag = true; bool gn_icarus_misc_flag = true;
bool gn_cadence_types_flag = true; bool gn_cadence_types_flag = true;
bool gn_specify_blocks_flag = true; bool gn_specify_blocks_flag = true;
bool gn_assertions_flag = true; bool gn_supported_assertions_flag = true;
bool gn_unsupported_assertions_flag = true;
bool gn_io_range_error_flag = true; bool gn_io_range_error_flag = true;
bool gn_strict_ca_eval_flag = false; bool gn_strict_ca_eval_flag = false;
bool gn_strict_expr_width_flag = false; bool gn_strict_expr_width_flag = false;
@ -331,10 +332,16 @@ static void process_generation_flag(const char*gen)
gn_specify_blocks_flag = false; gn_specify_blocks_flag = false;
} else if (strcmp(gen,"assertions") == 0) { } else if (strcmp(gen,"assertions") == 0) {
gn_assertions_flag = true; gn_supported_assertions_flag = true;
gn_unsupported_assertions_flag = true;
} else if (strcmp(gen,"supported-assertions") == 0) {
gn_supported_assertions_flag = true;
gn_unsupported_assertions_flag = false;
} else if (strcmp(gen,"no-assertions") == 0) { } else if (strcmp(gen,"no-assertions") == 0) {
gn_assertions_flag = false; gn_supported_assertions_flag = false;
gn_unsupported_assertions_flag = false;
} else if (strcmp(gen,"verilog-ams") == 0) { } else if (strcmp(gen,"verilog-ams") == 0) {
gn_verilog_ams_flag = true; gn_verilog_ams_flag = true;

View File

@ -83,8 +83,8 @@ const NetProc* NetBlock::proc_next(const NetProc*cur) const
return cur->next_; return cur->next_;
} }
NetCase::NetCase(NetCase::TYPE c, NetExpr*ex, unsigned cnt) NetCase::NetCase(ivl_case_quality_t q, NetCase::TYPE c, NetExpr*ex, unsigned cnt)
: type_(c), expr_(ex), items_(cnt) : quality_(q), type_(c), expr_(ex), items_(cnt)
{ {
ivl_assert(*this, expr_); ivl_assert(*this, expr_);
} }

View File

@ -3050,6 +3050,9 @@ class NetBlock : public NetProc {
* way the comparisons are performed. Also, it is likely that the * way the comparisons are performed. Also, it is likely that the
* target may be able to optimize differently. * target may be able to optimize differently.
* *
* Case statements can have unique, unique0, or priority attached to
* them. If not otherwise adorned, it is QBASIC.
*
* Case can be one of three types: * Case can be one of three types:
* EQ -- All bits must exactly match * EQ -- All bits must exactly match
* EQZ -- z bits are don't care * EQZ -- z bits are don't care
@ -3059,13 +3062,15 @@ class NetCase : public NetProc {
public: public:
enum TYPE { EQ, EQX, EQZ }; enum TYPE { EQ, EQX, EQZ };
NetCase(TYPE c, NetExpr*ex, unsigned cnt);
NetCase(ivl_case_quality_t q, TYPE c, NetExpr*ex, unsigned cnt);
~NetCase(); ~NetCase();
void set_case(unsigned idx, NetExpr*ex, NetProc*st); void set_case(unsigned idx, NetExpr*ex, NetProc*st);
void prune(); void prune();
inline ivl_case_quality_t case_quality() const { return quality_; }
TYPE type() const; TYPE type() const;
const NetExpr*expr() const { return expr_; } const NetExpr*expr() const { return expr_; }
inline unsigned nitems() const { return items_.size(); } inline unsigned nitems() const { return items_.size(); }
@ -3097,6 +3102,7 @@ class NetCase : public NetProc {
NexusSet&nex_map, NetBus&nex_out, NexusSet&nex_map, NetBus&nex_out,
NetBus&enables, vector<mask_t>&bitmasks); NetBus&enables, vector<mask_t>&bitmasks);
ivl_case_quality_t quality_;
TYPE type_; TYPE type_;
struct Item { struct Item {

356
parse.y
View File

@ -408,6 +408,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
svector<PEEvent*>*event_expr; svector<PEEvent*>*event_expr;
ivl_case_quality_t case_quality;
NetNet::Type nettype; NetNet::Type nettype;
PGBuiltin::Type gatetype; PGBuiltin::Type gatetype;
NetNet::PortType porttype; NetNet::PortType porttype;
@ -575,6 +576,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
%type <expr> udp_initial_expr_opt %type <expr> udp_initial_expr_opt
%type <text> register_variable net_variable event_variable endlabel_opt class_declaration_endlabel_opt %type <text> register_variable net_variable event_variable endlabel_opt class_declaration_endlabel_opt
%type <text> block_identifier_opt
%type <perm_strings> register_variable_list net_variable_list event_variable_list %type <perm_strings> register_variable_list net_variable_list event_variable_list
%type <perm_strings> list_of_identifiers loop_variables %type <perm_strings> list_of_identifiers loop_variables
%type <port_list> list_of_port_identifiers list_of_variable_port_identifiers %type <port_list> list_of_port_identifiers list_of_variable_port_identifiers
@ -652,6 +654,9 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
%type <statement> statement statement_item statement_or_null %type <statement> statement statement_item statement_or_null
%type <statement> compressed_statement %type <statement> compressed_statement
%type <statement> loop_statement for_step jump_statement %type <statement> loop_statement for_step jump_statement
%type <statement> concurrent_assertion_statement
%type <statement> deferred_immediate_assertion_statement
%type <statement> simple_immediate_assertion_statement
%type <statement> procedural_assertion_statement %type <statement> procedural_assertion_statement
%type <statement_list> statement_or_null_list statement_or_null_list_opt %type <statement_list> statement_or_null_list statement_or_null_list_opt
@ -667,11 +672,14 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
%type <real_type> non_integer_type %type <real_type> non_integer_type
%type <int_val> assert_or_assume %type <int_val> assert_or_assume
%type <int_val> deferred_mode
%type <int_val> atom2_type %type <int_val> atom2_type
%type <int_val> module_start module_end %type <int_val> module_start module_end
%type <lifetime> lifetime lifetime_opt %type <lifetime> lifetime lifetime_opt
%type <case_quality> unique_priority
%token K_TAND %token K_TAND
%right K_PLUS_EQ K_MINUS_EQ K_MUL_EQ K_DIV_EQ K_MOD_EQ K_AND_EQ K_OR_EQ %right K_PLUS_EQ K_MINUS_EQ K_MUL_EQ K_DIV_EQ K_MOD_EQ K_AND_EQ K_OR_EQ
%right K_XOR_EQ K_LS_EQ K_RS_EQ K_RSS_EQ %right K_XOR_EQ K_LS_EQ K_RS_EQ K_RSS_EQ
@ -724,6 +732,7 @@ assert_or_assume
assertion_item /* IEEE1800-2012: A.6.10 */ assertion_item /* IEEE1800-2012: A.6.10 */
: concurrent_assertion_item : concurrent_assertion_item
| deferred_immediate_assertion_item
; ;
assignment_pattern /* IEEE1800-2005: A.6.7.1 */ assignment_pattern /* IEEE1800-2005: A.6.7.1 */
@ -744,7 +753,9 @@ assignment_pattern /* IEEE1800-2005: A.6.7.1 */
implements it in a LALR way. */ implements it in a LALR way. */
block_identifier_opt /* */ block_identifier_opt /* */
: IDENTIFIER ':' : IDENTIFIER ':'
{ $$ = $1; }
| |
{ $$ = 0; }
; ;
class_declaration /* IEEE1800-2005: A.1.2 */ class_declaration /* IEEE1800-2005: A.1.2 */
@ -988,16 +999,98 @@ class_new /* IEEE1800-2005 A.2.4 */
concurrent_assertion_statement and checker_instantiation rules. */ concurrent_assertion_statement and checker_instantiation rules. */
concurrent_assertion_item /* IEEE1800-2012 A.2.10 */ concurrent_assertion_item /* IEEE1800-2012 A.2.10 */
: block_identifier_opt K_assert K_property '(' property_spec ')' statement_or_null : block_identifier_opt concurrent_assertion_statement
{ delete $1;
delete $2;
}
;
concurrent_assertion_statement /* IEEE1800-2012 A.2.10 */
: assert_or_assume K_property '(' property_spec ')' statement_or_null %prec less_than_K_else
{ /* */ { /* */
if (gn_assertions_flag) { if (gn_unsupported_assertions_flag) {
yyerror(@1, "sorry: concurrent_assertion_item not supported."
" Try -gno-assertions or -gsupported-assertions"
" to turn this message off.");
}
$$ = 0;
}
| assert_or_assume K_property '(' property_spec ')' K_else statement_or_null
{ /* */
if (gn_unsupported_assertions_flag) {
yyerror(@1, "sorry: concurrent_assertion_item not supported."
" Try -gno-assertions or -gsupported-assertions"
" to turn this message off.");
}
$$ = 0;
}
| assert_or_assume K_property '(' property_spec ')' statement_or_null K_else statement_or_null
{ /* */
if (gn_unsupported_assertions_flag) {
yyerror(@1, "sorry: concurrent_assertion_item not supported."
" Try -gno-assertions or -gsupported-assertions"
" to turn this message off.");
}
$$ = 0;
}
| K_cover K_property '(' property_spec ')' statement_or_null
{ /* */
if (gn_unsupported_assertions_flag) {
yyerror(@1, "sorry: concurrent_assertion_item not supported."
" Try -gno-assertions or -gsupported-assertions"
" to turn this message off.");
}
$$ = 0;
}
/* For now, cheat, and use property_spec for the sequence specification.
They are syntactically identical. */
| K_cover K_sequence '(' property_spec ')' statement_or_null
{ /* */
if (gn_unsupported_assertions_flag) {
yyerror(@1, "sorry: concurrent_assertion_item not supported."
" Try -gno-assertions or -gsupported-assertions"
" to turn this message off.");
}
$$ = 0;
}
| K_restrict K_property '(' property_spec ')' ';'
{ /* */
if (gn_unsupported_assertions_flag) {
yyerror(@2, "sorry: concurrent_assertion_item not supported." yyerror(@2, "sorry: concurrent_assertion_item not supported."
" Try -gno-assertion to turn this message off."); " Try -gno-assertions or -gsupported-assertions"
" to turn this message off.");
} }
$$ = 0;
} }
| block_identifier_opt K_assert K_property '(' error ')' statement_or_null | assert_or_assume K_property '(' error ')' statement_or_null %prec less_than_K_else
{ yyerrok; { yyerrok;
yyerror(@2, "error: Error in property_spec of concurrent assertion item."); yyerror(@2, "error: Error in property_spec of concurrent assertion item.");
$$ = 0;
}
| assert_or_assume K_property '(' error ')' K_else statement_or_null
{ yyerrok;
yyerror(@2, "error: Error in property_spec of concurrent assertion item.");
$$ = 0;
}
| assert_or_assume K_property '(' error ')' statement_or_null K_else statement_or_null
{ yyerrok;
yyerror(@2, "error: Error in property_spec of concurrent assertion item.");
$$ = 0;
}
| K_cover K_property '(' error ')' statement_or_null
{ yyerrok;
yyerror(@2, "error: Error in property_spec of concurrent assertion item.");
$$ = 0;
}
| K_cover K_sequence '(' error ')' statement_or_null
{ yyerrok;
yyerror(@2, "error: Error in property_spec of concurrent assertion item.");
$$ = 0;
}
| K_restrict K_property '(' error ')' ';'
{ yyerrok;
yyerror(@2, "error: Error in property_spec of concurrent assertion item.");
$$ = 0;
} }
; ;
@ -1061,6 +1154,7 @@ data_declaration /* IEEE1800-2005: A.2.1.3 */
| attribute_list_opt K_event event_variable_list ';' | attribute_list_opt K_event event_variable_list ';'
{ if ($3) pform_make_events($3, @2.text, @2.first_line); { if ($3) pform_make_events($3, @2.text, @2.first_line);
} }
| attribute_list_opt package_import_declaration
; ;
data_type /* IEEE1800-2005: A.2.2.1 */ data_type /* IEEE1800-2005: A.2.2.1 */
@ -1166,6 +1260,84 @@ data_type_or_implicit_or_void
} }
; ;
deferred_immediate_assertion_item /* IEEE1800-2012: A.6.10 */
: block_identifier_opt deferred_immediate_assertion_statement
{ delete $1;
delete $2;
}
;
deferred_immediate_assertion_statement /* IEEE1800-2012 A.6.10 */
: assert_or_assume deferred_mode '(' expression ')' statement_or_null %prec less_than_K_else
{
if (gn_unsupported_assertions_flag) {
yyerror(@1, "sorry: Deferred assertions are not supported."
" Try -gno-assertions or -gsupported-assertions"
" to turn this message off.");
}
delete $4;
delete $6;
$$ = 0;
}
| assert_or_assume deferred_mode '(' expression ')' K_else statement_or_null
{
if (gn_unsupported_assertions_flag) {
yyerror(@1, "sorry: Deferred assertions are not supported."
" Try -gno-assertions or -gsupported-assertions"
" to turn this message off.");
}
delete $4;
delete $7;
$$ = 0;
}
| assert_or_assume deferred_mode '(' expression ')' statement_or_null K_else statement_or_null
{
if (gn_unsupported_assertions_flag) {
yyerror(@1, "sorry: Deferred assertions are not supported."
" Try -gno-assertions or -gsupported-assertions"
" to turn this message off.");
}
delete $4;
delete $6;
delete $8;
$$ = 0;
}
| K_cover deferred_mode '(' expression ')' statement_or_null
{
/* Coverage collection is not currently supported. */
delete $4;
delete $6;
$$ = 0;
}
| assert_or_assume deferred_mode '(' error ')' statement_or_null %prec less_than_K_else
{ yyerror(@1, "error: Malformed conditional expression.");
$$ = $6;
}
| assert_or_assume deferred_mode '(' error ')' K_else statement_or_null
{ yyerror(@1, "error: Malformed conditional expression.");
$$ = $7;
}
| assert_or_assume deferred_mode '(' error ')' statement_or_null K_else statement_or_null
{ yyerror(@1, "error: Malformed conditional expression.");
$$ = $6;
}
| K_cover deferred_mode '(' error ')' statement_or_null
{ yyerror(@1, "error: Malformed conditional expression.");
$$ = $6;
}
;
deferred_mode
: '#' DEC_NUMBER
{ if (!$2->is_zero()) {
yyerror(@2, "error: Delay value must be zero for deferred assertion.");
}
delete $2;
$$ = 0; }
| K_final
{ $$ = 1; }
;
/* NOTE: The "module" rule of the description combines the /* NOTE: The "module" rule of the description combines the
module_declaration, program_declaration, and interface_declaration module_declaration, program_declaration, and interface_declaration
rules from the standard description. */ rules from the standard description. */
@ -1574,12 +1746,10 @@ variable_decl_assignment /* IEEE1800-2005 A.2.3 */
delete[]$1; delete[]$1;
$$ = tmp; $$ = tmp;
} }
| IDENTIFIER '=' K_new '(' ')' | IDENTIFIER '=' class_new
{ decl_assignment_t*tmp = new decl_assignment_t; { decl_assignment_t*tmp = new decl_assignment_t;
tmp->name = lex_strings.make($1); tmp->name = lex_strings.make($1);
PENewClass*expr = new PENewClass; tmp->expr .reset($3);
FILE_NAME(expr, @3);
tmp->expr .reset(expr);
delete[]$1; delete[]$1;
$$ = tmp; $$ = tmp;
} }
@ -1845,65 +2015,17 @@ port_direction_opt
| { $$ = NetNet::PIMPLICIT; } | { $$ = NetNet::PIMPLICIT; }
; ;
property_expr /* IEEE1800-2012 A.2.10 */ procedural_assertion_statement /* IEEE1800-2012 A.6.10 */
: expression : concurrent_assertion_statement
{ $$ = $1; }
| simple_immediate_assertion_statement
{ $$ = $1; }
| deferred_immediate_assertion_statement
{ $$ = $1; }
; ;
procedural_assertion_statement /* IEEE1800-2012 A.6.10 */ property_expr /* IEEE1800-2012 A.2.10 */
// $assertcontrol is not yet supported. : expression
: assert_or_assume '(' expression ')' statement_or_null %prec less_than_K_else
{
if (gn_assertions_flag) {
list<PExpr*>arg_list;
PCallTask*tmp1 = new PCallTask(lex_strings.make("$error"), arg_list);
FILE_NAME(tmp1, @1);
PCondit*tmp2 = new PCondit($3, $5, tmp1);
FILE_NAME(tmp2, @1);
$$ = tmp2;
} else {
$$ = 0;
}
}
| assert_or_assume '(' expression ')' K_else statement_or_null
{
if (gn_assertions_flag) {
PCondit*tmp = new PCondit($3, 0, $6);
FILE_NAME(tmp, @1);
$$ = tmp;
} else {
$$ = 0;
}
}
| assert_or_assume '(' expression ')' statement_or_null K_else statement_or_null
{
if (gn_assertions_flag) {
PCondit*tmp = new PCondit($3, $5, $7);
FILE_NAME(tmp, @1);
$$ = tmp;
} else {
$$ = 0;
}
}
| K_cover '(' expression ')' statement_or_null
// Coverage collection is not currently supported.
{ $$ = 0; }
| assert_or_assume '(' error ')' statement_or_null %prec less_than_K_else
{ yyerror(@1, "error: Malformed conditional expression.");
$$ = $5;
}
| assert_or_assume '(' error ')' K_else statement_or_null
{ yyerror(@1, "error: Malformed conditional expression.");
$$ = $6;
}
| assert_or_assume '(' error ')' statement_or_null K_else statement_or_null
{ yyerror(@1, "error: Malformed conditional expression.");
$$ = $5;
}
| K_cover '(' error ')' statement_or_null
{ yyerror(@1, "error: Malformed conditional expression.");
$$ = $5;
}
; ;
/* The property_qualifier rule is as literally described in the LRM, /* The property_qualifier rule is as literally described in the LRM,
@ -1956,6 +2078,72 @@ signing /* IEEE1800-2005: A.2.2.1 */
| K_unsigned { $$ = false; } | K_unsigned { $$ = false; }
; ;
simple_immediate_assertion_statement /* IEEE1800-2012 A.6.10 */
: assert_or_assume '(' expression ')' statement_or_null %prec less_than_K_else
{
if (gn_supported_assertions_flag) {
list<PExpr*>arg_list;
PCallTask*tmp1 = new PCallTask(lex_strings.make("$error"), arg_list);
FILE_NAME(tmp1, @1);
PCondit*tmp2 = new PCondit($3, $5, tmp1);
FILE_NAME(tmp2, @1);
$$ = tmp2;
} else {
delete $3;
delete $5;
$$ = 0;
}
}
| assert_or_assume '(' expression ')' K_else statement_or_null
{
if (gn_supported_assertions_flag) {
PCondit*tmp = new PCondit($3, 0, $6);
FILE_NAME(tmp, @1);
$$ = tmp;
} else {
delete $3;
delete $6;
$$ = 0;
}
}
| assert_or_assume '(' expression ')' statement_or_null K_else statement_or_null
{
if (gn_supported_assertions_flag) {
PCondit*tmp = new PCondit($3, $5, $7);
FILE_NAME(tmp, @1);
$$ = tmp;
} else {
delete $3;
delete $5;
delete $7;
$$ = 0;
}
}
| K_cover '(' expression ')' statement_or_null
{
/* Coverage collection is not currently supported. */
delete $3;
delete $5;
$$ = 0;
}
| assert_or_assume '(' error ')' statement_or_null %prec less_than_K_else
{ yyerror(@1, "error: Malformed conditional expression.");
$$ = $5;
}
| assert_or_assume '(' error ')' K_else statement_or_null
{ yyerror(@1, "error: Malformed conditional expression.");
$$ = $6;
}
| assert_or_assume '(' error ')' statement_or_null K_else statement_or_null
{ yyerror(@1, "error: Malformed conditional expression.");
$$ = $5;
}
| K_cover '(' error ')' statement_or_null
{ yyerror(@1, "error: Malformed conditional expression.");
$$ = $5;
}
;
simple_type_or_string /* IEEE1800-2005: A.2.2.1 */ simple_type_or_string /* IEEE1800-2005: A.2.2.1 */
: integer_vector_type : integer_vector_type
{ ivl_variable_type_t use_vtype = $1; { ivl_variable_type_t use_vtype = $1;
@ -6433,27 +6621,28 @@ statement_item /* This is roughly statement_item in the LRM */
| jump_statement { $$ = $1; } | jump_statement { $$ = $1; }
| K_case '(' expression ')' case_items K_endcase | unique_priority K_case '(' expression ')' case_items K_endcase
{ PCase*tmp = new PCase(NetCase::EQ, $3, $5); { PCase*tmp = new PCase($1, NetCase::EQ, $4, $6);
FILE_NAME(tmp, @2);
$$ = tmp;
}
| unique_priority K_casex '(' expression ')' case_items K_endcase
{ PCase*tmp = new PCase($1, NetCase::EQX, $4, $6);
FILE_NAME(tmp, @2);
$$ = tmp;
}
| unique_priority K_casez '(' expression ')' case_items K_endcase
{ PCase*tmp = new PCase($1, NetCase::EQZ, $4, $6);
FILE_NAME(tmp, @1); FILE_NAME(tmp, @1);
$$ = tmp; $$ = tmp;
} }
| K_casex '(' expression ')' case_items K_endcase | unique_priority K_case '(' expression ')' error K_endcase
{ PCase*tmp = new PCase(NetCase::EQX, $3, $5);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| K_casez '(' expression ')' case_items K_endcase
{ PCase*tmp = new PCase(NetCase::EQZ, $3, $5);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| K_case '(' expression ')' error K_endcase
{ yyerrok; } { yyerrok; }
| K_casex '(' expression ')' error K_endcase | unique_priority K_casex '(' expression ')' error K_endcase
{ yyerrok; } { yyerrok; }
| K_casez '(' expression ')' error K_endcase | unique_priority K_casez '(' expression ')' error K_endcase
{ yyerrok; } { yyerrok; }
| K_if '(' expression ')' statement_or_null %prec less_than_K_else | K_if '(' expression ')' statement_or_null %prec less_than_K_else
{ PCondit*tmp = new PCondit($3, $5, 0); { PCondit*tmp = new PCondit($3, $5, 0);
FILE_NAME(tmp, @1); FILE_NAME(tmp, @1);
@ -7108,6 +7297,13 @@ udp_primitive
} }
; ;
unique_priority
: { $$ = IVL_CASE_QUALITY_BASIC; }
| K_unique { $$ = IVL_CASE_QUALITY_UNIQUE; }
| K_unique0 { $$ = IVL_CASE_QUALITY_UNIQUE0; }
| K_priority { $$ = IVL_CASE_QUALITY_PRIORITY; }
;
/* Many keywords can be optional in the syntax, although their /* Many keywords can be optional in the syntax, although their
presence is significant. This is a fairly common pattern so presence is significant. This is a fairly common pattern so
collect those rules here. */ collect those rules here. */

View File

@ -2356,7 +2356,22 @@ void pform_make_modgates(const struct vlltype&loc,
svector<lgate>*gates, svector<lgate>*gates,
std::list<named_pexpr_t>*attr) std::list<named_pexpr_t>*attr)
{ {
// The grammer should not allow module gates to happen outside
// an active module. But if really bad input errors combine in
// an ugly way with error recovery, then catch this
// implausible situation and return an error.
if (pform_cur_module.empty()) {
cerr << loc << ": internal error: "
<< "Module instantiations outside module scope are not possible."
<< endl;
error_count += 1;
delete gates;
return;
}
assert(! pform_cur_module.empty()); assert(! pform_cur_module.empty());
// Detect some more realistic errors.
if (pform_cur_module.front()->program_block) { if (pform_cur_module.front()->program_block) {
cerr << loc << ": error: Module instantiations are not allowed in " cerr << loc << ": error: Module instantiations are not allowed in "
<< "program blocks." << endl; << "program blocks." << endl;
@ -2492,7 +2507,7 @@ void pform_make_var_init(const struct vlltype&li,
PEIdent*lval = new PEIdent(name); PEIdent*lval = new PEIdent(name);
FILE_NAME(lval, li); FILE_NAME(lval, li);
PAssign*ass = new PAssign(lval, expr, true); PAssign*ass = new PAssign(lval, expr, !gn_system_verilog());
FILE_NAME(ass, li); FILE_NAME(ass, li);
lexical_scope->var_inits.push_back(ass); lexical_scope->var_inits.push_back(ass);

View File

@ -840,6 +840,19 @@ void PCallTask::dump(ostream&out, unsigned ind) const
void PCase::dump(ostream&out, unsigned ind) const void PCase::dump(ostream&out, unsigned ind) const
{ {
out << setw(ind) << ""; out << setw(ind) << "";
switch (quality_) {
case IVL_CASE_QUALITY_BASIC:
break;
case IVL_CASE_QUALITY_UNIQUE:
out << "unique ";
break;
case IVL_CASE_QUALITY_UNIQUE0:
out << "unique0 ";
break;
case IVL_CASE_QUALITY_PRIORITY:
out << "priority ";
break;
}
switch (type_) { switch (type_) {
case NetCase::EQ: case NetCase::EQ:
out << "case"; out << "case";

View File

@ -2728,6 +2728,22 @@ extern "C" ivl_expr_t ivl_stmt_case_expr(ivl_statement_t net, unsigned idx)
} }
} }
extern "C" ivl_case_quality_t ivl_stmt_case_quality(ivl_statement_t net)
{
assert(net);
switch (net->type_) {
case IVL_ST_CASE:
case IVL_ST_CASER:
case IVL_ST_CASEX:
case IVL_ST_CASEZ:
return net->u_.case_.quality;
default:
assert(0);
return IVL_CASE_QUALITY_BASIC;
}
}
extern "C" ivl_statement_t ivl_stmt_case_stmt(ivl_statement_t net, unsigned idx) extern "C" ivl_statement_t ivl_stmt_case_stmt(ivl_statement_t net, unsigned idx)
{ {
assert(net); assert(net);

View File

@ -497,6 +497,7 @@ void dll_target::proc_case(const NetCase*net)
} }
assert(stmt_cur_->type_ != IVL_ST_NONE); assert(stmt_cur_->type_ != IVL_ST_NONE);
stmt_cur_->u_.case_.quality = net->case_quality();
assert(expr_ == 0); assert(expr_ == 0);
assert(net->expr()); assert(net->expr());
net->expr()->expr_scan(this); net->expr()->expr_scan(this);

View File

@ -810,6 +810,7 @@ struct ivl_statement_s {
} block_; } block_;
struct { /* IVL_ST_CASE, IVL_ST_CASEX, IVL_ST_CASEZ */ struct { /* IVL_ST_CASE, IVL_ST_CASEX, IVL_ST_CASEZ */
ivl_case_quality_t quality;
ivl_expr_t cond; ivl_expr_t cond;
unsigned ncase; unsigned ncase;
ivl_expr_t*case_ex; ivl_expr_t*case_ex;

View File

@ -375,8 +375,24 @@ void show_statement(ivl_statement_t net, unsigned ind)
case IVL_ST_CASEZ: case IVL_ST_CASEZ:
case IVL_ST_CASER: case IVL_ST_CASER:
case IVL_ST_CASE: { case IVL_ST_CASE: {
ivl_case_quality_t qual = ivl_stmt_case_quality(net);
unsigned cnt = ivl_stmt_case_count(net); unsigned cnt = ivl_stmt_case_count(net);
fprintf(out, "%*scase (...) <%u cases>\n", ind, "", cnt); const char*qual_txt = "";
switch (qual) {
case IVL_CASE_QUALITY_BASIC:
qual_txt = "basic";
break;
case IVL_CASE_QUALITY_UNIQUE:
qual_txt = "unique";
break;
case IVL_CASE_QUALITY_UNIQUE0:
qual_txt = "unique0";
break;
case IVL_CASE_QUALITY_PRIORITY:
qual_txt = "priority";
break;
}
fprintf(out, "%*scase (...) <%u cases, %s>\n", ind, "", cnt, qual_txt);
show_expression(ivl_stmt_cond_expr(net), ind+4); show_expression(ivl_stmt_cond_expr(net), ind+4);
for (idx = 0 ; idx < cnt ; idx += 1) { for (idx = 0 ; idx < cnt ; idx += 1) {

View File

@ -1084,8 +1084,9 @@ static int show_stmt_assign_sig_cobject(ivl_statement_t net)
ivl_type_t prop_type = ivl_type_prop_type(sig_type, prop_idx); ivl_type_t prop_type = ivl_type_prop_type(sig_type, prop_idx);
if (ivl_type_base(prop_type) == IVL_VT_BOOL) { if (ivl_type_base(prop_type) == IVL_VT_BOOL) {
assert(ivl_type_packed_dimensions(prop_type) == 1); assert(ivl_type_packed_dimensions(prop_type) == 0 ||
assert(ivl_type_packed_msb(prop_type,0) >= ivl_type_packed_lsb(prop_type, 0)); (ivl_type_packed_dimensions(prop_type) == 1 &&
ivl_type_packed_msb(prop_type,0) >= ivl_type_packed_lsb(prop_type, 0)));
draw_eval_vec4(rval); draw_eval_vec4(rval);
if (ivl_expr_value(rval)!=IVL_VT_BOOL) if (ivl_expr_value(rval)!=IVL_VT_BOOL)
@ -1097,8 +1098,9 @@ static int show_stmt_assign_sig_cobject(ivl_statement_t net)
fprintf(vvp_out, " %%pop/obj 1, 0;\n"); fprintf(vvp_out, " %%pop/obj 1, 0;\n");
} else if (ivl_type_base(prop_type) == IVL_VT_LOGIC) { } else if (ivl_type_base(prop_type) == IVL_VT_LOGIC) {
assert(ivl_type_packed_dimensions(prop_type) == 1); assert(ivl_type_packed_dimensions(prop_type) == 0 ||
assert(ivl_type_packed_msb(prop_type,0) >= ivl_type_packed_lsb(prop_type, 0)); (ivl_type_packed_dimensions(prop_type) == 1 &&
ivl_type_packed_msb(prop_type,0) >= ivl_type_packed_lsb(prop_type, 0)));
draw_eval_vec4(rval); draw_eval_vec4(rval);

View File

@ -644,6 +644,7 @@ static int show_stmt_block_named(ivl_statement_t net, ivl_scope_t scope)
static int show_stmt_case(ivl_statement_t net, ivl_scope_t sscope) static int show_stmt_case(ivl_statement_t net, ivl_scope_t sscope)
{ {
int rc = 0; int rc = 0;
ivl_case_quality_t qual = ivl_stmt_case_quality(net);
ivl_expr_t expr = ivl_stmt_cond_expr(net); ivl_expr_t expr = ivl_stmt_cond_expr(net);
unsigned count = ivl_stmt_case_count(net); unsigned count = ivl_stmt_case_count(net);
@ -651,6 +652,12 @@ static int show_stmt_case(ivl_statement_t net, ivl_scope_t sscope)
unsigned idx, default_case; unsigned idx, default_case;
if (qual != IVL_CASE_QUALITY_BASIC) {
fprintf(stderr, "%s:%u: tgt-vvp sorry: "
"Case unique/unique0/priority qualities are ignored.\n",
ivl_stmt_file(net), ivl_stmt_lineno(net));
}
show_stmt_file_line(net, "Case statement."); show_stmt_file_line(net, "Case statement.");
local_count += count + 1; local_count += count + 1;