Merge branch 'v10-branch' of github.com:steveicarus/iverilog into v10-branch

This commit is contained in:
Stephen Williams 2018-07-24 09:37:50 -07:00
commit c831ce0aae
47 changed files with 570 additions and 325 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999-2011 Stephen Williams (steve@icarus.com) * Copyright (c) 1999-2017 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -26,11 +26,6 @@
# include "verinum.h" # include "verinum.h"
# include "netmisc.h" # include "netmisc.h"
bool dly_used_no_timescale = false;
bool dly_used_timescale = false;
bool display_ts_dly_warning = true;
PDelays::PDelays() PDelays::PDelays()
{ {
delete_flag_ = true; delete_flag_ = true;
@ -80,19 +75,7 @@ static NetExpr*calculate_val(Design*des, NetScope*scope, PExpr*expr)
{ {
NetExpr*dex = elab_and_eval(des, scope, expr, -1); NetExpr*dex = elab_and_eval(des, scope, expr, -1);
/* Print a warning if we find default and `timescale based check_for_inconsistent_delays(scope);
* delays in the design, since this is likely an error. */
if (scope->time_from_timescale()) dly_used_timescale = true;
else dly_used_no_timescale = true;
if (display_ts_dly_warning &&
dly_used_no_timescale && dly_used_timescale) {
cerr << "warning: Found both default and "
"`timescale based delays. Use" << endl;
cerr << " -Wtimescale to find the "
"module(s) with no `timescale." << endl;
display_ts_dly_warning = false;
}
/* If the delay expression is a real constant or vector /* If the delay expression is a real constant or vector
constant, then evaluate it, scale it to the local time constant, then evaluate it, scale it to the local time

View File

@ -4,7 +4,7 @@
%{ %{
/* /*
* Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com) * Copyright (c) 2001-2017 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -252,7 +252,7 @@ void destroy_lexor(void)
{ {
# ifdef FLEX_SCANNER # ifdef FLEX_SCANNER
# if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5 # if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5
# if defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9 # if YY_FLEX_MINOR_VERSION > 5 || defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
yylex_destroy(); yylex_destroy();
# endif # endif
# endif # endif

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999-2016 Stephen Williams (steve@icarus.com) * Copyright (c) 1999-2018 Stephen Williams (steve@icarus.com)
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com) * Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
@ -1446,6 +1446,13 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope,
return 0; return 0;
} }
if (!type_is_vectorable(expr_type_)) {
cerr << get_fileline() << ": error: The argument to "
<< name << " must be a vector type." << endl;
des->errors += 1;
return 0;
}
if (debug_elaborate) { if (debug_elaborate) {
cerr << get_fileline() << ": PECallFunction::elaborate_sfunc_: " cerr << get_fileline() << ": PECallFunction::elaborate_sfunc_: "
<< name << " expression is the argument cast to expr_wid=" << expr_wid << endl; << name << " expression is the argument cast to expr_wid=" << expr_wid << endl;
@ -3440,29 +3447,41 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
} }
if (net == 0) { if (net == 0) {
cerr << get_fileline() << ": internal error: " cerr << get_fileline() << ": error: Unable to bind variable `"
<< "Expecting idents with ntype to be signals." << endl; << path_ << "' in `" << scope_path(use_scope) << "'" << endl;
des->errors += 1; des->errors += 1;
return 0; return 0;
} }
if (! ntype->type_compatible(net->net_type())) { if (const netdarray_t*array_type = dynamic_cast<const netdarray_t*> (ntype)) {
cerr << get_fileline() << ": internal_error: " if (array_type->type_compatible(net->net_type())) {
<< "net type doesn't match context type." << endl; NetESignal*tmp = new NetESignal(net);
tmp->set_line(*this);
return tmp;
}
cerr << get_fileline() << ": : " // Icarus allows a dynamic array to be initialised with a
<< "net type="; // single elementary value, so try that next.
ntype = array_type->element_type();
}
if (! ntype->type_compatible(net->net_type())) {
cerr << get_fileline() << ": error: the type of the variable '"
<< path_ << "' doesn't match the context type." << endl;
cerr << get_fileline() << ": : " << "variable type=";
if (net->net_type()) if (net->net_type())
net->net_type()->debug_dump(cerr); net->net_type()->debug_dump(cerr);
else else
cerr << "<nil>"; cerr << "<nil>";
cerr << endl; cerr << endl;
cerr << get_fileline() << ": : " cerr << get_fileline() << ": : " << "context type=";
<< "context type=";
ivl_assert(*this, ntype); ivl_assert(*this, ntype);
ntype->debug_dump(cerr); ntype->debug_dump(cerr);
cerr << endl; cerr << endl;
des->errors += 1;
return 0;
} }
ivl_assert(*this, ntype->type_compatible(net->net_type())); ivl_assert(*this, ntype->type_compatible(net->net_type()));
@ -5318,9 +5337,8 @@ NetExpr* PENewArray::elaborate_expr(Design*des, NetScope*scope,
// expression. Elaborate the expression as an element // expression. Elaborate the expression as an element
// type. The run-time will assign this value to each element. // type. The run-time will assign this value to each element.
const netarray_t*array_type = dynamic_cast<const netarray_t*> (ntype); const netarray_t*array_type = dynamic_cast<const netarray_t*> (ntype);
ivl_type_t elem_type = array_type->element_type();
init_val = init_->elaborate_expr(des, scope, elem_type, flags); init_val = init_->elaborate_expr(des, scope, array_type, flags);
} }
NetENew*tmp = new NetENew(ntype, size, init_val); NetENew*tmp = new NetENew(ntype, size, init_val);
@ -5571,6 +5589,10 @@ unsigned PENumber::test_width(Design*, NetScope*, width_mode_t&mode)
NetExpr* PENumber::elaborate_expr(Design*des, NetScope*, ivl_type_t ntype, unsigned) const NetExpr* PENumber::elaborate_expr(Design*des, NetScope*, ivl_type_t ntype, unsigned) const
{ {
// Icarus allows dynamic arrays to be initialised with a single value.
if (const netdarray_t*array_type = dynamic_cast<const netdarray_t*> (ntype))
ntype = array_type->element_type();
const netvector_t*use_type = dynamic_cast<const netvector_t*> (ntype); const netvector_t*use_type = dynamic_cast<const netvector_t*> (ntype);
if (use_type == 0) { if (use_type == 0) {
cerr << get_fileline() << ": internal error: " cerr << get_fileline() << ": internal error: "

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2000-2016 Stephen Williams (steve@icarus.com) * Copyright (c) 2000-2017 Stephen Williams (steve@icarus.com)
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com) * Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
@ -509,8 +509,10 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
netclass_t*use_base_class = 0; netclass_t*use_base_class = 0;
if (base_class) { if (base_class) {
ivl_assert(*pclass, scope); if (scope)
use_base_class = scope->find_class(base_class->name); use_base_class = scope->find_class(base_class->name);
if (use_base_class == 0)
use_base_class = des->find_class(base_class->name);
if (use_base_class == 0) { if (use_base_class == 0) {
cerr << pclass->get_fileline() << ": error: " cerr << pclass->get_fileline() << ": error: "
<< "Base class " << base_class->name << "Base class " << base_class->name
@ -605,13 +607,9 @@ static void elaborate_scope_classes(Design*des, NetScope*scope,
void elaborate_rootscope_classes(Design*des) void elaborate_rootscope_classes(Design*des)
{ {
if (pform_classes.empty()) for (size_t idx = 0 ; idx < pform_classes.size() ; idx += 1) {
return; blend_class_constructors(pform_classes[idx]);
elaborate_scope_class(des, 0, pform_classes[idx]);
for (map<perm_string,PClass*>::iterator cur = pform_classes.begin()
; cur != pform_classes.end() ; ++ cur) {
blend_class_constructors(cur->second);
elaborate_scope_class(des, 0, cur->second);
} }
} }

View File

@ -2374,19 +2374,7 @@ static NetExpr*elaborate_delay_expr(PExpr*expr, Design*des, NetScope*scope)
{ {
NetExpr*dex = elab_and_eval(des, scope, expr, -1); NetExpr*dex = elab_and_eval(des, scope, expr, -1);
/* Print a warning if we find default and `timescale based check_for_inconsistent_delays(scope);
* delays in the design, since this is likely an error. */
if (scope->time_from_timescale()) dly_used_timescale = true;
else dly_used_no_timescale = true;
if (display_ts_dly_warning &&
dly_used_no_timescale && dly_used_timescale) {
cerr << "warning: Found both default and "
"`timescale based delays. Use" << endl;
cerr << " -Wtimescale to find the "
"module(s) with no `timescale." << endl;
display_ts_dly_warning = false;
}
/* If the delay expression is a real constant or vector /* If the delay expression is a real constant or vector
constant, then evaluate it, scale it to the local time constant, then evaluate it, scale it to the local time
@ -5434,19 +5422,7 @@ void PSpecPath::elaborate(Design*des, NetScope*scope) const
ndelays = delays.size(); ndelays = delays.size();
if (ndelays > 12) ndelays = 12; if (ndelays > 12) ndelays = 12;
/* Print a warning if we find default and `timescale based check_for_inconsistent_delays(scope);
* delays in the design, since this is likely an error. */
if (scope->time_from_timescale()) dly_used_timescale = true;
else dly_used_no_timescale = true;
if (display_ts_dly_warning &&
dly_used_no_timescale && dly_used_timescale) {
cerr << "warning: Found both default and "
"`timescale based delays. Use" << endl;
cerr << " -Wtimescale to find the "
"module(s) with no `timescale." << endl;
display_ts_dly_warning = false;
}
/* Elaborate the delay values themselves. Remember to scale /* Elaborate the delay values themselves. Remember to scale
them for the timescale/precision of the scope. */ them for the timescale/precision of the scope. */

View File

@ -2100,7 +2100,7 @@ void destroy_lexor(void)
{ {
# ifdef FLEX_SCANNER # ifdef FLEX_SCANNER
# if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5 # if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5
# if defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9 # if YY_FLEX_MINOR_VERSION > 5 || defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
yylex_destroy(); yylex_destroy();
# endif # endif
# endif # endif

View File

@ -1606,7 +1606,7 @@ void destroy_lexor()
{ {
# ifdef FLEX_SCANNER # ifdef FLEX_SCANNER
# if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5 # if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5
# if defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9 # if YY_FLEX_MINOR_VERSION > 5 || defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
yylex_destroy(); yylex_destroy();
# endif # endif
# endif # endif

View File

@ -32,8 +32,8 @@ static unsigned string_pool_count = 0;
StringHeap::StringHeap() StringHeap::StringHeap()
{ {
cell_base_ = 0; cell_base_ = 0;
cell_ptr_ = HEAPCELL; cell_size_ = 0;
cell_count_ = 0; cell_ptr_ = 0;
} }
StringHeap::~StringHeap() StringHeap::~StringHeap()
@ -45,20 +45,24 @@ StringHeap::~StringHeap()
const char* StringHeap::add(const char*text) const char* StringHeap::add(const char*text)
{ {
unsigned len = strlen(text); unsigned len = strlen(text);
assert((len+1) <= HEAPCELL); unsigned rem = cell_size_ - cell_ptr_;
unsigned rem = HEAPCELL - cell_ptr_;
if (rem < (len+1)) { if (rem < (len+1)) {
cell_base_ = (char*)malloc(HEAPCELL); // release any unused memory
if (rem > 0) {
cell_base_ = (char*)realloc(cell_base_, cell_ptr_);
assert(cell_base_ != 0);
}
// start new cell
cell_size_ = (len+1) > DEFAULT_CELL_SIZE ? len+1 : DEFAULT_CELL_SIZE;
cell_base_ = (char*)malloc(cell_size_);
cell_ptr_ = 0;
assert(cell_base_ != 0);
#ifdef CHECK_WITH_VALGRIND #ifdef CHECK_WITH_VALGRIND
string_pool_count += 1; string_pool_count += 1;
string_pool = (char **) realloc(string_pool, string_pool = (char **) realloc(string_pool,
string_pool_count*sizeof(char **)); string_pool_count*sizeof(char **));
string_pool[string_pool_count-1] = cell_base_; string_pool[string_pool_count-1] = cell_base_;
#endif #endif
cell_ptr_ = 0;
cell_count_ += 1;
assert(cell_base_ != 0);
} }
char*res = cell_base_ + cell_ptr_; char*res = cell_base_ + cell_ptr_;
@ -66,7 +70,7 @@ const char* StringHeap::add(const char*text)
cell_ptr_ += len; cell_ptr_ += len;
cell_base_[cell_ptr_++] = 0; cell_base_[cell_ptr_++] = 0;
assert(cell_ptr_ <= HEAPCELL); assert(cell_ptr_ <= cell_size_);
return res; return res;
} }

View File

@ -78,11 +78,11 @@ class StringHeap {
perm_string make(const char*); perm_string make(const char*);
private: private:
enum { HEAPCELL = 0x10000 }; static const unsigned DEFAULT_CELL_SIZE = 0x10000;
char*cell_base_; char*cell_base_;
unsigned cell_size_;
unsigned cell_ptr_; unsigned cell_ptr_;
unsigned cell_count_;
private: // not implemented private: // not implemented
StringHeap(const StringHeap&); StringHeap(const StringHeap&);

View File

@ -1,5 +1,5 @@
const char COPYRIGHT[] = const char COPYRIGHT[] =
"Copyright (c) 1998-2015 Stephen Williams (steve@icarus.com)"; "Copyright (c) 1998-2017 Stephen Williams (steve@icarus.com)";
/* /*
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
@ -1037,9 +1037,8 @@ int main(int argc, char*argv[])
pform_dump(out, cur->second); pform_dump(out, cur->second);
} }
out << "PFORM DUMP $ROOT CLASSES:" << endl; out << "PFORM DUMP $ROOT CLASSES:" << endl;
for (map<perm_string,PClass*>::iterator cur = pform_classes.begin() for (size_t idx = 0 ; idx < pform_classes.size() ; idx += 1) {
; cur != pform_classes.end() ; ++ cur) { pform_dump(out, pform_classes[idx]);
pform_dump(out, cur->second);
} }
out << "PFORM DUMP PACKAGES:" << endl; out << "PFORM DUMP PACKAGES:" << endl;
for (map<perm_string,PPackage*>::iterator pac = pform_packages.begin() for (map<perm_string,PPackage*>::iterator pac = pform_packages.begin()

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012-2014 Stephen Williams (steve@icarus.com) * Copyright (c) 2012-2017 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -165,7 +165,8 @@ bool netclass_t::test_for_missing_initializers() const
NetScope*netclass_t::method_from_name(perm_string name) const NetScope*netclass_t::method_from_name(perm_string name) const
{ {
NetScope*task = class_scope_->child( hname_t(name) ); NetScope*task = class_scope_->child( hname_t(name) );
if (task == 0) return 0; if ((task == 0) && super_)
task = super_->method_from_name(name);
return task; return task;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1998-2015 Stephen Williams (steve@icarus.com) * Copyright (c) 1998-2017 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -2724,13 +2724,28 @@ DelayType NetProc::delay_type() const
DelayType NetBlock::delay_type() const DelayType NetBlock::delay_type() const
{ {
DelayType result = NO_DELAY; // A join_none has no delay.
if (type() == PARA_JOIN_NONE) return NO_DELAY;
DelayType result;
// A join_any has the minimum delay.
if (type() == PARA_JOIN_ANY) {
result = DEFINITE_DELAY;
for (const NetProc*cur = proc_first(); cur; cur = proc_next(cur)) {
DelayType dt = cur->delay_type();
if (dt < result) result = dt;
if (dt == NO_DELAY) break;
}
// A begin or join has the maximum delay.
} else {
result = NO_DELAY;
for (const NetProc*cur = proc_first(); cur; cur = proc_next(cur)) { for (const NetProc*cur = proc_first(); cur; cur = proc_next(cur)) {
DelayType dt = cur->delay_type(); DelayType dt = cur->delay_type();
if (dt > result) result = dt; if (dt > result) result = dt;
if (dt == DEFINITE_DELAY) break; if (dt == DEFINITE_DELAY) break;
} }
}
return result; return result;
} }
@ -2800,9 +2815,10 @@ DelayType NetPDelay::delay_type() const
return DEFINITE_DELAY; return DEFINITE_DELAY;
} else { } else {
if (statement_) { if (statement_) {
return statement_->delay_type(); return combine_delays(ZERO_DELAY,
statement_->delay_type());
} else { } else {
return NO_DELAY; return ZERO_DELAY;
} }
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com) * Copyright (c) 2001-2017 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -1665,3 +1665,38 @@ NetScope* find_method_containing_scope(const LineInfo&, NetScope*scope)
return scope; return scope;
} }
/*
* Print a warning if we find a mixture of default and explicit timescale
* based delays in the design, since this is likely an error.
*/
void check_for_inconsistent_delays(NetScope*scope)
{
static bool used_implicit_timescale = false;
static bool used_explicit_timescale = false;
static bool display_ts_dly_warning = true;
if (scope->time_from_timescale())
used_explicit_timescale = true;
else
used_implicit_timescale = true;
if (display_ts_dly_warning &&
used_explicit_timescale &&
used_implicit_timescale) {
if (gn_system_verilog()) {
cerr << "warning: Found both default and explicit "
"timescale based delays. Use" << endl;
cerr << " : -Wtimescale to find the design "
"element(s) with no explicit" << endl;
cerr << " : timescale." << endl;
} else {
cerr << "warning: Found both default and "
"`timescale based delays. Use" << endl;
cerr << " : -Wtimescale to find the "
"module(s) with no `timescale." << endl;
}
display_ts_dly_warning = false;
}
}

View File

@ -1,7 +1,7 @@
#ifndef IVL_netmisc_H #ifndef IVL_netmisc_H
#define IVL_netmisc_H #define IVL_netmisc_H
/* /*
* Copyright (c) 1999-2016 Stephen Williams (steve@icarus.com) * Copyright (c) 1999-2017 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -378,10 +378,6 @@ const char *human_readable_op(const char op, bool unary = false);
enum const_bool { C_NON, C_0, C_1, C_X }; enum const_bool { C_NON, C_0, C_1, C_X };
const_bool const_logical(const NetExpr*expr); const_bool const_logical(const NetExpr*expr);
extern bool dly_used_no_timescale;
extern bool dly_used_timescale;
extern bool display_ts_dly_warning;
/* /*
* When scaling a real value to a time we need to do some standard * When scaling a real value to a time we need to do some standard
* processing. * processing.
@ -409,4 +405,10 @@ extern void assign_unpacked_with_bufz(Design*des, NetScope*scope,
extern NetPartSelect* detect_partselect_lval(Link&pin); extern NetPartSelect* detect_partselect_lval(Link&pin);
/*
* Print a warning if we find a mixture of default and explicit timescale
* based delays in the design, since this is likely an error.
*/
extern void check_for_inconsistent_delays(NetScope*scope);
#endif /* IVL_netmisc_H */ #endif /* IVL_netmisc_H */

29
parse.y
View File

@ -598,7 +598,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
%type <tf_ports> function_item function_item_list function_item_list_opt %type <tf_ports> function_item function_item_list function_item_list_opt
%type <tf_ports> task_item task_item_list task_item_list_opt %type <tf_ports> task_item task_item_list task_item_list_opt
%type <tf_ports> tf_port_declaration tf_port_item tf_port_list tf_port_list_opt %type <tf_ports> tf_port_declaration tf_port_item tf_port_item_list tf_port_list tf_port_list_opt
%type <named_pexpr> modport_simple_port port_name parameter_value_byname %type <named_pexpr> modport_simple_port port_name parameter_value_byname
%type <named_pexprs> port_name_list parameter_value_byname_list %type <named_pexprs> port_name_list parameter_value_byname_list
@ -2044,7 +2044,10 @@ task_declaration /* IEEE1800-2005: A.2.7 */
| K_task lifetime_opt IDENTIFIER error K_endtask | K_task lifetime_opt IDENTIFIER error K_endtask
{ {
assert(current_task == 0); if (current_task) {
pform_pop_scope();
current_task = 0;
}
} }
endlabel_opt endlabel_opt
{ // Last step: check any closing name. This is done late so { // Last step: check any closing name. This is done late so
@ -2119,10 +2122,16 @@ tf_port_item /* IEEE1800-2005: A.2.7 */
: port_direction_opt data_type_or_implicit IDENTIFIER dimensions_opt tf_port_item_expr_opt : port_direction_opt data_type_or_implicit IDENTIFIER dimensions_opt tf_port_item_expr_opt
{ vector<pform_tf_port_t>*tmp; { vector<pform_tf_port_t>*tmp;
NetNet::PortType use_port_type = $1==NetNet::PIMPLICIT? NetNet::PINPUT : $1; NetNet::PortType use_port_type = $1;
if ((use_port_type == NetNet::PIMPLICIT) && (gn_system_verilog() || ($2 == 0)))
use_port_type = port_declaration_context.port_type;
perm_string name = lex_strings.make($3); perm_string name = lex_strings.make($3);
list<perm_string>* ilist = list_from_identifier($3); list<perm_string>* ilist = list_from_identifier($3);
if (use_port_type == NetNet::PIMPLICIT) {
yyerror(@1, "error: missing task/function port direction.");
use_port_type = NetNet::PINPUT; // for error recovery
}
if (($2 == 0) && ($1==NetNet::PIMPLICIT)) { if (($2 == 0) && ($1==NetNet::PIMPLICIT)) {
// Detect special case this is an undecorated // Detect special case this is an undecorated
// identifier and we need to get the declaration from // identifier and we need to get the declaration from
@ -2134,7 +2143,6 @@ tf_port_item /* IEEE1800-2005: A.2.7 */
port_declaration_context.data_type, port_declaration_context.data_type,
ilist); ilist);
} else { } else {
// Otherwise, the decorations for this identifier // Otherwise, the decorations for this identifier
// indicate the type. Save the type for any right // indicate the type. Save the type for any right
@ -2181,8 +2189,15 @@ tf_port_item_expr_opt
; ;
tf_port_list /* IEEE1800-2005: A.2.7 */ tf_port_list /* IEEE1800-2005: A.2.7 */
: { port_declaration_context.port_type = gn_system_verilog() ? NetNet::PINPUT : NetNet::PIMPLICIT;
port_declaration_context.data_type = 0;
}
tf_port_item_list
{ $$ = $2; }
;
: tf_port_list ',' tf_port_item tf_port_item_list
: tf_port_item_list ',' tf_port_item
{ vector<pform_tf_port_t>*tmp; { vector<pform_tf_port_t>*tmp;
if ($1 && $3) { if ($1 && $3) {
size_t s1 = $1->size(); size_t s1 = $1->size();
@ -2208,11 +2223,11 @@ tf_port_list /* IEEE1800-2005: A.2.7 */
{ yyerror(@2, "error: Syntax error in task/function port declaration."); { yyerror(@2, "error: Syntax error in task/function port declaration.");
$$ = $3; $$ = $3;
} }
| tf_port_list ',' | tf_port_item_list ','
{ yyerror(@2, "error: NULL port declarations are not allowed."); { yyerror(@2, "error: NULL port declarations are not allowed.");
$$ = $1; $$ = $1;
} }
| tf_port_list ';' | tf_port_item_list ';'
{ yyerror(@2, "error: ';' is an invalid port declaration separator."); { yyerror(@2, "error: ';' is an invalid port declaration separator.");
$$ = $1; $$ = $1;
} }

View File

@ -1,7 +1,7 @@
#ifndef IVL_parse_api_H #ifndef IVL_parse_api_H
#define IVL_parse_api_H #define IVL_parse_api_H
/* /*
* Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com) * Copyright (c) 2001-2017 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -45,7 +45,7 @@ extern std::map<perm_string,PUdp*> pform_primitives;
extern std::map<perm_string,data_type_t*> pform_typedefs; extern std::map<perm_string,data_type_t*> pform_typedefs;
extern std::set<enum_type_t*> pform_enum_sets; extern std::set<enum_type_t*> pform_enum_sets;
extern std::map<perm_string,PTaskFunc*> pform_tasks; extern std::map<perm_string,PTaskFunc*> pform_tasks;
extern std::map<perm_string,PClass*> pform_classes; extern std::vector<PClass*> pform_classes;
extern std::map<perm_string,PPackage*> pform_packages; extern std::map<perm_string,PPackage*> pform_packages;
extern void pform_dump(std::ostream&out, const PClass*pac); extern void pform_dump(std::ostream&out, const PClass*pac);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com) * Copyright (c) 1998-2017 Stephen Williams (steve@icarus.com)
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com) * Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
@ -71,7 +71,7 @@ set<enum_type_t*>pform_enum_sets;
/* /*
* Class definitions in the $root scope go here. * Class definitions in the $root scope go here.
*/ */
map<perm_string,PClass*> pform_classes; vector<PClass*> pform_classes;
/* /*
* Task and function definitions in the $root scope go here. * Task and function definitions in the $root scope go here.
@ -467,7 +467,7 @@ PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name,
/* If no scope was found then this is being defined in the /* If no scope was found then this is being defined in the
* compilation unit scope. */ * compilation unit scope. */
if (scopex == 0) { if (scopex == 0) {
pform_classes[name] = class_scope; pform_classes.push_back(class_scope);
lexical_scope = class_scope; lexical_scope = class_scope;
return class_scope; return class_scope;
} }

View File

@ -281,6 +281,13 @@ ivl_scope_t dll_target::find_scope(ivl_design_s &des, const NetScope*cur)
return scope; return scope;
} }
for (map<const NetScope*,ivl_scope_t>::iterator idx = des.root_tasks.begin()
; idx != des.root_tasks.end() ; ++ idx) {
ivl_scope_t scope = find_scope_from_root(idx->second, cur);
if (scope)
return scope;
}
return 0; return 0;
} }

View File

@ -6,7 +6,7 @@
%{ %{
/* /*
* Copyright (C) 2011-2013 Stephen Williams (steve@icarus.com) * Copyright (C) 2011-2017 Stephen Williams (steve@icarus.com)
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -79,11 +79,14 @@ void init_fp_lexor(FILE*fd)
yyrestart(fd); yyrestart(fd);
} }
/*
* Modern version of flex (>=2.5.9) can clean up the scanner data.
*/
void destroy_fp_lexor() void destroy_fp_lexor()
{ {
# ifdef FLEX_SCANNER # ifdef FLEX_SCANNER
# if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5 # if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5
# if defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9 # if YY_FLEX_MINOR_VERSION > 5 || defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
yylex_destroy(); yylex_destroy();
# endif # endif
# endif # endif

View File

@ -82,6 +82,7 @@ static int eval_darray_new(ivl_expr_t ex)
unsigned idx; unsigned idx;
switch (ivl_type_base(element_type)) { switch (ivl_type_base(element_type)) {
case IVL_VT_BOOL: case IVL_VT_BOOL:
case IVL_VT_LOGIC:
for (idx = 0 ; idx < ivl_expr_parms(init_expr) ; idx += 1) { for (idx = 0 ; idx < ivl_expr_parms(init_expr) ; idx += 1) {
draw_eval_vec4(ivl_expr_parm(init_expr,idx)); draw_eval_vec4(ivl_expr_parm(init_expr,idx));
fprintf(vvp_out, " %%ix/load 3, %u, 0;\n", idx); fprintf(vvp_out, " %%ix/load 3, %u, 0;\n", idx);
@ -110,6 +111,11 @@ static int eval_darray_new(ivl_expr_t ex)
errors += 1; errors += 1;
break; break;
} }
} else if (init_expr && (ivl_expr_value(init_expr) == IVL_VT_DARRAY)) {
ivl_signal_t sig = ivl_expr_signal(init_expr);
fprintf(vvp_out, " %%load/obj v%p_0;\n", sig);
fprintf(vvp_out, " %%scopy;\n");
} else if (init_expr && number_is_immediate(size_expr,32,0)) { } else if (init_expr && number_is_immediate(size_expr,32,0)) {
/* In this case, there is an init expression, the /* In this case, there is an init expression, the
expression is NOT an array_pattern, and the size expression is NOT an array_pattern, and the size

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1998-2014 Stephen Williams (steve@icarus.com) * Copyright (c) 1998-2018 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -22,6 +22,7 @@
# include "verinum.h" # include "verinum.h"
# include <iostream> # include <iostream>
# include <cassert> # include <cassert>
# include <climits>
# include <cmath> // Needed to get pow for as_double(). # include <cmath> // Needed to get pow for as_double().
# include <cstdio> // Needed to get snprintf for as_string(). # include <cstdio> // Needed to get snprintf for as_string().
# include <algorithm> # include <algorithm>
@ -1444,7 +1445,8 @@ verinum operator / (const verinum&left, const verinum&right)
if (use_len <= (8*sizeof(long) - 1)) { if (use_len <= (8*sizeof(long) - 1)) {
long l = left.as_long(); long l = left.as_long();
long r = right.as_long(); long r = right.as_long();
long v = l / r; bool overflow = (l == LONG_MIN) && (r == -1);
long v = overflow ? LONG_MIN : l / r;
for (unsigned idx = 0 ; idx < use_len ; idx += 1) { for (unsigned idx = 0 ; idx < use_len ; idx += 1) {
result.set(idx, (v & 1)? verinum::V1 : verinum::V0); result.set(idx, (v & 1)? verinum::V1 : verinum::V0);
v >>= 1; v >>= 1;
@ -1518,7 +1520,8 @@ verinum operator % (const verinum&left, const verinum&right)
/* Use native signed modulus to do the work. */ /* Use native signed modulus to do the work. */
long l = left.as_long(); long l = left.as_long();
long r = right.as_long(); long r = right.as_long();
long v = l % r; bool overflow = (l == LONG_MIN) && (r == -1);
long v = overflow ? 0 : l % r;
for (unsigned idx = 0 ; idx < use_len ; idx += 1) { for (unsigned idx = 0 ; idx < use_len ; idx += 1) {
result.set(idx, (v & 1)? verinum::V1 : verinum::V0); result.set(idx, (v & 1)? verinum::V1 : verinum::V0);
v >>= 1; v >>= 1;

View File

@ -6,7 +6,7 @@
%{ %{
/* /*
* Copyright (c) 2011 Stephen Williams (steve@icarus.com) * Copyright (c) 2011-2017 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -751,7 +751,16 @@ yyscan_t prepare_lexor(FILE*fd)
return scanner; return scanner;
} }
/*
* Modern version of flex (>=2.5.9) can clean up the scanner data.
*/
void destroy_lexor(yyscan_t scanner) void destroy_lexor(yyscan_t scanner)
{ {
# ifdef FLEX_SCANNER
# if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5
# if YY_FLEX_MINOR_VERSION > 5 || defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
yylex_destroy(scanner); yylex_destroy(scanner);
# endif
# endif
# endif
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright CERN 2015 * Copyright CERN 2016-2018
* @author Maciej Suminski (maciej.suminski@cern.ch) * @author Maciej Suminski (maciej.suminski@cern.ch)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
@ -120,7 +120,7 @@ void preload_std_funcs(void)
std::list<InterfacePort*>*fn_integer_args = new std::list<InterfacePort*>(); std::list<InterfacePort*>*fn_integer_args = new std::list<InterfacePort*>();
fn_integer_args->push_back(new InterfacePort(&primitive_INTEGER)); fn_integer_args->push_back(new InterfacePort(&primitive_INTEGER));
fn_integer = new SubprogramBuiltin(perm_string::literal("integer"), fn_integer = new SubprogramBuiltin(perm_string::literal("integer"),
perm_string::literal("$signed"), perm_string::literal("int'"),
fn_integer_args, &primitive_INTEGER); fn_integer_args, &primitive_INTEGER);
std_subprograms[fn_integer->name()] = fn_integer; std_subprograms[fn_integer->name()] = fn_integer;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2015 Tony Bybell. * Copyright (c) 2009-2018 Tony Bybell.
* *
* Permission is hereby granted, free of charge, to any person obtaining a * Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"), * copy of this software and associated documentation files (the "Software"),
@ -128,6 +128,7 @@ void **JenkinsIns(void *base_i, const unsigned char *mem, uint32_t length, uint3
#include <sys/sysctl.h> #include <sys/sysctl.h>
#endif #endif
#define FST_APIMESS "FSTAPI | "
/***********************/ /***********************/
/*** ***/ /*** ***/
@ -193,7 +194,7 @@ if(nam) /* cppcheck warning fix: nam is always defined, so this is not needed */
dwRetVal = GetTempPath(MAX_PATH, lpTempPathBuffer); dwRetVal = GetTempPath(MAX_PATH, lpTempPathBuffer);
if((dwRetVal > MAX_PATH) || (dwRetVal == 0)) if((dwRetVal > MAX_PATH) || (dwRetVal == 0))
{ {
fprintf(stderr, "GetTempPath() failed in "__FILE__" line %d, exiting.\n", __LINE__); fprintf(stderr, FST_APIMESS"GetTempPath() failed in "__FILE__" line %d, exiting.\n", __LINE__);
exit(255); exit(255);
} }
else else
@ -201,7 +202,7 @@ if(nam) /* cppcheck warning fix: nam is always defined, so this is not needed */
uRetVal = GetTempFileName(lpTempPathBuffer, TEXT("FSTW"), 0, szTempFileName); uRetVal = GetTempFileName(lpTempPathBuffer, TEXT("FSTW"), 0, szTempFileName);
if (uRetVal == 0) if (uRetVal == 0)
{ {
fprintf(stderr, "GetTempFileName() failed in "__FILE__" line %d, exiting.\n", __LINE__); fprintf(stderr, FST_APIMESS"GetTempFileName() failed in "__FILE__" line %d, exiting.\n", __LINE__);
exit(255); exit(255);
} }
else else
@ -803,7 +804,7 @@ if(rc<0)
{ {
xc->fseek_failed = 1; xc->fseek_failed = 1;
#ifdef FST_DEBUG #ifdef FST_DEBUG
fprintf(stderr, "Seek to #%"PRId64" (whence = %d) failed!\n", offset, whence); fprintf(stderr, FST_APIMESS"Seek to #%"PRId64" (whence = %d) failed!\n", offset, whence);
perror("Why"); perror("Why");
#endif #endif
} }
@ -1663,7 +1664,7 @@ if(zerocnt)
/* fpos += */ fstWriterVarint(f, (zerocnt << 1)); /* scan-build */ /* fpos += */ fstWriterVarint(f, (zerocnt << 1)); /* scan-build */
} }
#ifdef FST_DEBUG #ifdef FST_DEBUG
fprintf(stderr, "value chains: %d\n", cnt); fprintf(stderr, FST_APIMESS"value chains: %d\n", cnt);
#endif #endif
xc->vchg_mem[0] = '!'; xc->vchg_mem[0] = '!';
@ -1738,7 +1739,7 @@ if(xc->dump_size_limit)
xc2->size_limit_locked = 1; xc2->size_limit_locked = 1;
xc2->is_initial_time = 1; /* to trick emit value and emit time change */ xc2->is_initial_time = 1; /* to trick emit value and emit time change */
#ifdef FST_DEBUG #ifdef FST_DEBUG
fprintf(stderr, "<< dump file size limit reached, stopping dumping >>\n"); fprintf(stderr, FST_APIMESS"<< dump file size limit reached, stopping dumping >>\n");
#endif #endif
} }
} }
@ -2478,7 +2479,7 @@ if(xc)
#ifndef FST_WRITER_PARALLEL #ifndef FST_WRITER_PARALLEL
if(xc->parallel_enabled) if(xc->parallel_enabled)
{ {
fprintf(stderr, "ERROR: fstWriterSetParallelMode(), FST_WRITER_PARALLEL not enabled during compile, exiting.\n"); fprintf(stderr, FST_APIMESS"fstWriterSetParallelMode(), FST_WRITER_PARALLEL not enabled during compile, exiting.\n");
exit(255); exit(255);
} }
#endif #endif
@ -2760,7 +2761,7 @@ if((xc) && (handle <= xc->maxhandle))
xc->vchg_mem = realloc(xc->vchg_mem, xc->vchg_alloc_siz); xc->vchg_mem = realloc(xc->vchg_mem, xc->vchg_alloc_siz);
if(!xc->vchg_mem) if(!xc->vchg_mem)
{ {
fprintf(stderr, "FATAL ERROR, could not realloc() in fstWriterEmitValueChange, exiting.\n"); fprintf(stderr, FST_APIMESS"Could not realloc() in fstWriterEmitValueChange, exiting.\n");
exit(255); exit(255);
} }
} }
@ -2874,7 +2875,7 @@ if((xc) && (handle <= xc->maxhandle))
xc->vchg_mem = realloc(xc->vchg_mem, xc->vchg_alloc_siz); xc->vchg_mem = realloc(xc->vchg_mem, xc->vchg_alloc_siz);
if(!xc->vchg_mem) if(!xc->vchg_mem)
{ {
fprintf(stderr, "FATAL ERROR, could not realloc() in fstWriterEmitVariableLengthValueChange, exiting.\n"); fprintf(stderr, FST_APIMESS"Could not realloc() in fstWriterEmitVariableLengthValueChange, exiting.\n");
exit(255); exit(255);
} }
} }
@ -3119,7 +3120,7 @@ if(rc<0)
{ {
xc->fseek_failed = 1; xc->fseek_failed = 1;
#ifdef FST_DEBUG #ifdef FST_DEBUG
fprintf(stderr, "Seek to #%"PRId64" (whence = %d) failed!\n", offset, whence); fprintf(stderr, FST_APIMESS"Seek to #%"PRId64" (whence = %d) failed!\n", offset, whence);
perror("Why"); perror("Why");
#endif #endif
} }
@ -3748,6 +3749,10 @@ if(!xc->fh)
else /* FST_BL_SKIP */ else /* FST_BL_SKIP */
{ {
pass_status = 0; pass_status = 0;
if(xc->fh)
{
fclose(xc->fh); xc->fh = NULL; /* needed in case .hier file is missing and there are no hier sections */
}
} }
free(mem); free(mem);
@ -4435,7 +4440,7 @@ if(gzread_pass_status)
if(rc != Z_OK) if(rc != Z_OK)
{ {
printf("geom uncompress rc = %d\n", rc); fprintf(stderr, FST_APIMESS"fstReaderInit(), geom uncompress rc = %d, exiting.\n", rc);
exit(255); exit(255);
} }
@ -4726,7 +4731,7 @@ for(;;)
if((sectype == EOF) || (sectype == FST_BL_SKIP)) if((sectype == EOF) || (sectype == FST_BL_SKIP))
{ {
#ifdef FST_DEBUG #ifdef FST_DEBUG
fprintf(stderr, "<< EOF >>\n"); fprintf(stderr, FST_APIMESS"<< EOF >>\n");
#endif #endif
break; break;
} }
@ -4765,9 +4770,9 @@ for(;;)
mem_required_for_traversal = fstReaderUint64(xc->f); mem_required_for_traversal = fstReaderUint64(xc->f);
mem_for_traversal = malloc(mem_required_for_traversal + 66); /* add in potential fastlz overhead */ mem_for_traversal = malloc(mem_required_for_traversal + 66); /* add in potential fastlz overhead */
#ifdef FST_DEBUG #ifdef FST_DEBUG
fprintf(stderr, "sec: %u seclen: %d begtim: %d endtim: %d\n", fprintf(stderr, FST_APIMESS"sec: %u seclen: %d begtim: %d endtim: %d\n",
secnum, (int)seclen, (int)beg_tim, (int)end_tim); secnum, (int)seclen, (int)beg_tim, (int)end_tim);
fprintf(stderr, "\tmem_required_for_traversal: %d\n", (int)mem_required_for_traversal); fprintf(stderr, FST_APIMESS"mem_required_for_traversal: %d\n", (int)mem_required_for_traversal);
#endif #endif
/* process time block */ /* process time block */
{ {
@ -4785,7 +4790,7 @@ for(;;)
tsec_clen = fstReaderUint64(xc->f); tsec_clen = fstReaderUint64(xc->f);
tsec_nitems = fstReaderUint64(xc->f); tsec_nitems = fstReaderUint64(xc->f);
#ifdef FST_DEBUG #ifdef FST_DEBUG
fprintf(stderr, "\ttime section unc: %d, com: %d (%d items)\n", fprintf(stderr, FST_APIMESS"time section unc: %d, com: %d (%d items)\n",
(int)tsec_uclen, (int)tsec_clen, (int)tsec_nitems); (int)tsec_uclen, (int)tsec_clen, (int)tsec_nitems);
#endif #endif
if(tsec_clen > seclen) break; /* corrupted tsec_clen: by definition it can't be larger than size of section */ if(tsec_clen > seclen) break; /* corrupted tsec_clen: by definition it can't be larger than size of section */
@ -4805,7 +4810,7 @@ for(;;)
if(rc != Z_OK) if(rc != Z_OK)
{ {
printf("tsec uncompress rc = %d\n", rc); fprintf(stderr, FST_APIMESS"fstReaderIterBlocks2(), tsec uncompress rc = %d, exiting.\n", rc);
exit(255); exit(255);
} }
@ -4881,7 +4886,7 @@ for(;;)
rc = uncompress(mu, &destlen, mc, sourcelen); rc = uncompress(mu, &destlen, mc, sourcelen);
if(rc != Z_OK) if(rc != Z_OK)
{ {
printf("rc: %d\n", rc); fprintf(stderr, FST_APIMESS"fstReaderIterBlocks2(), frame uncompress rc: %d, exiting.\n", rc);
exit(255); exit(255);
} }
free(mc); free(mc);
@ -5044,9 +5049,9 @@ for(;;)
packtype = fgetc(xc->f); packtype = fgetc(xc->f);
#ifdef FST_DEBUG #ifdef FST_DEBUG
fprintf(stderr, "\tframe_uclen: %d, frame_clen: %d, frame_maxhandle: %d\n", fprintf(stderr, FST_APIMESS"frame_uclen: %d, frame_clen: %d, frame_maxhandle: %d\n",
(int)frame_uclen, (int)frame_clen, (int)frame_maxhandle); (int)frame_uclen, (int)frame_clen, (int)frame_maxhandle);
fprintf(stderr, "\tvc_maxhandle: %d, packtype: %c\n", (int)vc_maxhandle, packtype); fprintf(stderr, FST_APIMESS"vc_maxhandle: %d, packtype: %c\n", (int)vc_maxhandle, packtype);
#endif #endif
indx_pntr = blkpos + seclen - 24 -tsec_clen -8; indx_pntr = blkpos + seclen - 24 -tsec_clen -8;
@ -5054,7 +5059,7 @@ for(;;)
chain_clen = fstReaderUint64(xc->f); chain_clen = fstReaderUint64(xc->f);
indx_pos = indx_pntr - chain_clen; indx_pos = indx_pntr - chain_clen;
#ifdef FST_DEBUG #ifdef FST_DEBUG
fprintf(stderr, "\tindx_pos: %d (%d bytes)\n", (int)indx_pos, (int)chain_clen); fprintf(stderr, FST_APIMESS"indx_pos: %d (%d bytes)\n", (int)indx_pos, (int)chain_clen);
#endif #endif
chain_cmem = malloc(chain_clen); chain_cmem = malloc(chain_clen);
if(!chain_cmem) goto block_err; if(!chain_cmem) goto block_err;
@ -5173,7 +5178,7 @@ for(;;)
} }
#ifdef FST_DEBUG #ifdef FST_DEBUG
fprintf(stderr, "\tdecompressed chain idx len: %"PRIu32"\n", idx); fprintf(stderr, FST_APIMESS"decompressed chain idx len: %"PRIu32"\n", idx);
#endif #endif
mc_mem_len = 16384; mc_mem_len = 16384;
@ -5241,7 +5246,7 @@ for(;;)
if(rc != Z_OK) if(rc != Z_OK)
{ {
printf("\tfac: %d clen: %d (rc=%d)\n", (int)i, (int)val, rc); fprintf(stderr, FST_APIMESS"fstReaderIterBlocks2(), fac: %d clen: %d (rc=%d), exiting.\n", (int)i, (int)val, rc);
exit(255); exit(255);
} }
@ -5793,9 +5798,9 @@ mem_required_for_traversal =
fstReaderUint64(xc->f); fstReaderUint64(xc->f);
#ifdef FST_DEBUG #ifdef FST_DEBUG
fprintf(stderr, "rvat sec: %u seclen: %d begtim: %d endtim: %d\n", fprintf(stderr, FST_APIMESS"rvat sec: %u seclen: %d begtim: %d endtim: %d\n",
secnum, (int)seclen, (int)beg_tim, (int)end_tim); secnum, (int)seclen, (int)beg_tim, (int)end_tim);
fprintf(stderr, "\tmem_required_for_traversal: %d\n", (int)mem_required_for_traversal); fprintf(stderr, FST_APIMESS"mem_required_for_traversal: %d\n", (int)mem_required_for_traversal);
#endif #endif
/* process time block */ /* process time block */
@ -5814,7 +5819,7 @@ tsec_uclen = fstReaderUint64(xc->f);
tsec_clen = fstReaderUint64(xc->f); tsec_clen = fstReaderUint64(xc->f);
tsec_nitems = fstReaderUint64(xc->f); tsec_nitems = fstReaderUint64(xc->f);
#ifdef FST_DEBUG #ifdef FST_DEBUG
fprintf(stderr, "\ttime section unc: %d, com: %d (%d items)\n", fprintf(stderr, FST_APIMESS"time section unc: %d, com: %d (%d items)\n",
(int)tsec_uclen, (int)tsec_clen, (int)tsec_nitems); (int)tsec_uclen, (int)tsec_clen, (int)tsec_nitems);
#endif #endif
ucdata = malloc(tsec_uclen); ucdata = malloc(tsec_uclen);
@ -5831,7 +5836,7 @@ if(tsec_uclen != tsec_clen)
if(rc != Z_OK) if(rc != Z_OK)
{ {
printf("tsec uncompress rc = %d\n", rc); fprintf(stderr, FST_APIMESS"fstReaderGetValueFromHandleAtTime(), tsec uncompress rc = %d, exiting.\n", rc);
exit(255); exit(255);
} }
@ -5879,7 +5884,7 @@ if(frame_uclen == frame_clen)
rc = uncompress(xc->rvat_frame_data, &destlen, mc, sourcelen); rc = uncompress(xc->rvat_frame_data, &destlen, mc, sourcelen);
if(rc != Z_OK) if(rc != Z_OK)
{ {
printf("decompress rc: %d\n", rc); fprintf(stderr, FST_APIMESS"fstReaderGetValueFromHandleAtTime(), frame decompress rc: %d, exiting.\n", rc);
exit(255); exit(255);
} }
free(mc); free(mc);
@ -5890,9 +5895,9 @@ xc->rvat_vc_start = ftello(xc->f); /* points to '!' character */
xc->rvat_packtype = fgetc(xc->f); xc->rvat_packtype = fgetc(xc->f);
#ifdef FST_DEBUG #ifdef FST_DEBUG
fprintf(stderr, "\tframe_uclen: %d, frame_clen: %d, frame_maxhandle: %d\n", fprintf(stderr, FST_APIMESS"frame_uclen: %d, frame_clen: %d, frame_maxhandle: %d\n",
(int)frame_uclen, (int)frame_clen, (int)xc->rvat_frame_maxhandle); (int)frame_uclen, (int)frame_clen, (int)xc->rvat_frame_maxhandle);
fprintf(stderr, "\tvc_maxhandle: %d\n", (int)xc->rvat_vc_maxhandle); fprintf(stderr, FST_APIMESS"vc_maxhandle: %d\n", (int)xc->rvat_vc_maxhandle);
#endif #endif
indx_pntr = blkpos + seclen - 24 -tsec_clen -8; indx_pntr = blkpos + seclen - 24 -tsec_clen -8;
@ -5900,7 +5905,7 @@ fstReaderFseeko(xc, xc->f, indx_pntr, SEEK_SET);
chain_clen = fstReaderUint64(xc->f); chain_clen = fstReaderUint64(xc->f);
indx_pos = indx_pntr - chain_clen; indx_pos = indx_pntr - chain_clen;
#ifdef FST_DEBUG #ifdef FST_DEBUG
fprintf(stderr, "\tindx_pos: %d (%d bytes)\n", (int)indx_pos, (int)chain_clen); fprintf(stderr, FST_APIMESS"indx_pos: %d (%d bytes)\n", (int)indx_pos, (int)chain_clen);
#endif #endif
chain_cmem = malloc(chain_clen); chain_cmem = malloc(chain_clen);
fstReaderFseeko(xc, xc->f, indx_pos, SEEK_SET); fstReaderFseeko(xc, xc->f, indx_pos, SEEK_SET);
@ -6011,7 +6016,7 @@ for(i=0;i<idx;i++)
} }
#ifdef FST_DEBUG #ifdef FST_DEBUG
fprintf(stderr, "\tdecompressed chain idx len: %"PRIu32"\n", idx); fprintf(stderr, FST_APIMESS"decompressed chain idx len: %"PRIu32"\n", idx);
#endif #endif
xc->rvat_data_valid = 1; xc->rvat_data_valid = 1;
@ -6071,7 +6076,7 @@ if(!xc->rvat_chain_mem)
if(rc != Z_OK) if(rc != Z_OK)
{ {
printf("\tclen: %d (rc=%d)\n", (int)xc->rvat_chain_len, rc); fprintf(stderr, FST_APIMESS"fstReaderGetValueFromHandleAtTime(), rvat decompress clen: %d (rc=%d), exiting.\n", (int)xc->rvat_chain_len, rc);
exit(255); exit(255);
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2015 Tony Bybell. * Copyright (c) 2009-2017 Tony Bybell.
* *
* Permission is hereby granted, free of charge, to any person obtaining a * Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"), * copy of this software and associated documentation files (the "Software"),
@ -168,7 +168,11 @@ enum fstHierType {
FST_HT_ATTRBEGIN = 3, FST_HT_ATTRBEGIN = 3,
FST_HT_ATTREND = 4, FST_HT_ATTREND = 4,
FST_HT_MAX = 4 /* FST_HT_TREEBEGIN and FST_HT_TREEEND are not yet used by FST but are currently used when fstHier bridges other formats */
FST_HT_TREEBEGIN = 5,
FST_HT_TREEEND = 6,
FST_HT_MAX = 6
}; };
enum fstAttrType { enum fstAttrType {

View File

@ -825,7 +825,7 @@ _next_match:
/* Match description too long : reduce it */ /* Match description too long : reduce it */
matchLength = (15-1) + (oMaxMatch-op) * 255; matchLength = (15-1) + (oMaxMatch-op) * 255;
} }
//printf("offset %5i, matchLength%5i \n", (int)(ip-match), matchLength + MINMATCH); /*printf("offset %5i, matchLength%5i \n", (int)(ip-match), matchLength + MINMATCH);*/
ip += MINMATCH + matchLength; ip += MINMATCH + matchLength;
if (matchLength>=ML_MASK) if (matchLength>=ML_MASK)

View File

@ -5,7 +5,7 @@
%{ %{
/* /*
* Copyright (c) 2007-2014 Stephen Williams (steve@icarus.com) * Copyright (c) 2007-2017 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -217,7 +217,7 @@ static void destroy_sdf_lexor(void)
{ {
# ifdef FLEX_SCANNER # ifdef FLEX_SCANNER
# if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5 # if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5
# if defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9 # if YY_FLEX_MINOR_VERSION > 5 || defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
yylex_destroy(); yylex_destroy();
# endif # endif
# endif # endif

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999-2015 Stephen Williams (steve@icarus.com) * Copyright (c) 1999-2017 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -1887,6 +1887,8 @@ static const char *pts_convert(int value)
{ {
const char *string; const char *string;
switch (value) { switch (value) {
case 2: string = "100s"; break;
case 1: string = "10s"; break;
case 0: string = "1s"; break; case 0: string = "1s"; break;
case -1: string = "100ms"; break; case -1: string = "100ms"; break;
case -2: string = "10ms"; break; case -2: string = "10ms"; break;

View File

@ -4,7 +4,7 @@
%{ %{
/* /*
* Copyright (c) 1999-2009 Stephen Williams (steve@icarus.com) * Copyright (c) 1999-2017 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -199,7 +199,7 @@ void destroy_readmem_lexor(void)
{ {
# ifdef FLEX_SCANNER # ifdef FLEX_SCANNER
# if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5 # if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5
# if defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9 # if YY_FLEX_MINOR_VERSION > 5 || defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
yylex_destroy(); yylex_destroy();
# endif # endif
# endif # endif

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2007-2014 Stephen Williams (steve@icarus.com) * Copyright (c) 2007-2017 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -289,7 +289,10 @@ static PLI_INT32 sys_sdf_annotate_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
FILE *sdf_fd; FILE *sdf_fd;
char *fname = get_filename(callh, name, vpi_scan(argv)); char *fname = get_filename(callh, name, vpi_scan(argv));
if (fname == 0) return 0; if (fname == 0) {
vpi_free_object(argv);
return 0;
}
sdf_fd = fopen(fname, "r"); sdf_fd = fopen(fname, "r");
if (sdf_fd == 0) { if (sdf_fd == 0) {
@ -297,6 +300,8 @@ static PLI_INT32 sys_sdf_annotate_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
(int)vpi_get(vpiLineNo, callh)); (int)vpi_get(vpiLineNo, callh));
vpi_printf("Unable to open SDF file \"%s\"." vpi_printf("Unable to open SDF file \"%s\"."
" Skipping this annotation.\n", fname); " Skipping this annotation.\n", fname);
vpi_free_object(argv);
free(fname);
return 0; return 0;
} }

View File

@ -6,7 +6,7 @@
%{ %{
/* /*
* Copyright (C) 2011-2013 Cary R. (cygcary@yahoo.com) * Copyright (C) 2011-2017 Cary R. (cygcary@yahoo.com)
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -154,7 +154,7 @@ void destroy_tblmod_lexor(void)
{ {
# ifdef FLEX_SCANNER # ifdef FLEX_SCANNER
# if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5 # if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5
# if defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9 # if YY_FLEX_MINOR_VERSION > 5 || defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
yylex_destroy(); yylex_destroy();
# endif # endif
# endif # endif

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2008-2012 Stephen Williams (steve@icarus.com) * Copyright (c) 2008-2018 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -45,14 +45,14 @@ struct vvp_island_branch_tran : public vvp_island_branch {
vvp_island_branch_tran(vvp_net_t*en__, bool active_high__, vvp_island_branch_tran(vvp_net_t*en__, bool active_high__,
unsigned width__, unsigned part__, unsigned width__, unsigned part__,
unsigned offset__); unsigned offset__, bool resistive__);
bool run_test_enabled(); bool run_test_enabled();
void run_resolution(); void run_resolution();
void run_output(); void run_output();
vvp_net_t*en; vvp_net_t*en;
unsigned width, part, offset; unsigned width, part, offset;
bool active_high; bool active_high, resistive;
tran_state_t state; tran_state_t state;
}; };
@ -60,9 +60,10 @@ vvp_island_branch_tran::vvp_island_branch_tran(vvp_net_t*en__,
bool active_high__, bool active_high__,
unsigned width__, unsigned width__,
unsigned part__, unsigned part__,
unsigned offset__) unsigned offset__,
bool resistive__)
: en(en__), width(width__), part(part__), offset(offset__), : en(en__), width(width__), part(part__), offset(offset__),
active_high(active_high__) active_high(active_high__), resistive(resistive__)
{ {
state = en__ ? tran_disabled : tran_enabled; state = en__ ? tran_disabled : tran_enabled;
} }
@ -235,7 +236,8 @@ bool vvp_island_branch_tran::run_test_enabled()
// input is 'x' or 'z'. We use the rules that are given for MOS switches. // 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, inline vvp_vector8_t resolve_ambiguous(const vvp_vector8_t&a,
const vvp_vector8_t&b, const vvp_vector8_t&b,
tran_state_t state) tran_state_t state,
unsigned str_map[8])
{ {
assert(a.size() == b.size()); assert(a.size() == b.size());
vvp_vector8_t out (a.size()); vvp_vector8_t out (a.size());
@ -243,6 +245,9 @@ inline vvp_vector8_t resolve_ambiguous(const vvp_vector8_t&a,
for (unsigned idx = 0 ; idx < out.size() ; idx += 1) { for (unsigned idx = 0 ; idx < out.size() ; idx += 1) {
vvp_scalar_t a_bit = a.value(idx); vvp_scalar_t a_bit = a.value(idx);
vvp_scalar_t b_bit = b.value(idx); vvp_scalar_t b_bit = b.value(idx);
b_bit = vvp_scalar_t(b_bit.value(),
str_map[b_bit.strength0()],
str_map[b_bit.strength1()]);
if (state == tran_unknown) { if (state == tran_unknown) {
switch (b_bit.value()) { switch (b_bit.value()) {
case BIT4_0: case BIT4_0:
@ -293,8 +298,8 @@ static void push_value_through_branch(const vvp_vector8_t&val,
// previously collected (and resolved) for the port. // previously collected (and resolved) for the port.
if (branch->width == 0) { if (branch->width == 0) {
// There are no part selects. // There are no part selects.
dst_port->value = resolve_ambiguous(dst_port->value, val, dst_port->value = resolve_ambiguous(dst_port->value, val, branch->state,
branch->state); vvp_switch_strength_map[branch->resistive]);
} else if (dst_ab == 1) { } else if (dst_ab == 1) {
// The other side is a strict subset (part select) // The other side is a strict subset (part select)
@ -413,7 +418,7 @@ void compile_island_tranif(int sense, char*island, char*pa, char*pb, char*pe)
vvp_island_branch_tran*br = new vvp_island_branch_tran(en, vvp_island_branch_tran*br = new vvp_island_branch_tran(en,
sense ? true : sense ? true :
false, false,
0, 0, 0); 0, 0, 0, false);
use_island->add_branch(br, pa, pb); use_island->add_branch(br, pa, pb);
@ -430,7 +435,7 @@ void compile_island_tranvp(char*island, char*pa, char*pb,
free(island); free(island);
vvp_island_branch_tran*br = new vvp_island_branch_tran(NULL, false, vvp_island_branch_tran*br = new vvp_island_branch_tran(NULL, false,
wid, par, off); wid, par, off, false);
use_island->add_branch(br, pa, pb); use_island->add_branch(br, pa, pb);

View File

@ -4,7 +4,7 @@
%{ %{
/* /*
* Copyright (c) 2001-2012 Stephen Williams (steve@icarus.com) * Copyright (c) 2001-2017 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -334,7 +334,7 @@ void destroy_lexor()
{ {
# ifdef FLEX_SCANNER # ifdef FLEX_SCANNER
# if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5 # if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5
# if defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9 # if YY_FLEX_MINOR_VERSION > 5 || defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
yylex_destroy(); yylex_destroy();
# endif # endif
# endif # endif

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2005-2016 Stephen Williams (steve@icarus.com) * Copyright (c) 2005-2018 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -19,9 +19,10 @@
# include "npmos.h" # include "npmos.h"
vvp_fun_pmos_::vvp_fun_pmos_(bool enable_invert) vvp_fun_pmos_::vvp_fun_pmos_(bool enable_invert, bool resistive)
{ {
inv_en_ = enable_invert; inv_en_ = enable_invert;
resistive_ = resistive;
} }
@ -58,12 +59,18 @@ void vvp_fun_pmos_::recv_vec8_pv(vvp_net_ptr_t ptr, const vvp_vector8_t&bit,
void vvp_fun_pmos_::generate_output_(vvp_net_ptr_t ptr) void vvp_fun_pmos_::generate_output_(vvp_net_ptr_t ptr)
{ {
const unsigned*strength_map = vvp_switch_strength_map[resistive_];
vvp_vector8_t out (bit_.size()); vvp_vector8_t out (bit_.size());
for (unsigned idx = 0 ; idx < out.size() ; idx += 1) { for (unsigned idx = 0 ; idx < out.size() ; idx += 1) {
vvp_bit4_t b_en = en_.value(idx); vvp_bit4_t b_en = en_.value(idx);
vvp_scalar_t b_bit = bit_.value(idx); vvp_scalar_t b_bit = bit_.value(idx);
b_bit = vvp_scalar_t(b_bit.value(),
strength_map[b_bit.strength0()],
strength_map[b_bit.strength1()]);
switch (b_en) { switch (b_en) {
case BIT4_0: case BIT4_0:
out.set_bit(idx, b_bit); out.set_bit(idx, b_bit);
@ -93,7 +100,7 @@ void vvp_fun_pmos_::generate_output_(vvp_net_ptr_t ptr)
vvp_fun_pmos::vvp_fun_pmos(bool enable_invert) vvp_fun_pmos::vvp_fun_pmos(bool enable_invert)
: vvp_fun_pmos_(enable_invert) : vvp_fun_pmos_(enable_invert, false)
{ {
} }
@ -112,7 +119,7 @@ void vvp_fun_pmos::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit)
} }
vvp_fun_rpmos::vvp_fun_rpmos(bool enable_invert) vvp_fun_rpmos::vvp_fun_rpmos(bool enable_invert)
: vvp_fun_pmos_(enable_invert) : vvp_fun_pmos_(enable_invert, true)
{ {
} }
@ -126,7 +133,7 @@ void vvp_fun_rpmos::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit)
if (ptr.port() != 0) if (ptr.port() != 0)
return; return;
bit_ = resistive_reduction(bit); bit_ = bit;
generate_output_(ptr); generate_output_(ptr);
} }
@ -135,8 +142,9 @@ void vvp_fun_rpmos::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit)
* CMOS primitive. * CMOS primitive.
*/ */
vvp_fun_cmos_::vvp_fun_cmos_() vvp_fun_cmos_::vvp_fun_cmos_(bool resistive)
{ {
resistive_ = resistive;
} }
void vvp_fun_cmos_::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t &bit, void vvp_fun_cmos_::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t &bit,
@ -175,6 +183,8 @@ void vvp_fun_cmos_::recv_vec8_pv(vvp_net_ptr_t ptr, const vvp_vector8_t&bit,
void vvp_fun_cmos_::generate_output_(vvp_net_ptr_t ptr) void vvp_fun_cmos_::generate_output_(vvp_net_ptr_t ptr)
{ {
const unsigned*strength_map = vvp_switch_strength_map[resistive_];
vvp_vector8_t out (bit_.size()); vvp_vector8_t out (bit_.size());
for (unsigned idx = 0 ; idx < out.size() ; idx += 1) { for (unsigned idx = 0 ; idx < out.size() ; idx += 1) {
@ -182,6 +192,10 @@ void vvp_fun_cmos_::generate_output_(vvp_net_ptr_t ptr)
vvp_bit4_t b_p_en = p_en_.value(idx); vvp_bit4_t b_p_en = p_en_.value(idx);
vvp_scalar_t b_bit = bit_.value(idx); vvp_scalar_t b_bit = bit_.value(idx);
b_bit = vvp_scalar_t(b_bit.value(),
strength_map[b_bit.strength0()],
strength_map[b_bit.strength1()]);
if (b_n_en == BIT4_1 || b_p_en == BIT4_0) { if (b_n_en == BIT4_1 || b_p_en == BIT4_0) {
out.set_bit(idx, b_bit); out.set_bit(idx, b_bit);
} else if (b_n_en == BIT4_0 && b_p_en == BIT4_1) { } else if (b_n_en == BIT4_0 && b_p_en == BIT4_1) {
@ -206,7 +220,7 @@ void vvp_fun_cmos_::generate_output_(vvp_net_ptr_t ptr)
} }
vvp_fun_cmos::vvp_fun_cmos() vvp_fun_cmos::vvp_fun_cmos()
: vvp_fun_cmos_() : vvp_fun_cmos_(false)
{ {
} }
@ -225,7 +239,7 @@ void vvp_fun_cmos::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit)
} }
vvp_fun_rcmos::vvp_fun_rcmos() vvp_fun_rcmos::vvp_fun_rcmos()
: vvp_fun_cmos_() : vvp_fun_cmos_(true)
{ {
} }
@ -239,6 +253,6 @@ void vvp_fun_rcmos::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit)
if (ptr.port() != 0) if (ptr.port() != 0)
return; return;
bit_ = resistive_reduction(bit); bit_ = bit;
generate_output_(ptr); generate_output_(ptr);
} }

View File

@ -1,7 +1,7 @@
#ifndef IVL_npmos_H #ifndef IVL_npmos_H
#define IVL_npmos_H #define IVL_npmos_H
/* /*
* Copyright (c) 2005-2016 Stephen Williams (steve@icarus.com) * Copyright (c) 2005-2018 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -46,7 +46,7 @@
class vvp_fun_pmos_ : public vvp_net_fun_t { class vvp_fun_pmos_ : public vvp_net_fun_t {
public: public:
explicit vvp_fun_pmos_(bool enable_invert); explicit vvp_fun_pmos_(bool enable_invert, bool resistive);
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit, void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
vvp_context_t); vvp_context_t);
@ -62,7 +62,7 @@ class vvp_fun_pmos_ : public vvp_net_fun_t {
vvp_vector8_t bit_; vvp_vector8_t bit_;
vvp_vector4_t en_; vvp_vector4_t en_;
bool inv_en_; bool inv_en_, resistive_;
}; };
class vvp_fun_pmos : public vvp_fun_pmos_ { class vvp_fun_pmos : public vvp_fun_pmos_ {
@ -109,7 +109,7 @@ class vvp_fun_rpmos : public vvp_fun_pmos_ {
class vvp_fun_cmos_ : public vvp_net_fun_t { class vvp_fun_cmos_ : public vvp_net_fun_t {
public: public:
explicit vvp_fun_cmos_(); explicit vvp_fun_cmos_(bool resistive);
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t &bit, void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t &bit,
vvp_context_t); vvp_context_t);
@ -126,6 +126,7 @@ class vvp_fun_cmos_ : public vvp_net_fun_t {
vvp_vector8_t bit_; vvp_vector8_t bit_;
vvp_vector4_t n_en_; vvp_vector4_t n_en_;
vvp_vector4_t p_en_; vvp_vector4_t p_en_;
bool resistive_;
}; };
class vvp_fun_cmos : public vvp_fun_cmos_ { class vvp_fun_cmos : public vvp_fun_cmos_ {

View File

@ -648,78 +648,42 @@ static void schedule_event_(struct event_s*cur, vvp_time64_t delay,
receive the event at hand. Put the event in to the receive the event at hand. Put the event in to the
appropriate list for the kind of assign we have at hand. */ appropriate list for the kind of assign we have at hand. */
switch (select_queue) { struct event_s** q = 0;
switch (select_queue) {
case SEQ_START: case SEQ_START:
if (ctim->start == 0) { q = &ctim->start;
ctim->start = cur;
} else {
cur->next = ctim->active->next;
ctim->active->next = cur;
ctim->active = cur;
}
break; break;
case SEQ_ACTIVE: case SEQ_ACTIVE:
if (ctim->active == 0) { q = &ctim->active;
ctim->active = cur;
} else {
/* Put the cur event on the end of the active list. */
cur->next = ctim->active->next;
ctim->active->next = cur;
ctim->active = cur;
}
break; break;
case SEQ_NBASSIGN: case SEQ_NBASSIGN:
if (ctim->nbassign == 0) { q = &ctim->nbassign;
ctim->nbassign = cur;
} else {
/* Put the cur event on the end of the active list. */
cur->next = ctim->nbassign->next;
ctim->nbassign->next = cur;
ctim->nbassign = cur;
}
break; break;
case SEQ_RWSYNC: case SEQ_RWSYNC:
if (ctim->rwsync == 0) { q = &ctim->rwsync;
ctim->rwsync = cur;
} else {
/* Put the cur event on the end of the active list. */
cur->next = ctim->rwsync->next;
ctim->rwsync->next = cur;
ctim->rwsync = cur;
}
break; break;
case SEQ_ROSYNC: case SEQ_ROSYNC:
if (ctim->rosync == 0) { q = &ctim->rosync;
ctim->rosync = cur;
} else {
/* Put the cur event on the end of the active list. */
cur->next = ctim->rosync->next;
ctim->rosync->next = cur;
ctim->rosync = cur;
}
break; break;
case DEL_THREAD: case DEL_THREAD:
if (ctim->del_thr == 0) { q = &ctim->del_thr;
ctim->del_thr = cur;
} else {
/* Put the cur event on the end of the active list. */
cur->next = ctim->del_thr->next;
ctim->del_thr->next = cur;
ctim->del_thr = cur;
}
break; break;
} }
if (q) {
if (*q) {
/* Put the cur event on the end of the queue. */
cur->next = (*q)->next;
(*q)->next = cur;
}
*q = cur;
}
} }
static void schedule_event_push_(struct event_s*cur) static void schedule_event_push_(struct event_s*cur)

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com) * Copyright (c) 2001-2018 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -780,6 +780,15 @@ void vvp_signal_value::get_signal_value(struct t_vpi_value*vp)
} }
} }
static double vlg_round(double rval)
{
if (rval >= 0.0) {
return floor(rval + 0.5);
} else {
return ceil(rval - 0.5);
}
}
static void real_signal_value(struct t_vpi_value*vp, double rval) static void real_signal_value(struct t_vpi_value*vp, double rval)
{ {
char*rbuf = (char *) need_result_buf(64 + 1, RBUF_VAL); char*rbuf = (char *) need_result_buf(64 + 1, RBUF_VAL);
@ -797,31 +806,26 @@ static void real_signal_value(struct t_vpi_value*vp, double rval)
if (rval != rval || (rval && (rval == 0.5*rval))) { if (rval != rval || (rval && (rval == 0.5*rval))) {
rval = 0.0; rval = 0.0;
} else { } else {
if (rval >= 0.0) rval = floor(rval + 0.5); rval = vlg_round(rval);
else rval = ceil(rval - 0.5);
} }
vp->value.integer = (PLI_INT32)rval; vp->value.integer = (PLI_INT32)rval;
break; break;
case vpiDecStrVal: case vpiDecStrVal:
#if !defined(__GNUC__)
if (isnan(rval)) if (isnan(rval))
sprintf(rbuf, "%s", "nan"); sprintf(rbuf, "%s", "nan");
else else
sprintf(rbuf, "%0.0f", rval); sprintf(rbuf, "%0.0f", vlg_round(rval));
#else
sprintf(rbuf, "%0.0f", rval);
#endif
vp->value.str = rbuf; vp->value.str = rbuf;
break; break;
case vpiHexStrVal: case vpiHexStrVal:
sprintf(rbuf, "%lx", (long)rval); sprintf(rbuf, "%lx", (long)vlg_round(rval));
vp->value.str = rbuf; vp->value.str = rbuf;
break; break;
case vpiBinStrVal: { case vpiBinStrVal: {
unsigned long val = (unsigned long)rval; unsigned long val = (unsigned long)vlg_round(rval);
unsigned len = 0; unsigned len = 0;
while (val > 0) { while (val > 0) {
@ -829,7 +833,7 @@ static void real_signal_value(struct t_vpi_value*vp, double rval)
val /= 2; val /= 2;
} }
val = (unsigned long)rval; val = (unsigned long)vlg_round(rval);
for (unsigned idx = 0 ; idx < len ; idx += 1) { for (unsigned idx = 0 ; idx < len ; idx += 1) {
rbuf[len-idx-1] = (val & 1)? '1' : '0'; rbuf[len-idx-1] = (val & 1)? '1' : '0';
val /= 2; val /= 2;

View File

@ -339,7 +339,8 @@ extern vpiHandle vpip_make_int4(const char*name, int msb, int lsb,
vvp_net_t*vec); vvp_net_t*vec);
extern vpiHandle vpip_make_var4(const char*name, int msb, int lsb, extern vpiHandle vpip_make_var4(const char*name, int msb, int lsb,
bool signed_flag, vvp_net_t*net); bool signed_flag, vvp_net_t*net);
extern vpiHandle vpip_make_net4(const char*name, int msb, int lsb, extern vpiHandle vpip_make_net4(__vpiScope*scope,
const char*name, int msb, int lsb,
bool signed_flag, vvp_net_t*node); bool signed_flag, vvp_net_t*node);
/* /*
@ -506,7 +507,9 @@ struct __vpiRealVar : public __vpiHandle {
}; };
extern struct __vpiScope* vpip_scope(__vpiRealVar*sig); extern struct __vpiScope* vpip_scope(__vpiRealVar*sig);
extern vpiHandle vpip_make_real_var(const char*name, vvp_net_t*net, bool is_wire); extern vpiHandle vpip_make_real_var(const char*name, vvp_net_t*net);
extern vpiHandle vpip_make_real_net(__vpiScope*scope,
const char*name, vvp_net_t*net);
class __vpiBaseVar : public __vpiHandle { class __vpiBaseVar : public __vpiHandle {

View File

@ -178,7 +178,8 @@ vpiHandle __vpiRealVar::vpi_handle(int code)
vpiHandle __vpiRealVar::vpi_iterate(int code) vpiHandle __vpiRealVar::vpi_iterate(int code)
{ return real_var_iterate(code, this); } { return real_var_iterate(code, this); }
vpiHandle vpip_make_real_var(const char*name, vvp_net_t*net, bool is_wire) static vpiHandle vpip_make_real_(__vpiScope*scope, const char*name,
vvp_net_t*net, bool is_wire)
{ {
struct __vpiRealVar*obj = new __vpiRealVar; struct __vpiRealVar*obj = new __vpiRealVar;
@ -187,11 +188,22 @@ vpiHandle vpip_make_real_var(const char*name, vvp_net_t*net, bool is_wire)
obj->is_wire = is_wire; obj->is_wire = is_wire;
obj->net = net; obj->net = net;
obj->within.scope = vpip_peek_current_scope(); obj->within.scope = scope;
return obj; return obj;
} }
vpiHandle vpip_make_real_var(const char*name, vvp_net_t*net)
{
return vpip_make_real_(vpip_peek_current_scope(), name, net, false);
}
vpiHandle vpip_make_real_net(__vpiScope*scope,
const char*name, vvp_net_t*net)
{
return vpip_make_real_(scope, name, net, true);
}
#ifdef CHECK_WITH_VALGRIND #ifdef CHECK_WITH_VALGRIND
void real_delete(vpiHandle item) void real_delete(vpiHandle item)
{ {

View File

@ -132,10 +132,20 @@ char *generic_get_str(int code, vpiHandle ref, const char *name, const char *ind
return res; return res;
} }
static vpiHandle fill_in_net4(struct __vpiSignal*obj, static vpiHandle fill_in_net4(struct __vpiSignal*obj, __vpiScope*scope,
const char*name, int msb, int lsb, const char*name, int msb, int lsb,
bool signed_flag, vvp_net_t*node); bool signed_flag, vvp_net_t*node);
static vpiHandle fill_in_var4(struct __vpiSignal*obj,
const char*name, int msb, int lsb,
bool signed_flag, vvp_net_t*node)
{
// Variable declarations are always resolved immediately,
// so we can assume they belong in the current scope.
return fill_in_net4(obj, vpip_peek_current_scope(),
name, msb, lsb, signed_flag, node);
}
/* /*
* The standard formatting/conversion routines. * The standard formatting/conversion routines.
* They work with full or partial signals. * They work with full or partial signals.
@ -972,7 +982,7 @@ struct signal_longint : public __vpiSignal {
vpiHandle vpip_make_int4(const char*name, int msb, int lsb, vvp_net_t*vec) vpiHandle vpip_make_int4(const char*name, int msb, int lsb, vvp_net_t*vec)
{ {
__vpiSignal*obj = new signal_integer; __vpiSignal*obj = new signal_integer;
return fill_in_net4(obj, name, msb, lsb, true, vec); return fill_in_var4(obj, name, msb, lsb, true, vec);
} }
/* /*
@ -1011,7 +1021,7 @@ vpiHandle vpip_make_int2(const char*name, int msb, int lsb, bool signed_flag,
} }
} }
return fill_in_net4(obj, name, msb, lsb, signed_flag, vec); return fill_in_var4(obj, name, msb, lsb, signed_flag, vec);
} }
/* /*
@ -1021,7 +1031,7 @@ vpiHandle vpip_make_var4(const char*name, int msb, int lsb,
bool signed_flag, vvp_net_t*vec) bool signed_flag, vvp_net_t*vec)
{ {
__vpiSignal*obj = new signal_reg; __vpiSignal*obj = new signal_reg;
return fill_in_net4(obj, name, msb, lsb, signed_flag, vec); return fill_in_var4(obj, name, msb, lsb, signed_flag, vec);
} }
#ifdef CHECK_WITH_VALGRIND #ifdef CHECK_WITH_VALGRIND
@ -1116,7 +1126,7 @@ void signal_pool_delete()
* The name is the PLI name for the object. If it is an array it is * The name is the PLI name for the object. If it is an array it is
* <name>[<index>]. * <name>[<index>].
*/ */
static vpiHandle fill_in_net4(struct __vpiSignal*obj, static vpiHandle fill_in_net4(struct __vpiSignal*obj, __vpiScope*scope,
const char*name, int msb, int lsb, const char*name, int msb, int lsb,
bool signed_flag, vvp_net_t*node) bool signed_flag, vvp_net_t*node)
{ {
@ -1130,18 +1140,19 @@ static vpiHandle fill_in_net4(struct __vpiSignal*obj,
// Place this object within a scope. If this object is // Place this object within a scope. If this object is
// attached to an array, then this value will be replaced with // attached to an array, then this value will be replaced with
// the handle to the parent. // the handle to the parent.
obj->within.scope = vpip_peek_current_scope(); obj->within.scope = scope;
count_vpi_nets += 1; count_vpi_nets += 1;
return obj; return obj;
} }
vpiHandle vpip_make_net4(const char*name, int msb, int lsb, vpiHandle vpip_make_net4(__vpiScope*scope,
const char*name, int msb, int lsb,
bool signed_flag, vvp_net_t*node) bool signed_flag, vvp_net_t*node)
{ {
struct __vpiSignal*obj = new signal_net; struct __vpiSignal*obj = new signal_net;
return fill_in_net4(obj, name, msb, lsb, signed_flag, node); return fill_in_net4(obj, scope, name, msb, lsb, signed_flag, node);
} }
static int PV_get_base(struct __vpiPV*rfp) static int PV_get_base(struct __vpiPV*rfp)

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2001-2015 Stephen Williams (steve@icarus.com) * Copyright (c) 2001-2018 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001 Stephan Boettcher <stephan@nevis.columbia.edu> * Copyright (c) 2001 Stephan Boettcher <stephan@nevis.columbia.edu>
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
@ -80,6 +80,15 @@ static int vthr_word_get(int code, vpiHandle ref)
} }
} }
static double vlg_round(double rval)
{
if (rval >= 0.0) {
return floor(rval + 0.5);
} else {
return ceil(rval - 0.5);
}
}
static void vthr_real_get_value(vpiHandle ref, s_vpi_value*vp) static void vthr_real_get_value(vpiHandle ref, s_vpi_value*vp)
{ {
struct __vpiVThrWord*obj = dynamic_cast<__vpiVThrWord*>(ref); struct __vpiVThrWord*obj = dynamic_cast<__vpiVThrWord*>(ref);
@ -108,31 +117,31 @@ static void vthr_real_get_value(vpiHandle ref, s_vpi_value*vp)
if (val != val || (val && (val == 0.5*val))) { if (val != val || (val && (val == 0.5*val))) {
val = 0.0; val = 0.0;
} else { } else {
if (val >= 0.0) val = floor(val + 0.5); val = vlg_round(val);
else val = ceil(val - 0.5);
} }
vp->value.integer = (PLI_INT32)val; vp->value.integer = (PLI_INT32)val;
break; break;
case vpiDecStrVal: case vpiDecStrVal:
#if !defined(__GNUC__)
if (isnan(val)) if (isnan(val))
sprintf(rbuf, "%s", "nan"); sprintf(rbuf, "%s", "nan");
else else
sprintf(rbuf, "%0.0f", val); sprintf(rbuf, "%0.0f", vlg_round(val));
#else vp->value.str = rbuf;
sprintf(rbuf, "%0.0f", val); break;
#endif
case vpiOctStrVal:
sprintf(rbuf, "%lo", (long)vlg_round(val));
vp->value.str = rbuf; vp->value.str = rbuf;
break; break;
case vpiHexStrVal: case vpiHexStrVal:
sprintf(rbuf, "%lx", (long)val); sprintf(rbuf, "%lx", (long)vlg_round(val));
vp->value.str = rbuf; vp->value.str = rbuf;
break; break;
case vpiBinStrVal: { case vpiBinStrVal: {
unsigned long vali = (unsigned long)val; unsigned long vali = (unsigned long)vlg_round(val);
unsigned len = 0; unsigned len = 0;
while (vali > 0) { while (vali > 0) {
@ -140,7 +149,7 @@ static void vthr_real_get_value(vpiHandle ref, s_vpi_value*vp)
vali /= 2; vali /= 2;
} }
vali = (unsigned long)val; vali = (unsigned long)vlg_round(val);
for (unsigned idx = 0 ; idx < len ; idx += 1) { for (unsigned idx = 0 ; idx < len ; idx += 1) {
rbuf[len-idx-1] = (vali & 1)? '1' : '0'; rbuf[len-idx-1] = (vali & 1)? '1' : '0';
vali /= 2; vali /= 2;
@ -279,6 +288,7 @@ class __vpiVThrVec4Stack : public __vpiHandle {
void vpi_get_value_int_ (p_vpi_value vp, const vvp_vector4_t&val); void vpi_get_value_int_ (p_vpi_value vp, const vvp_vector4_t&val);
void vpi_get_value_real_ (p_vpi_value vp, const vvp_vector4_t&val); void vpi_get_value_real_ (p_vpi_value vp, const vvp_vector4_t&val);
void vpi_get_value_strength_(p_vpi_value vp, const vvp_vector4_t&val); void vpi_get_value_strength_(p_vpi_value vp, const vvp_vector4_t&val);
void vpi_get_value_octstr_(p_vpi_value vp, const vvp_vector4_t&val);
void vpi_get_value_hexstr_(p_vpi_value vp, const vvp_vector4_t&val); void vpi_get_value_hexstr_(p_vpi_value vp, const vvp_vector4_t&val);
void vpi_get_value_vector_(p_vpi_value vp, const vvp_vector4_t&val); void vpi_get_value_vector_(p_vpi_value vp, const vvp_vector4_t&val);
private: private:
@ -346,6 +356,9 @@ void __vpiVThrVec4Stack::vpi_get_value(p_vpi_value vp)
case vpiDecStrVal: case vpiDecStrVal:
vpi_get_value_decstr_(vp, val); vpi_get_value_decstr_(vp, val);
break; break;
case vpiOctStrVal:
vpi_get_value_octstr_(vp, val);
break;
case vpiHexStrVal: case vpiHexStrVal:
vpi_get_value_hexstr_(vp, val); vpi_get_value_hexstr_(vp, val);
break; break;
@ -396,6 +409,48 @@ void __vpiVThrVec4Stack::vpi_get_value_decstr_(p_vpi_value vp, const vvp_vector4
vp->value.str = rbuf; vp->value.str = rbuf;
} }
void __vpiVThrVec4Stack::vpi_get_value_octstr_(p_vpi_value vp, const vvp_vector4_t&val)
{
unsigned wid = val.size();
unsigned owid = (wid + 2) / 3;
char*rbuf = (char*) need_result_buf(owid+1, RBUF_VAL);
rbuf[owid] = 0;
unsigned oval = 0;
for (unsigned idx = 0; idx < wid ; idx += 1) {
unsigned tmp = 0;
switch (val.value(idx)) {
case BIT4_0:
tmp = 0;
break;
case BIT4_1:
tmp = 1;
break;
case BIT4_X:
tmp = 2;
break;
case BIT4_Z:
tmp = 3;
break;
}
oval = oval | (tmp << 2*(idx%3));
if (idx%3 == 2) {
owid -= 1;
rbuf[owid] = oct_digits[oval];
oval = 0;
}
}
if (owid > 0) {
owid -= 1;
rbuf[owid] = oct_digits[oval];
oval = 0;
}
vp->value.str = rbuf;
}
void __vpiVThrVec4Stack::vpi_get_value_hexstr_(p_vpi_value vp, const vvp_vector4_t&val) void __vpiVThrVec4Stack::vpi_get_value_hexstr_(p_vpi_value vp, const vvp_vector4_t&val)
{ {
unsigned wid = val.size(); unsigned wid = val.size();

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2001-2015 Stephen Williams (steve@icarus.com) * Copyright (c) 2001-2018 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -2200,7 +2200,7 @@ static bool do_disable(vthread_t thr, vthread_t match)
} }
vthread_t parent = thr->parent; vthread_t parent = thr->parent;
if (parent && parent->i_am_joining) { if (parent && parent->i_am_joining && test_joinable(parent, thr)) {
// If a parent is waiting in a %join, wake it up. Note // If a parent is waiting in a %join, wake it up. Note
// that it is possible to be waiting in a %join yet // that it is possible to be waiting in a %join yet
// already scheduled if multiple child threads are // already scheduled if multiple child threads are
@ -2210,8 +2210,7 @@ static bool do_disable(vthread_t thr, vthread_t match)
if (! parent->i_have_ended) if (! parent->i_have_ended)
schedule_vthread(parent, 0, true); schedule_vthread(parent, 0, true);
// Let the parent do the reaping. do_join(parent, thr);
vthread_reap(thr);
} else if (parent) { } else if (parent) {
/* If the parent is yet to %join me, let its %join /* If the parent is yet to %join me, let its %join
@ -2518,6 +2517,10 @@ bool of_DIV_S(vthread_t thr, vvp_code_t)
if (bp[0] == 0) { if (bp[0] == 0) {
vvp_vector4_t tmp(wid, BIT4_X); vvp_vector4_t tmp(wid, BIT4_X);
vala = tmp; vala = tmp;
} else if (((long)ap[0] == LONG_MIN) && ((long)bp[0] == -1)) {
vvp_vector4_t tmp(wid, BIT4_0);
tmp.set_bit(wid-1, BIT4_1);
vala = tmp;
} else { } else {
long tmpa = (long) ap[0]; long tmpa = (long) ap[0];
long tmpb = (long) bp[0]; long tmpb = (long) bp[0];
@ -2614,7 +2617,7 @@ bool of_END(vthread_t thr, vvp_code_t)
/* If I have a parent who is waiting for me, then mark that I /* If I have a parent who is waiting for me, then mark that I
have ended, and schedule that parent. Also, finish the have ended, and schedule that parent. Also, finish the
%join for the parent. */ %join for the parent. */
if (thr->parent && thr->parent->i_am_joining) { if (!thr->i_am_detached && thr->parent && thr->parent->i_am_joining) {
vthread_t tmp = thr->parent; vthread_t tmp = thr->parent;
assert(! thr->i_am_detached); assert(! thr->i_am_detached);
@ -3768,6 +3771,9 @@ bool of_MOD_S(vthread_t thr, vvp_code_t)
if (rv == 0) if (rv == 0)
goto x_out; goto x_out;
if ((lv == LONG_LONG_MIN) && (rv == -1))
goto zero_out;
/* Sign extend the signed operands when needed. */ /* Sign extend the signed operands when needed. */
if (wid < 8*sizeof(long long)) { if (wid < 8*sizeof(long long)) {
if (lv & (1LL << (wid-1))) if (lv & (1LL << (wid-1)))
@ -3799,6 +3805,9 @@ bool of_MOD_S(vthread_t thr, vvp_code_t)
x_out: x_out:
vala = vvp_vector4_t(wid, BIT4_X); vala = vvp_vector4_t(wid, BIT4_X);
return true; return true;
zero_out:
vala = vvp_vector4_t(wid, BIT4_0);
return true;
} }
/* /*

View File

@ -67,6 +67,11 @@ void vvp_darray::get_word(unsigned, vvp_object_t&)
cerr << "XXXX get_word(vvp_object_t) not implemented for " << typeid(*this).name() << endl; cerr << "XXXX get_word(vvp_object_t) not implemented for " << typeid(*this).name() << endl;
} }
void vvp_darray::shallow_copy(const vvp_object*)
{
cerr << "XXXX shallow_copy(vvp_object_t) not implemented for " << typeid(*this).name() << endl;
}
template <class TYPE> vvp_darray_atom<TYPE>::~vvp_darray_atom() template <class TYPE> vvp_darray_atom<TYPE>::~vvp_darray_atom()
{ {
} }
@ -101,6 +106,16 @@ template <class TYPE> void vvp_darray_atom<TYPE>::get_word(unsigned adr, vvp_vec
value = tmp; value = tmp;
} }
template <class TYPE> void vvp_darray_atom<TYPE>::shallow_copy(const vvp_object*obj)
{
const vvp_darray_atom<TYPE>*that = dynamic_cast<const vvp_darray_atom<TYPE>*>(obj);
assert(that);
unsigned num_items = min(array_.size(), that->array_.size());
for (unsigned idx = 0 ; idx < num_items ; idx += 1)
array_[idx] = that->array_[idx];
}
template class vvp_darray_atom<uint8_t>; template class vvp_darray_atom<uint8_t>;
template class vvp_darray_atom<uint16_t>; template class vvp_darray_atom<uint16_t>;
template class vvp_darray_atom<uint32_t>; template class vvp_darray_atom<uint32_t>;
@ -140,6 +155,16 @@ void vvp_darray_vec4::get_word(unsigned adr, vvp_vector4_t&value)
assert(value.size() == word_wid_); assert(value.size() == word_wid_);
} }
void vvp_darray_vec4::shallow_copy(const vvp_object*obj)
{
const vvp_darray_vec4*that = dynamic_cast<const vvp_darray_vec4*>(obj);
assert(that);
unsigned num_items = min(array_.size(), that->array_.size());
for (unsigned idx = 0 ; idx < num_items ; idx += 1)
array_[idx] = that->array_[idx];
}
vvp_darray_vec2::~vvp_darray_vec2() vvp_darray_vec2::~vvp_darray_vec2()
{ {
} }
@ -173,6 +198,15 @@ void vvp_darray_vec2::get_word(unsigned adr, vvp_vector4_t&value)
} }
} }
void vvp_darray_vec2::shallow_copy(const vvp_object*obj)
{
const vvp_darray_vec2*that = dynamic_cast<const vvp_darray_vec2*>(obj);
assert(that);
unsigned num_items = min(array_.size(), that->array_.size());
for (unsigned idx = 0 ; idx < num_items ; idx += 1)
array_[idx] = that->array_[idx];
}
vvp_darray_object::~vvp_darray_object() vvp_darray_object::~vvp_darray_object()
{ {
@ -200,6 +234,16 @@ void vvp_darray_object::get_word(unsigned adr, vvp_object_t&value)
value = array_[adr]; value = array_[adr];
} }
void vvp_darray_object::shallow_copy(const vvp_object*obj)
{
const vvp_darray_object*that = dynamic_cast<const vvp_darray_object*>(obj);
assert(that);
unsigned num_items = min(array_.size(), that->array_.size());
for (unsigned idx = 0 ; idx < num_items ; idx += 1)
array_[idx] = that->array_[idx];
}
vvp_darray_real::~vvp_darray_real() vvp_darray_real::~vvp_darray_real()
{ {
} }
@ -226,6 +270,16 @@ void vvp_darray_real::get_word(unsigned adr, double&value)
value = array_[adr]; value = array_[adr];
} }
void vvp_darray_real::shallow_copy(const vvp_object*obj)
{
const vvp_darray_real*that = dynamic_cast<const vvp_darray_real*>(obj);
assert(that);
unsigned num_items = min(array_.size(), that->array_.size());
for (unsigned idx = 0 ; idx < num_items ; idx += 1)
array_[idx] = that->array_[idx];
}
vvp_darray_string::~vvp_darray_string() vvp_darray_string::~vvp_darray_string()
{ {
} }
@ -252,6 +306,16 @@ void vvp_darray_string::get_word(unsigned adr, string&value)
value = array_[adr]; value = array_[adr];
} }
void vvp_darray_string::shallow_copy(const vvp_object*obj)
{
const vvp_darray_string*that = dynamic_cast<const vvp_darray_string*>(obj);
assert(that);
unsigned num_items = min(array_.size(), that->array_.size());
for (unsigned idx = 0 ; idx < num_items ; idx += 1)
array_[idx] = that->array_[idx];
}
vvp_queue::~vvp_queue() vvp_queue::~vvp_queue()
{ {
} }

View File

@ -44,6 +44,8 @@ class vvp_darray : public vvp_object {
virtual void set_word(unsigned adr, const vvp_object_t&value); virtual void set_word(unsigned adr, const vvp_object_t&value);
virtual void get_word(unsigned adr, vvp_object_t&value); virtual void get_word(unsigned adr, vvp_object_t&value);
virtual void shallow_copy(const vvp_object*obj);
}; };
template <class TYPE> class vvp_darray_atom : public vvp_darray { template <class TYPE> class vvp_darray_atom : public vvp_darray {
@ -55,6 +57,7 @@ template <class TYPE> class vvp_darray_atom : public vvp_darray {
size_t get_size(void) const; size_t get_size(void) const;
void set_word(unsigned adr, const vvp_vector4_t&value); void set_word(unsigned adr, const vvp_vector4_t&value);
void get_word(unsigned adr, vvp_vector4_t&value); void get_word(unsigned adr, vvp_vector4_t&value);
void shallow_copy(const vvp_object*obj);
private: private:
std::vector<TYPE> array_; std::vector<TYPE> array_;
@ -70,6 +73,7 @@ class vvp_darray_vec4 : public vvp_darray {
size_t get_size(void) const; size_t get_size(void) const;
void set_word(unsigned adr, const vvp_vector4_t&value); void set_word(unsigned adr, const vvp_vector4_t&value);
void get_word(unsigned adr, vvp_vector4_t&value); void get_word(unsigned adr, vvp_vector4_t&value);
void shallow_copy(const vvp_object*obj);
private: private:
std::vector<vvp_vector4_t> array_; std::vector<vvp_vector4_t> array_;
@ -86,6 +90,7 @@ class vvp_darray_vec2 : public vvp_darray {
size_t get_size(void) const; size_t get_size(void) const;
void set_word(unsigned adr, const vvp_vector4_t&value); void set_word(unsigned adr, const vvp_vector4_t&value);
void get_word(unsigned adr, vvp_vector4_t&value); void get_word(unsigned adr, vvp_vector4_t&value);
void shallow_copy(const vvp_object*obj);
private: private:
std::vector<vvp_vector2_t> array_; std::vector<vvp_vector2_t> array_;
@ -101,6 +106,7 @@ class vvp_darray_real : public vvp_darray {
size_t get_size(void) const; size_t get_size(void) const;
void set_word(unsigned adr, double value); void set_word(unsigned adr, double value);
void get_word(unsigned adr, double&value); void get_word(unsigned adr, double&value);
void shallow_copy(const vvp_object*obj);
private: private:
std::vector<double> array_; std::vector<double> array_;
@ -115,6 +121,7 @@ class vvp_darray_string : public vvp_darray {
size_t get_size(void) const; size_t get_size(void) const;
void set_word(unsigned adr, const std::string&value); void set_word(unsigned adr, const std::string&value);
void get_word(unsigned adr, std::string&value); void get_word(unsigned adr, std::string&value);
void shallow_copy(const vvp_object*obj);
private: private:
std::vector<std::string> array_; std::vector<std::string> array_;
@ -129,6 +136,7 @@ class vvp_darray_object : public vvp_darray {
size_t get_size(void) const; size_t get_size(void) const;
void set_word(unsigned adr, const vvp_object_t&value); void set_word(unsigned adr, const vvp_object_t&value);
void get_word(unsigned adr, vvp_object_t&value); void get_word(unsigned adr, vvp_object_t&value);
void shallow_copy(const vvp_object*obj);
private: private:
std::vector<vvp_object_t> array_; std::vector<vvp_object_t> array_;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2004-2015 Stephen Williams (steve@icarus.com) * Copyright (c) 2004-2018 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -3421,7 +3421,8 @@ unsigned vvp_wide_fun_core::port_count() const
vvp_vector4_t& vvp_wide_fun_core::value(unsigned idx) vvp_vector4_t& vvp_wide_fun_core::value(unsigned idx)
{ {
assert(idx < nports_); assert(idx < nports_);
assert(port_values_); if (port_values_ == 0)
port_values_ = new vvp_vector4_t [nports_];
return port_values_[idx]; return port_values_[idx];
} }
@ -3685,31 +3686,28 @@ vvp_scalar_t fully_featured_resolv_(vvp_scalar_t a, vvp_scalar_t b)
return res; return res;
} }
vvp_vector8_t resistive_reduction(const vvp_vector8_t&that) unsigned vvp_switch_strength_map[2][8] = {
{ { // non-resistive
static unsigned rstr[8] = { 0, /* High impedance --> High impedance */
0, /* Hi-Z --> Hi-Z */ 1, /* Small capacitor --> Small capacitor */
1, /* Small capacitance --> Small capacitance */ 2, /* Medium capacitor --> Medium capacitor */
1, /* Medium capacitance --> Small capacitance */ 3, /* Weak drive --> Weak drive */
2, /* Weak drive --> Medium capacitance */ 4, /* Large capacitor --> Large capacitor */
2, /* Large capacitance --> Medium capacitance */ 5, /* Pull drive --> Pull drive */
6, /* Strong drive --> Strong drive */
6 /* Supply drive --> Strong drive */
},
{ // resistive
0, /* High impedance --> High impedance */
1, /* Small capacitor --> Small capacitor */
1, /* Medium capacitor --> Small capacitor */
2, /* Weak drive --> Medium capacitor */
2, /* Large capacitor --> Medium capacitor */
3, /* Pull drive --> Weak drive */ 3, /* Pull drive --> Weak drive */
5, /* Strong drive --> Pull drive */ 5, /* Strong drive --> Pull drive */
5 /* Supply drive --> Pull drive */ 5 /* Supply drive --> Pull drive */
};
vvp_vector8_t res (that.size());
for (unsigned idx = 0 ; idx < res.size() ; idx += 1) {
vvp_scalar_t bit = that.value(idx);
bit = vvp_scalar_t(bit.value(),
rstr[bit.strength0()],
rstr[bit.strength1()]);
res.set_bit(idx, bit);
} }
};
return res;
}
vvp_vector4_t reduce4(const vvp_vector8_t&that) vvp_vector4_t reduce4(const vvp_vector8_t&that)
{ {

View File

@ -1,7 +1,7 @@
#ifndef IVL_vvp_net_H #ifndef IVL_vvp_net_H
#define IVL_vvp_net_H #define IVL_vvp_net_H
/* /*
* Copyright (c) 2004-2016 Stephen Williams (steve@icarus.com) * Copyright (c) 2004-2018 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -954,9 +954,11 @@ inline vvp_vector8_t resolve(const vvp_vector8_t&a, const vvp_vector8_t&b)
return out; return out;
} }
/* This function implements the strength reduction implied by /* This lookup tabke implements the strength reduction implied by
Verilog standard resistive devices. */ Verilog standard switch devices. The major dimension selects
extern vvp_vector8_t resistive_reduction(const vvp_vector8_t&a); between non-resistive and resistive devices. */
extern unsigned vvp_switch_strength_map[2][8];
/* The reduce4 function converts a vector8 to a vector4, losing /* The reduce4 function converts a vector8 to a vector4, losing
strength information in the process. */ strength information in the process. */
extern vvp_vector4_t reduce4(const vvp_vector8_t&that); extern vvp_vector4_t reduce4(const vvp_vector8_t&that);

View File

@ -48,7 +48,7 @@ static void __compile_var_real(char*label, char*name,
define_functor_symbol(label, net); define_functor_symbol(label, net);
vpiHandle obj = vpip_make_real_var(name, net, false); vpiHandle obj = vpip_make_real_var(name, net);
compile_vpi_symbol(label, obj); compile_vpi_symbol(label, obj);
if (name) { if (name) {
@ -350,7 +350,7 @@ static void do_compile_net(vvp_net_t*node, vvp_array_t array,
vpiHandle obj = 0; vpiHandle obj = 0;
if (! local_flag) { if (! local_flag) {
/* Make the vpiHandle for the reg. */ /* Make the vpiHandle for the reg. */
obj = vpip_make_net4(name, msb, lsb, signed_flag, node); obj = vpip_make_net4(scope, name, msb, lsb, signed_flag, node);
/* This attaches the label to the vpiHandle */ /* This attaches the label to the vpiHandle */
compile_vpi_symbol(my_label, obj); compile_vpi_symbol(my_label, obj);
} }
@ -481,7 +481,7 @@ static void __compile_real_net2(vvp_net_t*node, vvp_array_t array,
vpiHandle obj = 0; vpiHandle obj = 0;
if (!local_flag) { if (!local_flag) {
obj = vpip_make_real_var(name, node, true); obj = vpip_make_real_net(scope, name, node);
compile_vpi_symbol(my_label, obj); compile_vpi_symbol(my_label, obj);
} }
#ifdef CHECK_WITH_VALGRIND #ifdef CHECK_WITH_VALGRIND