-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
🎨 Add an example
CellLevelLayout
type to pyfiction to showcase Pyth…
…onic naming and factory classes
- Loading branch information
Showing
4 changed files
with
285 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
185 changes: 185 additions & 0 deletions
185
bindings/mnt/pyfiction/include/pyfiction/layouts/CellLevelLayout.hpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,185 @@ | ||
// | ||
// Created by marcel on 04.06.22. | ||
// | ||
|
||
#ifndef PYFICTION_CELLLEVELLAYOUT_HPP | ||
#define PYFICTION_CELLLEVELLAYOUT_HPP | ||
|
||
#include "pyfiction/documentation.hpp" | ||
#include "pyfiction/types.hpp" | ||
|
||
#include <fiction/technology/cell_technologies.hpp> | ||
#include <fiction/traits.hpp> | ||
#include <fiction/utils/layout_utils.hpp> | ||
|
||
#include <fmt/format.h> | ||
#include <pybind11/pybind11.h> | ||
#include <pybind11/stl.h> | ||
|
||
#include <algorithm> | ||
#include <cctype> | ||
#include <string> | ||
#include <type_traits> | ||
#include <variant> | ||
#include <vector> | ||
|
||
namespace pyfiction | ||
{ | ||
|
||
namespace detail | ||
{ | ||
|
||
class py_cartesian_cell_layout : public fiction::clocked_layout< | ||
fiction::tile_based_layout<fiction::cartesian_layout<fiction::offset::ucoord_t>>> | ||
{ | ||
public: | ||
template <typename... Args> | ||
py_cartesian_cell_layout(std::string technology, Args... args) | ||
{ | ||
std::transform(technology.begin(), technology.end(), technology.begin(), ::tolower); | ||
|
||
if (technology == "qca") | ||
{ | ||
underlying_layout = py_qca_layout(args...); | ||
} | ||
else if (technology == "inml") | ||
{ | ||
underlying_layout = py_inml_layout(args...); | ||
} | ||
else if (technology == "sidb") | ||
{ | ||
underlying_layout = py_sidb_layout(args...); | ||
} | ||
else | ||
{ | ||
throw std::runtime_error(fmt::format("'{}' does not refer to a supported technology", technology)); | ||
} | ||
} | ||
|
||
std::variant<py_qca_layout, py_inml_layout, py_sidb_layout> underlying_layout{}; | ||
}; | ||
|
||
inline void cell_level_layout(pybind11::module& m) | ||
{ | ||
namespace py = pybind11; | ||
|
||
/** | ||
* Cell-level clocked Cartesian layout. | ||
*/ | ||
py::class_< | ||
py_cartesian_cell_layout, | ||
fiction::clocked_layout<fiction::tile_based_layout<fiction::cartesian_layout<fiction::offset::ucoord_t>>>>( | ||
m, "CellLevelLayout", DOC(fiction_cell_level_layout)) | ||
.def(py::init<std::string>(), py::arg("technology"), DOC(fiction_cell_level_layout_cell_level_layout)) | ||
.def(py::init<std::string, const fiction::aspect_ratio<py_cartesian_cell_layout>&>(), py::arg("technology"), | ||
py::arg("dimension"), DOC(fiction_cell_level_layout_cell_level_layout)) | ||
// .def(py::init( | ||
// [](const fiction::aspect_ratio<py_cartesian_cell_layout>& dimension, | ||
// const std::string& scheme_name, | ||
// const std::string& layout_name) -> py_cartesian_cell_layout | ||
// { | ||
// if (const auto scheme = | ||
// fiction::get_clocking_scheme<py_cartesian_cell_layout>(scheme_name); | ||
// scheme.has_value()) | ||
// { | ||
// return py_cartesian_cell_layout{dimension, *scheme, layout_name}; | ||
// } | ||
// | ||
// throw std::runtime_error("Given name does not refer to a supported clocking scheme"); | ||
// }), | ||
// py::arg("dimension"), py::arg("clocking_scheme") = "2DDWave", py::arg("layout_name") = "", | ||
// DOC(fiction_cell_level_layout_cell_level_layout_2)) | ||
// | ||
// .def("assign_cell_type", &py_cartesian_technology_cell_layout::assign_cell_type, py::arg("c"), py::arg("ct"), | ||
// DOC(fiction_cell_level_layout_assign_cell_type)) | ||
// .def("get_cell_type", &py_cartesian_technology_cell_layout::get_cell_type, py::arg("c"), | ||
// DOC(fiction_cell_level_layout_get_cell_type)) | ||
// .def("is_empty_cell", &py_cartesian_technology_cell_layout::is_empty_cell, py::arg("c"), | ||
// DOC(fiction_cell_level_layout_is_empty_cell)) | ||
// .def("assign_cell_name", &py_cartesian_technology_cell_layout::assign_cell_name, py::arg("c"), py::arg("n"), | ||
// DOC(fiction_cell_level_layout_assign_cell_name)) | ||
// .def("get_cell_name", &py_cartesian_technology_cell_layout::get_cell_name, py::arg("c"), | ||
// DOC(fiction_cell_level_layout_get_cell_name)) | ||
// .def("set_layout_name", &py_cartesian_technology_cell_layout::set_layout_name, py::arg("name"), | ||
// DOC(fiction_cell_level_layout_set_layout_name)) | ||
// .def("get_layout_name", &py_cartesian_technology_cell_layout::get_layout_name, | ||
// DOC(fiction_cell_level_layout_get_layout_name)) | ||
// .def("num_cells", &py_cartesian_technology_cell_layout::num_cells, DOC(fiction_cell_level_layout_num_cells)) | ||
// .def("is_empty", &py_cartesian_technology_cell_layout::is_empty, DOC(fiction_cell_level_layout_is_empty)) | ||
// .def("num_pis", &py_cartesian_technology_cell_layout::num_pis, DOC(fiction_cell_level_layout_num_pis)) | ||
// .def("num_pos", &py_cartesian_technology_cell_layout::num_pos, DOC(fiction_cell_level_layout_num_pos)) | ||
// .def("is_pi", &py_cartesian_technology_cell_layout::is_pi, py::arg("c"), | ||
// DOC(fiction_cell_level_layout_is_pi)) .def("is_po", &py_cartesian_technology_cell_layout::is_po, | ||
// py::arg("c"), DOC(fiction_cell_level_layout_is_po)) | ||
// | ||
.def("cells", | ||
[](const py_cartesian_cell_layout& lyt) | ||
{ | ||
const auto apply = [](const auto& cell_layout) | ||
{ | ||
using Lyt = std::decay_t<decltype(cell_layout)>; | ||
|
||
std::vector<fiction::coordinate<Lyt>> cells{}; | ||
cells.reserve(cell_layout.num_cells()); | ||
cell_layout.foreach_cell([&cells](const auto& c) { cells.push_back(c); }); | ||
|
||
return cells; | ||
}; | ||
|
||
return std::visit(apply, lyt.underlying_layout); | ||
}) | ||
// .def("pis", | ||
// [](const py_cartesian_technology_cell_layout& lyt) | ||
// { | ||
// std::vector<fiction::coordinate<py_cartesian_technology_cell_layout>> pis{}; | ||
// pis.reserve(lyt.num_pis()); | ||
// lyt.foreach_pi([&pis](const auto& c) { pis.push_back(c); }); | ||
// return pis; | ||
// }) | ||
// .def("pos", | ||
// [](const py_cartesian_technology_cell_layout& lyt) | ||
// { | ||
// std::vector<fiction::coordinate<py_cartesian_technology_cell_layout>> pos{}; | ||
// pos.reserve(lyt.num_pos()); | ||
// lyt.foreach_po([&pos](const auto& c) { pos.push_back(c); }); | ||
// return pos; | ||
// }) | ||
// .def( | ||
// "bounding_box_2d", | ||
// [](const py_cartesian_technology_cell_layout& lyt) | ||
// { | ||
// const auto bb = fiction::bounding_box_2d<py_cartesian_technology_cell_layout>(lyt); | ||
// return std::make_pair(bb.get_min(), bb.get_max()); | ||
// }, | ||
// DOC(fiction_bounding_box_2d_overridden)) | ||
// | ||
// .def("__repr__", | ||
// [](const py_cartesian_technology_cell_layout& lyt) -> std::string | ||
// { | ||
// std::stringstream stream{}; | ||
// | ||
// if constexpr (std::is_same_v<Technology, fiction::sidb_technology>) | ||
// { | ||
// print_layout(convert_layout_to_siqad_coordinates(lyt), stream); | ||
// } | ||
// else | ||
// { | ||
// print_layout(lyt, stream); | ||
// } | ||
// | ||
// return stream.str(); | ||
// }) | ||
|
||
; | ||
} | ||
|
||
} // namespace detail | ||
|
||
inline void cell_level_layout(pybind11::module& m) | ||
{ | ||
detail::cell_level_layout(m); | ||
} | ||
|
||
} // namespace pyfiction | ||
|
||
#endif // PYFICTION_CELLLEVELLAYOUT_HPP |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
96 changes: 96 additions & 0 deletions
96
bindings/mnt/pyfiction/test/layouts/TestCellLevelLayout.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
from mnt.pyfiction import (CellLevelLayout) | ||
import unittest | ||
|
||
|
||
class TestCellLevelLayout(unittest.TestCase): | ||
|
||
def test_cell_layout_inheritance(self): | ||
for tech in ["qca", "inml", "sidb"]: | ||
layout = CellLevelLayout(tech, (9, 9, 1)) | ||
|
||
for t in layout.coordinates(): | ||
self.assertTrue(t <= (9, 9, 1)) | ||
self.assertTrue(layout.is_within_bounds(t)) | ||
|
||
for t in layout.ground_coordinates(): | ||
self.assertTrue(t.z == 0) | ||
self.assertTrue(t <= (9, 9, 0)) | ||
self.assertTrue(layout.is_within_bounds(t)) | ||
|
||
for t in layout.adjacent_coordinates((2, 2)): | ||
self.assertIn(t, [(1, 2), (2, 1), (3, 2), (2, 3)]) | ||
|
||
# def test_cell_type_assignment(self): | ||
# layout = qca_layout((4, 4), "OPEN", "AND") | ||
# | ||
# self.assertTrue(layout.is_empty()) | ||
# | ||
# layout.assign_cell_type((0, 2), qca_technology.cell_type.INPUT) | ||
# layout.assign_cell_type((2, 4), qca_technology.cell_type.INPUT) | ||
# layout.assign_cell_type((2, 0), qca_technology.cell_type.CONST_0) | ||
# layout.assign_cell_type((2, 1), qca_technology.cell_type.NORMAL) | ||
# layout.assign_cell_type((2, 2), qca_technology.cell_type.NORMAL) | ||
# layout.assign_cell_type((2, 3), qca_technology.cell_type.NORMAL) | ||
# layout.assign_cell_type((1, 2), qca_technology.cell_type.NORMAL) | ||
# layout.assign_cell_type((3, 2), qca_technology.cell_type.NORMAL) | ||
# layout.assign_cell_type((4, 2), qca_technology.cell_type.OUTPUT) | ||
# | ||
# self.assertFalse(layout.is_empty()) | ||
# | ||
# layout.assign_cell_name((0, 2), "a") | ||
# layout.assign_cell_name((2, 4), "b") | ||
# layout.assign_cell_name((4, 2), "f") | ||
# | ||
# self.assertEqual(layout.get_layout_name(), "AND") | ||
# self.assertEqual(layout.get_cell_name((0, 2)), "a") | ||
# self.assertEqual(layout.get_cell_name((2, 4)), "b") | ||
# self.assertEqual(layout.get_cell_name((4, 2)), "f") | ||
# | ||
# self.assertEqual(layout.num_cells(), 9) | ||
# self.assertEqual(layout.num_pis(), 2) | ||
# self.assertEqual(layout.num_pos(), 1) | ||
# | ||
# self.assertTrue(layout.is_pi((0, 2))) | ||
# self.assertTrue(layout.is_pi((2, 4))) | ||
# self.assertTrue(layout.is_po((4, 2))) | ||
# | ||
# self.assertEqual(layout.get_cell_type((2, 0)), qca_technology.cell_type.CONST_0) | ||
# self.assertEqual(layout.get_cell_type((2, 4)), qca_technology.cell_type.INPUT) | ||
# self.assertEqual(layout.get_cell_type((0, 2)), qca_technology.cell_type.INPUT) | ||
# self.assertEqual(layout.get_cell_type((2, 1)), qca_technology.cell_type.NORMAL) | ||
# self.assertEqual(layout.get_cell_type((2, 2)), qca_technology.cell_type.NORMAL) | ||
# self.assertEqual(layout.get_cell_type((2, 3)), qca_technology.cell_type.NORMAL) | ||
# self.assertEqual(layout.get_cell_type((1, 2)), qca_technology.cell_type.NORMAL) | ||
# self.assertEqual(layout.get_cell_type((3, 2)), qca_technology.cell_type.NORMAL) | ||
# self.assertEqual(layout.get_cell_type((4, 2)), qca_technology.cell_type.OUTPUT) | ||
# | ||
# self.assertTrue(layout.is_empty_cell((0, 0))) | ||
# self.assertTrue(layout.is_empty_cell((0, 1))) | ||
# self.assertTrue(layout.is_empty_cell((1, 0))) | ||
# self.assertTrue(layout.is_empty_cell((1, 1))) | ||
# self.assertTrue(layout.is_empty_cell((3, 0))) | ||
# self.assertTrue(layout.is_empty_cell((3, 1))) | ||
# self.assertTrue(layout.is_empty_cell((4, 0))) | ||
# self.assertTrue(layout.is_empty_cell((4, 1))) | ||
# self.assertTrue(layout.is_empty_cell((0, 3))) | ||
# self.assertTrue(layout.is_empty_cell((1, 3))) | ||
# self.assertTrue(layout.is_empty_cell((0, 4))) | ||
# self.assertTrue(layout.is_empty_cell((1, 0))) | ||
# self.assertTrue(layout.is_empty_cell((3, 3))) | ||
# self.assertTrue(layout.is_empty_cell((3, 4))) | ||
# self.assertTrue(layout.is_empty_cell((4, 3))) | ||
# self.assertTrue(layout.is_empty_cell((4, 4))) | ||
# | ||
# self.assertFalse(layout.is_empty_cell((2, 0))) | ||
# self.assertFalse(layout.is_empty_cell((2, 4))) | ||
# self.assertFalse(layout.is_empty_cell((0, 2))) | ||
# self.assertFalse(layout.is_empty_cell((2, 1))) | ||
# self.assertFalse(layout.is_empty_cell((2, 2))) | ||
# self.assertFalse(layout.is_empty_cell((2, 3))) | ||
# self.assertFalse(layout.is_empty_cell((1, 2))) | ||
# self.assertFalse(layout.is_empty_cell((3, 2))) | ||
# self.assertFalse(layout.is_empty_cell((4, 2))) | ||
|
||
|
||
if __name__ == '__main__': | ||
unittest.main() |