Skip to content

Commit

Permalink
added caching to get_next_matching_gates
Browse files Browse the repository at this point in the history
  • Loading branch information
SJulianS committed May 13, 2024
1 parent 593ce5a commit 32a395f
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -51,42 +51,49 @@ namespace hal
* Traverse over gates that do not meet the `target_gate_filter` condition.
* Stop traversal if (1) `continue_on_match` is `false` the `target_gate_filter` evaluates to `true`, (2) the `exit_endpoint_filter` evaluates to `false` on a fan-in/out endpoint (i.e., when exiting the current gate during traversal), or (3) the `entry_endpoint_filter` evaluates to `false` on a successor/predecessor endpoint (i.e., when entering the next gate during traversal).
* Both the `entry_endpoint_filter` and the `exit_endpoint_filter` may be omitted.
* Provide a cache to speed up traversal when calling this function multiple times on the same netlist using the same forbidden pins.
* Do not use a cache if the filter functions operate on the `current_depth`.
*
* @param[in] net - Start net.
* @param[in] successors - Set `true` to get successors, set `false` to get predecessors.
* @param[in] target_gate_filter - Filter condition that must be met for the target gates.
* @param[in] continue_on_match - Set `true` to continue even if `target_gate_filter` evaluated to `true`, `false` otherwise. Defaults to `false`.
* @param[in] exit_endpoint_filter - Filter condition that determines whether to stop traversal on a fan-in/out endpoint.
* @param[in] entry_endpoint_filter - Filter condition that determines whether to stop traversal on a successor/predecessor endpoint.
* @param[inout] cache - An optional cache that can be used for better performance on repeated calls. Defaults to a `nullptr`.
* @returns The next gates fulfilling the target gate filter condition on success, an error otherwise.
*/
Result<std::set<Gate*>> get_next_matching_gates(const Net* net,
bool successors,
const std::function<bool(const Gate*)>& target_gate_filter,
bool continue_on_match = false,
const std::function<bool(const Endpoint*, const u32 current_depth)>& exit_endpoint_filter = nullptr,
const std::function<bool(const Endpoint*, const u32 current_depth)>& entry_endpoint_filter = nullptr) const;
const std::function<bool(const Endpoint*, const u32 current_depth)>& entry_endpoint_filter = nullptr,
std::unordered_map<const Net*, std::set<Gate*>>* cache = nullptr) const;

/**
* Starting from the given gate, traverse the netlist and return only the successor/predecessor gates for which the `target_gate_filter` evaluates to `true`.
* Traverse over gates that do not meet the `target_gate_filter` condition.
* Stop traversal if (1) `continue_on_match` is `false` the `target_gate_filter` evaluates to `true`, (2) the `exit_endpoint_filter` evaluates to `false` on a fan-in/out endpoint (i.e., when exiting the current gate during traversal), or (3) the `entry_endpoint_filter` evaluates to `false` on a successor/predecessor endpoint (i.e., when entering the next gate during traversal).
* Both the `entry_endpoint_filter` and the `exit_endpoint_filter` may be omitted.
* Do not use a cache if the filter functions operate on the `current_depth`.
*
* @param[in] gate - Start gate.
* @param[in] successors - Set `true` to get successors, set `false` to get predecessors.
* @param[in] target_gate_filter - Filter condition that must be met for the target gates.
* @param[in] continue_on_match - Set `true` to continue even if `target_gate_filter` evaluated to `true`, `false` otherwise. Defaults to `false`.
* @param[in] exit_endpoint_filter - Filter condition that determines whether to stop traversal on a fan-in/out endpoint.
* @param[in] entry_endpoint_filter - Filter condition that determines whether to stop traversal on a successor/predecessor endpoint.
* @param[inout] cache - An optional cache that can be used for better performance on repeated calls. Defaults to a `nullptr`.
* @returns The next gates fulfilling the target gate filter condition on success, an error otherwise.
*/
Result<std::set<Gate*>> get_next_matching_gates(const Gate* gate,
bool successors,
const std::function<bool(const Gate*)>& target_gate_filter,
bool continue_on_match = false,
const std::function<bool(const Endpoint*, const u32 current_depth)>& exit_endpoint_filter = nullptr,
const std::function<bool(const Endpoint*, const u32 current_depth)>& entry_endpoint_filter = nullptr) const;
const std::function<bool(const Endpoint*, const u32 current_depth)>& entry_endpoint_filter = nullptr,
std::unordered_map<const Net*, std::set<Gate*>>* cache = nullptr) const;

/**
* Starting from the given net, traverse the netlist and return only the successor/predecessor gates for which the `target_gate_filter` evaluates to `true`.
Expand Down
66 changes: 56 additions & 10 deletions src/netlist/decorators/netlist_traversal_decorator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ namespace hal
const std::function<bool(const Gate*)>& target_gate_filter,
bool continue_on_match,
const std::function<bool(const Endpoint*, u32 current_depth)>& exit_endpoint_filter,
const std::function<bool(const Endpoint*, u32 current_depth)>& entry_endpoint_filter) const
const std::function<bool(const Endpoint*, u32 current_depth)>& entry_endpoint_filter,
std::unordered_map<const Net*, std::set<Gate*>>* cache) const
{
if (net == nullptr)
{
Expand Down Expand Up @@ -56,29 +57,59 @@ namespace hal
continue;
}

auto* g = entry_ep->get_gate();
auto* gate = entry_ep->get_gate();

if (target_gate_filter(g))
if (target_gate_filter(gate))
{
res.insert(g);
res.insert(gate);

// update cache
if (cache)
{
(*cache)[current].insert(gate);
for (const auto* n : previous)
{
(*cache)[n].insert(gate);
}
}

if (!continue_on_match)
{
continue;
}
}

for (const auto* exit_ep : successors ? g->get_fan_out_endpoints() : g->get_fan_in_endpoints())
for (const auto* exit_ep : successors ? gate->get_fan_out_endpoints() : gate->get_fan_in_endpoints())
{
if (exit_endpoint_filter != nullptr && !exit_endpoint_filter(exit_ep, previous.size() + 1))
{
continue;
}

const Net* n = exit_ep->get_net();
if (visited.find(n) == visited.end())
const Net* exit_net = exit_ep->get_net();
if (cache)
{
stack.push_back(n);
if (const auto it = cache->find(exit_net); it != cache->end())
{
const auto& cached_gates = std::get<1>(*it);

// append cached gates to result
res.insert(cached_gates.begin(), cached_gates.end());

// update cache
(*cache)[current].insert(cached_gates.begin(), cached_gates.end());
for (const auto* n : previous)
{
(*cache)[n].insert(cached_gates.begin(), cached_gates.end());
}

continue;
}
}

if (visited.find(exit_net) == visited.end())
{
stack.push_back(exit_net);
added = true;
}
}
Expand All @@ -102,7 +133,8 @@ namespace hal
const std::function<bool(const Gate*)>& target_gate_filter,
bool continue_on_match,
const std::function<bool(const Endpoint*, u32 current_depth)>& exit_endpoint_filter,
const std::function<bool(const Endpoint*, u32 current_depth)>& entry_endpoint_filter) const
const std::function<bool(const Endpoint*, u32 current_depth)>& entry_endpoint_filter,
std::unordered_map<const Net*, std::set<Gate*>>* cache) const
{
if (gate == nullptr)
{
Expand All @@ -122,7 +154,21 @@ namespace hal
continue;
}

const auto next_res = this->get_next_matching_gates(exit_ep->get_net(), successors, target_gate_filter, continue_on_match, exit_endpoint_filter, entry_endpoint_filter);
const auto* exit_net = exit_ep->get_net();
if (cache)
{
if (const auto it = cache->find(exit_net); it != cache->end())
{
const auto& cached_gates = std::get<1>(*it);

// append cached gates to result
res.insert(cached_gates.begin(), cached_gates.end());

continue;
}
}

const auto next_res = this->get_next_matching_gates(exit_net, successors, target_gate_filter, continue_on_match, exit_endpoint_filter, entry_endpoint_filter, cache);
if (next_res.is_error())
{
return ERR(next_res.get_error());
Expand Down
18 changes: 18 additions & 0 deletions tests/netlist/decorators.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -672,6 +672,15 @@ namespace hal {
EXPECT_TRUE(res.is_ok());
EXPECT_EQ(res.get(), std::set<Gate*>({dff4, dff5, dff6}));
}
{
std::unordered_map<const Net*, std::set<Gate*>> cache;
const auto res1 = trav_dec.get_next_matching_gates(dff2, true, [](const Gate* g) { return g->get_type()->has_property(GateTypeProperty::ff); }, false, nullptr, nullptr, &cache);
EXPECT_TRUE(res1.is_ok());
EXPECT_EQ(res1.get(), std::set<Gate*>({dff5, dff6, dff7, dff3}));
const auto res2 = trav_dec.get_next_matching_gates(dff3, true, [](const Gate* g) { return g->get_type()->has_property(GateTypeProperty::ff); }, false, nullptr, nullptr, &cache);
EXPECT_TRUE(res2.is_ok());
EXPECT_EQ(res2.get(), std::set<Gate*>({dff6, dff7, dff3}));
}

// predecessors
{
Expand All @@ -684,6 +693,15 @@ namespace hal {
EXPECT_TRUE(res.is_ok());
EXPECT_EQ(res.get(), std::set<Gate*>({dff0, dff1, dff2}));
}
{
std::unordered_map<const Net*, std::set<Gate*>> cache;
const auto res1 = trav_dec.get_next_matching_gates(dff6, false, [](const Gate* g) { return g->get_type()->has_property(GateTypeProperty::ff); }, false, nullptr, nullptr, &cache);
EXPECT_TRUE(res1.is_ok());
EXPECT_EQ(res1.get(), std::set<Gate*>({dff1, dff2, dff3, sff0, sff1}));
const auto res2 = trav_dec.get_next_matching_gates(dff7, false, [](const Gate* g) { return g->get_type()->has_property(GateTypeProperty::ff); }, false, nullptr, nullptr, &cache);
EXPECT_TRUE(res2.is_ok());
EXPECT_EQ(res2.get(), std::set<Gate*>({dff2, dff3, sff0, sff1}));
}
}
{
// test NetlistModificationDecorator::get_next_matching_gates_until
Expand Down

0 comments on commit 32a395f

Please sign in to comment.