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)
{
assert(left_ && right_);
left_->declare_implicit_nets(scope, type);
right_->declare_implicit_nets(scope, type);
if (left_) left_->declare_implicit_nets(scope, type);
if (right_) right_->declare_implicit_nets(scope, type);
}
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_;
}
PCase::PCase(NetCase::TYPE t, PExpr*ex, svector<PCase::Item*>*l)
: type_(t), expr_(ex), items_(l)
PCase::PCase(ivl_case_quality_t q, NetCase::TYPE t, PExpr*ex, svector<PCase::Item*>*l)
: quality_(q), type_(t), expr_(ex), items_(l)
{
}

View File

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

View File

@ -1,7 +1,7 @@
#ifndef 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
* 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. */
extern bool gn_specify_blocks_flag;
/* If this flag is true, then elaborate assertions. If this flag is
false, then stub out assertion statements. */
extern bool gn_assertions_flag;
/* If this flag is true, then elaborate supported assertion statements. If
this flag is false, then stub out supported assertion statements. */
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. */
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
{
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_) {
case EQ:
o << setw(ind) << "" << "case (" << *expr_ << ")" << endl;
o << "case (" << *expr_ << ")" << endl;
break;
case EQX:
o << setw(ind) << "" << "casex (" << *expr_ << ")" << endl;
o << "casex (" << *expr_ << ")" << endl;
break;
case EQZ:
o << setw(ind) << "" << "casez (" << *expr_ << ")" << endl;
o << "casez (" << *expr_ << ")" << endl;
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
iverilog - Icarus Verilog compiler
@ -80,10 +80,11 @@ use any of the new \fIIEEE1800\fP keywords.
Enable or disable (default) support for Verilog\-AMS.
Very little Verilog\-AMS specific functionality is currently supported.
.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,
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
.B -gspecify\fI|\fP-gno-specify
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
to a function that doesn't depend solely on its input values or 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).
.TP 8
.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
* 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)
gen_assertions = "assertions";
else if (strcmp(name,"supported-assertions") == 0)
gen_assertions = "supported-assertions";
else if (strcmp(name,"no-assertions") == 0)
gen_assertions = "no-assertions";
@ -804,6 +807,7 @@ static int process_generation(const char*name)
" 2009 -- IEEE1800-2009\n"
" 2012 -- IEEE1800-2012\n"
"Other generation flags:\n"
" assertions | supported-assertions | no-assertions\n"
" specify | no-specify\n"
" verilog-ams | no-verilog-ams\n"
" std-include | no-std-include\n"
@ -1176,7 +1180,7 @@ int main(int argc, char **argv)
if (version_flag || verbose_flag) {
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);
}

View File

@ -2321,8 +2321,6 @@ NetExpr* PAssign_::elaborate_rval_(Design*des, NetScope*scope,
if (!is_constant_ || !rv) return rv;
if (dynamic_cast<NetENew*>(rv)) return rv;
cerr << get_fileline() << ": error: "
"The RHS expression must be constant." << endl;
cerr << get_fileline() << " : "
@ -3129,7 +3127,7 @@ NetProc* PCase::elaborate(Design*des, NetScope*scope) const
icount += cur->expr.size();
}
NetCase*res = new NetCase(type_, expr, icount);
NetCase*res = new NetCase(quality_, type_, expr, icount);
res->set_line(*this);
/* 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_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. */
typedef enum ivl_sfunc_as_task_e {
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);
/* 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);
/* 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 */
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 */

15
main.cc
View File

@ -1,5 +1,5 @@
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
@ -104,7 +104,8 @@ generation_t generation_flag = GN_DEFAULT;
bool gn_icarus_misc_flag = true;
bool gn_cadence_types_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_strict_ca_eval_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;
} 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) {
gn_assertions_flag = false;
gn_supported_assertions_flag = false;
gn_unsupported_assertions_flag = false;
} else if (strcmp(gen,"verilog-ams") == 0) {
gn_verilog_ams_flag = true;

View File

@ -83,8 +83,8 @@ const NetProc* NetBlock::proc_next(const NetProc*cur) const
return cur->next_;
}
NetCase::NetCase(NetCase::TYPE c, NetExpr*ex, unsigned cnt)
: type_(c), expr_(ex), items_(cnt)
NetCase::NetCase(ivl_case_quality_t q, NetCase::TYPE c, NetExpr*ex, unsigned cnt)
: quality_(q), type_(c), expr_(ex), items_(cnt)
{
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
* 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:
* EQ -- All bits must exactly match
* EQZ -- z bits are don't care
@ -3059,13 +3062,15 @@ class NetCase : public NetProc {
public:
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();
void set_case(unsigned idx, NetExpr*ex, NetProc*st);
void prune();
inline ivl_case_quality_t case_quality() const { return quality_; }
TYPE type() const;
const NetExpr*expr() const { return expr_; }
inline unsigned nitems() const { return items_.size(); }
@ -3097,6 +3102,7 @@ class NetCase : public NetProc {
NexusSet&nex_map, NetBus&nex_out,
NetBus&enables, vector<mask_t>&bitmasks);
ivl_case_quality_t quality_;
TYPE type_;
struct Item {

374
parse.y
View File

@ -408,6 +408,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
svector<PEEvent*>*event_expr;
ivl_case_quality_t case_quality;
NetNet::Type nettype;
PGBuiltin::Type gatetype;
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 <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> list_of_identifiers loop_variables
%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> compressed_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_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 <int_val> assert_or_assume
%type <int_val> deferred_mode
%type <int_val> atom2_type
%type <int_val> module_start module_end
%type <lifetime> lifetime lifetime_opt
%type <case_quality> unique_priority
%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_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 */
: concurrent_assertion_item
| deferred_immediate_assertion_item
;
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. */
block_identifier_opt /* */
: IDENTIFIER ':'
{ $$ = $1; }
|
{ $$ = 0; }
;
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_item /* IEEE1800-2012 A.2.10 */
: block_identifier_opt K_assert K_property '(' property_spec ')' statement_or_null
{ /* */
if (gn_assertions_flag) {
yyerror(@2, "sorry: concurrent_assertion_item not supported."
" Try -gno-assertion to turn this message off.");
}
: block_identifier_opt concurrent_assertion_statement
{ delete $1;
delete $2;
}
| block_identifier_opt K_assert K_property '(' error ')' statement_or_null
;
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_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."
" Try -gno-assertions or -gsupported-assertions"
" to turn this message off.");
}
$$ = 0;
}
| assert_or_assume K_property '(' error ')' statement_or_null %prec less_than_K_else
{ yyerrok;
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 ';'
{ 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 */
@ -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
module_declaration, program_declaration, and interface_declaration
rules from the standard description. */
@ -1574,12 +1746,10 @@ variable_decl_assignment /* IEEE1800-2005 A.2.3 */
delete[]$1;
$$ = tmp;
}
| IDENTIFIER '=' K_new '(' ')'
| IDENTIFIER '=' class_new
{ decl_assignment_t*tmp = new decl_assignment_t;
tmp->name = lex_strings.make($1);
PENewClass*expr = new PENewClass;
FILE_NAME(expr, @3);
tmp->expr .reset(expr);
tmp->expr .reset($3);
delete[]$1;
$$ = tmp;
}
@ -1845,65 +2015,17 @@ port_direction_opt
| { $$ = NetNet::PIMPLICIT; }
;
property_expr /* IEEE1800-2012 A.2.10 */
: expression
procedural_assertion_statement /* IEEE1800-2012 A.6.10 */
: concurrent_assertion_statement
{ $$ = $1; }
| simple_immediate_assertion_statement
{ $$ = $1; }
| deferred_immediate_assertion_statement
{ $$ = $1; }
;
procedural_assertion_statement /* IEEE1800-2012 A.6.10 */
// $assertcontrol is not yet supported.
: 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;
}
property_expr /* IEEE1800-2012 A.2.10 */
: expression
;
/* 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; }
;
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 */
: integer_vector_type
{ ivl_variable_type_t use_vtype = $1;
@ -6433,27 +6621,28 @@ statement_item /* This is roughly statement_item in the LRM */
| jump_statement { $$ = $1; }
| K_case '(' expression ')' case_items K_endcase
{ PCase*tmp = new PCase(NetCase::EQ, $3, $5);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| K_casex '(' expression ')' case_items 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; }
| K_casex '(' expression ')' error K_endcase
{ yyerrok; }
| K_casez '(' expression ')' error K_endcase
{ yyerrok; }
| unique_priority K_case '(' expression ')' case_items K_endcase
{ 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);
$$ = tmp;
}
| unique_priority K_case '(' expression ')' error K_endcase
{ yyerrok; }
| unique_priority K_casex '(' expression ')' error K_endcase
{ yyerrok; }
| unique_priority K_casez '(' expression ')' error K_endcase
{ yyerrok; }
| K_if '(' expression ')' statement_or_null %prec less_than_K_else
{ PCondit*tmp = new PCondit($3, $5, 0);
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
presence is significant. This is a fairly common pattern so
collect those rules here. */

View File

@ -2356,7 +2356,22 @@ void pform_make_modgates(const struct vlltype&loc,
svector<lgate>*gates,
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());
// Detect some more realistic errors.
if (pform_cur_module.front()->program_block) {
cerr << loc << ": error: Module instantiations are not allowed in "
<< "program blocks." << endl;
@ -2492,7 +2507,7 @@ void pform_make_var_init(const struct vlltype&li,
PEIdent*lval = new PEIdent(name);
FILE_NAME(lval, li);
PAssign*ass = new PAssign(lval, expr, true);
PAssign*ass = new PAssign(lval, expr, !gn_system_verilog());
FILE_NAME(ass, li);
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
{
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_) {
case NetCase::EQ:
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)
{
assert(net);

View File

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

View File

@ -810,6 +810,7 @@ struct ivl_statement_s {
} block_;
struct { /* IVL_ST_CASE, IVL_ST_CASEX, IVL_ST_CASEZ */
ivl_case_quality_t quality;
ivl_expr_t cond;
unsigned ncase;
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_CASER:
case IVL_ST_CASE: {
ivl_case_quality_t qual = ivl_stmt_case_quality(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);
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);
if (ivl_type_base(prop_type) == IVL_VT_BOOL) {
assert(ivl_type_packed_dimensions(prop_type) == 1);
assert(ivl_type_packed_msb(prop_type,0) >= ivl_type_packed_lsb(prop_type, 0));
assert(ivl_type_packed_dimensions(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);
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");
} else if (ivl_type_base(prop_type) == IVL_VT_LOGIC) {
assert(ivl_type_packed_dimensions(prop_type) == 1);
assert(ivl_type_packed_msb(prop_type,0) >= ivl_type_packed_lsb(prop_type, 0));
assert(ivl_type_packed_dimensions(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);

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)
{
int rc = 0;
ivl_case_quality_t qual = ivl_stmt_case_quality(net);
ivl_expr_t expr = ivl_stmt_cond_expr(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;
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.");
local_count += count + 1;