Make muxz and muxr functors use scheduled events.

This patch makes the muxz and muxr functors schedule events
instead of directly calling vvp_send_*(). This prevents the
code from going into an infinite loop when the output feeds
back to the select.
This commit is contained in:
Cary R 2008-03-20 15:32:54 -07:00 committed by Stephen Williams
parent 48990d8e2d
commit 01eb298228
2 changed files with 73 additions and 40 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2007 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2008 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
@ -16,9 +16,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: logic.cc,v 1.38 2007/02/12 05:08:27 steve Exp $"
#endif
# include "logic.h"
# include "compile.h"
@ -259,6 +256,7 @@ void vvp_fun_bufz::recv_real(vvp_net_ptr_t ptr, double bit)
vvp_fun_muxr::vvp_fun_muxr()
: a_(0.0), b_(0.0)
{
net_ = 0;
count_functors_logic += 1;
select_ = 2;
}
@ -270,7 +268,7 @@ vvp_fun_muxr::~vvp_fun_muxr()
void vvp_fun_muxr::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
{
/* The real valued mux can only take in the select as a
vector4_t. the muxed data is rea. */
vector4_t. The muxed data is real. */
if (ptr.port() != 2)
return;
@ -278,30 +276,21 @@ void vvp_fun_muxr::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
switch (bit.value(0)) {
case BIT4_0:
if (select_ == 0) return;
select_ = 0;
break;
case BIT4_1:
if (select_ == 1) return;
select_ = 1;
break;
default:
if (select_ == 2) return;
select_ = 2;
}
switch (select_) {
case 0:
vvp_send_real(ptr.ptr()->out, a_);
break;
case 1:
vvp_send_real(ptr.ptr()->out, b_);
break;
default:
if (a_ == b_) {
vvp_send_real(ptr.ptr()->out, a_);
} else {
// Should send NaN?
vvp_send_real(ptr.ptr()->out, 0.0);
}
break;
if (net_ == 0) {
net_ = ptr.ptr();
schedule_generic(this, 0, false);
}
}
@ -309,32 +298,54 @@ void vvp_fun_muxr::recv_real(vvp_net_ptr_t ptr, double bit)
{
switch (ptr.port()) {
case 0:
if (a_ == bit)
break;
if (a_ == bit) return;
a_ = bit;
if (select_ == 0)
vvp_send_real(ptr.ptr()->out, a_);
if (select_ == 1) return; // The other port is selected.
break;
case 1:
if (b_ == bit)
break;
if (b_ == bit) return;
b_ = bit;
if (select_ == 1)
vvp_send_real(ptr.ptr()->out, b_);
if (select_ == 0) return; // The other port is selected.
break;
default:
fprintf(stderr, "Unsupported port type %d.\n", ptr.port());
assert(0);
}
if (net_ == 0) {
net_ = ptr.ptr();
schedule_generic(this, 0, false);
}
}
void vvp_fun_muxr::run_run()
{
vvp_net_t*ptr = net_;
net_ = 0;
switch (select_) {
case 0:
vvp_send_real(ptr->out, a_);
break;
case 1:
vvp_send_real(ptr->out, b_);
break;
default:
if (a_ == b_) {
vvp_send_real(ptr->out, a_);
} else {
vvp_send_real(ptr->out, 0.0); // Should this be NaN?
}
break;
}
}
vvp_fun_muxz::vvp_fun_muxz(unsigned wid)
: a_(wid), b_(wid)
{
net_ = 0;
count_functors_logic += 1;
select_ = 2;
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
@ -351,21 +362,28 @@ void vvp_fun_muxz::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
{
switch (ptr.port()) {
case 0:
if (a_ .eeq(bit)) return;
a_ = bit;
if (select_ == 1) return; // The other port is selected.
break;
case 1:
if (b_ .eeq(bit)) return;
b_ = bit;
if (select_ == 0) return; // The other port is selected.
break;
case 2:
assert(bit.size() == 1);
switch (bit.value(0)) {
case BIT4_0:
if (select_ == 0) return;
select_ = 0;
break;
case BIT4_1:
if (select_ == 1) return;
select_ = 1;
break;
default:
if (select_ == 2) return;
select_ = 2;
}
break;
@ -373,12 +391,23 @@ void vvp_fun_muxz::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
return;
}
if (net_ == 0) {
net_ = ptr.ptr();
schedule_generic(this, 0, false);
}
}
void vvp_fun_muxz::run_run()
{
vvp_net_t*ptr = net_;
net_ = 0;
switch (select_) {
case 0:
vvp_send_vec4(ptr.ptr()->out, a_);
vvp_send_vec4(ptr->out, a_);
break;
case 1:
vvp_send_vec4(ptr.ptr()->out, b_);
vvp_send_vec4(ptr->out, b_);
break;
default:
{
@ -401,7 +430,7 @@ void vvp_fun_muxz::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
for (unsigned idx = min_size ; idx < max_size ; idx += 1)
res.set_bit(idx, BIT4_X);
vvp_send_vec4(ptr.ptr()->out, res);
vvp_send_vec4(ptr->out, res);
}
break;
}
@ -645,4 +674,3 @@ void compile_functor(char*label, char*type, unsigned width,
define_functor_symbol(label, net_drv);
free(label);
}

View File

@ -1,7 +1,7 @@
#ifndef __logic_H
#define __logic_H
/*
* Copyright (c) 2000-2007 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2008 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
@ -18,9 +18,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: logic.h,v 1.25 2006/11/28 05:57:20 steve Exp $"
#endif
# include "vvp_net.h"
# include "schedule.h"
@ -135,7 +132,7 @@ class vvp_fun_bufz: public vvp_net_fun_t {
* input (port-0 or port-1) to enter the device. The narrow vector is
* padded with X values.
*/
class vvp_fun_muxz : public vvp_net_fun_t {
class vvp_fun_muxz : public vvp_net_fun_t, private vvp_gen_event_s {
public:
explicit vvp_fun_muxz(unsigned width);
@ -143,13 +140,17 @@ class vvp_fun_muxz : public vvp_net_fun_t {
void recv_vec4(vvp_net_ptr_t p, const vvp_vector4_t&bit);
private:
void run_run();
private:
vvp_vector4_t a_;
vvp_vector4_t b_;
int select_;
vvp_net_t*net_;
};
class vvp_fun_muxr : public vvp_net_fun_t {
class vvp_fun_muxr : public vvp_net_fun_t, private vvp_gen_event_s {
public:
explicit vvp_fun_muxr();
@ -158,10 +159,14 @@ class vvp_fun_muxr : public vvp_net_fun_t {
void recv_vec4(vvp_net_ptr_t p, const vvp_vector4_t&bit);
void recv_real(vvp_net_ptr_t p, double bit);
private:
void run_run();
private:
double a_;
double b_;
int select_;
vvp_net_t*net_;
};
class vvp_fun_not: public vvp_net_fun_t, private vvp_gen_event_s {