Rework last value storage in vvp_fun_anyedge functors.

This prepares the way to support strings and object handle values.
This commit is contained in:
Martin Whitaker 2020-08-22 22:33:01 +01:00
parent 0a69303164
commit a69de8b94a
2 changed files with 152 additions and 37 deletions

View File

@ -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<anyedge_vec4_value*>(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<anyedge_real_value*>(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_fun_anyedge_state_s*>
(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_fun_anyedge_state_s*>
(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);
}
}

View File

@ -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];
};
/*