Initial support for $countdrivers.
This patch implements the $countdrivers system function. It does not yet support wires connected to islands (and outputs a suitable "sorry" message when this is detected).
This commit is contained in:
parent
a290c58a2e
commit
6836068a16
|
|
@ -52,11 +52,11 @@ CXXFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CXX@ @CXXFLAGS@
|
|||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
# Object files for system.vpi
|
||||
O = sys_table.o sys_convert.o sys_deposit.o sys_display.o sys_fileio.o \
|
||||
sys_finish.o sys_icarus.o sys_plusargs.o sys_queue.o sys_random.o \
|
||||
sys_random_mti.o sys_readmem.o sys_readmem_lex.o sys_scanf.o sys_sdf.o \
|
||||
sys_time.o sys_vcd.o sys_vcdoff.o vcd_priv.o mt19937int.o sys_priv.o \
|
||||
sdf_lexor.o sdf_parse.o stringheap.o vams_simparam.o \
|
||||
O = sys_table.o sys_convert.o sys_countdrivers.o sys_deposit.o sys_display.o \
|
||||
sys_fileio.o sys_finish.o sys_icarus.o sys_plusargs.o sys_queue.o \
|
||||
sys_random.o sys_random_mti.o sys_readmem.o sys_readmem_lex.o sys_scanf.o \
|
||||
sys_sdf.o sys_time.o sys_vcd.o sys_vcdoff.o vcd_priv.o mt19937int.o \
|
||||
sys_priv.o sdf_lexor.o sdf_parse.o stringheap.o vams_simparam.o \
|
||||
table_mod.o table_mod_lexor.o table_mod_parse.o
|
||||
OPP = vcd_priv2.o
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,212 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Martin Whitaker. (icarus@martin-whitaker.me.uk)
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "sys_priv.h"
|
||||
#include <assert.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
#include "ivl_alloc.h"
|
||||
|
||||
/*
|
||||
* Check to see if an argument is a single bit net.
|
||||
*/
|
||||
static void check_net_arg(vpiHandle arg, vpiHandle callh, const char *name)
|
||||
{
|
||||
assert(arg);
|
||||
|
||||
switch (vpi_get(vpiType, arg)) {
|
||||
case vpiPartSelect:
|
||||
if (vpi_get(vpiType, vpi_handle(vpiParent, arg)) != vpiNet)
|
||||
break;
|
||||
case vpiNet:
|
||||
if (vpi_get(vpiSize, arg) != 1)
|
||||
break;
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s's first argument must be a scalar net or "
|
||||
"a bit-select of a vector net.\n", name);
|
||||
vpi_control(vpiFinish, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to see if an argument is a variable.
|
||||
*/
|
||||
static void check_var_arg(vpiHandle arg, vpiHandle callh, const char *name,
|
||||
const char *arg_name)
|
||||
{
|
||||
assert(arg);
|
||||
|
||||
switch (vpi_get(vpiType, arg)) {
|
||||
case vpiPartSelect:
|
||||
if (vpi_get(vpiType, vpi_handle(vpiParent, arg)) == vpiNet)
|
||||
break;
|
||||
case vpiMemoryWord:
|
||||
case vpiBitVar:
|
||||
case vpiReg:
|
||||
case vpiIntegerVar:
|
||||
case vpiIntVar:
|
||||
case vpiLongIntVar:
|
||||
case vpiTimeVar:
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s's %s argument must be a variable.\n",
|
||||
name, arg_name);
|
||||
vpi_control(vpiFinish, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that the given $countdrivers() call has valid arguments.
|
||||
*/
|
||||
static PLI_INT32 sys_countdrivers_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *name)
|
||||
{
|
||||
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
|
||||
vpiHandle argv = vpi_iterate(vpiArgument, callh);
|
||||
vpiHandle arg;
|
||||
unsigned arg_num;
|
||||
|
||||
/* Check that there are arguments. */
|
||||
if (argv == 0) {
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s requires at least one argument.\n", name);
|
||||
vpi_control(vpiFinish, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The first argument must be a scalar net or a net bit select. */
|
||||
arg = vpi_scan(argv);
|
||||
check_net_arg(arg, callh, name);
|
||||
|
||||
/* The optional arguments must be variables. */
|
||||
for (arg_num = 2; arg_num < 7; arg_num += 1) {
|
||||
char *arg_name = NULL;
|
||||
switch (arg_num) {
|
||||
case 2: arg_name = "second"; break;
|
||||
case 3: arg_name = "third"; break;
|
||||
case 4: arg_name = "fourth"; break;
|
||||
case 5: arg_name = "fifth"; break;
|
||||
case 6: arg_name = "sixth"; break;
|
||||
default: assert(0);
|
||||
}
|
||||
|
||||
arg = vpi_scan(argv);
|
||||
if (arg == 0)
|
||||
return 0;
|
||||
|
||||
check_var_arg(arg, callh, name, arg_name);
|
||||
}
|
||||
|
||||
/* Make sure there are no extra arguments. */
|
||||
check_for_extra_args(argv, callh, name, "six arguments", 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The runtime code for $countdrivers().
|
||||
*/
|
||||
static PLI_INT32 sys_countdrivers_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name)
|
||||
{
|
||||
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
|
||||
vpiHandle argv = vpi_iterate(vpiArgument, callh);
|
||||
vpiHandle arg;
|
||||
unsigned idx;
|
||||
unsigned counts[4];
|
||||
unsigned num_drivers;
|
||||
s_vpi_value val;
|
||||
|
||||
/* All returned values are integers. */
|
||||
val.format = vpiIntVal;
|
||||
|
||||
/* Get the base net reference and bit select */
|
||||
idx = 0;
|
||||
arg = vpi_scan(argv);
|
||||
assert(arg);
|
||||
if (vpi_get(vpiType, arg) == vpiPartSelect) {
|
||||
idx = vpi_get(vpiLeftRange, arg);
|
||||
arg = vpi_handle(vpiParent, arg);
|
||||
assert(arg);
|
||||
}
|
||||
|
||||
/* Get the net driver counts from the runtime. */
|
||||
vpip_count_drivers(arg, idx, counts);
|
||||
num_drivers = counts[0] + counts[1] + counts[2];
|
||||
|
||||
/* Handle optional net_is_forced argument. */
|
||||
arg = vpi_scan(argv);
|
||||
if (arg == 0) goto args_done;
|
||||
val.value.integer = counts[3];
|
||||
vpi_put_value(arg, &val, 0, vpiNoDelay);
|
||||
|
||||
/* Handle optional number_of_01x_drivers argument. */
|
||||
arg = vpi_scan(argv);
|
||||
if (arg == 0) goto args_done;
|
||||
val.value.integer = num_drivers;
|
||||
vpi_put_value(arg, &val, 0, vpiNoDelay);
|
||||
|
||||
/* Handle optional number_of_0_drivers argument. */
|
||||
arg = vpi_scan(argv);
|
||||
if (arg == 0) goto args_done;
|
||||
val.value.integer = counts[0];
|
||||
vpi_put_value(arg, &val, 0, vpiNoDelay);
|
||||
|
||||
/* Handle optional number_of_1_drivers argument. */
|
||||
arg = vpi_scan(argv);
|
||||
if (arg == 0) goto args_done;
|
||||
val.value.integer = counts[1];
|
||||
vpi_put_value(arg, &val, 0, vpiNoDelay);
|
||||
|
||||
/* Handle optional number_of_x_drivers argument. */
|
||||
arg = vpi_scan(argv);
|
||||
if (arg == 0) goto args_done;
|
||||
val.value.integer = counts[2];
|
||||
vpi_put_value(arg, &val, 0, vpiNoDelay);
|
||||
|
||||
/* Free the argument iterator. */
|
||||
vpi_free_object(argv);
|
||||
|
||||
args_done:
|
||||
val.value.integer = (num_drivers > 1) ? 1 : 0;
|
||||
vpi_put_value(callh, &val, 0, vpiNoDelay);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Routine to register the system tasks/functions provided in this file.
|
||||
*/
|
||||
void sys_countdrivers_register()
|
||||
{
|
||||
s_vpi_systf_data tf_data;
|
||||
vpiHandle res;
|
||||
|
||||
tf_data.type = vpiSysFunc;
|
||||
tf_data.tfname = "$countdrivers";
|
||||
tf_data.calltf = sys_countdrivers_calltf;
|
||||
tf_data.compiletf = sys_countdrivers_compiletf;
|
||||
tf_data.sizetf = 0;
|
||||
tf_data.user_data = "$countdrivers";
|
||||
res = vpi_register_systf(&tf_data);
|
||||
vpip_make_systf_system_defined(res);
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2008-2011 Cary R. (cygcary@yahoo.com)
|
||||
* Copyright (C) 2008-2012 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
|
||||
|
|
@ -301,11 +301,6 @@ void sys_special_register(void)
|
|||
tf_data.type = vpiSysFunc;
|
||||
tf_data.sysfunctype = vpiIntFunc;
|
||||
|
||||
tf_data.tfname = "$countdrivers";
|
||||
tf_data.user_data = "$countdrivers";
|
||||
res = vpi_register_systf(&tf_data);
|
||||
vpip_make_systf_system_defined(res);
|
||||
|
||||
tf_data.tfname = "$getpattern";
|
||||
tf_data.user_data = "$getpattern";
|
||||
res = vpi_register_systf(&tf_data);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1999-2010 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2010,2012 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
|
||||
|
|
@ -24,6 +24,7 @@
|
|||
# include <string.h>
|
||||
|
||||
extern void sys_convert_register();
|
||||
extern void sys_countdrivers_register();
|
||||
extern void sys_fileio_register();
|
||||
extern void sys_finish_register();
|
||||
extern void sys_deposit_register();
|
||||
|
|
@ -195,6 +196,7 @@ static void sys_lxt_or_vcd_register()
|
|||
|
||||
void (*vlog_startup_routines[])() = {
|
||||
sys_convert_register,
|
||||
sys_countdrivers_register,
|
||||
sys_fileio_register,
|
||||
sys_finish_register,
|
||||
sys_deposit_register,
|
||||
|
|
|
|||
11
vpi_user.h
11
vpi_user.h
|
|
@ -616,6 +616,17 @@ extern void vpip_set_return_value(int value);
|
|||
extern s_vpi_vecval vpip_calc_clog2(vpiHandle arg);
|
||||
extern void vpip_make_systf_system_defined(vpiHandle ref);
|
||||
|
||||
/* Return driver information for a net bit. The information is returned
|
||||
in the 'counts' array as follows:
|
||||
counts[0] - number of drivers driving '0' onto the net
|
||||
counts[1] - number of drivers driving '1' onto the net
|
||||
counts[2] - number of drivers driving 'X' onto the net
|
||||
counts[3] - set to 1 if the net is forced, 0 otherwise
|
||||
The 'ref' argument should reference a net. The 'idx' argument selects
|
||||
which bit of the net is examined. */
|
||||
extern void vpip_count_drivers(vpiHandle ref, unsigned idx,
|
||||
unsigned counts[4]);
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -23,12 +23,16 @@
|
|||
# include "schedule.h"
|
||||
# include <list>
|
||||
|
||||
# include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class vvp_island_tran : public vvp_island {
|
||||
|
||||
public:
|
||||
void run_island();
|
||||
void count_drivers(vvp_island_port*port, unsigned bit_idx,
|
||||
unsigned counts[3]);
|
||||
};
|
||||
|
||||
enum tran_state_t {
|
||||
|
|
@ -102,6 +106,18 @@ void vvp_island_tran::run_island()
|
|||
}
|
||||
}
|
||||
|
||||
static bool warn_count_drivers = true;
|
||||
|
||||
void vvp_island_tran::count_drivers(vvp_island_port*port, unsigned bit_idx,
|
||||
unsigned counts[3])
|
||||
{
|
||||
if (warn_count_drivers) {
|
||||
cerr << "sorry: $countdrivers is not yet fully implemented." << endl;
|
||||
cerr << " Some driver counts will not be correct." << endl;
|
||||
warn_count_drivers = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool vvp_island_branch_tran::run_test_enabled()
|
||||
{
|
||||
vvp_island_port*ep = en? dynamic_cast<vvp_island_port*> (en->fun) : 0;
|
||||
|
|
|
|||
|
|
@ -178,6 +178,16 @@ void resolv_tri::recv_vec8_(unsigned port, const vvp_vector8_t&bit)
|
|||
net_->send_vec8(val_[base]);
|
||||
}
|
||||
|
||||
void resolv_tri::count_drivers(unsigned bit_idx, unsigned counts[3])
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < nports_ ; idx += 1) {
|
||||
if (val_[idx].size() == 0)
|
||||
continue;
|
||||
|
||||
update_driver_counts(val_[idx].value(bit_idx).value(), counts);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
resolv_wired_logic::resolv_wired_logic(unsigned nports, vvp_net_t*net)
|
||||
: resolv_core(nports, net)
|
||||
|
|
@ -253,6 +263,16 @@ void resolv_wired_logic::recv_vec8_(unsigned port, const vvp_vector8_t&bit)
|
|||
recv_vec4_(port, reduce4(bit));
|
||||
}
|
||||
|
||||
void resolv_wired_logic::count_drivers(unsigned bit_idx, unsigned counts[3])
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < nports_ ; idx += 1) {
|
||||
if (val_[idx].size() == 0)
|
||||
continue;
|
||||
|
||||
update_driver_counts(val_[idx].value(bit_idx), counts);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
resolv_triand::resolv_triand(unsigned nports, vvp_net_t*net)
|
||||
: resolv_wired_logic(nports, net)
|
||||
|
|
|
|||
|
|
@ -52,6 +52,8 @@ class resolv_core : public vvp_net_fun_t {
|
|||
unsigned base, unsigned wid, unsigned vwid)
|
||||
{ recv_vec8_pv_(port.port(), bit, base, wid, vwid); }
|
||||
|
||||
virtual void count_drivers(unsigned bit_idx, unsigned counts[3]) =0;
|
||||
|
||||
private:
|
||||
friend class resolv_extend;
|
||||
virtual void recv_vec4_(unsigned port, const vvp_vector4_t&bit) =0;
|
||||
|
|
@ -115,6 +117,8 @@ class resolv_tri : public resolv_core {
|
|||
vvp_scalar_t hiz_value);
|
||||
~resolv_tri();
|
||||
|
||||
void count_drivers(unsigned bit_idx, unsigned counts[3]);
|
||||
|
||||
private:
|
||||
void recv_vec4_(unsigned port, const vvp_vector4_t&bit);
|
||||
void recv_vec8_(unsigned port, const vvp_vector8_t&bit);
|
||||
|
|
@ -141,6 +145,8 @@ class resolv_wired_logic : public resolv_core {
|
|||
explicit resolv_wired_logic(unsigned nports, vvp_net_t*net);
|
||||
virtual ~resolv_wired_logic();
|
||||
|
||||
void count_drivers(unsigned bit_idx, unsigned counts[3]);
|
||||
|
||||
protected:
|
||||
virtual vvp_vector4_t wired_logic_math_(vvp_vector4_t&a, vvp_vector4_t&b) =0;
|
||||
|
||||
|
|
|
|||
|
|
@ -1458,3 +1458,16 @@ extern "C" s_vpi_vecval vpip_calc_clog2(vpiHandle arg)
|
|||
rtn.bval = 0;
|
||||
return rtn;
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine provides the information needed to implement $countdrivers.
|
||||
* It is done here for performance reasons - interrogating the drivers
|
||||
* individually via the VPI interface would be much slower.
|
||||
*/
|
||||
extern "C" void vpip_count_drivers(vpiHandle ref, unsigned idx,
|
||||
unsigned counts[4])
|
||||
{
|
||||
struct __vpiSignal*rfp = dynamic_cast<__vpiSignal*>(ref);
|
||||
assert(rfp);
|
||||
rfp->node->count_drivers(idx, counts);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@
|
|||
*/
|
||||
|
||||
struct vvp_island_branch;
|
||||
class vvp_island_node;
|
||||
class vvp_island_port;
|
||||
|
||||
class vvp_island : private vvp_gen_event_s {
|
||||
|
||||
|
|
@ -74,6 +74,10 @@ class vvp_island : private vvp_gen_event_s {
|
|||
// method to give the island its character.
|
||||
virtual void run_island() =0;
|
||||
|
||||
// Support for $countdrivers.
|
||||
virtual void count_drivers(vvp_island_port*port, unsigned bit_idx,
|
||||
unsigned counts[3]) =0;
|
||||
|
||||
protected:
|
||||
// The base class collects a list of all the branches in the
|
||||
// island. The derived island class can access this list for
|
||||
|
|
@ -144,6 +148,12 @@ class vvp_island_port : public vvp_net_fun_t {
|
|||
private:
|
||||
vvp_island*island_;
|
||||
|
||||
public: // Support for $countdrivers.
|
||||
inline void count_drivers(unsigned bit_idx, unsigned counts[3])
|
||||
{
|
||||
island_->count_drivers(this, bit_idx, counts);
|
||||
}
|
||||
|
||||
private: // not implemented
|
||||
vvp_island_port(const vvp_island_port&);
|
||||
vvp_island_port& operator = (const vvp_island_port&);
|
||||
|
|
|
|||
|
|
@ -19,7 +19,10 @@
|
|||
|
||||
# include "config.h"
|
||||
# include "vvp_net.h"
|
||||
# include "vvp_net_sig.h"
|
||||
# include "vvp_island.h"
|
||||
# include "vpi_priv.h"
|
||||
# include "resolv.h"
|
||||
# include "schedule.h"
|
||||
# include "statistics.h"
|
||||
# include <cstdio>
|
||||
|
|
@ -209,6 +212,36 @@ void vvp_net_t::unlink(vvp_net_ptr_t dst_ptr)
|
|||
net->port[net_port] = vvp_net_ptr_t(0,0);
|
||||
}
|
||||
|
||||
void vvp_net_t::count_drivers(unsigned idx, unsigned counts[4])
|
||||
{
|
||||
counts[0] = 0;
|
||||
counts[1] = 0;
|
||||
counts[2] = 0;
|
||||
counts[3] = 0;
|
||||
|
||||
/* $countdrivers can only be used on wires. */
|
||||
vvp_wire_base*wire=dynamic_cast<vvp_wire_base*>(fil);
|
||||
assert(wire);
|
||||
|
||||
if (wire->is_forced(idx))
|
||||
counts[3] = 1;
|
||||
|
||||
/* If the net has multiple drivers, we need to interrogate the
|
||||
resolver network to get the driven values. */
|
||||
if (resolv_core*resolver = dynamic_cast<resolv_core*>(fun)) {
|
||||
resolver->count_drivers(idx, counts);
|
||||
return;
|
||||
}
|
||||
if (vvp_island_port*resolver = dynamic_cast<vvp_island_port*>(fun)) {
|
||||
resolver->count_drivers(idx, counts);
|
||||
return;
|
||||
}
|
||||
|
||||
/* If the functor is not a resolver, there is only one driver, so
|
||||
we can just interrogate the filter to get the driven value. */
|
||||
update_driver_counts(wire->driven_value(idx), counts);
|
||||
}
|
||||
|
||||
void vvp_net_fun_t::operator delete(void*)
|
||||
{
|
||||
assert(0);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __vvp_net_H
|
||||
#define __vvp_net_H
|
||||
/*
|
||||
* Copyright (c) 2004-2011 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2004-2012 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
|
||||
|
|
@ -187,6 +187,24 @@ extern ostream& operator<< (ostream&o, vvp_bit4_t a);
|
|||
posedge, no edge, or negedge. */
|
||||
extern int edge(vvp_bit4_t from, vvp_bit4_t to);
|
||||
|
||||
/* Support for $countdrivers. */
|
||||
inline void update_driver_counts(vvp_bit4_t bit, unsigned counts[3])
|
||||
{
|
||||
switch (bit) {
|
||||
case BIT4_0:
|
||||
counts[0] += 1;
|
||||
break;
|
||||
case BIT4_1:
|
||||
counts[1] += 1;
|
||||
break;
|
||||
case BIT4_X:
|
||||
counts[2] += 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This class represents scalar values collected into vectors. The
|
||||
* vector values can be accessed individually, or treated as a
|
||||
|
|
@ -1100,6 +1118,9 @@ class vvp_net_t {
|
|||
void force_vec8(const vvp_vector8_t&val, vvp_vector2_t mask);
|
||||
void force_real(double val, vvp_vector2_t mask);
|
||||
|
||||
public: // Method to support $countdrivers
|
||||
void count_drivers(unsigned idx, unsigned counts[4]);
|
||||
|
||||
private:
|
||||
vvp_net_ptr_t out_;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2004-2010 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2004-2010,2012 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
|
||||
|
|
@ -621,6 +621,18 @@ vvp_wire_base::~vvp_wire_base()
|
|||
{
|
||||
}
|
||||
|
||||
vvp_bit4_t vvp_wire_base::driven_value(unsigned) const
|
||||
{
|
||||
assert(0);
|
||||
return BIT4_X;
|
||||
}
|
||||
|
||||
bool vvp_wire_base::is_forced(unsigned) const
|
||||
{
|
||||
assert(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
vvp_wire_vec4::vvp_wire_vec4(unsigned wid, vvp_bit4_t init)
|
||||
: bits4_(wid, init)
|
||||
{
|
||||
|
|
@ -795,6 +807,16 @@ void vvp_wire_vec4::vec4_value(vvp_vector4_t&val) const
|
|||
val.set_bit(idx, filtered_value_(idx));
|
||||
}
|
||||
|
||||
vvp_bit4_t vvp_wire_vec4::driven_value(unsigned idx) const
|
||||
{
|
||||
return bits4_.value(idx);
|
||||
}
|
||||
|
||||
bool vvp_wire_vec4::is_forced(unsigned idx) const
|
||||
{
|
||||
return test_force_mask(idx);
|
||||
}
|
||||
|
||||
vvp_wire_vec8::vvp_wire_vec8(unsigned wid)
|
||||
: bits8_(wid)
|
||||
{
|
||||
|
|
@ -954,6 +976,16 @@ void vvp_wire_vec8::vec4_value(vvp_vector4_t&val) const
|
|||
val = reduce4(vec8_value());
|
||||
}
|
||||
|
||||
vvp_bit4_t vvp_wire_vec8::driven_value(unsigned idx) const
|
||||
{
|
||||
return bits8_.value(idx).value();
|
||||
}
|
||||
|
||||
bool vvp_wire_vec8::is_forced(unsigned idx) const
|
||||
{
|
||||
return test_force_mask(idx);
|
||||
}
|
||||
|
||||
vvp_wire_real::vvp_wire_real()
|
||||
: bit_(0.0), force_(0.0)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __vvp_net_sig_H
|
||||
#define __vvp_net_sig_H
|
||||
/*
|
||||
* Copyright (c) 2004-2011 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2004-2012 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
|
||||
|
|
@ -272,6 +272,10 @@ class vvp_wire_base : public vvp_net_fil_t, public vvp_signal_value {
|
|||
public:
|
||||
vvp_wire_base();
|
||||
~vvp_wire_base();
|
||||
|
||||
// Support for $countdrivers
|
||||
virtual vvp_bit4_t driven_value(unsigned idx) const;
|
||||
virtual bool is_forced(unsigned idx) const;
|
||||
};
|
||||
|
||||
class vvp_wire_vec4 : public vvp_wire_base {
|
||||
|
|
@ -304,6 +308,10 @@ class vvp_wire_vec4 : public vvp_wire_base {
|
|||
vvp_scalar_t scalar_value(unsigned idx) const;
|
||||
void vec4_value(vvp_vector4_t&) const;
|
||||
|
||||
// Support for $countdrivers
|
||||
vvp_bit4_t driven_value(unsigned idx) const;
|
||||
bool is_forced(unsigned idx) const;
|
||||
|
||||
private:
|
||||
vvp_bit4_t filtered_value_(unsigned idx) const;
|
||||
|
||||
|
|
@ -347,6 +355,10 @@ class vvp_wire_vec8 : public vvp_wire_base {
|
|||
// This is new to vvp_wire_vec8
|
||||
vvp_vector8_t vec8_value() const;
|
||||
|
||||
// Support for $countdrivers
|
||||
vvp_bit4_t driven_value(unsigned idx) const;
|
||||
bool is_forced(unsigned idx) const;
|
||||
|
||||
private:
|
||||
vvp_scalar_t filtered_value_(unsigned idx) const;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue