Skip to content

Commit

Permalink
added get_next_sequential_gates (untested)
Browse files Browse the repository at this point in the history
  • Loading branch information
SJulianS committed May 9, 2024
1 parent ebdba47 commit b826e4e
Show file tree
Hide file tree
Showing 3 changed files with 187 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,13 @@ namespace hal
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;

// TODO implement get_next_sequential_gates (get all sequential successors of the current gate by traversing other gates)
// test & document
Result<std::set<Gate*>>
get_next_sequential_gates(const Net* net, bool successors, const std::set<PinType>& forbidden_input_pins = {}, std::unordered_map<const Net*, std::set<Gate*>>* cache = nullptr) const;

// test & document
Result<std::set<Gate*>>
get_next_sequential_gates(const Gate* gate, bool successors, const std::set<PinType>& forbidden_input_pins = {}, std::unordered_map<const Net*, std::set<Gate*>>* cache = nullptr) const;

// TODO implement get_next_combinational_gates (get all combinational successor gates until sequential (non-combinational) gates are hit)

Expand Down
126 changes: 126 additions & 0 deletions src/netlist/decorators/netlist_traversal_decorator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,4 +234,130 @@ namespace hal
}
return OK(res);
}

Result<std::set<Gate*>> NetlistTraversalDecorator::get_next_sequential_gates(const Net* net,
bool successors,
const std::set<PinType>& forbidden_input_pins,
std::unordered_map<const Net*, std::set<Gate*>>* cache) const
{
if (net == nullptr)
{
return ERR("nullptr given as net");
}

if (!m_netlist.is_net_in_netlist(net))
{
return ERR("net does not belong to netlist");
}

std::unordered_set<const Net*> visited;
std::vector<const Net*> stack = {net};
std::vector<const Net*> previous;
std::set<Gate*> res;
while (!stack.empty())
{
const Net* current = stack.back();

if (!previous.empty() && current == previous.back())
{
stack.pop_back();
previous.pop_back();
continue;
}

visited.insert(current);

if (cache)
{
if (const auto it = cache->find(current); 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;
}
}

bool added = false;
for (const auto* entry_ep : successors ? current->get_destinations() : current->get_sources())
{
auto pin = entry_ep->get_pin();
auto* gate = entry_ep->get_gate();

if (gate->get_type()->has_property(GateTypeProperty::sequential))
{
// stop traversal if gate is sequential
if (forbidden_input_pins.find(pin->get_type()) == forbidden_input_pins.end())
{
// only add gate to result if it has not been reached through a forbidden pin (e.g., control pin)
res.insert(gate);

// update cache
if (cache)
{
(*cache)[current].insert(gate);
for (const auto* n : previous)
{
(*cache)[n].insert(gate);
}
}
}
}
else
{
for (const auto* exit_ep : successors ? gate->get_fan_out_endpoints() : gate->get_fan_in_endpoints())
{
const Net* n = exit_ep->get_net();
if (visited.find(n) == visited.end())
{
stack.push_back(n);
added = true;
}
}
}
}

if (added)
{
previous.push_back(current);
}
else
{
stack.pop_back();
}
}

return OK(res);
}

Result<std::set<Gate*>> NetlistTraversalDecorator::get_next_sequential_gates(const Gate* gate,
bool successors,
const std::set<PinType>& forbidden_input_pins,
std::unordered_map<const Net*, std::set<Gate*>>* cache) const
{
if (gate == nullptr)
{
return ERR("nullptr given as gate");
}

if (!m_netlist.is_gate_in_netlist(gate))
{
return ERR("net does not belong to netlist");
}

std::set<Gate*> res;
for (const auto* exit_ep : successors ? gate->get_fan_out_endpoints() : gate->get_fan_in_endpoints())
{
const auto next_res = this->get_next_sequential_gates(exit_ep->get_net(), successors, forbidden_input_pins, cache);
if (next_res.is_error())
{
return ERR(next_res.get_error());
}
auto next = next_res.get();
res.insert(next.begin(), next.end());
}
return OK(res);
}
} // namespace hal
54 changes: 54 additions & 0 deletions src/python_bindings/bindings/netlist_traversal_decorator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,5 +169,59 @@ namespace hal
:returns: The next gates fulfilling the target gate filter condition on success, ``None`` otherwise.
:rtype: set[hal_py.Gate] or None
)");

py_netlist_traversal_decorator.def(
"get_next_sequential_gates",
[](NetlistTraversalDecorator& self, const Net* net, bool successors, const std::set<PinType>& forbidden_input_pins = {}, std::unordered_map<const Net*, std::set<Gate*>>* cache = nullptr)
-> std::optional<std::set<Gate*>> {
auto res = self.get_next_sequential_gates(net, successors, forbidden_input_pins, cache);
if (res.is_ok())
{
return res.get();
}
else
{
log_error("python_context", "error encountered while getting next sequential gates:\n{}", res.get_error().get());
return std::nullopt;
}
},
py::arg("net"),
py::arg("successors"),
py::arg("forbidden_input_pins") = std::set<PinType>(),
py::arg("cache") = nullptr,
R"(
:param hal_py.Net net: Start net.
:param bool successors: Set ``True`` to get successors, set ``False`` to get predecessors.
:rtype: set[hal_py.Gate] or None
)");

py_netlist_traversal_decorator.def(
"get_next_sequential_gates",
[](NetlistTraversalDecorator& self, const Gate* gate, bool successors, const std::set<PinType>& forbidden_input_pins = {}, std::unordered_map<const Net*, std::set<Gate*>>* cache = nullptr)
-> std::optional<std::set<Gate*>> {
auto res = self.get_next_sequential_gates(gate, successors, forbidden_input_pins, cache);
if (res.is_ok())
{
return res.get();
}
else
{
log_error("python_context", "error encountered while getting next sequential gates:\n{}", res.get_error().get());
return std::nullopt;
}
},
py::arg("gate"),
py::arg("successors"),
py::arg("forbidden_input_pins") = std::set<PinType>(),
py::arg("cache") = nullptr,
R"(
:param hal_py.Gate gate: Start gate.
:param bool successors: Set ``True`` to get successors, set ``False`` to get predecessors.
:rtype: set[hal_py.Gate] or None
)");
}
} // namespace hal

0 comments on commit b826e4e

Please sign in to comment.