Merge branch 'master' of github.com:steveicarus/iverilog
This commit is contained in:
commit
e5f84002b1
2
PExpr.h
2
PExpr.h
|
|
@ -328,6 +328,8 @@ class PEIdent : public PExpr {
|
|||
// elaborate/calculate, or false if there is some sort of
|
||||
// source error.
|
||||
|
||||
bool calculate_bits_(Design*, NetScope*, long&msb, bool&defined) const;
|
||||
|
||||
// The calculate_parts_ method calculates the range
|
||||
// expressions of a part select for the current object. The
|
||||
// part select expressions are elaborated and evaluated, and
|
||||
|
|
|
|||
|
|
@ -92,6 +92,9 @@ extern bool warn_inf_loop;
|
|||
extern bool warn_sens_entire_vec;
|
||||
extern bool warn_sens_entire_arr;
|
||||
|
||||
/* Warn about level-appropriate anochronisms. */
|
||||
extern bool warn_anachronisms;
|
||||
|
||||
/* This is true if verbose output is requested. */
|
||||
extern bool verbose_flag;
|
||||
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ int gen_std_include = 1;
|
|||
of the include list. */
|
||||
int gen_relative_include = 0;
|
||||
|
||||
char warning_flags[16] = "";
|
||||
char warning_flags[16] = "n";
|
||||
|
||||
unsigned integer_width = 32;
|
||||
|
||||
|
|
@ -491,11 +491,15 @@ static int t_compile()
|
|||
static void process_warning_switch(const char*name)
|
||||
{
|
||||
if (strcmp(name,"all") == 0) {
|
||||
process_warning_switch("anachronisms");
|
||||
process_warning_switch("implicit");
|
||||
process_warning_switch("portbind");
|
||||
process_warning_switch("select-range");
|
||||
process_warning_switch("timescale");
|
||||
process_warning_switch("sensitivity-entire-array");
|
||||
} else if (strcmp(name,"anachronisms") == 0) {
|
||||
if (! strchr(warning_flags, 'n'))
|
||||
strcat(warning_flags, "n");
|
||||
} else if (strcmp(name,"implicit") == 0) {
|
||||
if (! strchr(warning_flags, 'i'))
|
||||
strcat(warning_flags, "i");
|
||||
|
|
@ -519,6 +523,12 @@ static void process_warning_switch(const char*name)
|
|||
} else if (strcmp(name,"sensitivity-entire-array") == 0) {
|
||||
if (! strchr(warning_flags, 'a'))
|
||||
strcat(warning_flags, "a");
|
||||
} else if (strcmp(name,"no-anachronisms") == 0) {
|
||||
char*cp = strchr(warning_flags, 'n');
|
||||
if (cp) while (*cp) {
|
||||
cp[0] = cp[1];
|
||||
cp += 1;
|
||||
}
|
||||
} else if (strcmp(name,"no-implicit") == 0) {
|
||||
char*cp = strchr(warning_flags, 'i');
|
||||
if (cp) while (*cp) {
|
||||
|
|
|
|||
37
elab_expr.cc
37
elab_expr.cc
|
|
@ -1879,6 +1879,43 @@ bool PEIdent::calculate_packed_indices_(Design*des, NetScope*scope, NetNet*net,
|
|||
return evaluate_index_prefix(des, scope, prefix_indices, index);
|
||||
}
|
||||
|
||||
|
||||
bool PEIdent::calculate_bits_(Design*des, NetScope*scope,
|
||||
long&msb, bool&defined) const
|
||||
{
|
||||
defined = true;
|
||||
const name_component_t&name_tail = path_.back();
|
||||
ivl_assert(*this, !name_tail.index.empty());
|
||||
|
||||
const index_component_t&index_tail = name_tail.index.back();
|
||||
ivl_assert(*this, index_tail.sel == index_component_t::SEL_BIT);
|
||||
ivl_assert(*this, index_tail.msb && !index_tail.lsb);
|
||||
|
||||
/* This handles bit selects. In this case, there in one
|
||||
bit select expressions which must be constant. */
|
||||
|
||||
NetExpr*msb_ex = elab_and_eval(des, scope, index_tail.msb, -1, true);
|
||||
NetEConst*msb_c = dynamic_cast<NetEConst*>(msb_ex);
|
||||
if (msb_c == 0) {
|
||||
cerr << index_tail.msb->get_fileline() << ": error: "
|
||||
"Bit select expressionsmust be constant."
|
||||
<< endl;
|
||||
cerr << index_tail.msb->get_fileline() << ": : "
|
||||
"This msb expression violates the rule: "
|
||||
<< *index_tail.msb << endl;
|
||||
des->errors += 1;
|
||||
/* Attempt to recover from error. */
|
||||
msb = 0;
|
||||
} else {
|
||||
if (! msb_c->value().is_defined())
|
||||
defined = false;
|
||||
msb = msb_c->value().as_long();
|
||||
}
|
||||
|
||||
delete msb_ex;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Given that the msb_ and lsb_ are part select expressions, this
|
||||
* function calculates their values. Note that this method does *not*
|
||||
|
|
|
|||
24
elab_net.cc
24
elab_net.cc
|
|
@ -360,24 +360,14 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
|
|||
|
||||
case index_component_t::SEL_BIT:
|
||||
if (name_tail.index.size() > sig->array_dimensions()) {
|
||||
verinum*mval = index_tail.msb->eval_const(des, scope);
|
||||
if (mval == 0) {
|
||||
cerr << get_fileline() << ": error: Index of " << path_ <<
|
||||
" needs to be constant in this context." <<
|
||||
endl;
|
||||
cerr << get_fileline() << ": : Index expression is: "
|
||||
<< *index_tail.msb << endl;
|
||||
cerr << get_fileline() << ": : Context scope is: "
|
||||
<< scope_path(scope) << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
assert(mval);
|
||||
|
||||
midx = sig->sb_to_idx(prefix_indices, mval->as_long());
|
||||
long msb;
|
||||
bool bit_defined_flag;
|
||||
/* bool flag = */ calculate_bits_(des, scope, msb, bit_defined_flag);
|
||||
ivl_assert(*this, bit_defined_flag);
|
||||
midx = sig->sb_to_idx(prefix_indices, msb);
|
||||
if (midx >= (long)sig->vector_width()) {
|
||||
cerr << get_fileline() << ": error: Index " << sig->name()
|
||||
<< "[" << mval->as_long() << "] is out of range."
|
||||
<< "[" << msb << "] is out of range."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
midx = 0;
|
||||
|
|
@ -453,7 +443,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
|||
wire. */
|
||||
if (gn_var_can_be_uwire()
|
||||
&& (sig->type() == NetNet::REG)
|
||||
&& (sig->peek_eref() == 0) ) {
|
||||
&& (sig->peek_lref() == 0) ) {
|
||||
sig->type(NetNet::UNRESOLVED_WIRE);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -961,6 +961,12 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
|
|||
return true;
|
||||
}
|
||||
|
||||
if (debug_scopes) {
|
||||
cerr << get_fileline() << ": PGenerate::generate_scope_case_: "
|
||||
<< "Generate subscope " << use_name
|
||||
<< " and elaborate." << endl;
|
||||
}
|
||||
|
||||
NetScope*scope = new NetScope(container, use_name,
|
||||
NetScope::GENBLOCK);
|
||||
scope->set_line(get_file(), get_lineno());
|
||||
|
|
@ -1030,7 +1036,13 @@ void PGenerate::elaborate_subscope_direct_(Design*des, NetScope*scope)
|
|||
typedef list<PGenerate*>::const_iterator generate_it_t;
|
||||
for (generate_it_t cur = generate_schemes.begin()
|
||||
; cur != generate_schemes.end() ; ++ cur ) {
|
||||
(*cur) -> generate_scope(des, scope);
|
||||
PGenerate*curp = *cur;
|
||||
if (debug_scopes) {
|
||||
cerr << get_fileline() << ": elaborate_subscope_direct_: "
|
||||
<< "Elaborate direct subscope " << curp->scope_name
|
||||
<< " within scope " << scope_name << endl;
|
||||
}
|
||||
curp -> generate_scope(des, scope);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1082,7 +1094,7 @@ void PGenerate::elaborate_subscope_(Design*des, NetScope*scope)
|
|||
|
||||
if (debug_scopes)
|
||||
cerr << get_fileline() << ": debug: Generated scope " << scope_path(scope)
|
||||
<< " by generate block " << scope_name << endl;
|
||||
<< " for generate block " << scope_name << endl;
|
||||
|
||||
// Save the scope that we created, for future use.
|
||||
scope_list_.push_back(scope);
|
||||
|
|
|
|||
17
elab_sig.cc
17
elab_sig.cc
|
|
@ -387,9 +387,20 @@ bool PGenerate::elaborate_sig_direct_(Design*des, NetScope*container) const
|
|||
for (generate_it_t cur = generate_schemes.begin()
|
||||
; cur != generate_schemes.end() ; ++ cur ) {
|
||||
PGenerate*item = *cur;
|
||||
if (item->direct_nested_ || !item->scope_list_.empty()) {
|
||||
// Found the item, and it is direct nested.
|
||||
flag &= item->elaborate_sig(des, container);
|
||||
if (item->scheme_type == PGenerate::GS_CASE) {
|
||||
typedef list<PGenerate*>::const_iterator generate_it_t;
|
||||
for (generate_it_t icur = item->generate_schemes.begin()
|
||||
; icur != item->generate_schemes.end() ; ++ icur ) {
|
||||
PGenerate*case_item = *icur;
|
||||
if (case_item->direct_nested_ || !case_item->scope_list_.empty()) {
|
||||
flag &= case_item->elaborate_sig(des, container);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (item->direct_nested_ || !item->scope_list_.empty()) {
|
||||
// Found the item, and it is direct nested.
|
||||
flag &= item->elaborate_sig(des, container);
|
||||
}
|
||||
}
|
||||
}
|
||||
return flag;
|
||||
|
|
|
|||
50
elaborate.cc
50
elaborate.cc
|
|
@ -4539,15 +4539,18 @@ bool PGenerate::elaborate(Design*des, NetScope*container) const
|
|||
|
||||
bool flag = true;
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PGenerate::elaborate: "
|
||||
"generate " << scheme_type
|
||||
<< " elaborating in scope " << scope_path(container)
|
||||
<< "." << endl;
|
||||
}
|
||||
|
||||
// Handle the special case that this is a CASE scheme. In this
|
||||
// case the PGenerate itself does not have the generated
|
||||
// item. Look instead for the case ITEM that has a scope
|
||||
// generated for it.
|
||||
if (scheme_type == PGenerate::GS_CASE) {
|
||||
if (debug_elaborate)
|
||||
cerr << get_fileline() << ": debug: generate case"
|
||||
<< " elaborating in scope "
|
||||
<< scope_path(container) << "." << endl;
|
||||
|
||||
typedef list<PGenerate*>::const_iterator generate_it_t;
|
||||
for (generate_it_t cur = generate_schemes.begin()
|
||||
|
|
@ -4593,23 +4596,50 @@ bool PGenerate::elaborate(Design*des, NetScope*container) const
|
|||
|
||||
bool PGenerate::elaborate_direct_(Design*des, NetScope*container) const
|
||||
{
|
||||
if (debug_elaborate)
|
||||
bool flag = true;
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: "
|
||||
<< "Direct nesting elaborate in scope "
|
||||
<< scope_path(container) << "." << endl;
|
||||
<< scope_path(container)
|
||||
<< ", scheme_type=" << scheme_type << endl;
|
||||
}
|
||||
|
||||
// Elaborate for a direct nested generated scheme knows
|
||||
// that there are only sub_schemes to be elaborated. There
|
||||
// should be exactly 1 active generate scheme, search for it
|
||||
// using this loop.
|
||||
bool flag = true;
|
||||
typedef list<PGenerate*>::const_iterator generate_it_t;
|
||||
for (generate_it_t cur = generate_schemes.begin()
|
||||
; cur != generate_schemes.end() ; ++ cur ) {
|
||||
PGenerate*item = *cur;
|
||||
if (item->direct_nested_ || !item->scope_list_.empty()) {
|
||||
// Found the item, and it is direct nested.
|
||||
flag &= item->elaborate(des, container);
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PGenerate::elaborate_direct_: "
|
||||
<< "item->scope_name=" << item->scope_name
|
||||
<< ", item->scheme_type=" << item->scheme_type
|
||||
<< ", item->direct_nested_=" << item->direct_nested_
|
||||
<< ", item->scope_list_.size()=" << item->scope_list_.size()
|
||||
<< "." << endl;
|
||||
}
|
||||
|
||||
// Special case: If this is a case generate scheme, then
|
||||
// the PGenerate object (item) does not acctually
|
||||
// contain anything. Instead scan the case items, which
|
||||
// are listed as sub-schemes of the item.
|
||||
if (item->scheme_type == PGenerate::GS_CASE) {
|
||||
typedef list<PGenerate*>::const_iterator generate_it_t;
|
||||
for (generate_it_t icur = item->generate_schemes.begin()
|
||||
; icur != item->generate_schemes.end() ; ++ icur ) {
|
||||
PGenerate*case_item = *icur;
|
||||
if (case_item->direct_nested_ || !case_item->scope_list_.empty()) {
|
||||
flag &= case_item->elaborate(des, container);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (item->direct_nested_ || !item->scope_list_.empty()) {
|
||||
// Found the item, and it is direct nested.
|
||||
flag &= item->elaborate(des, container);
|
||||
}
|
||||
}
|
||||
}
|
||||
return flag;
|
||||
|
|
|
|||
4
main.cc
4
main.cc
|
|
@ -158,6 +158,7 @@ bool warn_inf_loop = false;
|
|||
bool warn_ob_select = false;
|
||||
bool warn_sens_entire_vec = false;
|
||||
bool warn_sens_entire_arr = false;
|
||||
bool warn_anachronisms = false;
|
||||
|
||||
/*
|
||||
* Debug message class flags.
|
||||
|
|
@ -667,6 +668,9 @@ static void read_iconfig_file(const char*ipath)
|
|||
case 'a':
|
||||
warn_sens_entire_arr = true;
|
||||
break;
|
||||
case 'n':
|
||||
warn_anachronisms = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -602,7 +602,11 @@ NetExpr* elab_sys_task_arg(Design*des, NetScope*scope, perm_string name,
|
|||
eval_expr(tmp, -1);
|
||||
|
||||
if (NetEConst*ce = dynamic_cast<NetEConst*>(tmp)) {
|
||||
if (mode != PExpr::SIZED)
|
||||
// For lossless/unsized constant expressions, we can now
|
||||
// determine the exact width required to hold the result.
|
||||
// But leave literal numbers exactly as the user supplied
|
||||
// them.
|
||||
if ((mode != PExpr::SIZED) && !dynamic_cast<PENumber*>(pe))
|
||||
ce->trim();
|
||||
}
|
||||
|
||||
|
|
|
|||
112
parse.y
112
parse.y
|
|
@ -66,6 +66,11 @@ static stack<PBlock*> current_block_stack;
|
|||
* simulation issues. */
|
||||
static unsigned args_after_notifier;
|
||||
|
||||
/* The rules sometimes push attributes into a global context where
|
||||
sub-rules may grab them. This makes parser rules a little easier to
|
||||
write in some cases. */
|
||||
static list<named_pexpr_t>*attributes_in_context = 0;
|
||||
|
||||
/* Later version of bison (including 1.35) will not compile in stack
|
||||
extension if the output is compiled with C++ and either the YYSTYPE
|
||||
or YYLTYPE are provided by the source code. However, I can get the
|
||||
|
|
@ -574,7 +579,8 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
|
|||
%type <event_expr> event_expression_list
|
||||
%type <event_expr> event_expression
|
||||
%type <event_statement> event_control
|
||||
%type <statement> statement statement_or_null compressed_statement
|
||||
%type <statement> statement statement_item statement_or_null
|
||||
%type <statement> compressed_statement
|
||||
%type <statement> loop_statement for_step jump_statement
|
||||
%type <statement_list> statement_or_null_list statement_or_null_list_opt
|
||||
|
||||
|
|
@ -749,7 +755,7 @@ class_item /* IEEE1800-2005: A.1.8 */
|
|||
cause a conflict. */
|
||||
| method_qualifier_opt K_function K_new '(' tf_port_list_opt ')' ';'
|
||||
function_item_list_opt
|
||||
implicit_class_handle '.' K_new '(' expression_list_with_nuls ')'
|
||||
attribute_list_opt implicit_class_handle '.' K_new '(' expression_list_with_nuls ')'
|
||||
statement_or_null_list_opt
|
||||
K_endfunction endnew_opt
|
||||
{ yyerror(@3, "sorry: Class constructors not supported yet.");
|
||||
|
|
@ -1316,13 +1322,20 @@ signing /* IEEE1800-2005: A.2.2.1 */
|
|||
| K_unsigned { $$ = false; }
|
||||
;
|
||||
|
||||
statement /* IEEE1800-2005: A.6.4 */
|
||||
: attribute_list_opt statement_item
|
||||
{ pform_bind_attributes($2->attributes, $1);
|
||||
$$ = $2;
|
||||
}
|
||||
;
|
||||
|
||||
/* Many places where statements are allowed can actually take a
|
||||
statement or a null statement marked with a naked semi-colon. */
|
||||
|
||||
statement_or_null /* IEEE1800-2005: A.6.4 */
|
||||
: statement
|
||||
{ $$ = $1; }
|
||||
| ';'
|
||||
| attribute_list_opt ';'
|
||||
{ $$ = 0; }
|
||||
;
|
||||
|
||||
|
|
@ -1797,35 +1810,31 @@ block_item_decl
|
|||
all the trappings of a general variable declaration. All of that
|
||||
is implicit in the "integer" of the declaration. */
|
||||
|
||||
: attribute_list_opt K_integer signed_unsigned_opt register_variable_list ';'
|
||||
{ pform_set_reg_integer($4);
|
||||
if ($1) delete $1;
|
||||
}
|
||||
: K_integer signed_unsigned_opt register_variable_list ';'
|
||||
{ pform_set_reg_integer($3, attributes_in_context);
|
||||
}
|
||||
|
||||
| attribute_list_opt K_time register_variable_list ';'
|
||||
{ pform_set_reg_time($3);
|
||||
if ($1) delete $1;
|
||||
}
|
||||
| K_time register_variable_list ';'
|
||||
{ pform_set_reg_time($2, attributes_in_context);
|
||||
}
|
||||
|
||||
/* variable declarations. Note that data_type can be 0 if we are
|
||||
recovering from an error. */
|
||||
|
||||
| attribute_list_opt data_type register_variable_list ';'
|
||||
{ if ($2) pform_set_data_type(@2, $2, $3);
|
||||
if ($1) delete $1;
|
||||
| data_type register_variable_list ';'
|
||||
{ if ($1) pform_set_data_type(@1, $1, $2, attributes_in_context);
|
||||
}
|
||||
|
||||
| attribute_list_opt K_reg data_type register_variable_list ';'
|
||||
{ if ($3) pform_set_data_type(@3, $3, $4);
|
||||
if ($1) delete $1;
|
||||
| K_reg data_type register_variable_list ';'
|
||||
{ if ($2) pform_set_data_type(@2, $2, $3, attributes_in_context);
|
||||
}
|
||||
|
||||
| K_event list_of_identifiers ';'
|
||||
{ pform_make_events($2, @1.text, @1.first_line);
|
||||
}
|
||||
| K_event list_of_identifiers ';'
|
||||
{ pform_make_events($2, @1.text, @1.first_line);
|
||||
}
|
||||
|
||||
| K_parameter parameter_assign_decl ';'
|
||||
| K_localparam localparam_assign_decl ';'
|
||||
| K_parameter parameter_assign_decl ';'
|
||||
| K_localparam localparam_assign_decl ';'
|
||||
|
||||
/* Blocks can have type declarations. */
|
||||
|
||||
|
|
@ -1833,15 +1842,16 @@ block_item_decl
|
|||
|
||||
/* Recover from errors that happen within variable lists. Use the
|
||||
trailing semi-colon to resync the parser. */
|
||||
| attribute_list_opt K_integer error ';'
|
||||
{ yyerror(@2, "error: syntax error in integer variable list.");
|
||||
yyerrok;
|
||||
if ($1) delete $1;
|
||||
}
|
||||
| attribute_list_opt K_time error ';'
|
||||
{ yyerror(@2, "error: syntax error in time variable list.");
|
||||
yyerrok;
|
||||
}
|
||||
|
||||
| K_integer error ';'
|
||||
{ yyerror(@1, "error: syntax error in integer variable list.");
|
||||
yyerrok;
|
||||
}
|
||||
|
||||
| K_time error ';'
|
||||
{ yyerror(@1, "error: syntax error in time variable list.");
|
||||
yyerrok;
|
||||
}
|
||||
|
||||
| K_parameter error ';'
|
||||
{ yyerror(@1, "error: syntax error in parameter list.");
|
||||
|
|
@ -4095,12 +4105,15 @@ module_item
|
|||
will see the discipline name as an identifier. We match it to the
|
||||
discipline or type name semantically. */
|
||||
| DISCIPLINE_IDENTIFIER list_of_identifiers ';'
|
||||
{ pform_attach_discipline(@1, $1, $2); }
|
||||
{ pform_attach_discipline(@1, $1, $2); }
|
||||
|
||||
/* block_item_decl rule is shared with task blocks and named
|
||||
begin/end. */
|
||||
begin/end. Careful to pass attributes to the block_item_decl. */
|
||||
|
||||
| block_item_decl
|
||||
| attribute_list_opt { attributes_in_context = $1; } block_item_decl
|
||||
{ delete attributes_in_context;
|
||||
attributes_in_context = 0;
|
||||
}
|
||||
|
||||
/* */
|
||||
|
||||
|
|
@ -4199,15 +4212,15 @@ module_item
|
|||
|
||||
/* Always and initial items are behavioral processes. */
|
||||
|
||||
| attribute_list_opt K_always statement
|
||||
| attribute_list_opt K_always statement_item
|
||||
{ PProcess*tmp = pform_make_behavior(IVL_PR_ALWAYS, $3, $1);
|
||||
FILE_NAME(tmp, @2);
|
||||
}
|
||||
| attribute_list_opt K_initial statement
|
||||
| attribute_list_opt K_initial statement_item
|
||||
{ PProcess*tmp = pform_make_behavior(IVL_PR_INITIAL, $3, $1);
|
||||
FILE_NAME(tmp, @2);
|
||||
}
|
||||
| attribute_list_opt K_final statement
|
||||
| attribute_list_opt K_final statement_item
|
||||
{ PProcess*tmp = pform_make_behavior(IVL_PR_FINAL, $3, $1);
|
||||
FILE_NAME(tmp, @2);
|
||||
}
|
||||
|
|
@ -4267,7 +4280,7 @@ module_item
|
|||
/* Handle some anachronistic syntax cases. */
|
||||
| K_generate K_begin module_item_list_opt K_end K_endgenerate
|
||||
{ /* Detect and warn about anachronistic begin/end use */
|
||||
if (generation_flag > GN_VER2001) {
|
||||
if (generation_flag > GN_VER2001 && warn_anachronisms) {
|
||||
warn_count += 1;
|
||||
cerr << @2 << ": warning: Anachronistic use of begin/end to surround generate schemes." << endl;
|
||||
}
|
||||
|
|
@ -4276,7 +4289,7 @@ module_item
|
|||
pform_start_generate_nblock(@2, $4);
|
||||
} module_item_list_opt K_end K_endgenerate
|
||||
{ /* Detect and warn about anachronistic named begin/end use */
|
||||
if (generation_flag > GN_VER2001) {
|
||||
if (generation_flag > GN_VER2001 && warn_anachronisms) {
|
||||
warn_count += 1;
|
||||
cerr << @2 << ": warning: Anachronistic use of named begin/end to surround generate schemes." << endl;
|
||||
}
|
||||
|
|
@ -5445,7 +5458,7 @@ spec_notifier
|
|||
;
|
||||
|
||||
|
||||
statement /* This is roughly statement_item in the LRM */
|
||||
statement_item /* This is roughly statement_item in the LRM */
|
||||
|
||||
/* assign and deassign statements are procedural code to do
|
||||
structural assignments, and to turn that structural assignment
|
||||
|
|
@ -5513,8 +5526,6 @@ statement /* This is roughly statement_item in the LRM */
|
|||
delete $6;
|
||||
$$ = tmp;
|
||||
}
|
||||
| K_begin error K_end
|
||||
{ yyerrok; }
|
||||
|
||||
/* fork-join blocks are very similar to begin-end blocks. In fact,
|
||||
from the parser's perspective there is no real difference. All we
|
||||
|
|
@ -5549,8 +5560,6 @@ statement /* This is roughly statement_item in the LRM */
|
|||
delete $6;
|
||||
$$ = tmp;
|
||||
}
|
||||
| K_fork error K_join
|
||||
{ yyerrok; }
|
||||
|
||||
| K_disable hierarchy_identifier ';'
|
||||
{ PDisable*tmp = new PDisable(*$2);
|
||||
|
|
@ -5630,29 +5639,26 @@ statement /* This is roughly statement_item in the LRM */
|
|||
$$ = tmp;
|
||||
}
|
||||
|
||||
| event_control attribute_list_opt statement_or_null
|
||||
| event_control statement_or_null
|
||||
{ PEventStatement*tmp = $1;
|
||||
if (tmp == 0) {
|
||||
yyerror(@1, "error: Invalid event control.");
|
||||
$$ = 0;
|
||||
} else {
|
||||
if ($3) pform_bind_attributes($3->attributes,$2);
|
||||
tmp->set_statement($3);
|
||||
tmp->set_statement($2);
|
||||
$$ = tmp;
|
||||
}
|
||||
}
|
||||
| '@' '*' attribute_list_opt statement_or_null
|
||||
| '@' '*' statement_or_null
|
||||
{ PEventStatement*tmp = new PEventStatement;
|
||||
FILE_NAME(tmp, @1);
|
||||
if ($4) pform_bind_attributes($4->attributes,$3);
|
||||
tmp->set_statement($4);
|
||||
tmp->set_statement($3);
|
||||
$$ = tmp;
|
||||
}
|
||||
| '@' '(' '*' ')' attribute_list_opt statement_or_null
|
||||
| '@' '(' '*' ')' statement_or_null
|
||||
{ PEventStatement*tmp = new PEventStatement;
|
||||
FILE_NAME(tmp, @1);
|
||||
if ($6) pform_bind_attributes($6->attributes,$5);
|
||||
tmp->set_statement($6);
|
||||
tmp->set_statement($5);
|
||||
$$ = tmp;
|
||||
}
|
||||
|
||||
|
|
|
|||
58
pform.cc
58
pform.cc
|
|
@ -1521,7 +1521,8 @@ static void pform_set_net_range(perm_string name,
|
|||
const list<pform_range_t>*range,
|
||||
bool signed_flag,
|
||||
ivl_variable_type_t dt,
|
||||
PWSRType rt)
|
||||
PWSRType rt,
|
||||
std::list<named_pexpr_t>*attr)
|
||||
{
|
||||
PWire*cur = pform_get_wire_in_scope(name);
|
||||
if (cur == 0) {
|
||||
|
|
@ -1541,17 +1542,20 @@ static void pform_set_net_range(perm_string name,
|
|||
|
||||
if (dt != IVL_VT_NO_TYPE)
|
||||
cur->set_data_type(dt);
|
||||
|
||||
pform_bind_attributes(cur->attributes, attr, true);
|
||||
}
|
||||
|
||||
void pform_set_net_range(list<perm_string>*names,
|
||||
list<pform_range_t>*range,
|
||||
bool signed_flag,
|
||||
ivl_variable_type_t dt)
|
||||
ivl_variable_type_t dt,
|
||||
std::list<named_pexpr_t>*attr)
|
||||
{
|
||||
for (list<perm_string>::iterator cur = names->begin()
|
||||
; cur != names->end() ; ++ cur ) {
|
||||
perm_string txt = *cur;
|
||||
pform_set_net_range(txt, range, signed_flag, dt, SR_NET);
|
||||
pform_set_net_range(txt, range, signed_flag, dt, SR_NET, attr);
|
||||
}
|
||||
|
||||
delete names;
|
||||
|
|
@ -2036,7 +2040,7 @@ void pform_makewire(const vlltype&li,
|
|||
pform_makewire(li, txt, type, pt, dt, attr);
|
||||
/* This has already been done for real variables. */
|
||||
if (dt != IVL_VT_REAL) {
|
||||
pform_set_net_range(txt, range, signed_flag, dt, rt);
|
||||
pform_set_net_range(txt, range, signed_flag, dt, rt, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2066,7 +2070,7 @@ void pform_makewire(const vlltype&li,
|
|||
/* This has already been done for real variables. */
|
||||
if (dt != IVL_VT_REAL) {
|
||||
pform_set_net_range(first->name, range, signed_flag, dt,
|
||||
SR_NET);
|
||||
SR_NET, 0);
|
||||
}
|
||||
|
||||
PWire*cur = pform_get_wire_in_scope(first->name);
|
||||
|
|
@ -2534,14 +2538,14 @@ void pform_set_port_type(const struct vlltype&li,
|
|||
perm_string txt = *cur;
|
||||
pform_set_port_type(txt, pt, li.text, li.first_line);
|
||||
pform_set_net_range(txt, range, signed_flag, IVL_VT_NO_TYPE,
|
||||
SR_PORT);
|
||||
SR_PORT, 0);
|
||||
}
|
||||
|
||||
delete names;
|
||||
delete range;
|
||||
}
|
||||
|
||||
static void pform_set_reg_integer(perm_string name)
|
||||
static void pform_set_reg_integer(perm_string name, list<named_pexpr_t>*attr)
|
||||
{
|
||||
PWire*cur = pform_get_make_wire_in_scope(name, NetNet::INTEGER, NetNet::NOT_A_PORT, IVL_VT_LOGIC);
|
||||
assert(cur);
|
||||
|
|
@ -2553,19 +2557,21 @@ static void pform_set_reg_integer(perm_string name)
|
|||
rlist.push_back(rng);
|
||||
cur->set_range(rlist, SR_NET);
|
||||
cur->set_signed(true);
|
||||
|
||||
pform_bind_attributes(cur->attributes, attr, true);
|
||||
}
|
||||
|
||||
void pform_set_reg_integer(list<perm_string>*names)
|
||||
void pform_set_reg_integer(list<perm_string>*names, list<named_pexpr_t>*attr)
|
||||
{
|
||||
for (list<perm_string>::iterator cur = names->begin()
|
||||
; cur != names->end() ; ++ cur ) {
|
||||
perm_string txt = *cur;
|
||||
pform_set_reg_integer(txt);
|
||||
pform_set_reg_integer(txt, attr);
|
||||
}
|
||||
delete names;
|
||||
}
|
||||
|
||||
static void pform_set_reg_time(perm_string name)
|
||||
static void pform_set_reg_time(perm_string name, list<named_pexpr_t>*attr)
|
||||
{
|
||||
PWire*cur = pform_get_make_wire_in_scope(name, NetNet::REG, NetNet::NOT_A_PORT, IVL_VT_LOGIC);
|
||||
assert(cur);
|
||||
|
|
@ -2576,19 +2582,21 @@ static void pform_set_reg_time(perm_string name)
|
|||
list<pform_range_t>rlist;
|
||||
rlist.push_back(rng);
|
||||
cur->set_range(rlist, SR_NET);
|
||||
|
||||
pform_bind_attributes(cur->attributes, attr, true);
|
||||
}
|
||||
|
||||
void pform_set_reg_time(list<perm_string>*names)
|
||||
void pform_set_reg_time(list<perm_string>*names, list<named_pexpr_t>*attr)
|
||||
{
|
||||
for (list<perm_string>::iterator cur = names->begin()
|
||||
; cur != names->end() ; ++ cur ) {
|
||||
perm_string txt = *cur;
|
||||
pform_set_reg_time(txt);
|
||||
pform_set_reg_time(txt, attr);
|
||||
}
|
||||
delete names;
|
||||
}
|
||||
|
||||
static void pform_set_integer_2atom(uint64_t width, bool signed_flag, perm_string name)
|
||||
static void pform_set_integer_2atom(uint64_t width, bool signed_flag, perm_string name, list<named_pexpr_t>*attr)
|
||||
{
|
||||
PWire*cur = pform_get_make_wire_in_scope(name, NetNet::REG, NetNet::NOT_A_PORT, IVL_VT_BOOL);
|
||||
assert(cur);
|
||||
|
|
@ -2601,14 +2609,15 @@ static void pform_set_integer_2atom(uint64_t width, bool signed_flag, perm_strin
|
|||
list<pform_range_t>rlist;
|
||||
rlist.push_back(rng);
|
||||
cur->set_range(rlist, SR_NET);
|
||||
pform_bind_attributes(cur->attributes, attr, true);
|
||||
}
|
||||
|
||||
void pform_set_integer_2atom(uint64_t width, bool signed_flag, list<perm_string>*names)
|
||||
static void pform_set_integer_2atom(uint64_t width, bool signed_flag, list<perm_string>*names, list<named_pexpr_t>*attr)
|
||||
{
|
||||
for (list<perm_string>::iterator cur = names->begin()
|
||||
; cur != names->end() ; ++ cur ) {
|
||||
perm_string txt = *cur;
|
||||
pform_set_integer_2atom(width, signed_flag, txt);
|
||||
pform_set_integer_2atom(width, signed_flag, txt, attr);
|
||||
}
|
||||
delete names;
|
||||
}
|
||||
|
|
@ -2617,32 +2626,32 @@ void pform_set_integer_2atom(uint64_t width, bool signed_flag, list<perm_string>
|
|||
* This function detects the derived class for the given type and
|
||||
* dispatches the type to the proper subtype function.
|
||||
*/
|
||||
void pform_set_data_type(const struct vlltype&li, data_type_t*data_type, list<perm_string>*names)
|
||||
void pform_set_data_type(const struct vlltype&li, data_type_t*data_type, list<perm_string>*names, list<named_pexpr_t>*attr)
|
||||
{
|
||||
if (atom2_type_t*atom2_type = dynamic_cast<atom2_type_t*> (data_type)) {
|
||||
pform_set_integer_2atom(atom2_type->type_code, atom2_type->signed_flag, names);
|
||||
pform_set_integer_2atom(atom2_type->type_code, atom2_type->signed_flag, names, attr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (struct_type_t*struct_type = dynamic_cast<struct_type_t*> (data_type)) {
|
||||
pform_set_struct_type(struct_type, names);
|
||||
pform_set_struct_type(struct_type, names, attr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (enum_type_t*enum_type = dynamic_cast<enum_type_t*> (data_type)) {
|
||||
pform_set_enum(li, enum_type, names);
|
||||
pform_set_enum(li, enum_type, names, attr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (vector_type_t*vec_type = dynamic_cast<vector_type_t*> (data_type)) {
|
||||
pform_set_net_range(names, vec_type->pdims.get(),
|
||||
vec_type->signed_flag,
|
||||
vec_type->base_type);
|
||||
vec_type->base_type, attr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (/*real_type_t*real_type =*/ dynamic_cast<real_type_t*> (data_type)) {
|
||||
pform_set_net_range(names, 0, true, IVL_VT_REAL);
|
||||
pform_set_net_range(names, 0, true, IVL_VT_REAL, attr);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -2655,7 +2664,7 @@ void pform_set_data_type(const struct vlltype&li, data_type_t*data_type, list<pe
|
|||
}
|
||||
|
||||
static void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type,
|
||||
perm_string name)
|
||||
perm_string name, std::list<named_pexpr_t>*attr)
|
||||
{
|
||||
(void) li; // The line information is not currently needed.
|
||||
PWire*cur = pform_get_make_wire_in_scope(name, NetNet::REG, NetNet::NOT_A_PORT, enum_type->base_type);
|
||||
|
|
@ -2667,9 +2676,10 @@ static void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type,
|
|||
assert(enum_type->range->size() == 1);
|
||||
cur->set_range(*enum_type->range, SR_NET);
|
||||
cur->set_enumeration(enum_type);
|
||||
pform_bind_attributes(cur->attributes, attr, true);
|
||||
}
|
||||
|
||||
void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type, list<perm_string>*names)
|
||||
void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type, list<perm_string>*names, std::list<named_pexpr_t>*attr)
|
||||
{
|
||||
// By definition, the base type can only be IVL_VT_LOGIC or
|
||||
// IVL_VT_BOOL.
|
||||
|
|
@ -2689,7 +2699,7 @@ void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type, list<perm_st
|
|||
for (list<perm_string>::iterator cur = names->begin()
|
||||
; cur != names->end() ; ++ cur) {
|
||||
perm_string txt = *cur;
|
||||
pform_set_enum(li, enum_type, txt);
|
||||
pform_set_enum(li, enum_type, txt, attr);
|
||||
}
|
||||
|
||||
delete names;
|
||||
|
|
|
|||
15
pform.h
15
pform.h
|
|
@ -292,18 +292,19 @@ extern void pform_set_port_type(const struct vlltype&li,
|
|||
extern void pform_set_net_range(list<perm_string>*names,
|
||||
list<pform_range_t>*,
|
||||
bool signed_flag,
|
||||
ivl_variable_type_t);
|
||||
ivl_variable_type_t,
|
||||
std::list<named_pexpr_t>*attr);
|
||||
extern void pform_set_reg_idx(perm_string name, PExpr*l, PExpr*r);
|
||||
extern void pform_set_reg_integer(list<perm_string>*names);
|
||||
extern void pform_set_reg_time(list<perm_string>*names);
|
||||
extern void pform_set_reg_integer(list<perm_string>*names, list<named_pexpr_t>*attr);
|
||||
extern void pform_set_reg_time(list<perm_string>*names, list<named_pexpr_t>*attr);
|
||||
|
||||
extern void pform_set_integer_2atom(uint64_t width, bool signed_flag, list<perm_string>*names);
|
||||
//XXXXextern void pform_set_integer_2atom(uint64_t width, bool signed_flag, list<perm_string>*names);
|
||||
|
||||
extern void pform_set_data_type(const struct vlltype&li, data_type_t*, list<perm_string>*names);
|
||||
extern void pform_set_data_type(const struct vlltype&li, data_type_t*, list<perm_string>*names, list<named_pexpr_t>*attr);
|
||||
|
||||
extern void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type, list<perm_string>*names);
|
||||
extern void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type, list<perm_string>*names, std::list<named_pexpr_t>*attr);
|
||||
|
||||
extern void pform_set_struct_type(struct_type_t*struct_type, list<perm_string>*names);
|
||||
extern void pform_set_struct_type(struct_type_t*struct_type, std::list<perm_string>*names, std::list<named_pexpr_t>*attr);
|
||||
|
||||
/* pform_set_attrib and pform_set_type_attrib exist to support the
|
||||
$attribute syntax, which can only set string values to
|
||||
|
|
|
|||
|
|
@ -48,18 +48,19 @@ static ivl_variable_type_t figure_struct_base_type(struct_type_t*struct_type)
|
|||
* out the base type of the packed variable. Elaboration, later on,
|
||||
* well figure out the rest.
|
||||
*/
|
||||
static void pform_set_packed_struct(struct_type_t*struct_type, perm_string name)
|
||||
static void pform_set_packed_struct(struct_type_t*struct_type, perm_string name, list<named_pexpr_t>*attr)
|
||||
{
|
||||
ivl_variable_type_t base_type = figure_struct_base_type(struct_type);
|
||||
|
||||
PWire*net = pform_get_make_wire_in_scope(name, NetNet::REG, NetNet::NOT_A_PORT, base_type);
|
||||
net->set_struct_type(struct_type);
|
||||
pform_bind_attributes(net->attributes, attr, true);
|
||||
}
|
||||
|
||||
static void pform_set_struct_type(struct_type_t*struct_type, perm_string name)
|
||||
static void pform_set_struct_type(struct_type_t*struct_type, perm_string name, list<named_pexpr_t>*attr)
|
||||
{
|
||||
if (struct_type->packed_flag) {
|
||||
pform_set_packed_struct(struct_type, name);
|
||||
pform_set_packed_struct(struct_type, name, attr);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -67,11 +68,11 @@ static void pform_set_struct_type(struct_type_t*struct_type, perm_string name)
|
|||
ivl_assert(*struct_type, 0);
|
||||
}
|
||||
|
||||
void pform_set_struct_type(struct_type_t*struct_type, list<perm_string>*names)
|
||||
void pform_set_struct_type(struct_type_t*struct_type, list<perm_string>*names, list<named_pexpr_t>*attr)
|
||||
{
|
||||
for (list<perm_string>::iterator cur = names->begin()
|
||||
; cur != names->end() ; ++ cur) {
|
||||
pform_set_struct_type(struct_type, *cur);
|
||||
pform_set_struct_type(struct_type, *cur, attr);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ iwidth:32
|
|||
sys_func:vpi/system.sft
|
||||
sys_func:vpi/v2005_math.sft
|
||||
sys_func:vpi/va_math.sft
|
||||
warnings:implicit
|
||||
warnings:ailnpstv
|
||||
debug:eval_tree
|
||||
debug:elaborate
|
||||
debug:elab_pexpr
|
||||
|
|
|
|||
|
|
@ -9,6 +9,6 @@
|
|||
#
|
||||
# NOTE: DO NOT INSTALL THIS FILE.
|
||||
|
||||
./ivl -v -Ctgt-stub/stub.conf -C./scripts/devel-stub.conf -Pa.pf -Na.net -fDLL=tgt-stub/stub.tgt foo.vl
|
||||
./ivl -v -Ctgt-stub/stub.conf -C./scripts/devel-stub.conf -Pa.pf -Na.net -fDLL=tgt-stub/stub.tgt foo.vl |& tee foo.log
|
||||
|
||||
echo "*** ivl command completed, rc=$?"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2011 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2012 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
|
||||
|
|
@ -703,11 +703,13 @@ static void draw_net_input_x(ivl_nexus_t nex,
|
|||
if ( (sw = ivl_nexus_ptr_switch(nptr)) ) {
|
||||
assert(island == 0 || island == ivl_switch_island(sw));
|
||||
island = ivl_switch_island(sw);
|
||||
if (nex == ivl_switch_a(sw))
|
||||
if (nex == ivl_switch_a(sw)) {
|
||||
nex_flags |= VVP_NEXUS_DATA_STR;
|
||||
island_input_flag = 0;
|
||||
else if (nex == ivl_switch_b(sw))
|
||||
} else if (nex == ivl_switch_b(sw)) {
|
||||
nex_flags |= VVP_NEXUS_DATA_STR;
|
||||
island_input_flag = 0;
|
||||
else if (island_input_flag == -1) {
|
||||
} else if (island_input_flag == -1) {
|
||||
assert(nex == ivl_switch_enable(sw));
|
||||
island_input_flag = 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#norootforbuild
|
||||
#
|
||||
%define rev_date 20111127
|
||||
%define rev_date 20120501
|
||||
# Normally, the suff-ix is %nil, meaning the suffix is to not be used.
|
||||
# But if the builder wants to make a suffixed package, he may set this
|
||||
# to a value (i.e. -test) to cause suffixes to be put in all the right
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2011 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2008-2012 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
|
||||
|
|
@ -31,6 +31,12 @@ class vvp_island_tran : public vvp_island {
|
|||
void run_island();
|
||||
};
|
||||
|
||||
enum tran_state_t {
|
||||
tran_disabled,
|
||||
tran_enabled,
|
||||
tran_unknown
|
||||
};
|
||||
|
||||
struct vvp_island_branch_tran : public vvp_island_branch {
|
||||
|
||||
vvp_island_branch_tran(vvp_net_t*en__, bool active_high__,
|
||||
|
|
@ -43,7 +49,7 @@ struct vvp_island_branch_tran : public vvp_island_branch {
|
|||
vvp_net_t*en;
|
||||
unsigned width, part, offset;
|
||||
bool active_high;
|
||||
bool enabled_flag;
|
||||
tran_state_t state;
|
||||
};
|
||||
|
||||
vvp_island_branch_tran::vvp_island_branch_tran(vvp_net_t*en__,
|
||||
|
|
@ -54,7 +60,7 @@ vvp_island_branch_tran::vvp_island_branch_tran(vvp_net_t*en__,
|
|||
: en(en__), width(width__), part(part__), offset(offset__),
|
||||
active_high(active_high__)
|
||||
{
|
||||
enabled_flag = en__ ? false : true;
|
||||
state = en__ ? tran_disabled : tran_enabled;
|
||||
}
|
||||
|
||||
static inline vvp_island_branch_tran* BRANCH_TRAN(vvp_island_branch*tmp)
|
||||
|
|
@ -73,7 +79,7 @@ void vvp_island_tran::run_island()
|
|||
{
|
||||
// Test to see if any of the branches are enabled. This loop
|
||||
// tests the enabled inputs for all the branches and caches
|
||||
// the results in the enabled_flag for each branch.
|
||||
// the results in the state for each branch.
|
||||
bool runnable = false;
|
||||
for (vvp_island_branch*cur = branches_ ; cur ; cur = cur->next_branch) {
|
||||
vvp_island_branch_tran*tmp = dynamic_cast<vvp_island_branch_tran*>(cur);
|
||||
|
|
@ -103,7 +109,7 @@ bool vvp_island_branch_tran::run_test_enabled()
|
|||
// If there is no ep port (no "enabled" input) then this is a
|
||||
// tran branch. Assume it is always enabled.
|
||||
if (ep == 0) {
|
||||
enabled_flag = true;
|
||||
state = tran_enabled;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -122,7 +128,6 @@ bool vvp_island_branch_tran::run_test_enabled()
|
|||
//
|
||||
// If the outvalue is nil, then we know that this port is a
|
||||
// .import after all, so just read the invalue.
|
||||
enabled_flag = false;
|
||||
vvp_bit4_t enable_val;
|
||||
if (ep->outvalue.size() != 0)
|
||||
enable_val = ep->outvalue.value(0).value();
|
||||
|
|
@ -131,14 +136,47 @@ bool vvp_island_branch_tran::run_test_enabled()
|
|||
else
|
||||
enable_val = ep->invalue.value(0).value();
|
||||
|
||||
if (active_high==true && enable_val != BIT4_1)
|
||||
return false;
|
||||
switch (enable_val) {
|
||||
case BIT4_0:
|
||||
state = active_high ? tran_disabled : tran_enabled;
|
||||
break;
|
||||
case BIT4_1:
|
||||
state = active_high ? tran_enabled : tran_disabled;
|
||||
break;
|
||||
default:
|
||||
state = tran_unknown;
|
||||
break;
|
||||
}
|
||||
return (state != tran_disabled);
|
||||
}
|
||||
|
||||
if (active_high==false && enable_val != BIT4_0)
|
||||
return false;
|
||||
// The IEEE standard does not specify the behaviour when a tranif control
|
||||
// input is 'x' or 'z'. We use the rules that are given for MOS switches.
|
||||
inline vvp_vector8_t resolve_ambiguous(const vvp_vector8_t&a,
|
||||
const vvp_vector8_t&b,
|
||||
tran_state_t state)
|
||||
{
|
||||
assert(a.size() == b.size());
|
||||
vvp_vector8_t out (a.size());
|
||||
|
||||
enabled_flag = true;
|
||||
return true;
|
||||
for (unsigned idx = 0 ; idx < out.size() ; idx += 1) {
|
||||
vvp_scalar_t a_bit = a.value(idx);
|
||||
vvp_scalar_t b_bit = b.value(idx);
|
||||
if (state == tran_unknown) {
|
||||
switch (b_bit.value()) {
|
||||
case BIT4_0:
|
||||
b_bit = vvp_scalar_t(BIT4_X, b_bit.strength0(), 0);
|
||||
break;
|
||||
case BIT4_1:
|
||||
b_bit = vvp_scalar_t(BIT4_X, 0, b_bit.strength1());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
out.set_bit(idx, resolve(a_bit, b_bit));
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
static void push_value_through_branches(const vvp_vector8_t&val,
|
||||
|
|
@ -149,8 +187,8 @@ static void push_value_through_branch(const vvp_vector8_t&val,
|
|||
{
|
||||
vvp_island_branch_tran*branch = BRANCH_TRAN(cur.ptr());
|
||||
|
||||
// If the branch is not enabled, skip.
|
||||
if (! branch->enabled_flag)
|
||||
// If the branch is disabled, skip.
|
||||
if (branch->state == tran_disabled)
|
||||
return;
|
||||
|
||||
unsigned src_ab = cur.port();
|
||||
|
|
@ -174,7 +212,8 @@ static void push_value_through_branch(const vvp_vector8_t&val,
|
|||
// previously collected (and resolved) for the port.
|
||||
if (branch->width == 0) {
|
||||
// There are no part selects.
|
||||
dst_port->value = resolve(dst_port->value, val);
|
||||
dst_port->value = resolve_ambiguous(dst_port->value, val,
|
||||
branch->state);
|
||||
|
||||
} else if (dst_ab == 1) {
|
||||
// The other side is a strict subset (part select)
|
||||
|
|
|
|||
|
|
@ -482,6 +482,9 @@ void vpiNextSimTime(void)
|
|||
{
|
||||
simulator_callback* cur;
|
||||
|
||||
assert(vpi_mode_flag == VPI_MODE_NONE);
|
||||
vpi_mode_flag = VPI_MODE_RWSYNC;
|
||||
|
||||
while (NextSimTime) {
|
||||
cur = NextSimTime;
|
||||
NextSimTime = dynamic_cast<simulator_callback*>(cur->next);
|
||||
|
|
@ -489,6 +492,7 @@ void vpiNextSimTime(void)
|
|||
delete cur;
|
||||
}
|
||||
|
||||
vpi_mode_flag = VPI_MODE_NONE;
|
||||
}
|
||||
|
||||
static simulator_callback* make_prepost(p_cb_data data)
|
||||
|
|
|
|||
Loading…
Reference in New Issue