Skip to content

Commit

Permalink
added sequential netlist graph generation and added some comments
Browse files Browse the repository at this point in the history
  • Loading branch information
SimonKlx committed Nov 6, 2024
1 parent 5e36d61 commit 0069b76
Show file tree
Hide file tree
Showing 5 changed files with 198 additions and 81 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
/**
* @file netlist_graph.h
* @brief This file contains structures and functions for creating and annotating netlist graphs used in machine learning applications.
*/

#pragma once

#include "hal_core/defines.h"
#include "machine_learning/types.h"

Expand All @@ -7,20 +13,65 @@
namespace hal
{
class Netlist;
class Gate;

namespace machine_learning
{
namespace graph

/**
* @struct NetlistGraph
* @brief Represents a directed graph structure for a netlist.
*
* This structure holds the edges of the graph as pairs of node indices and the graph's directional configuration.
*/
struct NetlistGraph
{
struct NetlistGraph
{
std::pair<std::vector<u32>, std::vector<u32>> edge_list;
GraphDirection direction;
};
/**
* @brief Edge list of the graph represented by pairs of node indices.
*/
std::pair<std::vector<u32>, std::vector<u32>> edge_list;

/**
* @brief The direction of the graph (e.g., forward or backward).
*/
GraphDirection direction;
};

/**
* @brief Constructs a graph representation of a netlist. The connections are an edge list of indices representing the position of the gates in the gates vector.
*
* This function constructs a netlist graph by analyzing the connections among all gates in a netlist.
*
* @param[in] nl - The netlist to operate on.
* @param[in] gates - The order of the gates, needed for the index representation.
* @param[in] dir - The direction of the graph.
* @returns A `NetlistGraph` representing the netlist connections.
*/
NetlistGraph construct_netlist_graph(const Netlist* nl, const std::vector<Gate*>& gates, const GraphDirection& dir);

/**
* @brief Constructs a sequential netlist graph representation. The connections are an edge list of indices representing the position of the gates in the gates vector.
*
* This function constructs a sequential graph representation of the netlist, capturing only the sequential dependencies between gates.
*
* @param[in] nl - The netlist to operate on.
* @param[in] gates - The order of the gates, needed for the index representation.
* @param[in] dir - The direction of the graph.
* @returns A `NetlistGraph` representing the sequential connections within the netlist.
*/
NetlistGraph construct_sequential_netlist_graph(const Netlist* nl, const std::vector<Gate*>& gates, const GraphDirection& dir);

NetlistGraph construct_netlist_graph(const Netlist* nl, const std::vector<Gate*>& gates, const GraphDirection& dir);
/**
* @brief Annotates a netlist graph with features for machine learning tasks.
*
* This function annotates a netlist graph by attaching features to each node. This is only for visualization and testing purposes.
*
* @param[in] nl - The netlist to annotate.
* @param[in] gates - The set of gates in the netlist graph.
* @param[in] nlg - The netlist graph to annotate.
* @param[in] node_features - A matrix of features for each node.
*/
void annotate_netlist_graph(Netlist* nl, const std::vector<Gate*>& gates, const NetlistGraph& nlg, const std::vector<std::vector<u32>>& node_features);

void annotate_netlist_graph(Netlist* nl, const std::vector<Gate*>& gates, const NetlistGraph& nlg, const std::vector<std::vector<u32>>& node_features);
} // namespace graph
} // namespace machine_learning
} // namespace hal
27 changes: 13 additions & 14 deletions plugins/machine_learning/python/python_bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ namespace hal
py::module py_gate_feature = m.def_submodule("gate_feature");
py::module py_gate_pair_feature = m.def_submodule("gate_pair_feature");
py::module py_gate_pair_label = m.def_submodule("gate_pair_label");
py::module py_graph = m.def_submodule("graph");

py::class_<MachineLearningPlugin, RawPtrWrapper<MachineLearningPlugin>, BasePluginInterface> py_machine_learning_plugin(
m, "MachineLearningPlugin", R"(Provides machine learning functionality as a plugin within the HAL framework.)");
Expand Down Expand Up @@ -104,12 +103,12 @@ namespace hal
)");

// Bindings for construct_netlist_graph
py_graph.def("construct_netlist_graph",
&machine_learning::graph::construct_netlist_graph,
py::arg("netlist"),
py::arg("gates"),
py::arg("direction"),
R"(
m.def("construct_netlist_graph",
&machine_learning::graph::construct_netlist_graph,
py::arg("netlist"),
py::arg("gates"),
py::arg("direction"),
R"(
Constructs a netlist graph from the given netlist and gates.
:param hal_py.Netlist netlist: The netlist.
Expand All @@ -120,13 +119,13 @@ namespace hal
)");

// Bindings for annotate_netlist_graph
py_graph.def("annotate_netlist_graph",
&machine_learning::graph::annotate_netlist_graph,
py::arg("netlist"),
py::arg("gates"),
py::arg("netlist_graph"),
py::arg("node_features"),
R"(
m.def("annotate_netlist_graph",
&machine_learning::graph::annotate_netlist_graph,
py::arg("netlist"),
py::arg("gates"),
py::arg("netlist_graph"),
py::arg("node_features"),
R"(
Annotates the netlist graph with the given node features.
:param hal_py.Netlist netlist: The netlist.
Expand Down
4 changes: 2 additions & 2 deletions plugins/machine_learning/scripts/ml_testing/minimal_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@
if user_name == "simon":
base_path = "/home/simon/projects/hal/"
benchmarks_base_path = pathlib.Path("/home/simon/projects/benchmarks")
if user_name == "klix":
elif user_name == "klix":
base_path = "/home/klix/projects/hal/"
benchmarks_base_path = pathlib.Path("/home/klix/projects/benchmarks")
else:
print("add base paths foe user {}before executing...".format(user_name))
print("add base paths for user {} before executing...".format(user_name))
exit()

sys.path.append(base_path + "build/lib/") #this is where your hal python lib is located
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import torch

samples = 128
noise_dimension = 1024
samples = 256
noise_dimension = 128

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

Expand Down Expand Up @@ -54,7 +54,7 @@ def forward(self, x):
model = NN().to(device)
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)

for epoch in range(10000):
for epoch in range(1000):
optimizer.zero_grad()

out = model(x.float())
Expand Down
173 changes: 120 additions & 53 deletions plugins/machine_learning/src/graph_neural_network.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "machine_learning/graph_neural_network.h"

#include "hal_core/defines.h"
#include "hal_core/netlist/decorators/netlist_abstraction_decorator.h"
#include "hal_core/netlist/gate.h"
#include "hal_core/netlist/netlist.h"
#include "hal_core/utilities/utils.h"
Expand All @@ -12,86 +13,152 @@ namespace hal
{
namespace machine_learning
{
namespace graph

NetlistGraph construct_netlist_graph(const Netlist* nl, const std::vector<Gate*>& gates, const GraphDirection& dir)
{
NetlistGraph construct_netlist_graph(const Netlist* nl, const std::vector<Gate*>& gates, const GraphDirection& dir)
std::unordered_map<const Gate*, u32> gate_to_idx;
// init gate to index mapping
for (u32 g_idx = 0; g_idx < gates.size(); g_idx++)
{
std::unordered_map<const Gate*, u32> gate_to_idx;
// init gate to index mapping
for (u32 g_idx = 0; g_idx < gates.size(); g_idx++)
{
const Gate* g = gates.at(g_idx);
gate_to_idx.insert({g, g_idx});
}
const Gate* g = gates.at(g_idx);
gate_to_idx.insert({g, g_idx});
}

// edge list
std::vector<u32> sources;
std::vector<u32> destinations;
// edge list
std::vector<u32> sources;
std::vector<u32> destinations;

for (const auto& g : gates)
for (const auto& g : gates)
{
const u32 g_idx = gate_to_idx.at(g);
if (dir == GraphDirection::directed_backward)
{
const u32 g_idx = gate_to_idx.at(g);
if (dir == GraphDirection::directed_backward)
for (const auto& pre : g->get_unique_predecessors())
{
for (const auto& pre : g->get_unique_predecessors())
{
sources.push_back(gate_to_idx.at(pre));
destinations.push_back(g_idx);
}
sources.push_back(gate_to_idx.at(pre));
destinations.push_back(g_idx);
}
}

if (dir == GraphDirection::directed_forward)
if (dir == GraphDirection::directed_forward)
{
for (const auto& suc : g->get_unique_successors())
{
for (const auto& suc : g->get_unique_successors())
{
sources.push_back(g_idx);
destinations.push_back(gate_to_idx.at(suc));
}
sources.push_back(g_idx);
destinations.push_back(gate_to_idx.at(suc));
}
}

if (dir == GraphDirection::bidirectional)
if (dir == GraphDirection::bidirectional)
{
for (const auto& suc : g->get_unique_successors())
{
for (const auto& suc : g->get_unique_successors())
{
sources.push_back(g_idx);
destinations.push_back(gate_to_idx.at(suc));

sources.push_back(gate_to_idx.at(suc));
destinations.push_back(g_idx);
}
sources.push_back(g_idx);
destinations.push_back(gate_to_idx.at(suc));

sources.push_back(gate_to_idx.at(suc));
destinations.push_back(g_idx);
}
}

return {{sources, destinations}, dir};
}

void annotate_netlist_graph(Netlist* nl, const std::vector<Gate*>& gates, const NetlistGraph& nlg, const std::vector<std::vector<u32>>& node_features)
return {{sources, destinations}, dir};
}

NetlistGraph construct_sequential_netlist_graph(const Netlist* nl, const std::vector<Gate*>& gates, const GraphDirection& dir)
{
std::unordered_map<const Gate*, u32> gate_to_idx;
// init gate to index mapping
for (u32 g_idx = 0; g_idx < gates.size(); g_idx++)
{
for (u32 g_idx = 0; g_idx < gates.size(); g_idx++)
const Gate* g = gates.at(g_idx);
if (!g->get_type()->has_property(GateTypeProperty::sequential))
{
gates.at(g_idx)->set_data("netlist_graph", "gate_index", "string", std::to_string(g_idx));
log_error("machine_learning", "got not sequnetial gate in gate vector for sequential netlist graph");
return {};
}

const auto feature_vec = node_features.at(g_idx);
const auto feature_str = utils::join(", ", feature_vec.begin(), feature_vec.end(), [](const u32 u) { return std::to_string(u); });
gate_to_idx.insert({g, g_idx});
}

gates.at(g_idx)->set_data("netlist_graph", "features", "string", feature_str);
}
const std::vector<PinType> forbidden_pins = {
PinType::clock, /*PinType::done, PinType::error, PinType::error_detection,*/ /*PinType::none,*/ PinType::ground, PinType::power /*, PinType::status*/};

const auto endpoint_filter = [forbidden_pins](const auto* ep, const auto& _d) {
UNUSED(_d);
return std::find(forbidden_pins.begin(), forbidden_pins.end(), ep->get_pin()->get_type()) == forbidden_pins.end();
};

std::unordered_map<u32, std::vector<u32>> edges;
for (u32 edge_idx = 0; edge_idx < nlg.edge_list.first.size(); edge_idx++)
const auto sequential_abstraction = NetlistAbstraction(nl, gates, true, endpoint_filter, endpoint_filter);

// edge list
std::vector<u32> sources;
std::vector<u32> destinations;

for (const auto& g : gates)
{
const u32 g_idx = gate_to_idx.at(g);
if (dir == GraphDirection::directed_backward)
{
const auto src = nlg.edge_list.first.at(edge_idx);
const auto dst = nlg.edge_list.second.at(edge_idx);
for (const auto& pre : sequential_abstraction.get_unique_predecessors(g))
{
sources.push_back(gate_to_idx.at(pre));
destinations.push_back(g_idx);
}
}

edges[src].push_back(dst);
if (dir == GraphDirection::directed_forward)
{
for (const auto& suc : sequential_abstraction.get_unique_successors(g))
{
sources.push_back(g_idx);
destinations.push_back(gate_to_idx.at(suc));
}
}

for (const auto [src, dsts] : edges)
if (dir == GraphDirection::bidirectional)
{
const auto vec_str = utils::join(", ", dsts.begin(), dsts.end(), [](const u32 u) { return std::to_string(u); });
gates.at(src)->set_data("netlist_graph", "destinations", "string", vec_str);
for (const auto& suc : sequential_abstraction.get_unique_successors(g))
{
sources.push_back(g_idx);
destinations.push_back(gate_to_idx.at(suc));

sources.push_back(gate_to_idx.at(suc));
destinations.push_back(g_idx);
}
}
}
} // namespace graph

return {{sources, destinations}, dir};
}

void annotate_netlist_graph(Netlist* nl, const std::vector<Gate*>& gates, const NetlistGraph& nlg, const std::vector<std::vector<u32>>& node_features)
{
for (u32 g_idx = 0; g_idx < gates.size(); g_idx++)
{
gates.at(g_idx)->set_data("netlist_graph", "gate_index", "string", std::to_string(g_idx));

const auto feature_vec = node_features.at(g_idx);
const auto feature_str = utils::join(", ", feature_vec.begin(), feature_vec.end(), [](const u32 u) { return std::to_string(u); });

gates.at(g_idx)->set_data("netlist_graph", "features", "string", feature_str);
}

std::unordered_map<u32, std::vector<u32>> edges;
for (u32 edge_idx = 0; edge_idx < nlg.edge_list.first.size(); edge_idx++)
{
const auto src = nlg.edge_list.first.at(edge_idx);
const auto dst = nlg.edge_list.second.at(edge_idx);

edges[src].push_back(dst);
}

for (const auto [src, dsts] : edges)
{
const auto vec_str = utils::join(", ", dsts.begin(), dsts.end(), [](const u32 u) { return std::to_string(u); });
gates.at(src)->set_data("netlist_graph", "destinations", "string", vec_str);
}
}

} // namespace machine_learning
} // namespace hal

0 comments on commit 0069b76

Please sign in to comment.