From 7b372c3a0c43adcca9302aa67021174302e3e156 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Mon, 11 Sep 2017 21:49:35 +0100 Subject: [PATCH 01/30] Fix for GitHub issue #162 : very wide busses cause assertion failure. This occurs when tgt-vvp attempts to generate a C4<..> constant value with a bit width >= 65536. The actual failure occurs in the StringHeap class, which originally supported a maximum string length of 65535. This fix enables the StringHeap class to support any size string (provided the system has sufficient memory). (cherry picked from commit c855b8926e9a950d5d65e35b443e2ad7f6d20015) --- libmisc/StringHeap.cc | 24 ++++++++++++++---------- libmisc/StringHeap.h | 4 ++-- 2 files changed, 16 insertions(+), 12 deletions(-) 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&); From 885e25120a4fb10bed854b8aa36825b02759b2fb Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sun, 17 Sep 2017 19:48:54 +0100 Subject: [PATCH 02/30] Fix use after free bug in vvp when a task or function is disabled. Use test_joinable() and do_join() to ensure everything gets cleaned up before the thread is reaped. This should fix br1016, br1017, and br1018. (cherry picked from commit 0bed890bc61542cac8b0785136a7620e33206aa0) (and subsequent fixup) --- vvp/vthread.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vvp/vthread.cc b/vvp/vthread.cc index 49fa73b94..07269b295 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -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,7 +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. +// do_join(parent, thr); vthread_reap(thr); } else if (parent) { From a3a8669c6f56f11742c7350aff659527b0389076 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sun, 17 Sep 2017 19:58:13 +0100 Subject: [PATCH 03/30] Fix error in last commit. (cherry picked from commit a1a7f5deff4e3c8262c1924f12f28a11a6228413) --- vvp/vthread.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/vvp/vthread.cc b/vvp/vthread.cc index 07269b295..1b4e806f8 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -2210,8 +2210,7 @@ static bool do_disable(vthread_t thr, vthread_t match) if (! parent->i_have_ended) schedule_vthread(parent, 0, true); -// do_join(parent, thr); - vthread_reap(thr); + do_join(parent, thr); } else if (parent) { /* If the parent is yet to %join me, let its %join From 95d35795099c28673067882d02ceeb947b04a91b Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Thu, 28 Sep 2017 19:24:04 +0100 Subject: [PATCH 04/30] Fix for GitHub issue #163 : assertion failure caused by syntax error in task. (cherry picked from commit 3566ff4cd4abff790b68737f0bcbe5ee1a7c87fe) --- parse.y | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/parse.y b/parse.y index cc7ff53da..da95f2b73 100644 --- a/parse.y +++ b/parse.y @@ -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 From 6b11df199994892e9e9b671d81bfe1ba194692ff Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Wed, 4 Oct 2017 21:31:56 +0100 Subject: [PATCH 05/30] Fix for br1025 : support nested scopes in root level tasks/functions. (cherry picked from commit 85fa24fa58021552e14ed68b6c5932503179cdd3) --- t-dll.cc | 7 +++++++ 1 file changed, 7 insertions(+) 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; } From bccb7e7defb578a614730f345d555831700d8052 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sat, 7 Oct 2017 16:41:26 +0100 Subject: [PATCH 06/30] Fix for GitHub issue #165 : assertion failure on thread join. If a thread becomes detached due to a join_any statement, that thread must not attempt to join its parent, even if the parent is waiting on a subsequent join statement. (cherry picked from commit e315cafa0167d86620802ab0663247ee4f5f708b) --- vvp/vthread.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vvp/vthread.cc b/vvp/vthread.cc index 1b4e806f8..4696776e0 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -2613,7 +2613,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); From a907200fb91f10d3d813598f9b2f70fb217cf850 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sun, 8 Oct 2017 12:59:30 +0100 Subject: [PATCH 07/30] Generate proper error messages for invalid dynamic array initialisers. Invalid user code should not result in an "internal_error". (cherry picked from commit 8a36849fdaecdbf6309e47471bdbf1f18c274e12) --- elab_expr.cc | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/elab_expr.cc b/elab_expr.cc index 7eb4bedd8..f0618b4c3 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -3440,29 +3440,29 @@ 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; + cerr << get_fileline() << ": error: the type of the variable '" + << path_ << "' doesn't match the context type." << endl; - cerr << get_fileline() << ": : " - << "net type="; + 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())); From 09c7c439a1c25a2069fae2a579405d2d8037034d Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sun, 8 Oct 2017 13:55:55 +0100 Subject: [PATCH 08/30] Add support for vec4 darray initialisation from an array pattern. This was just a missing case label in tgt-vvp. (cherry picked from commit 1aeaafa96c29ed0db35bc7b0d37da0578fc95111) --- tgt-vvp/eval_object.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tgt-vvp/eval_object.c b/tgt-vvp/eval_object.c index fb6240d17..2bcd1500e 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); From 1f7588d3a4ff43f961463f801a8f3665f1297cd2 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sun, 8 Oct 2017 13:52:50 +0100 Subject: [PATCH 09/30] Add support for darray initialisation from another darray. Fixes GitHub issue #164. (cherry picked from commit 5ca058bfb5fdb6fdc3382e10895b2d8ba75385c7) --- elab_expr.cc | 19 +++++++++++-- tgt-vvp/eval_object.c | 5 ++++ vvp/vvp_darray.cc | 64 +++++++++++++++++++++++++++++++++++++++++++ vvp/vvp_darray.h | 8 ++++++ 4 files changed, 94 insertions(+), 2 deletions(-) diff --git a/elab_expr.cc b/elab_expr.cc index f0618b4c3..eae0a0df5 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -3446,6 +3446,18 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope, return 0; } + 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; + } + + // 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; @@ -5318,9 +5330,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 +5582,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/tgt-vvp/eval_object.c b/tgt-vvp/eval_object.c index 2bcd1500e..7a307b150 100644 --- a/tgt-vvp/eval_object.c +++ b/tgt-vvp/eval_object.c @@ -111,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/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_; From a18fe22d321ba85a060b65236149a63fd88b45fa Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sun, 8 Oct 2017 20:45:07 +0100 Subject: [PATCH 10/30] Fix for GitHub issue #98 and #167 Two fixes needed: - when searching for a base class, we need to look in the root scope if the base class isn't found in the scope hierarchy - the classes in the root scope need to be stored in an ordered list, not a map, to ensure they are elaborated in the order they were declared. Without this, the compiler may try elaborating an extended class before its base class is known about. (cherry picked from commit 87cddf33dcadec01bf2738a297aa4ea7572bb189) --- elab_scope.cc | 18 ++++++++---------- main.cc | 7 +++---- parse_api.h | 4 ++-- pform.cc | 6 +++--- 4 files changed, 16 insertions(+), 19 deletions(-) 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/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/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; } From bb2e270087482202c0cd3d35ecad87c99bc585f7 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sun, 8 Oct 2017 21:16:50 +0100 Subject: [PATCH 11/30] Enable base class tasks to be used in an extended class. (cherry picked from commit 4f383a8a119b8dc00c1fa6491c44e08f1309b8b1) --- netclass.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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; } From 1b0843c94c49e5b495dba08ca9bcf7e4464730a7 Mon Sep 17 00:00:00 2001 From: Cary R Date: Sun, 22 Oct 2017 19:39:07 -0700 Subject: [PATCH 12/30] Update to latest files from GTKWave --- vpi/fstapi.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) 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 { From dec9a8b5274783c38b42f5ee2511fe50fab890f6 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sun, 5 Nov 2017 09:26:33 +0000 Subject: [PATCH 13/30] Fix $printtimescale to support 10s and 100s values. (cherry picked from commit e54d19e2d2f3838cd23e8027ec4ef6162d9ed7cf) --- vpi/sys_display.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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; From a74c3a12070de428ae93eaaa1ae243c665fde19e Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sun, 5 Nov 2017 09:35:02 +0000 Subject: [PATCH 14/30] Factor out common code for warning about inconsistent timescales. Also reword the warning for SystemVerilog, where `timescale is not the only (or indeed preferred) way of specifying timescales. (cherry picked from commit 9382d22063fc2e0b0636eced774610c222d1c36c) --- PDelays.cc | 21 ++------------------- elaborate.cc | 28 ++-------------------------- netmisc.cc | 37 ++++++++++++++++++++++++++++++++++++- netmisc.h | 12 +++++++----- 4 files changed, 47 insertions(+), 51 deletions(-) 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/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/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 */ From 99f66e2781a81aa0eef67099d450fffd71538ce3 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Tue, 7 Nov 2017 18:48:48 +0000 Subject: [PATCH 15/30] Fix for GitHub issue #169: nets can get given wrong scope in VPI. In vvp, the __vpiSignal object holds a pointer to the scope containing the signal. This was getting set to the current scope when the net was finally resolved, rather than to the scope where the net was declared. (cherry picked from commit c622d372f90f721b2750f74d042c597d17744958) --- vvp/vpi_priv.h | 7 +++++-- vvp/vpi_real.cc | 16 ++++++++++++++-- vvp/vpi_signal.cc | 31 +++++++++++++++++++++---------- vvp/words.cc | 6 +++--- 4 files changed, 43 insertions(+), 17 deletions(-) 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/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 From 03764a400d6a9cd7757ecacf046a30c678efe17d Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Wed, 8 Nov 2017 20:35:18 +0000 Subject: [PATCH 16/30] Fix assertion failure in vvp wide functor. If the functor output is read before any values have propagated to the functor inputs, the internal storage won't have been initialised. (cherry picked from commit ad83a135e51f8eeeba4bf51225a13cab6459e021) --- vvp/vvp_net.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/vvp/vvp_net.cc b/vvp/vvp_net.cc index 7a3c3bb7b..9b0c83a5d 100644 --- a/vvp/vvp_net.cc +++ b/vvp/vvp_net.cc @@ -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]; } From cc3e9d791a7bd66201127e87b8cd5b7c3260d366 Mon Sep 17 00:00:00 2001 From: Cary R Date: Thu, 16 Nov 2017 19:16:22 -0800 Subject: [PATCH 17/30] Update flex destroy to work for version 2.6 and greater --- driver/cflexor.lex | 4 ++-- ivlpp/lexor.lex | 2 +- lexor.lex | 2 +- tgt-pcb/fp.lex | 7 +++++-- vhdlpp/lexor.lex | 11 ++++++++++- vpi/sdf_lexor.lex | 4 ++-- vpi/sys_readmem_lex.lex | 4 ++-- vpi/table_mod_lexor.lex | 4 ++-- vvp/lexor.lex | 4 ++-- 9 files changed, 27 insertions(+), 15 deletions(-) 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/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/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/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/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_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/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/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 From 94861872e575af37cda837b06f3f557d184ca723 Mon Sep 17 00:00:00 2001 From: Cary R Date: Thu, 16 Nov 2017 19:40:09 -0800 Subject: [PATCH 18/30] Fix a couple memory leaks in $sdf_annotate() --- vpi/sys_sdf.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) 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; } From dab896c4632a6bb07a9d6052c1bd1bbd86e29225 Mon Sep 17 00:00:00 2001 From: Cary R Date: Tue, 5 Dec 2017 21:48:33 -0800 Subject: [PATCH 19/30] The delay for a join_any and join_none is different than join --- netlist.cc | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) 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; } } } From 480fb0b418c483933c7185edec2ecdb0b5cc114b Mon Sep 17 00:00:00 2001 From: Cary R Date: Wed, 13 Dec 2017 21:55:27 -0800 Subject: [PATCH 20/30] Update tp the latest files from GTKWave --- vpi/lz4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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) From 6dce878638d09f714eb83921932db9479283fbe3 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Tue, 20 Feb 2018 20:59:26 +0000 Subject: [PATCH 21/30] Fix for br1027: incorrect inference of task/function port direction. In traditional Verilog, each task_port_item must have an explicit port direction. In SystemVerilog, if the port direction is not specified, it should be inherited from the preceding task_port_item for that task/function, and only the first task_port_item should infer the direction to be 'input'. (cherry picked from commit 6b1b402a790d29a7948897d33462b934c2e97cca) --- parse.y | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/parse.y b/parse.y index da95f2b73..9544382f6 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 @@ -2122,10 +2122,14 @@ 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==NetNet::PIMPLICIT ? port_declaration_context.port_type : $1; 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 @@ -2137,7 +2141,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 @@ -2184,8 +2187,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(); @@ -2211,11 +2221,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; } From fc62c914961c134b24293065dee8680fc66c9242 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Wed, 21 Feb 2018 20:07:13 +0000 Subject: [PATCH 22/30] Improved check for missing task/function port direction. (cherry picked from commit 69d80839a5156202ea3b0704218bde5bc31424fb) --- parse.y | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/parse.y b/parse.y index 9544382f6..cfaa6617a 100644 --- a/parse.y +++ b/parse.y @@ -2122,7 +2122,9 @@ 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 ? port_declaration_context.port_type : $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); From 02e220097dfbf0fe76ad4d41b24ed3c7b346c4a9 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Fri, 23 Feb 2018 22:07:59 +0000 Subject: [PATCH 23/30] Implement supply->strong strength reduction for non-resistive switches. As specified in 1364-2005 section 7.11. (cherry picked from commit 36eef5154ff156703fbe99ab43901b8e33f7d557) --- vvp/island_tran.cc | 25 ++++++++++++++---------- vvp/npmos.cc | 32 ++++++++++++++++++++++--------- vvp/npmos.h | 9 +++++---- vvp/vvp_net.cc | 47 ++++++++++++++++++++++------------------------ vvp/vvp_net.h | 10 ++++++---- 5 files changed, 71 insertions(+), 52 deletions(-) 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/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/vvp_net.cc b/vvp/vvp_net.cc index 9b0c83a5d..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 @@ -3686,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); From 0f28b03dd3ba8908029c53c0500c8c2cfe74a90a Mon Sep 17 00:00:00 2001 From: Yury Gribov Date: Sun, 10 Jul 2016 20:37:35 +0100 Subject: [PATCH 24/30] Put start events to proper queue. (cherry picked from commit 43cd693fe07b16467b2d66cc9678dfcb63ff485c) --- vvp/schedule.cc | 70 ++++++++++++------------------------------------- 1 file changed, 17 insertions(+), 53 deletions(-) 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) From 24731227b452b68396044a5e34eb18c76d8ecd81 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sat, 12 May 2018 23:40:29 +0100 Subject: [PATCH 25/30] Fix br1029 - correct rounding when vpi_get_value converts real to integer string. (cherry picked from commit 5a4e99b0e8a973a5e8002ae76da0d46d83236547) --- vvp/vpi_callback.cc | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) 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; From 7df0f0c65930c0ba4a767c467cde379e078df0f5 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Mon, 14 May 2018 22:14:51 +0100 Subject: [PATCH 26/30] Further fix for br1029. The code in vpi_callback.cc is replicated in vpi_vthr_vector.cc, so we have to replicate the fix. This should really be factored out. (cherry picked from commit 6e49ab10ec13a7c90deb07195724e917eb5188ec) --- vvp/vpi_vthr_vector.cc | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/vvp/vpi_vthr_vector.cc b/vvp/vpi_vthr_vector.cc index c001767f9..fd1368439 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,26 @@ 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 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 +144,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; From e79d226082f66071a06683a70a4b7a6b89be335f Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Mon, 14 May 2018 21:30:56 +0100 Subject: [PATCH 27/30] Don't allow non-vectorable arguments to $signed/$unsigned. This led to an assertion failure in many cases (see br1029). 1364-2012 indicates it is illegal. (cherry picked from commit 87c01c55c05a13bf2a471a8600346809ab85040d) --- elab_expr.cc | 9 ++++++++- vhdlpp/std_funcs.cc | 4 ++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/elab_expr.cc b/elab_expr.cc index eae0a0df5..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; 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; From 703363feafa60cb567e8863324fb07ed54ba8aaa Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Tue, 12 Jun 2018 21:59:58 +0100 Subject: [PATCH 28/30] Fix for GitHub issue #199: handle signed division overflow. When performing a signed division or modulus operation using native arithmetic, trap the special case that the numerator is the minimum integer value and the denominator is -1, as this gives an undefined result in C++. (cherry picked from commit 7ad5b59a6f7d2e46aefe9dbb85bcc8ea1c7dd9b5) --- verinum.cc | 9 ++++++--- vvp/vthread.cc | 12 +++++++++++- 2 files changed, 17 insertions(+), 4 deletions(-) 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/vvp/vthread.cc b/vvp/vthread.cc index 4696776e0..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 @@ -2517,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]; @@ -3767,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))) @@ -3798,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; } /* From 52b136d8a89b9cedd8d0ea8740255a2a5a0347d3 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Tue, 12 Jun 2018 22:58:07 +0100 Subject: [PATCH 29/30] Fix for GitHub issue #198 - support octal display for thread variables. (cherry picked from commit 11c826216a63cfeefe05f79f7023f669ef6e962a) --- vvp/vpi_vthr_vector.cc | 51 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/vvp/vpi_vthr_vector.cc b/vvp/vpi_vthr_vector.cc index fd1368439..4b4c580de 100644 --- a/vvp/vpi_vthr_vector.cc +++ b/vvp/vpi_vthr_vector.cc @@ -130,6 +130,11 @@ static void vthr_real_get_value(vpiHandle ref, s_vpi_value*vp) 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)vlg_round(val)); vp->value.str = rbuf; @@ -283,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: @@ -350,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; @@ -400,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(); From ab6ae797b3dab2ac38899b71a60dcb14dd5981fa Mon Sep 17 00:00:00 2001 From: Cary R Date: Mon, 16 Jul 2018 09:02:24 -0700 Subject: [PATCH 30/30] Update fstapi.c to the latest version --- vpi/fstapi.c | 69 ++++++++++++++++++++++++++++------------------------ 1 file changed, 37 insertions(+), 32 deletions(-) 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); }