commit
cce30e89bb
5
PExpr.cc
5
PExpr.cc
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
|
||||
|
|
|
|||
11
compiler.h
11
compiler.h
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
10
ivl_target.h
10
ivl_target.h
|
|
@ -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
15
main.cc
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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_);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
374
parse.y
|
|
@ -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. */
|
||||
|
|
|
|||
17
pform.cc
17
pform.cc
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
16
t-dll-api.cc
16
t-dll-api.cc
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
1
t-dll.h
1
t-dll.h
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue