diff --git a/PDelays.cc b/PDelays.cc index 5fd72a37b..3759d39fe 100644 --- a/PDelays.cc +++ b/PDelays.cc @@ -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 * and/or modify it in source code form under the terms of the GNU @@ -26,11 +26,6 @@ # include "verinum.h" # include "netmisc.h" -bool dly_used_no_timescale = false; -bool dly_used_timescale = false; -bool display_ts_dly_warning = true; - - PDelays::PDelays() { 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); - /* Print a warning if we find default and `timescale based - * 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; - } + check_for_inconsistent_delays(scope); /* If the delay expression is a real constant or vector constant, then evaluate it, scale it to the local time diff --git a/driver/cflexor.lex b/driver/cflexor.lex index 3f3e46e80..c6e3eb860 100644 --- a/driver/cflexor.lex +++ b/driver/cflexor.lex @@ -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 * 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 # 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(); # endif # endif diff --git a/elab_expr.cc b/elab_expr.cc index 7eb4bedd8..14038e0f3 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -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) * * This source code is free software; you can redistribute it @@ -1446,6 +1446,13 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope, 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) { cerr << get_fileline() << ": PECallFunction::elaborate_sfunc_: " << 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) { - cerr << get_fileline() << ": internal error: " - << "Expecting idents with ntype to be signals." << endl; + cerr << get_fileline() << ": error: Unable to bind variable `" + << path_ << "' in `" << scope_path(use_scope) << "'" << endl; des->errors += 1; return 0; } - if (! ntype->type_compatible(net->net_type())) { - cerr << get_fileline() << ": internal_error: " - << "net type doesn't match context type." << endl; + if (const netdarray_t*array_type = dynamic_cast (ntype)) { + if (array_type->type_compatible(net->net_type())) { + NetESignal*tmp = new NetESignal(net); + tmp->set_line(*this); + return tmp; + } - cerr << get_fileline() << ": : " - << "net type="; + // Icarus allows a dynamic array to be initialised with a + // 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()) net->net_type()->debug_dump(cerr); else cerr << ""; cerr << endl; - cerr << get_fileline() << ": : " - << "context type="; + cerr << get_fileline() << ": : " << "context type="; ivl_assert(*this, ntype); ntype->debug_dump(cerr); cerr << endl; + des->errors += 1; + return 0; } 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 // type. The run-time will assign this value to each element. const netarray_t*array_type = dynamic_cast (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); @@ -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 { + // Icarus allows dynamic arrays to be initialised with a single value. + if (const netdarray_t*array_type = dynamic_cast (ntype)) + ntype = array_type->element_type(); + const netvector_t*use_type = dynamic_cast (ntype); if (use_type == 0) { cerr << get_fileline() << ": internal error: " diff --git a/elab_scope.cc b/elab_scope.cc index 73834249c..5407fcfe8 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -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) * * 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; if (base_class) { - ivl_assert(*pclass, scope); - use_base_class = scope->find_class(base_class->name); + if (scope) + 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) { cerr << pclass->get_fileline() << ": error: " << "Base class " << base_class->name @@ -605,13 +607,9 @@ static void elaborate_scope_classes(Design*des, NetScope*scope, void elaborate_rootscope_classes(Design*des) { - if (pform_classes.empty()) - return; - - for (map::iterator cur = pform_classes.begin() - ; cur != pform_classes.end() ; ++ cur) { - blend_class_constructors(cur->second); - elaborate_scope_class(des, 0, cur->second); + for (size_t idx = 0 ; idx < pform_classes.size() ; idx += 1) { + blend_class_constructors(pform_classes[idx]); + elaborate_scope_class(des, 0, pform_classes[idx]); } } diff --git a/elaborate.cc b/elaborate.cc index f0b440f0c..b2a14b36d 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -2374,19 +2374,7 @@ static NetExpr*elaborate_delay_expr(PExpr*expr, Design*des, NetScope*scope) { NetExpr*dex = elab_and_eval(des, scope, expr, -1); - /* Print a warning if we find default and `timescale based - * 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; - } + check_for_inconsistent_delays(scope); /* If the delay expression is a real constant or vector 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(); if (ndelays > 12) ndelays = 12; - /* Print a warning if we find default and `timescale based - * 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; - } + check_for_inconsistent_delays(scope); /* Elaborate the delay values themselves. Remember to scale them for the timescale/precision of the scope. */ diff --git a/ivlpp/lexor.lex b/ivlpp/lexor.lex index c81af7397..56e90c79d 100644 --- a/ivlpp/lexor.lex +++ b/ivlpp/lexor.lex @@ -2100,7 +2100,7 @@ void destroy_lexor(void) { # ifdef FLEX_SCANNER # 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(); # endif # endif diff --git a/lexor.lex b/lexor.lex index 15591d402..ae557e45e 100644 --- a/lexor.lex +++ b/lexor.lex @@ -1606,7 +1606,7 @@ void destroy_lexor() { # ifdef FLEX_SCANNER # 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(); # endif # endif diff --git a/libmisc/StringHeap.cc b/libmisc/StringHeap.cc index f87c4fcf8..10259dc34 100644 --- a/libmisc/StringHeap.cc +++ b/libmisc/StringHeap.cc @@ -32,8 +32,8 @@ static unsigned string_pool_count = 0; StringHeap::StringHeap() { cell_base_ = 0; - cell_ptr_ = HEAPCELL; - cell_count_ = 0; + cell_size_ = 0; + cell_ptr_ = 0; } StringHeap::~StringHeap() @@ -45,20 +45,24 @@ StringHeap::~StringHeap() const char* StringHeap::add(const char*text) { unsigned len = strlen(text); - assert((len+1) <= HEAPCELL); - - unsigned rem = HEAPCELL - cell_ptr_; + unsigned rem = cell_size_ - cell_ptr_; 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 string_pool_count += 1; string_pool = (char **) realloc(string_pool, string_pool_count*sizeof(char **)); string_pool[string_pool_count-1] = cell_base_; #endif - cell_ptr_ = 0; - cell_count_ += 1; - assert(cell_base_ != 0); } char*res = cell_base_ + cell_ptr_; @@ -66,7 +70,7 @@ const char* StringHeap::add(const char*text) cell_ptr_ += len; cell_base_[cell_ptr_++] = 0; - assert(cell_ptr_ <= HEAPCELL); + assert(cell_ptr_ <= cell_size_); return res; } diff --git a/libmisc/StringHeap.h b/libmisc/StringHeap.h index 5c791e104..7d3666c82 100644 --- a/libmisc/StringHeap.h +++ b/libmisc/StringHeap.h @@ -78,11 +78,11 @@ class StringHeap { perm_string make(const char*); private: - enum { HEAPCELL = 0x10000 }; + static const unsigned DEFAULT_CELL_SIZE = 0x10000; char*cell_base_; + unsigned cell_size_; unsigned cell_ptr_; - unsigned cell_count_; private: // not implemented StringHeap(const StringHeap&); diff --git a/main.cc b/main.cc index 9e54f5c50..30da7bacd 100644 --- a/main.cc +++ b/main.cc @@ -1,5 +1,5 @@ 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 @@ -1037,9 +1037,8 @@ int main(int argc, char*argv[]) pform_dump(out, cur->second); } out << "PFORM DUMP $ROOT CLASSES:" << endl; - for (map::iterator cur = pform_classes.begin() - ; cur != pform_classes.end() ; ++ cur) { - pform_dump(out, cur->second); + for (size_t idx = 0 ; idx < pform_classes.size() ; idx += 1) { + pform_dump(out, pform_classes[idx]); } out << "PFORM DUMP PACKAGES:" << endl; for (map::iterator pac = pform_packages.begin() diff --git a/netclass.cc b/netclass.cc index 0ae3ba1dc..7e69a604d 100644 --- a/netclass.cc +++ b/netclass.cc @@ -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 * 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*task = class_scope_->child( hname_t(name) ); - if (task == 0) return 0; + if ((task == 0) && super_) + task = super_->method_from_name(name); return task; } diff --git a/netlist.cc b/netlist.cc index bb162a021..5c08aef56 100644 --- a/netlist.cc +++ b/netlist.cc @@ -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 * and/or modify it in source code form under the terms of the GNU @@ -2724,12 +2724,27 @@ DelayType NetProc::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; - for (const NetProc*cur = proc_first(); cur; cur = proc_next(cur)) { - DelayType dt = cur->delay_type(); - if (dt > result) result = dt; - if (dt == DEFINITE_DELAY) break; + 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)) { + DelayType dt = cur->delay_type(); + if (dt > result) result = dt; + if (dt == DEFINITE_DELAY) break; + } } return result; @@ -2800,9 +2815,10 @@ DelayType NetPDelay::delay_type() const return DEFINITE_DELAY; } else { if (statement_) { - return statement_->delay_type(); + return combine_delays(ZERO_DELAY, + statement_->delay_type()); } else { - return NO_DELAY; + return ZERO_DELAY; } } } diff --git a/netmisc.cc b/netmisc.cc index 377263326..55c840d57 100644 --- a/netmisc.cc +++ b/netmisc.cc @@ -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 * 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; } + + +/* + * 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; + } +} diff --git a/netmisc.h b/netmisc.h index e0569bce0..f7b68130e 100644 --- a/netmisc.h +++ b/netmisc.h @@ -1,7 +1,7 @@ #ifndef 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 * 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 }; 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 * processing. @@ -409,4 +405,10 @@ extern void assign_unpacked_with_bufz(Design*des, NetScope*scope, 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 */ diff --git a/parse.y b/parse.y index cc7ff53da..cfaa6617a 100644 --- a/parse.y +++ b/parse.y @@ -598,7 +598,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector %type function_item function_item_list function_item_list_opt %type task_item task_item_list task_item_list_opt -%type tf_port_declaration tf_port_item tf_port_list tf_port_list_opt +%type tf_port_declaration tf_port_item tf_port_item_list tf_port_list tf_port_list_opt %type modport_simple_port port_name parameter_value_byname %type 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 { - assert(current_task == 0); + if (current_task) { + pform_pop_scope(); + current_task = 0; + } } endlabel_opt { // 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 { vector*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); list* 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)) { // Detect special case this is an undecorated // 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, ilist); - } else { // Otherwise, the decorations for this identifier // 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 */ + : { 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*tmp; if ($1 && $3) { 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."); $$ = $3; } - | tf_port_list ',' + | tf_port_item_list ',' { yyerror(@2, "error: NULL port declarations are not allowed."); $$ = $1; } - | tf_port_list ';' + | tf_port_item_list ';' { yyerror(@2, "error: ';' is an invalid port declaration separator."); $$ = $1; } diff --git a/parse_api.h b/parse_api.h index a698c3bee..87ae28d11 100644 --- a/parse_api.h +++ b/parse_api.h @@ -1,7 +1,7 @@ #ifndef 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 * and/or modify it in source code form under the terms of the GNU @@ -45,7 +45,7 @@ extern std::map pform_primitives; extern std::map pform_typedefs; extern std::set pform_enum_sets; extern std::map pform_tasks; -extern std::map pform_classes; +extern std::vector pform_classes; extern std::map pform_packages; extern void pform_dump(std::ostream&out, const PClass*pac); diff --git a/pform.cc b/pform.cc index 14eb57a48..c7d94970c 100644 --- a/pform.cc +++ b/pform.cc @@ -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) * * This source code is free software; you can redistribute it @@ -71,7 +71,7 @@ setpform_enum_sets; /* * Class definitions in the $root scope go here. */ -map pform_classes; +vector pform_classes; /* * 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 * compilation unit scope. */ if (scopex == 0) { - pform_classes[name] = class_scope; + pform_classes.push_back(class_scope); lexical_scope = class_scope; return class_scope; } diff --git a/t-dll.cc b/t-dll.cc index c3ad49d0e..47ed90aaa 100644 --- a/t-dll.cc +++ b/t-dll.cc @@ -281,6 +281,13 @@ ivl_scope_t dll_target::find_scope(ivl_design_s &des, const NetScope*cur) return scope; } + for (map::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; } diff --git a/tgt-pcb/fp.lex b/tgt-pcb/fp.lex index af3292252..3536f51ae 100644 --- a/tgt-pcb/fp.lex +++ b/tgt-pcb/fp.lex @@ -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 * 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); } +/* + * Modern version of flex (>=2.5.9) can clean up the scanner data. + */ void destroy_fp_lexor() { # ifdef FLEX_SCANNER # 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(); # endif # endif diff --git a/tgt-vvp/eval_object.c b/tgt-vvp/eval_object.c index fb6240d17..7a307b150 100644 --- a/tgt-vvp/eval_object.c +++ b/tgt-vvp/eval_object.c @@ -82,6 +82,7 @@ static int eval_darray_new(ivl_expr_t ex) unsigned idx; switch (ivl_type_base(element_type)) { case IVL_VT_BOOL: + case IVL_VT_LOGIC: for (idx = 0 ; idx < ivl_expr_parms(init_expr) ; idx += 1) { draw_eval_vec4(ivl_expr_parm(init_expr,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; 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)) { /* In this case, there is an init expression, the expression is NOT an array_pattern, and the size diff --git a/verinum.cc b/verinum.cc index c5f4be65e..7b466053b 100644 --- a/verinum.cc +++ b/verinum.cc @@ -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 * and/or modify it in source code form under the terms of the GNU @@ -22,6 +22,7 @@ # include "verinum.h" # include # include +# include # include // Needed to get pow for as_double(). # include // Needed to get snprintf for as_string(). # include @@ -1444,7 +1445,8 @@ verinum operator / (const verinum&left, const verinum&right) if (use_len <= (8*sizeof(long) - 1)) { long l = left.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) { result.set(idx, (v & 1)? verinum::V1 : verinum::V0); v >>= 1; @@ -1518,7 +1520,8 @@ verinum operator % (const verinum&left, const verinum&right) /* Use native signed modulus to do the work. */ long l = left.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) { result.set(idx, (v & 1)? verinum::V1 : verinum::V0); v >>= 1; diff --git a/vhdlpp/lexor.lex b/vhdlpp/lexor.lex index 1cbda23c9..b0129f77f 100644 --- a/vhdlpp/lexor.lex +++ b/vhdlpp/lexor.lex @@ -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 * 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; } +/* + * Modern version of flex (>=2.5.9) can clean up the scanner data. + */ 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); +# endif +# endif +# endif } diff --git a/vhdlpp/std_funcs.cc b/vhdlpp/std_funcs.cc index ec843dd13..89448e483 100644 --- a/vhdlpp/std_funcs.cc +++ b/vhdlpp/std_funcs.cc @@ -1,5 +1,5 @@ /* - * Copyright CERN 2015 + * Copyright CERN 2016-2018 * @author Maciej Suminski (maciej.suminski@cern.ch) * * This source code is free software; you can redistribute it @@ -120,7 +120,7 @@ void preload_std_funcs(void) std::list*fn_integer_args = new std::list(); fn_integer_args->push_back(new InterfacePort(&primitive_INTEGER)); fn_integer = new SubprogramBuiltin(perm_string::literal("integer"), - perm_string::literal("$signed"), + perm_string::literal("int'"), fn_integer_args, &primitive_INTEGER); std_subprograms[fn_integer->name()] = fn_integer; diff --git a/vpi/fstapi.c b/vpi/fstapi.c index 18d38ec99..386d6705e 100644 --- a/vpi/fstapi.c +++ b/vpi/fstapi.c @@ -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 * 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 #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); 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); } 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); 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); } else @@ -803,7 +804,7 @@ if(rc<0) { xc->fseek_failed = 1; #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"); #endif } @@ -1663,7 +1664,7 @@ if(zerocnt) /* fpos += */ fstWriterVarint(f, (zerocnt << 1)); /* scan-build */ } #ifdef FST_DEBUG -fprintf(stderr, "value chains: %d\n", cnt); +fprintf(stderr, FST_APIMESS"value chains: %d\n", cnt); #endif xc->vchg_mem[0] = '!'; @@ -1738,7 +1739,7 @@ if(xc->dump_size_limit) xc2->size_limit_locked = 1; xc2->is_initial_time = 1; /* to trick emit value and emit time change */ #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 } } @@ -2478,7 +2479,7 @@ if(xc) #ifndef FST_WRITER_PARALLEL 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); } #endif @@ -2760,7 +2761,7 @@ if((xc) && (handle <= xc->maxhandle)) xc->vchg_mem = realloc(xc->vchg_mem, xc->vchg_alloc_siz); 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); } } @@ -2874,7 +2875,7 @@ if((xc) && (handle <= xc->maxhandle)) xc->vchg_mem = realloc(xc->vchg_mem, xc->vchg_alloc_siz); 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); } } @@ -3119,7 +3120,7 @@ if(rc<0) { xc->fseek_failed = 1; #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"); #endif } @@ -3748,6 +3749,10 @@ if(!xc->fh) else /* FST_BL_SKIP */ { 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); @@ -4435,7 +4440,7 @@ if(gzread_pass_status) 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); } @@ -4726,7 +4731,7 @@ for(;;) if((sectype == EOF) || (sectype == FST_BL_SKIP)) { #ifdef FST_DEBUG - fprintf(stderr, "<< EOF >>\n"); + fprintf(stderr, FST_APIMESS"<< EOF >>\n"); #endif break; } @@ -4765,9 +4770,9 @@ for(;;) mem_required_for_traversal = fstReaderUint64(xc->f); mem_for_traversal = malloc(mem_required_for_traversal + 66); /* add in potential fastlz overhead */ #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); - 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 /* process time block */ { @@ -4785,7 +4790,7 @@ for(;;) tsec_clen = fstReaderUint64(xc->f); tsec_nitems = fstReaderUint64(xc->f); #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); #endif 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) { - printf("tsec uncompress rc = %d\n", rc); + fprintf(stderr, FST_APIMESS"fstReaderIterBlocks2(), tsec uncompress rc = %d, exiting.\n", rc); exit(255); } @@ -4881,7 +4886,7 @@ for(;;) rc = uncompress(mu, &destlen, mc, sourcelen); if(rc != Z_OK) { - printf("rc: %d\n", rc); + fprintf(stderr, FST_APIMESS"fstReaderIterBlocks2(), frame uncompress rc: %d, exiting.\n", rc); exit(255); } free(mc); @@ -5044,9 +5049,9 @@ for(;;) packtype = fgetc(xc->f); #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); - 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 indx_pntr = blkpos + seclen - 24 -tsec_clen -8; @@ -5054,7 +5059,7 @@ for(;;) chain_clen = fstReaderUint64(xc->f); indx_pos = indx_pntr - chain_clen; #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 chain_cmem = malloc(chain_clen); if(!chain_cmem) goto block_err; @@ -5173,7 +5178,7 @@ for(;;) } #ifdef FST_DEBUG - fprintf(stderr, "\tdecompressed chain idx len: %"PRIu32"\n", idx); + fprintf(stderr, FST_APIMESS"decompressed chain idx len: %"PRIu32"\n", idx); #endif mc_mem_len = 16384; @@ -5241,7 +5246,7 @@ for(;;) 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); } @@ -5793,9 +5798,9 @@ mem_required_for_traversal = fstReaderUint64(xc->f); #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); -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 /* process time block */ @@ -5814,7 +5819,7 @@ tsec_uclen = fstReaderUint64(xc->f); tsec_clen = fstReaderUint64(xc->f); tsec_nitems = fstReaderUint64(xc->f); #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); #endif ucdata = malloc(tsec_uclen); @@ -5831,7 +5836,7 @@ if(tsec_uclen != tsec_clen) 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); } @@ -5879,7 +5884,7 @@ if(frame_uclen == frame_clen) rc = uncompress(xc->rvat_frame_data, &destlen, mc, sourcelen); if(rc != Z_OK) { - printf("decompress rc: %d\n", rc); + fprintf(stderr, FST_APIMESS"fstReaderGetValueFromHandleAtTime(), frame decompress rc: %d, exiting.\n", rc); exit(255); } free(mc); @@ -5890,9 +5895,9 @@ xc->rvat_vc_start = ftello(xc->f); /* points to '!' character */ xc->rvat_packtype = fgetc(xc->f); #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); -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 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); indx_pos = indx_pntr - chain_clen; #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 chain_cmem = malloc(chain_clen); fstReaderFseeko(xc, xc->f, indx_pos, SEEK_SET); @@ -6011,7 +6016,7 @@ for(i=0;irvat_data_valid = 1; @@ -6071,7 +6076,7 @@ if(!xc->rvat_chain_mem) 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); } diff --git a/vpi/fstapi.h b/vpi/fstapi.h index df86ef079..e66c20467 100644 --- a/vpi/fstapi.h +++ b/vpi/fstapi.h @@ -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 * copy of this software and associated documentation files (the "Software"), @@ -168,7 +168,11 @@ enum fstHierType { FST_HT_ATTRBEGIN = 3, 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 { diff --git a/vpi/lz4.c b/vpi/lz4.c index 08cf6b5cd..c050cf1e0 100644 --- a/vpi/lz4.c +++ b/vpi/lz4.c @@ -825,7 +825,7 @@ _next_match: /* Match description too long : reduce it */ 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; if (matchLength>=ML_MASK) diff --git a/vpi/sdf_lexor.lex b/vpi/sdf_lexor.lex index 0b8c7767e..9f05dd230 100644 --- a/vpi/sdf_lexor.lex +++ b/vpi/sdf_lexor.lex @@ -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 * 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 # 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(); # endif # endif diff --git a/vpi/sys_display.c b/vpi/sys_display.c index b5e0737c8..30200d85a 100644 --- a/vpi/sys_display.c +++ b/vpi/sys_display.c @@ -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 * 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; switch (value) { + case 2: string = "100s"; break; + case 1: string = "10s"; break; case 0: string = "1s"; break; case -1: string = "100ms"; break; case -2: string = "10ms"; break; diff --git a/vpi/sys_readmem_lex.lex b/vpi/sys_readmem_lex.lex index 22e5b0e80..c7f4c53ef 100644 --- a/vpi/sys_readmem_lex.lex +++ b/vpi/sys_readmem_lex.lex @@ -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 * 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 # 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(); # endif # endif diff --git a/vpi/sys_sdf.c b/vpi/sys_sdf.c index 5d69ff623..9d3cd2b7b 100644 --- a/vpi/sys_sdf.c +++ b/vpi/sys_sdf.c @@ -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 * 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; 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"); 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)); vpi_printf("Unable to open SDF file \"%s\"." " Skipping this annotation.\n", fname); + vpi_free_object(argv); + free(fname); return 0; } diff --git a/vpi/table_mod_lexor.lex b/vpi/table_mod_lexor.lex index bd518ee7e..36031821b 100644 --- a/vpi/table_mod_lexor.lex +++ b/vpi/table_mod_lexor.lex @@ -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 * 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 # 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(); # endif # endif diff --git a/vvp/island_tran.cc b/vvp/island_tran.cc index 17240dc78..ae51b41f5 100644 --- a/vvp/island_tran.cc +++ b/vvp/island_tran.cc @@ -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 * 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__, unsigned width__, unsigned part__, - unsigned offset__); + unsigned offset__, bool resistive__); bool run_test_enabled(); void run_resolution(); void run_output(); vvp_net_t*en; unsigned width, part, offset; - bool active_high; + bool active_high, resistive; tran_state_t state; }; @@ -60,9 +60,10 @@ vvp_island_branch_tran::vvp_island_branch_tran(vvp_net_t*en__, bool active_high__, unsigned width__, unsigned part__, - unsigned offset__) + unsigned offset__, + bool resistive__) : en(en__), width(width__), part(part__), offset(offset__), - active_high(active_high__) + active_high(active_high__), resistive(resistive__) { 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. inline vvp_vector8_t resolve_ambiguous(const vvp_vector8_t&a, const vvp_vector8_t&b, - tran_state_t state) + tran_state_t state, + unsigned str_map[8]) { assert(a.size() == b.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) { vvp_scalar_t a_bit = a.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) { switch (b_bit.value()) { 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. if (branch->width == 0) { // There are no part selects. - dst_port->value = resolve_ambiguous(dst_port->value, val, - branch->state); + dst_port->value = resolve_ambiguous(dst_port->value, val, branch->state, + vvp_switch_strength_map[branch->resistive]); } else if (dst_ab == 1) { // 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, sense ? true : false, - 0, 0, 0); + 0, 0, 0, false); use_island->add_branch(br, pa, pb); @@ -430,7 +435,7 @@ void compile_island_tranvp(char*island, char*pa, char*pb, free(island); 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); diff --git a/vvp/lexor.lex b/vvp/lexor.lex index c6848a6cd..7ee563379 100644 --- a/vvp/lexor.lex +++ b/vvp/lexor.lex @@ -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 * and/or modify it in source code form under the terms of the GNU @@ -334,7 +334,7 @@ void destroy_lexor() { # ifdef FLEX_SCANNER # 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(); # endif # endif diff --git a/vvp/npmos.cc b/vvp/npmos.cc index 1359c9691..1eae2bc07 100644 --- a/vvp/npmos.cc +++ b/vvp/npmos.cc @@ -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 * and/or modify it in source code form under the terms of the GNU @@ -19,9 +19,10 @@ # 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; + 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) { + const unsigned*strength_map = vvp_switch_strength_map[resistive_]; + vvp_vector8_t out (bit_.size()); for (unsigned idx = 0 ; idx < out.size() ; idx += 1) { vvp_bit4_t b_en = en_.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) { case BIT4_0: 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_(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_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) return; - bit_ = resistive_reduction(bit); + bit_ = bit; 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. */ -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, @@ -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) { + const unsigned*strength_map = vvp_switch_strength_map[resistive_]; + vvp_vector8_t out (bit_.size()); 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_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) { out.set_bit(idx, b_bit); } 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_(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_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) return; - bit_ = resistive_reduction(bit); + bit_ = bit; generate_output_(ptr); } diff --git a/vvp/npmos.h b/vvp/npmos.h index cb6950685..9a91ca49d 100644 --- a/vvp/npmos.h +++ b/vvp/npmos.h @@ -1,7 +1,7 @@ #ifndef 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 * 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 { 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, vvp_context_t); @@ -62,7 +62,7 @@ class vvp_fun_pmos_ : public vvp_net_fun_t { vvp_vector8_t bit_; vvp_vector4_t en_; - bool inv_en_; + bool inv_en_, resistive_; }; 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 { public: - explicit vvp_fun_cmos_(); + explicit vvp_fun_cmos_(bool resistive); void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t &bit, vvp_context_t); @@ -126,6 +126,7 @@ class vvp_fun_cmos_ : public vvp_net_fun_t { vvp_vector8_t bit_; vvp_vector4_t n_en_; vvp_vector4_t p_en_; + bool resistive_; }; class vvp_fun_cmos : public vvp_fun_cmos_ { diff --git a/vvp/schedule.cc b/vvp/schedule.cc index e6d06604b..4556f5f9d 100644 --- a/vvp/schedule.cc +++ b/vvp/schedule.cc @@ -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 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: - if (ctim->start == 0) { - ctim->start = cur; - } else { - cur->next = ctim->active->next; - ctim->active->next = cur; - ctim->active = cur; - } + q = &ctim->start; break; case SEQ_ACTIVE: - if (ctim->active == 0) { - 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; - } + q = &ctim->active; break; case SEQ_NBASSIGN: - if (ctim->nbassign == 0) { - 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; - } + q = &ctim->nbassign; break; case SEQ_RWSYNC: - if (ctim->rwsync == 0) { - 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; - } + q = &ctim->rwsync; break; case SEQ_ROSYNC: - if (ctim->rosync == 0) { - 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; - } + q = &ctim->rosync; break; case DEL_THREAD: - if (ctim->del_thr == 0) { - 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; - } + q = &ctim->del_thr; 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) diff --git a/vvp/vpi_callback.cc b/vvp/vpi_callback.cc index 7a3995ec6..77d7bc4ae 100644 --- a/vvp/vpi_callback.cc +++ b/vvp/vpi_callback.cc @@ -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 * 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) { 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))) { rval = 0.0; } else { - if (rval >= 0.0) rval = floor(rval + 0.5); - else rval = ceil(rval - 0.5); + rval = vlg_round(rval); } vp->value.integer = (PLI_INT32)rval; break; case vpiDecStrVal: -#if !defined(__GNUC__) - if (isnan(rval)) - sprintf(rbuf, "%s", "nan"); - else - sprintf(rbuf, "%0.0f", rval); -#else - sprintf(rbuf, "%0.0f", rval); -#endif + if (isnan(rval)) + sprintf(rbuf, "%s", "nan"); + else + sprintf(rbuf, "%0.0f", vlg_round(rval)); vp->value.str = rbuf; break; case vpiHexStrVal: - sprintf(rbuf, "%lx", (long)rval); + sprintf(rbuf, "%lx", (long)vlg_round(rval)); vp->value.str = rbuf; break; case vpiBinStrVal: { - unsigned long val = (unsigned long)rval; + unsigned long val = (unsigned long)vlg_round(rval); unsigned len = 0; while (val > 0) { @@ -829,7 +833,7 @@ static void real_signal_value(struct t_vpi_value*vp, double rval) val /= 2; } - val = (unsigned long)rval; + val = (unsigned long)vlg_round(rval); for (unsigned idx = 0 ; idx < len ; idx += 1) { rbuf[len-idx-1] = (val & 1)? '1' : '0'; val /= 2; diff --git a/vvp/vpi_priv.h b/vvp/vpi_priv.h index ab8c0cc46..a54ec29b6 100644 --- a/vvp/vpi_priv.h +++ b/vvp/vpi_priv.h @@ -339,7 +339,8 @@ extern vpiHandle vpip_make_int4(const char*name, int msb, int lsb, vvp_net_t*vec); extern vpiHandle vpip_make_var4(const char*name, int msb, int lsb, 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); /* @@ -506,7 +507,9 @@ struct __vpiRealVar : public __vpiHandle { }; 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 { diff --git a/vvp/vpi_real.cc b/vvp/vpi_real.cc index acc426b68..526ac6113 100644 --- a/vvp/vpi_real.cc +++ b/vvp/vpi_real.cc @@ -178,7 +178,8 @@ vpiHandle __vpiRealVar::vpi_handle(int code) vpiHandle __vpiRealVar::vpi_iterate(int code) { 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; @@ -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->net = net; - obj->within.scope = vpip_peek_current_scope(); + obj->within.scope = scope; 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 void real_delete(vpiHandle item) { diff --git a/vvp/vpi_signal.cc b/vvp/vpi_signal.cc index 243254853..27965db4d 100644 --- a/vvp/vpi_signal.cc +++ b/vvp/vpi_signal.cc @@ -132,9 +132,19 @@ char *generic_get_str(int code, vpiHandle ref, const char *name, const char *ind return res; } -static vpiHandle fill_in_net4(struct __vpiSignal*obj, - const char*name, int msb, int lsb, - bool signed_flag, vvp_net_t*node); +static vpiHandle fill_in_net4(struct __vpiSignal*obj, __vpiScope*scope, + const char*name, int msb, int lsb, + 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. @@ -972,7 +982,7 @@ struct signal_longint : public __vpiSignal { vpiHandle vpip_make_int4(const char*name, int msb, int lsb, vvp_net_t*vec) { __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) { __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 @@ -1116,7 +1126,7 @@ void signal_pool_delete() * The name is the PLI name for the object. If it is an array it is * []. */ -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, 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 // attached to an array, then this value will be replaced with // the handle to the parent. - obj->within.scope = vpip_peek_current_scope(); + obj->within.scope = scope; count_vpi_nets += 1; 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) { 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) diff --git a/vvp/vpi_vthr_vector.cc b/vvp/vpi_vthr_vector.cc index c001767f9..4b4c580de 100644 --- a/vvp/vpi_vthr_vector.cc +++ b/vvp/vpi_vthr_vector.cc @@ -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 * * 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) { 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))) { val = 0.0; } else { - if (val >= 0.0) val = floor(val + 0.5); - else val = ceil(val - 0.5); + val = vlg_round(val); } vp->value.integer = (PLI_INT32)val; break; case vpiDecStrVal: -#if !defined(__GNUC__) - if (isnan(val)) - sprintf(rbuf, "%s", "nan"); - else - sprintf(rbuf, "%0.0f", val); -#else - sprintf(rbuf, "%0.0f", val); -#endif + if (isnan(val)) + sprintf(rbuf, "%s", "nan"); + else + sprintf(rbuf, "%0.0f", vlg_round(val)); + vp->value.str = rbuf; + break; + + case vpiOctStrVal: + sprintf(rbuf, "%lo", (long)vlg_round(val)); vp->value.str = rbuf; break; case vpiHexStrVal: - sprintf(rbuf, "%lx", (long)val); + sprintf(rbuf, "%lx", (long)vlg_round(val)); vp->value.str = rbuf; break; case vpiBinStrVal: { - unsigned long vali = (unsigned long)val; + unsigned long vali = (unsigned long)vlg_round(val); unsigned len = 0; while (vali > 0) { @@ -140,7 +149,7 @@ static void vthr_real_get_value(vpiHandle ref, s_vpi_value*vp) vali /= 2; } - vali = (unsigned long)val; + vali = (unsigned long)vlg_round(val); for (unsigned idx = 0 ; idx < len ; idx += 1) { rbuf[len-idx-1] = (vali & 1)? '1' : '0'; 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_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_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_vector_(p_vpi_value vp, const vvp_vector4_t&val); private: @@ -346,6 +356,9 @@ void __vpiVThrVec4Stack::vpi_get_value(p_vpi_value vp) case vpiDecStrVal: vpi_get_value_decstr_(vp, val); break; + case vpiOctStrVal: + vpi_get_value_octstr_(vp, val); + break; case vpiHexStrVal: vpi_get_value_hexstr_(vp, val); break; @@ -396,6 +409,48 @@ void __vpiVThrVec4Stack::vpi_get_value_decstr_(p_vpi_value vp, const vvp_vector4 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) { unsigned wid = val.size(); diff --git a/vvp/vthread.cc b/vvp/vthread.cc index 49fa73b94..f2b1760cb 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -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 * 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; - 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 // that it is possible to be waiting in a %join yet // 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) schedule_vthread(parent, 0, true); - // Let the parent do the reaping. - vthread_reap(thr); + do_join(parent, thr); } else if (parent) { /* 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) { vvp_vector4_t tmp(wid, BIT4_X); 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 { long tmpa = (long) ap[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 have ended, and schedule that parent. Also, finish the %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; assert(! thr->i_am_detached); @@ -3768,6 +3771,9 @@ bool of_MOD_S(vthread_t thr, vvp_code_t) if (rv == 0) goto x_out; + if ((lv == LONG_LONG_MIN) && (rv == -1)) + goto zero_out; + /* Sign extend the signed operands when needed. */ if (wid < 8*sizeof(long long)) { if (lv & (1LL << (wid-1))) @@ -3799,6 +3805,9 @@ bool of_MOD_S(vthread_t thr, vvp_code_t) x_out: vala = vvp_vector4_t(wid, BIT4_X); return true; + zero_out: + vala = vvp_vector4_t(wid, BIT4_0); + return true; } /* diff --git a/vvp/vvp_darray.cc b/vvp/vvp_darray.cc index 3c8086c03..94e940f45 100644 --- a/vvp/vvp_darray.cc +++ b/vvp/vvp_darray.cc @@ -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; } +void vvp_darray::shallow_copy(const vvp_object*) +{ + cerr << "XXXX shallow_copy(vvp_object_t) not implemented for " << typeid(*this).name() << endl; +} + template vvp_darray_atom::~vvp_darray_atom() { } @@ -101,6 +106,16 @@ template void vvp_darray_atom::get_word(unsigned adr, vvp_vec value = tmp; } +template void vvp_darray_atom::shallow_copy(const vvp_object*obj) +{ + const vvp_darray_atom*that = dynamic_cast*>(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; template class vvp_darray_atom; template class vvp_darray_atom; @@ -140,6 +155,16 @@ void vvp_darray_vec4::get_word(unsigned adr, vvp_vector4_t&value) assert(value.size() == word_wid_); } +void vvp_darray_vec4::shallow_copy(const vvp_object*obj) +{ + const vvp_darray_vec4*that = dynamic_cast(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() { } @@ -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(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() { @@ -200,6 +234,16 @@ void vvp_darray_object::get_word(unsigned adr, vvp_object_t&value) value = array_[adr]; } +void vvp_darray_object::shallow_copy(const vvp_object*obj) +{ + const vvp_darray_object*that = dynamic_cast(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() { } @@ -226,6 +270,16 @@ void vvp_darray_real::get_word(unsigned adr, double&value) value = array_[adr]; } +void vvp_darray_real::shallow_copy(const vvp_object*obj) +{ + const vvp_darray_real*that = dynamic_cast(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() { } @@ -252,6 +306,16 @@ void vvp_darray_string::get_word(unsigned adr, string&value) value = array_[adr]; } +void vvp_darray_string::shallow_copy(const vvp_object*obj) +{ + const vvp_darray_string*that = dynamic_cast(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() { } diff --git a/vvp/vvp_darray.h b/vvp/vvp_darray.h index e6d164698..4de0f9a13 100644 --- a/vvp/vvp_darray.h +++ b/vvp/vvp_darray.h @@ -44,6 +44,8 @@ class vvp_darray : public vvp_object { virtual void set_word(unsigned adr, const vvp_object_t&value); virtual void get_word(unsigned adr, vvp_object_t&value); + + virtual void shallow_copy(const vvp_object*obj); }; template class vvp_darray_atom : public vvp_darray { @@ -55,6 +57,7 @@ template class vvp_darray_atom : public vvp_darray { size_t get_size(void) const; void set_word(unsigned adr, const vvp_vector4_t&value); void get_word(unsigned adr, vvp_vector4_t&value); + void shallow_copy(const vvp_object*obj); private: std::vector array_; @@ -70,6 +73,7 @@ class vvp_darray_vec4 : public vvp_darray { size_t get_size(void) const; void set_word(unsigned adr, const vvp_vector4_t&value); void get_word(unsigned adr, vvp_vector4_t&value); + void shallow_copy(const vvp_object*obj); private: std::vector array_; @@ -86,6 +90,7 @@ class vvp_darray_vec2 : public vvp_darray { size_t get_size(void) const; void set_word(unsigned adr, const vvp_vector4_t&value); void get_word(unsigned adr, vvp_vector4_t&value); + void shallow_copy(const vvp_object*obj); private: std::vector array_; @@ -101,6 +106,7 @@ class vvp_darray_real : public vvp_darray { size_t get_size(void) const; void set_word(unsigned adr, double value); void get_word(unsigned adr, double&value); + void shallow_copy(const vvp_object*obj); private: std::vector array_; @@ -115,6 +121,7 @@ class vvp_darray_string : public vvp_darray { size_t get_size(void) const; void set_word(unsigned adr, const std::string&value); void get_word(unsigned adr, std::string&value); + void shallow_copy(const vvp_object*obj); private: std::vector array_; @@ -129,6 +136,7 @@ class vvp_darray_object : public vvp_darray { size_t get_size(void) const; void set_word(unsigned adr, const vvp_object_t&value); void get_word(unsigned adr, vvp_object_t&value); + void shallow_copy(const vvp_object*obj); private: std::vector array_; diff --git a/vvp/vvp_net.cc b/vvp/vvp_net.cc index 7a3c3bb7b..544dfa624 100644 --- a/vvp/vvp_net.cc +++ b/vvp/vvp_net.cc @@ -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 * 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) { assert(idx < nports_); - assert(port_values_); + if (port_values_ == 0) + port_values_ = new vvp_vector4_t [nports_]; return port_values_[idx]; } @@ -3685,31 +3686,28 @@ vvp_scalar_t fully_featured_resolv_(vvp_scalar_t a, vvp_scalar_t b) return res; } -vvp_vector8_t resistive_reduction(const vvp_vector8_t&that) -{ - static unsigned rstr[8] = { - 0, /* Hi-Z --> Hi-Z */ - 1, /* Small capacitance --> Small capacitance */ - 1, /* Medium capacitance --> Small capacitance */ - 2, /* Weak drive --> Medium capacitance */ - 2, /* Large capacitance --> Medium capacitance */ - 3, /* Pull drive --> Weak drive */ - 5, /* Strong 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); +unsigned vvp_switch_strength_map[2][8] = { + { // non-resistive + 0, /* High impedance --> High impedance */ + 1, /* Small capacitor --> Small capacitor */ + 2, /* Medium capacitor --> Medium capacitor */ + 3, /* Weak drive --> Weak drive */ + 4, /* Large capacitor --> Large capacitor */ + 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 */ + 5, /* Strong drive --> Pull drive */ + 5 /* Supply drive --> Pull drive */ } - - return res; -} +}; vvp_vector4_t reduce4(const vvp_vector8_t&that) { diff --git a/vvp/vvp_net.h b/vvp/vvp_net.h index a59045780..625ef7393 100644 --- a/vvp/vvp_net.h +++ b/vvp/vvp_net.h @@ -1,7 +1,7 @@ #ifndef 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 * 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; } - /* This function implements the strength reduction implied by - Verilog standard resistive devices. */ -extern vvp_vector8_t resistive_reduction(const vvp_vector8_t&a); + /* This lookup tabke implements the strength reduction implied by + Verilog standard switch devices. The major dimension selects + between non-resistive and resistive devices. */ +extern unsigned vvp_switch_strength_map[2][8]; + /* The reduce4 function converts a vector8 to a vector4, losing strength information in the process. */ extern vvp_vector4_t reduce4(const vvp_vector8_t&that); diff --git a/vvp/words.cc b/vvp/words.cc index 139171032..f88864e5c 100644 --- a/vvp/words.cc +++ b/vvp/words.cc @@ -48,7 +48,7 @@ static void __compile_var_real(char*label, char*name, 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); if (name) { @@ -350,7 +350,7 @@ static void do_compile_net(vvp_net_t*node, vvp_array_t array, vpiHandle obj = 0; if (! local_flag) { /* 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 */ 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; 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); } #ifdef CHECK_WITH_VALGRIND