Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ MIG inverter optimization and propagation #248

Merged
merged 5 commits into from
Nov 21, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 90 additions & 0 deletions cli/cmd/logic/miginvopt.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
//
// Created by marcel on 07.06.23.
//

#ifndef FICTION_CMD_MIGINVOPT_HPP
#define FICTION_CMD_MIGINVOPT_HPP

#include <fiction/algorithms/network_transformation/network_conversion.hpp>
#include <fiction/types.hpp>
#include <fiction/utils/name_utils.hpp>

#include <alice/alice.hpp>
#include <fmt/format.h>
#include <mockturtle/algorithms/mig_inv_optimization.hpp>
#include <mockturtle/views/fanout_view.hpp>

#include <type_traits>
#include <variant>

namespace alice
{
/**
* Optimizes inverter costs of the current MIG in store.
*/
class miginvopt_command : public command
{
public:
/**
* Standard constructor. Adds descriptive information, options, and flags.
*
* @param e alice::environment that specifies stores etc.
*/
explicit miginvopt_command(const environment::ptr& e) :
command(e, "Optimizes the inverter cost of the current MIG in store via node replacement.")
{}

protected:
/**
* Function to perform the balancing call. Inserts buffer nodes to equalize path lengths.
*/
void execute() override
{
auto& s = store<fiction::logic_network_t>();

// error case: empty logic network store
if (s.empty())
{
env->out() << "[w] no logic network in store" << std::endl;

return;
}

const auto perform_inverter_optimization = [&](auto&& ntk_ptr) -> void
{
using Ntk = typename std::decay_t<decltype(ntk_ptr)>::element_type;

mockturtle::mig_inv_optimization_stats st{};
marcelwa marked this conversation as resolved.
Show resolved Hide resolved

// if the current logic network is an MIG
if constexpr (std::is_same_v<Ntk, fiction::mig_nt>)
{
// clone it because inverter optimization is an in-place algorithm
auto ntk_clone = ntk_ptr->clone();

// mockturtle::fanout_view fo_ntk_clone{ntk_clone};
mockturtle::mig_inv_optimization(ntk_clone, &st);

const auto mig_ptr = std::make_shared<fiction::mig_nt>(ntk_clone);

env->out() << "[i] inverter cost reduction: " << st.total_gain << std::endl;

fiction::restore_names(*ntk_ptr, *mig_ptr);

s.extend() = mig_ptr;
}
else // not an MIG
{
env->out() << fmt::format("[e] {} is not an MIG", fiction::get_name(ntk_ptr)) << std::endl;
}
};

std::visit(perform_inverter_optimization, s.current());
}
};

ALICE_ADD_COMMAND(miginvopt, "Logic")

} // namespace alice

#endif // FICTION_CMD_MIGINVOPT_HPP
96 changes: 96 additions & 0 deletions cli/cmd/logic/miginvprop.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
//
// Created by marcel on 07.06.23.
//

#ifndef FICTION_CMD_MIGINVPROP_HPP
#define FICTION_CMD_MIGINVPROP_HPP

#include <fiction/algorithms/network_transformation/network_conversion.hpp>
#include <fiction/types.hpp>
#include <fiction/utils/name_utils.hpp>

#include <alice/alice.hpp>
#include <fmt/format.h>
#include <mockturtle/algorithms/mig_inv_propagation.hpp>
#include <mockturtle/views/fanout_view.hpp>

#include <type_traits>
#include <variant>

namespace alice
{
/**
* Optimizes inverter costs of the current MIG in store.
*/
class miginvprop_command : public command
{
public:
/**
* Standard constructor. Adds descriptive information, options, and flags.
*
* @param e alice::environment that specifies stores etc.
*/
explicit miginvprop_command(const environment::ptr& e) :
command(
e,
"Propagates inverting edges present in the current MIG in store to the primary inputs of the network, "
"thus reducing inverter cost but potentially increasing node count due to logic duplication.")
{}

protected:
/**
* Function to perform the balancing call. Inserts buffer nodes to equalize path lengths.
*/
void execute() override
{
auto& s = store<fiction::logic_network_t>();

// error case: empty logic network store
if (s.empty())
{
env->out() << "[w] no logic network in store" << std::endl;

return;
}

const auto perform_inverter_optimization = [&](auto&& ntk_ptr) -> void
{
using Ntk = typename std::decay_t<decltype(ntk_ptr)>::element_type;

mockturtle::mig_inv_propagation_stats st{};
marcelwa marked this conversation as resolved.
Show resolved Hide resolved

// if the current logic network is an MIG
if constexpr (std::is_same_v<Ntk, fiction::mig_nt>)
{
// clone it because inverter optimization is an in-place algorithm
auto ntk_clone = ntk_ptr->clone();

mockturtle::fanout_view fo_ntk_clone{ntk_clone};
mockturtle::mig_inv_propagation(fo_ntk_clone, &st);

const auto mig_ptr = std::make_shared<fiction::mig_nt>(ntk_clone);

env->out() << fmt::format("[i] inverter cost reduction: {}\n"
"[i] node count increase: {}",
st.total_gain, st.node_increase)
<< std::endl;

fiction::restore_names(*ntk_ptr, *mig_ptr);

s.extend() = mig_ptr;
}
else // not an MIG
{
env->out() << fmt::format("[e] {} is not an MIG", fiction::get_name(ntk_ptr)) << std::endl;
}
};

std::visit(perform_inverter_optimization, s.current());
}
};

ALICE_ADD_COMMAND(miginvprop, "Logic")

} // namespace alice

#endif // FICTION_CMD_MIGINVPROP_HPP
2 changes: 2 additions & 0 deletions cli/commands.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
#include "cmd/logic/fanouts.hpp"
#include "cmd/logic/gates.hpp"
#include "cmd/logic/map.hpp"
#include "cmd/logic/miginvopt.hpp"
#include "cmd/logic/miginvprop.hpp"
#include "cmd/logic/random.hpp"
#include "cmd/logic/simulate.hpp"
#include "cmd/physical_design/exact.hpp"
Expand Down