-
Notifications
You must be signed in to change notification settings - Fork 89
Custom Plugins
To use the full capabilities of HAL, you can develop plugins yourself. Although we can use scripts to use the HAL API, sometimes the speed of C++ is necessary to achieve the desired performance. Here we show you how to develop your own plugins. Furthermore, we show how to include python bindings to the code.
This plugin contains the minimal amount of code to run and be used in HAL. This plugin just outputs "Hello World!" to the console and the python binding just returns the string "Hello World Py".
One can ether create all the necessary files from scratch or use the plugin-set-up-script provided with HAL. Just cd into your working directory for the plugin located at <Path to HAL>/plugins/<plugin name> and run <pathToHAL>/tools/new_plugin.py <name>. In the following documentation the plugin name is barebone.
This script creates the following directories and files in the current working directory.
├── CMakeLists.txt
├── include/barebone
│ └── barebone.h
├── python
│ └── python_bindings.cpp
└── src
└── barebone.cpp
So let's start by implementing the code necessary to produce the a basic HAL plugin. Let us create both the header and source file.
// include/barebone/barebone.h
#pragma once
#include "hal_core/defines.h"
#include "hal_core/plugin_system/plugin_interface_base.h"
#include "hal_core/utilities/result.h"
#include "hal_core/netlist/netlist.h"
namespace hal
{
class PLUGIN_API BarebonePlugin : public BasePluginInterface
{
public:
std::string get_name() const override;
std::string get_version() const override;
void initialize() override;
// this is a custom function used for the py binding
static void barebone_test();
};
} // namespace halAll methods except barebone_test() are necessary functions of the provided BasePluginInterface.
The actual functionality is implemented in the barebone.cpp file.
// src/barebone.cpp
#include "barebone/barebone.h"
#include "boost/functional/hash.hpp"
#include "hal_core/netlist/gate.h"
#include "hal_core/netlist/module.h"
#include <deque>
namespace hal
{
extern std::unique_ptr<BasePluginInterface> create_plugin_instance()
{
return std::make_unique<BarebonePlugin>();
}
std::string BarebonePlugin::get_name() const
{
return std::string("barebone");
}
std::string BarebonePlugin::get_version() const
{
return std::string("0.1");
}
void BarebonePlugin::initialize()
{
}
void BarebonePlugin::barebone_test() {
std::cout << "Hello World!" << std::endl;
}
} // namespace halAs HAL also brings a python shell for scripted analysis with it, you might want to expose your plugin to this environment. For this purpose, we use pybind11. The actual mapping is done in the python/python_bindings.cpp file.
// python/python_bindings.cpp
#include "hal_core/python_bindings/python_bindings.h"
#include "barebone/barebone.h"
#include "pybind11/operators.h"
#include "pybind11/pybind11.h"
#include "pybind11/stl.h"
#include "pybind11/stl_bind.h"
namespace py = pybind11;
namespace hal
{
// the name in PYBIND11_MODULE/PYBIND11_PLUGIN *MUST* match the filename of the output library (without extension),
// otherwise you will get "ImportError: dynamic module does not define module export function" when importing the module
#ifdef PYBIND11_MODULE
PYBIND11_MODULE(barebone, m)
{
m.doc() = "hal barebone python bindings";
#else
PYBIND11_PLUGIN(barebone)
{
py::module m("barebone", "hal barebone python bindings");
#endif
// define all exposed functions
py::class_<BarebonePlugin, RawPtrWrapper<BarebonePlugin>, BasePluginInterface>(m, "BarebonePlugin")
.def_property_readonly("name", &BarebonePlugin::get_name)
.def("get_name", &BarebonePlugin::get_name)
.def_property_readonly("version", &BarebonePlugin::get_version)
.def("get_version", &BarebonePlugin::get_version)
// this is an example function
.def_static(
"barebone_test",
[]() -> std::string {
// we can call for example functions of the plugin here
BarebonePlugin::barebone_test();
return "Hello World Py";
});
#ifndef PYBIND11_MODULE
return m.ptr();
#endif
}
} // namespace halTo build this plugin using HAL, we use the CMakeLists.txt file. The file should look something like this.
# CMakeLists.txt
option(PL_BAREBONE "PL_BAREBONE" OFF)
if(PL_BAREBONE OR BUILD_ALL_PLUGINS)
file(GLOB_RECURSE BAREBONE_INC ${CMAKE_CURRENT_SOURCE_DIR}/include/*.h)
file(GLOB_RECURSE BAREBONE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)
file(GLOB_RECURSE BAREBONE_PYTHON_SRC ${CMAKE_CURRENT_SOURCE_DIR}/python/*.cpp)
hal_add_plugin(barebone
SHARED
HEADER ${BAREBONE_INC}
SOURCES ${BAREBONE_SRC} ${BAREBONE_PYTHON_SRC}
PYDOC SPHINX_DOC_INDEX_FILE ${CMAKE_CURRENT_SOURCE_DIR}/documentation/barebone.rst
)
endif()Now you can build HAL using cmake .. -DBUILD_ALL_PLUGINS=1 to automatically build your newly created plugin. You can also call it using python as followed:
from hal_plugins.barebone import BarebonePlugin
output = BarebonePlugin.barebone_test()
print(output) # this prints the string "Hello World Py"