Additional support for $countdrivers.

This patch extends the implementation of $countdrivers to handle wires
connected to islands.
This commit is contained in:
Martin Whitaker 2012-07-13 19:28:16 +01:00 committed by Stephen Williams
parent 6836068a16
commit dd284ee582
3 changed files with 84 additions and 13 deletions

View File

@ -106,16 +106,81 @@ void vvp_island_tran::run_island()
}
}
static bool warn_count_drivers = true;
static void count_drivers_(vvp_branch_ptr_t cur, bool other_side_visited,
unsigned bit_idx, unsigned counts[3])
{
// First count any value driven into the port associated with
// the current endpoint.
vvp_net_t*net = cur.port() ? cur.ptr()->b : cur.ptr()->a;
vvp_scalar_t bit = island_get_value(net).value(bit_idx);
update_driver_counts(bit.value(), counts);
// Now handle all the branches attached to that port.
vvp_branch_ptr_t idx = cur;
do {
vvp_island_branch_tran*tmp = BRANCH_TRAN(idx.ptr());
// If this branch represents a tran gate, we count the
// value on the other side of the tran (providing it is
// enabled) as a single driver.
if (tmp->width == 0) {
if (tmp->state == tran_enabled) {
net = idx.port() ? idx.ptr()->a : idx.ptr()->b;
bit = island_get_sent_value(net).value(bit_idx);
update_driver_counts(bit.value(), counts);
}
continue;
}
// If we get here, this branch is a part select. If we've
// just come from the other end of the branch, we're done.
if ((idx == cur) && other_side_visited)
continue;
// If this is the narrow end of the part select, the other
// end must include the bit we are interested in. Follow
// the branch to collect any drivers on the other side.
if (idx.port() == 1) {
vvp_branch_ptr_t a_side(tmp, 0);
count_drivers_(a_side, true, tmp->offset + bit_idx, counts);
continue;
}
// If we get here, this branch is the wide end of a part
// select. If the bit we are interested in is within the
// selected part, follow the branch to collect any drivers
// on the other side.
if ((bit_idx >= tmp->offset) && (bit_idx < tmp->offset+tmp->part)) {
vvp_branch_ptr_t b_side(tmp, 1);
count_drivers_(b_side, true, bit_idx - tmp->offset, counts);
continue;
}
} while ((idx = next(idx)) != cur);
}
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;
// First we need to find a branch that is attached to the specified
// port. Unfortunately there's no quick way to do this.
vvp_island_branch*branch = branches_;
unsigned side = 0;
while (branch) {
if (branch->a->fun == port) {
side = 0;
break;
}
if (branch->b->fun == port) {
side = 1;
break;
}
branch = branch->next_branch;
}
assert(branch);
// Now count the drivers, pushing through the network as necessary.
vvp_branch_ptr_t endpoint(branch, side);
count_drivers_(endpoint, false, bit_idx, counts);
}
bool vvp_island_branch_tran::run_test_enabled()

View File

@ -226,13 +226,6 @@ vvp_island_branch::~vvp_island_branch()
{
}
static vvp_branch_ptr_t next(vvp_branch_ptr_t cur)
{
vvp_island_branch*ptr = cur.ptr();
unsigned ab = cur.port();
return ptr->link[ab];
}
void island_collect_node(list<vvp_branch_ptr_t>&conn, vvp_branch_ptr_t cur)
{
conn .push_back(cur);

View File

@ -1,7 +1,7 @@
#ifndef __vvp_island_H
#define __vvp_island_H
/*
* Copyright (c) 2008-2011 Stephen Williams (steve@icarus.com)
* Copyright (c) 2008-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
@ -182,6 +182,12 @@ inline vvp_vector8_t island_get_value(vvp_net_t*net)
}
}
inline vvp_vector8_t island_get_sent_value(vvp_net_t*net)
{
vvp_island_port*fun = dynamic_cast<vvp_island_port*>(net->fun);
return fun->outvalue;
}
extern void island_send_value(vvp_net_t*net, const vvp_vector8_t&val);
/*
@ -206,6 +212,13 @@ struct vvp_island_branch {
vvp_net_t*b;
};
static inline vvp_branch_ptr_t next(vvp_branch_ptr_t cur)
{
vvp_island_branch*ptr = cur.ptr();
unsigned ab = cur.port();
return ptr->link[ab];
}
/*
* This function collects into the conn list all the branch ends
* that are connected together with the reference branch endpoint