Additional support for $countdrivers.
This patch extends the implementation of $countdrivers to handle wires connected to islands.
This commit is contained in:
parent
6836068a16
commit
dd284ee582
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue