From a69de8b94aa6e26a8ef2f102ae99c3e83b6a3d47 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sat, 22 Aug 2020 22:33:01 +0100 Subject: [PATCH] Rework last value storage in vvp_fun_anyedge functors. This prepares the way to support strings and object handle values. --- vvp/event.cc | 172 ++++++++++++++++++++++++++++++++++++++++++--------- vvp/event.h | 17 +++-- 2 files changed, 152 insertions(+), 37 deletions(-) diff --git a/vvp/event.cc b/vvp/event.cc index 6c6c7fe00..b94207ba6 100644 --- a/vvp/event.cc +++ b/vvp/event.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2018 Stephen Williams (steve@icarus.com) + * Copyright (c) 2004-2020 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 @@ -343,29 +343,114 @@ void vvp_fun_edge_aa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit, } } +class anyedge_value { + + public: + anyedge_value() {}; + virtual ~anyedge_value() {}; + + virtual void reset() = 0; + + virtual void duplicate(anyedge_value*&dup) = 0; +}; + +class anyedge_vec4_value : public anyedge_value { + + public: + anyedge_vec4_value() {}; + virtual ~anyedge_vec4_value() {}; + + void reset() { old_bits.set_to_x(); } + + void set(const vvp_vector4_t&bit) { old_bits = bit; }; + + void duplicate(anyedge_value*&dup); + + bool recv_vec4(const vvp_vector4_t&bit); + + bool recv_vec4_pv(const vvp_vector4_t&bit, unsigned base, + unsigned wid, unsigned vwid); + + private: + vvp_vector4_t old_bits; +}; + +static anyedge_vec4_value*get_vec4_value(anyedge_value*&value) +{ + anyedge_vec4_value*vec4_value = dynamic_cast(value); + if (!value) { + vec4_value = new anyedge_vec4_value(); + delete value; + value = vec4_value; + } + return vec4_value; +} + +class anyedge_real_value : public anyedge_value { + + public: + anyedge_real_value() : old_bits(0.0) {}; + virtual ~anyedge_real_value() {}; + + void reset() { old_bits = 0.0; } + + void set(double bit) { old_bits = bit; }; + + void duplicate(anyedge_value*&dup); + + bool recv_real(double bit); + + private: + double old_bits; +}; + +static anyedge_real_value*get_real_value(anyedge_value*&value) +{ + anyedge_real_value*real_value = dynamic_cast(value); + if (!value) { + real_value = new anyedge_real_value(); + delete value; + value = real_value; + } + return real_value; +} + struct vvp_fun_anyedge_state_s : public waitable_state_s { vvp_fun_anyedge_state_s() { for (unsigned idx = 0 ; idx < 4 ; idx += 1) - bitsr[idx] = 0.0; + last_value_[idx] = 0; } - vvp_vector4_t bits[4]; - double bitsr[4]; + ~vvp_fun_anyedge_state_s() + { + for (unsigned idx = 0 ; idx < 4 ; idx += 1) + delete last_value_[idx]; + } + + anyedge_value *last_value_[4]; }; vvp_fun_anyedge::vvp_fun_anyedge() { for (unsigned idx = 0 ; idx < 4 ; idx += 1) - bitsr_[idx] = 0.0; + last_value_[idx] = 0; } vvp_fun_anyedge::~vvp_fun_anyedge() { + for (unsigned idx = 0 ; idx < 4 ; idx += 1) + delete last_value_[idx]; } -bool vvp_fun_anyedge::recv_vec4_(const vvp_vector4_t&bit, - vvp_vector4_t&old_bits, vthread_t&threads) +void anyedge_vec4_value::duplicate(anyedge_value*&dup) +{ + anyedge_vec4_value*dup_vec4 = get_vec4_value(dup); + assert(dup_vec4); + dup_vec4->set(old_bits); +} + +bool anyedge_vec4_value::recv_vec4(const vvp_vector4_t&bit) { bool flag = false; @@ -396,18 +481,36 @@ bool vvp_fun_anyedge::recv_vec4_(const vvp_vector4_t&bit, if (flag) { old_bits = bit; - run_waiting_threads_(threads); } return flag; } -bool vvp_fun_anyedge::recv_real_(double bit, - double&old_bits, vthread_t&threads) +bool anyedge_vec4_value::recv_vec4_pv(const vvp_vector4_t&bit, unsigned base, + unsigned wid, unsigned vwid) +{ + vvp_vector4_t tmp = old_bits; + if (tmp.size() == 0) + tmp = vvp_vector4_t(vwid, BIT4_Z); + assert(wid == bit.size()); + assert(base+wid <= vwid); + assert(tmp.size() == vwid); + tmp.set_vec(base, bit); + + return recv_vec4(tmp); +} + +void anyedge_real_value::duplicate(anyedge_value*&dup) +{ + anyedge_real_value*dup_real = get_real_value(dup); + assert(dup_real); + dup_real->set(old_bits); +} + +bool anyedge_real_value::recv_real(double bit) { if (old_bits != bit) { old_bits = bit; - run_waiting_threads_(threads); return true; } return false; @@ -433,7 +536,10 @@ vthread_t vvp_fun_anyedge_sa::add_waiting_thread(vthread_t thread) void vvp_fun_anyedge_sa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit, vvp_context_t) { - if (recv_vec4_(bit, bits_[port.port()], threads_)) { + anyedge_vec4_value*value = get_vec4_value(last_value_[port.port()]); + assert(value); + if (value->recv_vec4(bit)) { + run_waiting_threads_(threads_); vvp_net_t*net = port.ptr(); net->send_vec4(bit, 0); } @@ -443,15 +549,10 @@ void vvp_fun_anyedge_sa::recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bi unsigned base, unsigned wid, unsigned vwid, vvp_context_t) { - vvp_vector4_t tmp = bits_[port.port()]; - if (tmp.size() == 0) - tmp = vvp_vector4_t(vwid, BIT4_Z); - assert(wid == bit.size()); - assert(base+wid <= vwid); - assert(tmp.size() == vwid); - tmp.set_vec(base, bit); - - if (recv_vec4_(tmp, bits_[port.port()], threads_)) { + anyedge_vec4_value*value = get_vec4_value(last_value_[port.port()]); + assert(value); + if (value->recv_vec4_pv(bit, base, wid, vwid)) { + run_waiting_threads_(threads_); vvp_net_t*net = port.ptr(); net->send_vec4(bit, 0); } @@ -460,7 +561,10 @@ void vvp_fun_anyedge_sa::recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bi void vvp_fun_anyedge_sa::recv_real(vvp_net_ptr_t port, double bit, vvp_context_t) { - if (recv_real_(bit, bitsr_[port.port()], threads_)) { + anyedge_real_value*value = get_real_value(last_value_[port.port()]); + assert(value); + if (value->recv_real(bit)) { + run_waiting_threads_(threads_); vvp_net_t*net = port.ptr(); net->send_vec4(vvp_vector4_t(), 0); } @@ -489,8 +593,10 @@ void vvp_fun_anyedge_aa::reset_instance(vvp_context_t context) state->threads = 0; for (unsigned idx = 0 ; idx < 4 ; idx += 1) { - state->bits[idx] = bits_[idx]; - state->bitsr[idx] = bitsr_[idx]; + if (last_value_[idx]) + last_value_[idx]->duplicate(state->last_value_[idx]); + else if (state->last_value_[idx]) + state->last_value_[idx]->reset(); } } @@ -521,7 +627,10 @@ void vvp_fun_anyedge_aa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit, vvp_fun_anyedge_state_s*state = static_cast (vvp_get_context_item(context, context_idx_)); - if (recv_vec4_(bit, state->bits[port.port()], state->threads)) { + anyedge_vec4_value*value = get_vec4_value(state->last_value_[port.port()]); + assert(value); + if (value->recv_vec4(bit)) { + run_waiting_threads_(state->threads); vvp_net_t*net = port.ptr(); net->send_vec4(bit, context); } @@ -531,7 +640,9 @@ void vvp_fun_anyedge_aa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit, recv_vec4(port, bit, context); context = vvp_get_next_context(context); } - bits_[port.port()] = bit; + anyedge_vec4_value*value = get_vec4_value(last_value_[port.port()]); + assert(value); + value->set(bit); } } @@ -542,7 +653,10 @@ void vvp_fun_anyedge_aa::recv_real(vvp_net_ptr_t port, double bit, vvp_fun_anyedge_state_s*state = static_cast (vvp_get_context_item(context, context_idx_)); - if (recv_real_(bit, state->bitsr[port.port()], state->threads)) { + anyedge_real_value*value = get_real_value(state->last_value_[port.port()]); + assert(value); + if (value->recv_real(bit)) { + run_waiting_threads_(state->threads); vvp_net_t*net = port.ptr(); net->send_vec4(vvp_vector4_t(), context); } @@ -552,7 +666,9 @@ void vvp_fun_anyedge_aa::recv_real(vvp_net_ptr_t port, double bit, recv_real(port, bit, context); context = vvp_get_next_context(context); } - bitsr_[port.port()] = bit; + anyedge_real_value*value = get_real_value(last_value_[port.port()]); + assert(value); + value->set(bit); } } diff --git a/vvp/event.h b/vvp/event.h index 8a12150ad..8f1363af3 100644 --- a/vvp/event.h +++ b/vvp/event.h @@ -1,7 +1,7 @@ #ifndef IVL_event_H #define IVL_event_H /* - * Copyright (c) 2004-2014 Stephen Williams (steve@icarus.com) + * Copyright (c) 2004-2020 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 @@ -216,6 +216,12 @@ class vvp_fun_edge_aa : public vvp_fun_edge, public automatic_hooks_s { unsigned context_idx_; }; +/* + * This is the base object for storing the last received values for a + * vvp_fun_anyedge functor. + */ +class anyedge_value; + /* * The vvp_fun_anyedge functor checks to see if any value in an input * vector changes. Unlike the vvp_fun_edge, which watches for the LSB @@ -233,14 +239,7 @@ class vvp_fun_anyedge : public vvp_net_fun_t, public waitable_hooks_s { virtual ~vvp_fun_anyedge(); protected: - bool recv_vec4_(const vvp_vector4_t&bit, - vvp_vector4_t&old_bits, vthread_t&threads); - bool recv_real_(double bit, - double&old_bits, vthread_t&threads); - - vvp_vector4_t bits_[4]; - // In case I'm a real-valued event. - double bitsr_[4]; + anyedge_value*last_value_[4]; }; /*