Skip to content

Commit

Permalink
Initial support for $countdrivers.
Browse files Browse the repository at this point in the history
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).
  • Loading branch information
martinwhitaker authored and steveicarus committed Jul 28, 2012
1 parent a290c58 commit 6836068
Show file tree
Hide file tree
Showing 14 changed files with 399 additions and 16 deletions.
10 changes: 5 additions & 5 deletions vpi/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
212 changes: 212 additions & 0 deletions vpi/sys_countdrivers.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
/*
* Copyright (C) 2012 Martin Whitaker. ([email protected])
*
* 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);
}
7 changes: 1 addition & 6 deletions vpi/sys_icarus.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2008-2011 Cary R. ([email protected])
* Copyright (C) 2008-2012 Cary R. ([email protected])
*
* 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
Expand Down Expand Up @@ -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);
Expand Down
4 changes: 3 additions & 1 deletion vpi/sys_table.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2010 Stephen Williams ([email protected])
* Copyright (c) 1999-2010,2012 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
Expand All @@ -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();
Expand Down Expand Up @@ -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,
Expand Down
11 changes: 11 additions & 0 deletions vpi_user.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
16 changes: 16 additions & 0 deletions vvp/island_tran.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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;
Expand Down
20 changes: 20 additions & 0 deletions vvp/resolv.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
6 changes: 6 additions & 0 deletions vvp/resolv.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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;

Expand Down
Loading

0 comments on commit 6836068

Please sign in to comment.