vvp: handle tranif enable changes that result from island resolution.
The tran island resolution tests and caches the state of all branch enable inputs before resolving the branch endpoint values. If a branch enable is connected directly to a branch endpoint, we need to update the cached stete and rerun the island resolution if any enable state changed. This fixes issue #1122.
This commit is contained in:
parent
615a01c6cd
commit
3b61c0088d
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008-2022 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2008-2024 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -47,6 +47,7 @@ struct vvp_island_branch_tran : public vvp_island_branch {
|
||||||
unsigned width__, unsigned part__,
|
unsigned width__, unsigned part__,
|
||||||
unsigned offset__, bool resistive__);
|
unsigned offset__, bool resistive__);
|
||||||
void run_test_enabled();
|
void run_test_enabled();
|
||||||
|
bool rerun_test_enabled();
|
||||||
void run_resolution();
|
void run_resolution();
|
||||||
void run_output();
|
void run_output();
|
||||||
|
|
||||||
|
|
@ -91,6 +92,7 @@ void vvp_island_tran::run_island()
|
||||||
tmp->run_test_enabled();
|
tmp->run_test_enabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rerun:
|
||||||
// Now resolve all the branches in the island.
|
// Now resolve all the branches in the island.
|
||||||
for (vvp_island_branch*cur = branches_ ; cur ; cur = cur->next_branch) {
|
for (vvp_island_branch*cur = branches_ ; cur ; cur = cur->next_branch) {
|
||||||
vvp_island_branch_tran*tmp = dynamic_cast<vvp_island_branch_tran*>(cur);
|
vvp_island_branch_tran*tmp = dynamic_cast<vvp_island_branch_tran*>(cur);
|
||||||
|
|
@ -104,6 +106,15 @@ void vvp_island_tran::run_island()
|
||||||
assert(tmp);
|
assert(tmp);
|
||||||
tmp->run_output();
|
tmp->run_output();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Now check if the enable inputs have been affected by the resolution.
|
||||||
|
bool enable_changed = false;
|
||||||
|
for (vvp_island_branch*cur = branches_ ; cur ; cur = cur->next_branch) {
|
||||||
|
vvp_island_branch_tran*tmp = dynamic_cast<vvp_island_branch_tran*>(cur);
|
||||||
|
assert(tmp);
|
||||||
|
enable_changed |= tmp->rerun_test_enabled();
|
||||||
|
}
|
||||||
|
if (enable_changed) goto rerun;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void count_drivers_(vvp_branch_ptr_t cur, bool other_side_visited,
|
static void count_drivers_(vvp_branch_ptr_t cur, bool other_side_visited,
|
||||||
|
|
@ -230,6 +241,38 @@ void vvp_island_branch_tran::run_test_enabled()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool vvp_island_branch_tran::rerun_test_enabled()
|
||||||
|
{
|
||||||
|
vvp_island_port*ep = en? dynamic_cast<vvp_island_port*> (en->fun) : NULL;
|
||||||
|
|
||||||
|
if (ep == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// We are only looking for changes resulting from running the island
|
||||||
|
// resolution. If the outvalue is nil, we know that the enable port
|
||||||
|
// is an .import, so won't be affected.
|
||||||
|
if (ep->outvalue.size() == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
vvp_bit4_t enable_val = ep->outvalue.value(0).value();
|
||||||
|
|
||||||
|
tran_state_t old_state = state;
|
||||||
|
|
||||||
|
switch (enable_val) {
|
||||||
|
case BIT4_0:
|
||||||
|
state = active_high ? tran_disabled : tran_enabled;
|
||||||
|
break;
|
||||||
|
case BIT4_1:
|
||||||
|
state = active_high ? tran_enabled : tran_disabled;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
state = tran_unknown;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return state != old_state;
|
||||||
|
}
|
||||||
|
|
||||||
// The IEEE standard does not specify the behaviour when a tranif control
|
// The IEEE standard does not specify the behaviour when a tranif control
|
||||||
// input is 'x' or 'z'. We use the rules that are given for MOS switches.
|
// input is 'x' or 'z'. We use the rules that are given for MOS switches.
|
||||||
inline vvp_vector8_t resolve_ambiguous(const vvp_vector8_t&a,
|
inline vvp_vector8_t resolve_ambiguous(const vvp_vector8_t&a,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue