From 8546100f7e07cbee2055c9f28cd66c2d22f51684 Mon Sep 17 00:00:00 2001 From: Simon Hofmann Date: Mon, 25 Sep 2023 17:54:55 +0200 Subject: [PATCH 01/36] basic parser for gate level layouts --- include/fiction/io/read_gate_level_layout.hpp | 198 ++++++++++++++++++ .../fiction/io/write_gate_level_layout.hpp | 120 +++++++++++ test/io/read_gate_level_layout.cpp | 46 ++++ 3 files changed, 364 insertions(+) create mode 100644 include/fiction/io/read_gate_level_layout.hpp create mode 100644 include/fiction/io/write_gate_level_layout.hpp create mode 100644 test/io/read_gate_level_layout.cpp diff --git a/include/fiction/io/read_gate_level_layout.hpp b/include/fiction/io/read_gate_level_layout.hpp new file mode 100644 index 000000000..7822510f9 --- /dev/null +++ b/include/fiction/io/read_gate_level_layout.hpp @@ -0,0 +1,198 @@ +// +// Created by simon on 25.09.23. +// + +#ifndef FICTION_READ_GATE_LEVEL_LAYOUT_HPP +#define FICTION_READ_GATE_LEVEL_LAYOUT_HPP + +#include "fiction/traits.hpp" +#include +#include +#include +#include "fiction/utils/name_utils.hpp" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace fiction +{ + +/** + * Exception thrown when an error occurs during parsing of an FCN file. + */ +class fcn_parsing_error : public std::runtime_error +{ + public: + explicit fcn_parsing_error(const std::string_view& msg) noexcept : std::runtime_error(msg.data()) {} +}; + +namespace detail +{ + +template +class read_gate_level_layout_impl +{ + public: + read_gate_level_layout_impl(std::istream& s, const std::string_view& name) : lyt{}, is{s} + { + set_name(lyt, name); + } + + read_gate_level_layout_impl(Lyt& tgt, std::istream& s) : lyt{tgt}, is{s} {} + + Lyt run() + { + // tinyXML2 does not support std::istream, so we have to read the whole file into a string first + std::stringstream buffer{}; + buffer << is.rdbuf(); + const std::string sqd_content{buffer.str()}; + + tinyxml2::XMLDocument xml_document{}; + xml_document.Parse(sqd_content.c_str()); + + if (xml_document.ErrorID() != 0) + { + throw fcn_parsing_error("Error parsing FCN file: " + std::string(xml_document.ErrorName())); + } + + auto* const fcn_root = xml_document.FirstChildElement("fcn"); + if (fcn_root == nullptr) + { + throw fcn_parsing_error("Error parsing FCN file: no root element 'fcn'"); + } + + auto* const layout = fcn_root->FirstChildElement("layout"); + if (layout == nullptr) + { + throw fcn_parsing_error("Error parsing FCN file: no element 'layout'"); + } + + auto* const name = layout->FirstChildElement("name"); + if (name != nullptr) + { + set_name(lyt, name->GetText()); + } + + auto* const clocking = layout->FirstChildElement("clocking"); + if (clocking != nullptr) + { + lyt.replace_clocking_scheme(*get_clocking_scheme(clocking->GetText())); + } + + return lyt; + } + + private: + /** + * The layout to which the parsed cells are added. + */ + Lyt lyt; + /** + * The input stream from which the FCN file is read. + */ + std::istream& is; +}; + +} // namespace detail + +/** + * Reads a gate-level layout from an fcn file provided as an input stream. The format is used by fiction + * (https://github.com/cda-tum/fiction). + * + * May throw an `fcn_parsing_exception` if the fcn file is malformed. + * + * @tparam Lyt The layout type to be created from an input. + * @param is The input stream to read from. + * @param name The name to give to the generated layout. + */ +template +Lyt read_gate_level_layout(std::istream& is, const std::string_view& name = "") +{ + detail::read_gate_level_layout_impl p{is, name}; + + const auto lyt = p.run(); + + return lyt; +} +/** + * Reads a gate-level layout from an fcn file provided as an input stream. The format is used by fiction + * (https://github.com/cda-tum/fiction). + * + * May throw an `fcn_parsing_exception` if the fcn file is malformed. + * + * This is an in-place version of read_gate_level_layout that utilizes the given layout as a target to write to. + * + * @tparam Lyt The layout type to be used as input. + * @param lyt The layout to write to. + * @param is The input stream to read from. + */ +template +void read_gate_level_layout(Lyt& lyt, std::istream& is) +{ + detail::read_gate_level_layout_impl p{lyt, is}; + + lyt = p.run(); +} +/** + * Reads a gate-level layout from an fcn file provided as an input stream. The format is used by fiction + * (https://github.com/cda-tum/fiction). + * + * May throw an `fcn_parsing_exception` if the fcn file is malformed. + * + * @tparam Lyt The layout type to be created from an input. + * @param filename The file name to open and read from. + * @param name The name to give to the generated layout. + */ +template +Lyt read_gate_level_layout(const std::string_view& filename, const std::string_view& name = "") +{ + std::ifstream is{filename.data(), std::ifstream::in}; + + if (!is.is_open()) + { + throw std::ifstream::failure("could not open file"); + } + + const auto lyt = read_gate_level_layout(is, name); + is.close(); + + return lyt; +} +/** + * Reads a gate-level layout from an fcn file provided as an input stream. The format is used by fiction + * (https://github.com/cda-tum/fiction). + + * May throw an `fcn_parsing_exception` if the fcn file is malformed. + * + * This is an in-place version of `read_gate_level_layout` that utilizes the given layout as a target to write to. + * + * @tparam Lyt The layout type to be used as input. Must be a cell-level SiDB layout. + * @param lyt The layout to write to. + * @param filename The file name to open and read from. + */ +template +void read_gate_level_layout(Lyt& lyt, const std::string_view& filename) +{ + std::ifstream is{filename.data(), std::ifstream::in}; + + if (!is.is_open()) + { + throw std::ifstream::failure("could not open file"); + } + + read_gate_level_layout(lyt, is); + is.close(); +} + +} // namespace fiction + +#endif // FICTION_READ_GATE_LEVEL_LAYOUT_HPP diff --git a/include/fiction/io/write_gate_level_layout.hpp b/include/fiction/io/write_gate_level_layout.hpp new file mode 100644 index 000000000..197eda276 --- /dev/null +++ b/include/fiction/io/write_gate_level_layout.hpp @@ -0,0 +1,120 @@ +// +// Created by simon on 25.09.23. +// + +#ifndef FICTION_WRITE_GATE_LEVEL_LAYOUT_HPP +#define FICTION_WRITE_GATE_LEVEL_LAYOUT_HPP + +#include "fiction/traits.hpp" +#include "utils/version_info.hpp" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace fiction +{ + +namespace detail +{ + +namespace fcn +{ + +inline constexpr const char* FCN_HEADER = "\n"; +inline constexpr const char* OPEN_FCN = "\n"; +inline constexpr const char* CLOSE_FCN = "\n"; +inline constexpr const char* FICTION_METADATA = " \n" + " {}\n" + " {}\n" + " {}\n" + " \n"; + +inline constexpr const char* LAYOUT_METADATA = " \n" + " {}\n" + " {}\n" + " {}\n" + " \n"; + +} // namespace fcn + +template +class write_gate_level_layout_impl +{ + public: + write_gate_level_layout_impl(const Lyt& src, std::ostream& s) : lyt{src}, os{s} {} + + void run() + { + std::stringstream header{}; + + header << fcn::FCN_HEADER << fcn::OPEN_FCN; + + const auto time_str = fmt::format("{:%Y-%m-%d %H:%M:%S}", fmt::localtime(std::time(nullptr))); + + header << fmt::format(fcn::FICTION_METADATA, FICTION_VERSION, FICTION_REPO, time_str); + + os << header.str(); + + os << fcn::CLOSE_FCN; + } + + private: + Lyt lyt; + + std::ostream& os; +}; + +} // namespace detail + +/** + * Writes a gate-level layout to a fcn file that is used by Fiction (https://github.com/cda-tum/fiction). + * + * This overload uses an output stream to write into. + * + * @tparam Lyt Layout. + * @param lyt The layout to be written. + * @param os The output stream to write into. + */ +template +void write_gate_level_layout(const Lyt& lyt, std::ostream& os) +{ + detail::write_gate_level_layout_impl p{lyt, os}; + + p.run(); +} +/** + * Writes a gate-level layout to a fcn file that is used by Fiction (https://github.com/cda-tum/fiction). + * + * This overload uses a file name to create and write into. + * + * @tparam Lyt Layout. + * @param lyt The layout to be written. + * @param filename The file name to create and write into. Should preferably use the `.fcn` extension. + */ +template +void write_gate_level_layout(const Lyt& lyt, const std::string_view& filename) +{ + std::ofstream os{filename.data(), std::ofstream::out}; + + if (!os.is_open()) + { + throw std::ofstream::failure("could not open file"); + } + + write_gate_level_layout(lyt, os); + os.close(); +} + +} // namespace fiction + +#endif // FICTION_WRITE_GATE_LEVEL_LAYOUT_HPP diff --git a/test/io/read_gate_level_layout.cpp b/test/io/read_gate_level_layout.cpp new file mode 100644 index 000000000..c0c696f63 --- /dev/null +++ b/test/io/read_gate_level_layout.cpp @@ -0,0 +1,46 @@ +// +// Created by simon on 25.09.23. +// + + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +using namespace fiction; + +TEST_CASE("Read empty FCN layout", "[fcn]") +{ + static constexpr const char* fcn_layout = "\n" + "\n" + " \n" + " Test\n" + " cartesian\n" + " 2DDWave\n" + " \n" + "\n"; + + std::istringstream layout_stream{fcn_layout}; + + const auto check = [](const auto& lyt) + { + CHECK(lyt.x() == 0); + CHECK(lyt.y() == 0); + CHECK(lyt.area() == 1); + CHECK(get_name(lyt) == "Test"); + CHECK(lyt.is_clocking_scheme(clock_name::TWODDWAVE)); + }; + + using gate_layout = gate_level_layout>>; + check(read_gate_level_layout(layout_stream)); +} From c429ae6b032b038ce09de1fbb94b967649899d4b Mon Sep 17 00:00:00 2001 From: Simon Hofmann Date: Tue, 26 Sep 2023 13:31:33 +0200 Subject: [PATCH 02/36] implement gate_level_layout reader for simple layouts --- include/fiction/io/read_gate_level_layout.hpp | 124 +++++++++++++++--- .../fiction/io/write_gate_level_layout.hpp | 5 + test/io/read_gate_level_layout.cpp | 104 ++++++++++++++- 3 files changed, 214 insertions(+), 19 deletions(-) diff --git a/include/fiction/io/read_gate_level_layout.hpp b/include/fiction/io/read_gate_level_layout.hpp index 7822510f9..58d725f86 100644 --- a/include/fiction/io/read_gate_level_layout.hpp +++ b/include/fiction/io/read_gate_level_layout.hpp @@ -6,10 +6,12 @@ #define FICTION_READ_GATE_LEVEL_LAYOUT_HPP #include "fiction/traits.hpp" +#include "fiction/utils/name_utils.hpp" + #include #include #include -#include "fiction/utils/name_utils.hpp" +#include #include @@ -27,12 +29,12 @@ namespace fiction { /** - * Exception thrown when an error occurs during parsing of an FCN file. + * Exception thrown when an error occurs during parsing of an gate_level file. */ -class fcn_parsing_error : public std::runtime_error +class gate_level_parsing_error : public std::runtime_error { public: - explicit fcn_parsing_error(const std::string_view& msg) noexcept : std::runtime_error(msg.data()) {} + explicit gate_level_parsing_error(const std::string_view& msg) noexcept : std::runtime_error(msg.data()) {} }; namespace detail @@ -61,19 +63,19 @@ class read_gate_level_layout_impl if (xml_document.ErrorID() != 0) { - throw fcn_parsing_error("Error parsing FCN file: " + std::string(xml_document.ErrorName())); + throw gate_level_parsing_error("Error parsing gate_level file: " + std::string(xml_document.ErrorName())); } auto* const fcn_root = xml_document.FirstChildElement("fcn"); if (fcn_root == nullptr) { - throw fcn_parsing_error("Error parsing FCN file: no root element 'fcn'"); + throw gate_level_parsing_error("Error parsing gate_level file: no root element 'fcn'"); } auto* const layout = fcn_root->FirstChildElement("layout"); if (layout == nullptr) { - throw fcn_parsing_error("Error parsing FCN file: no element 'layout'"); + throw gate_level_parsing_error("Error parsing gate_level file: no element 'layout'"); } auto* const name = layout->FirstChildElement("name"); @@ -88,6 +90,82 @@ class read_gate_level_layout_impl lyt.replace_clocking_scheme(*get_clocking_scheme(clocking->GetText())); } + auto* const size = layout->FirstChildElement("size"); + if (size != nullptr) + { + int x = std::stoi(size->FirstChildElement("x")->GetText()); + int y = std::stoi(size->FirstChildElement("y")->GetText()); + int z = std::stoi(size->FirstChildElement("z")->GetText()); + tile max_pos{x, y, z}; + lyt.resize(max_pos); + } + + std::vector gates{}; + auto* const gates_xml = fcn_root->FirstChildElement("gates"); + if (gates_xml != nullptr) + { + for (const auto* gate_xml = gates_xml->FirstChildElement("gate"); gate_xml != nullptr; + gate_xml = gate_xml->NextSiblingElement("gate")) + { + Gate gate; + gate.id = std::stoi(gate_xml->FirstChildElement("id")->GetText()); + gate.type = gate_xml->FirstChildElement("type")->GetText(); + + auto* const pi_name = gate_xml->FirstChildElement("name"); + if (pi_name != nullptr) + { + gate.name = pi_name->GetText(); + } + + auto* const loc = gate_xml->FirstChildElement("loc"); + gate.loc.x = std::stoull(loc->FirstChildElement("x")->GetText()); + gate.loc.y = std::stoull(loc->FirstChildElement("y")->GetText()); + gate.loc.z = std::stoull(loc->FirstChildElement("z")->GetText()); + + auto* const incoming = gate_xml->FirstChildElement("incoming"); + if (incoming != nullptr) + { + for (const auto* signal = incoming->FirstChildElement("signal"); signal != nullptr; + signal = incoming->NextSiblingElement("signal")) + { + tile incoming_signal{}; + incoming_signal.x = std::stoull(signal->FirstChildElement("x")->GetText()); + incoming_signal.y = std::stoull(signal->FirstChildElement("y")->GetText()); + incoming_signal.z = std::stoull(signal->FirstChildElement("z")->GetText()); + gate.incoming.push_back(incoming_signal); + } + } + + gates.push_back(gate); + } + } + std::sort(gates.begin(), gates.end(), Gate::compareById); + + for (const Gate& gate : gates) + { + auto location = gate.loc; + + if (gate.type == "PI") + { + lyt.create_pi(gate.name, {location.x, location.y, location.z}); + } + + else if (gate.type == "AND") + { + auto incoming_tile_1 = gate.incoming.front(); + auto incoming_tile_2 = gate.incoming.back(); + lyt.create_and(lyt.make_signal(lyt.get_node(incoming_tile_1)), + lyt.make_signal(lyt.get_node(incoming_tile_2)), {location.x, location.y, location.z}); + } + + else if (gate.type == "PO") + { + auto incoming_tile = gate.incoming.front(); + lyt.create_po(lyt.make_signal(lyt.get_node(incoming_tile)), gate.name, + {location.x, location.y, location.z}); + } + } + return lyt; } @@ -97,18 +175,32 @@ class read_gate_level_layout_impl */ Lyt lyt; /** - * The input stream from which the FCN file is read. + * The input stream from which the gate_level file is read. */ std::istream& is; + + struct Gate + { + int id; + std::string type; + std::string name; + tile loc; + std::vector> incoming; + + static bool compareById(const Gate& gate1, const Gate& gate2) + { + return gate1.id < gate2.id; + } + }; }; } // namespace detail /** - * Reads a gate-level layout from an fcn file provided as an input stream. The format is used by fiction + * Reads a gate-level layout from a gate_level file provided as an input stream. The format is used by fiction * (https://github.com/cda-tum/fiction). * - * May throw an `fcn_parsing_exception` if the fcn file is malformed. + * May throw an `gate_level_parsing_exception` if the gate_level file is malformed. * * @tparam Lyt The layout type to be created from an input. * @param is The input stream to read from. @@ -124,10 +216,10 @@ Lyt read_gate_level_layout(std::istream& is, const std::string_view& name = "") return lyt; } /** - * Reads a gate-level layout from an fcn file provided as an input stream. The format is used by fiction + * Reads a gate-level layout from an gate_level file provided as an input stream. The format is used by fiction * (https://github.com/cda-tum/fiction). * - * May throw an `fcn_parsing_exception` if the fcn file is malformed. + * May throw an `gate_level_parsing_exception` if the gate_level file is malformed. * * This is an in-place version of read_gate_level_layout that utilizes the given layout as a target to write to. * @@ -143,10 +235,10 @@ void read_gate_level_layout(Lyt& lyt, std::istream& is) lyt = p.run(); } /** - * Reads a gate-level layout from an fcn file provided as an input stream. The format is used by fiction + * Reads a gate-level layout from a gate_level file provided as an input stream. The format is used by fiction * (https://github.com/cda-tum/fiction). * - * May throw an `fcn_parsing_exception` if the fcn file is malformed. + * May throw an `gate_level_parsing_exception` if the gate_level file is malformed. * * @tparam Lyt The layout type to be created from an input. * @param filename The file name to open and read from. @@ -168,10 +260,10 @@ Lyt read_gate_level_layout(const std::string_view& filename, const std::string_v return lyt; } /** - * Reads a gate-level layout from an fcn file provided as an input stream. The format is used by fiction + * Reads a gate-level layout from an gate_level file provided as an input stream. The format is used by fiction * (https://github.com/cda-tum/fiction). - * May throw an `fcn_parsing_exception` if the fcn file is malformed. + * May throw an `gate_level_parsing_exception` if the gate_level file is malformed. * * This is an in-place version of `read_gate_level_layout` that utilizes the given layout as a target to write to. * diff --git a/include/fiction/io/write_gate_level_layout.hpp b/include/fiction/io/write_gate_level_layout.hpp index 197eda276..a0aa24daf 100644 --- a/include/fiction/io/write_gate_level_layout.hpp +++ b/include/fiction/io/write_gate_level_layout.hpp @@ -43,6 +43,11 @@ inline constexpr const char* LAYOUT_METADATA = " \n" " {}\n" " {}\n" " {}\n" + " \n" + " {}\n" + " {}\n" + " {}\n" + " \n" " \n"; } // namespace fcn diff --git a/test/io/read_gate_level_layout.cpp b/test/io/read_gate_level_layout.cpp index c0c696f63..74f61fa2f 100644 --- a/test/io/read_gate_level_layout.cpp +++ b/test/io/read_gate_level_layout.cpp @@ -2,14 +2,14 @@ // Created by simon on 25.09.23. // - #include #include #include -#include #include +#include #include +#include #include #include @@ -41,6 +41,104 @@ TEST_CASE("Read empty FCN layout", "[fcn]") CHECK(lyt.is_clocking_scheme(clock_name::TWODDWAVE)); }; - using gate_layout = gate_level_layout>>; + using gate_layout = gate_level_layout>>>; check(read_gate_level_layout(layout_stream)); } + +TEST_CASE("Read simple FCN layout", "[fcn]") +{ + static constexpr const char* fcn_layout = "\n" + "\n" + " \n" + " Test\n" + " cartesian\n" + " 2DDWave\n" + " \n" + " 2\n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" + " \n" + " 0\n" + " PI\n" + " pi0\n" + " \n" + " 0\n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" + " 1\n" + " PI\n" + " pi1\n" + " \n" + " 1\n" + " 0\n" + " 0\n" + " \n" + " \n" + " \n" + " 2\n" + " AND\n" + " \n" + " 1\n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" + " 0\n" + " 1\n" + " 0\n" + " \n" + " \n" + " 1\n" + " 0\n" + " 0\n" + " \n" + " \n" + " \n" + " \n" + " 3\n" + " PO\n" + " po0\n" + " \n" + " 2\n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" + " 1\n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" + " \n" + "\n"; + + std::istringstream layout_stream{fcn_layout}; + + const auto check = [](const auto& lyt) + { + CHECK(lyt.x() == 2); + CHECK(lyt.y() == 1); + CHECK(lyt.area() == 6); + CHECK(get_name(lyt) == "Test"); + CHECK(lyt.is_clocking_scheme(clock_name::TWODDWAVE)); + CHECK(lyt.is_pi_tile({0, 1})); + CHECK(lyt.get_name(lyt.get_node({0, 1})) == "pi0"); + CHECK(lyt.is_pi_tile({1, 0})); + CHECK(lyt.get_name(lyt.get_node({1, 0})) == "pi1"); + CHECK(lyt.is_and(lyt.get_node({1, 1}))); + CHECK(lyt.is_po_tile({2, 1})); + CHECK(lyt.get_name(lyt.get_node({2, 1})) == "po0"); + }; + + using gate_layout = gate_level_layout>>>; + check(read_gate_level_layout(layout_stream)); +} \ No newline at end of file From 5306758af5f6022af90c5e45e3d6b9b0950663e8 Mon Sep 17 00:00:00 2001 From: Simon Hofmann Date: Tue, 26 Sep 2023 14:24:22 +0200 Subject: [PATCH 03/36] add missing gate types --- include/fiction/io/read_gate_level_layout.hpp | 77 +++++++++++++++---- 1 file changed, 61 insertions(+), 16 deletions(-) diff --git a/include/fiction/io/read_gate_level_layout.hpp b/include/fiction/io/read_gate_level_layout.hpp index 58d725f86..3af47e036 100644 --- a/include/fiction/io/read_gate_level_layout.hpp +++ b/include/fiction/io/read_gate_level_layout.hpp @@ -122,11 +122,11 @@ class read_gate_level_layout_impl gate.loc.y = std::stoull(loc->FirstChildElement("y")->GetText()); gate.loc.z = std::stoull(loc->FirstChildElement("z")->GetText()); - auto* const incoming = gate_xml->FirstChildElement("incoming"); - if (incoming != nullptr) + auto* const incoming_signals = gate_xml->FirstChildElement("incoming"); + if (incoming_signals != nullptr) { - for (const auto* signal = incoming->FirstChildElement("signal"); signal != nullptr; - signal = incoming->NextSiblingElement("signal")) + for (const auto* signal = incoming_signals->FirstChildElement("signal"); signal != nullptr; + signal = signal->NextSiblingElement("signal")) { tile incoming_signal{}; incoming_signal.x = std::stoull(signal->FirstChildElement("x")->GetText()); @@ -143,26 +143,71 @@ class read_gate_level_layout_impl for (const Gate& gate : gates) { - auto location = gate.loc; - + tile location{gate.loc.x, gate.loc.y, gate.loc.z}; + for (tile i : gate.incoming) std::cout << i << std::endl; if (gate.type == "PI") { - lyt.create_pi(gate.name, {location.x, location.y, location.z}); + lyt.create_pi(gate.name, location); } - else if (gate.type == "AND") + else if (gate.incoming.size() == 1) { - auto incoming_tile_1 = gate.incoming.front(); - auto incoming_tile_2 = gate.incoming.back(); - lyt.create_and(lyt.make_signal(lyt.get_node(incoming_tile_1)), - lyt.make_signal(lyt.get_node(incoming_tile_2)), {location.x, location.y, location.z}); + auto incoming_tile = gate.incoming.front(); + auto incoming_signal = lyt.make_signal(lyt.get_node(incoming_tile)); + + if (gate.type == "PO") + { + lyt.create_po(lyt.make_signal(lyt.get_node(incoming_tile)), gate.name, location); + } + + else if (gate.type == "BUF") + { + lyt.create_buf(incoming_signal, location); + } + + else if (gate.type == "INV") + { + lyt.create_not(incoming_signal, location); + } } - else if (gate.type == "PO") + else if (gate.incoming.size() == 2) { - auto incoming_tile = gate.incoming.front(); - lyt.create_po(lyt.make_signal(lyt.get_node(incoming_tile)), gate.name, - {location.x, location.y, location.z}); + auto incoming_tile_1 = gate.incoming.front(); + auto incoming_tile_2 = gate.incoming.back(); + + auto incoming_signal_1 = lyt.make_signal(lyt.get_node(incoming_tile_1)); + auto incoming_signal_2 = lyt.make_signal(lyt.get_node(incoming_tile_2)); + + if (gate.type == "AND") + { + lyt.create_and(incoming_signal_1, incoming_signal_2, location); + } + + else if (gate.type == "NAND") + { + lyt.create_nand(incoming_signal_1, incoming_signal_2, location); + } + + else if (gate.type == "OR") + { + lyt.create_or(incoming_signal_1, incoming_signal_2, location); + } + + else if (gate.type == "NOR") + { + lyt.create_nor(incoming_signal_1, incoming_signal_2, location); + } + + else if (gate.type == "XOR") + { + lyt.create_xor(incoming_signal_1, incoming_signal_2, location); + } + + else if (gate.type == "XNOR") + { + lyt.create_xnor(incoming_signal_1, incoming_signal_2, location); + } } } From 4973ad239debdacdbcab7f42769f6cee9fd464d7 Mon Sep 17 00:00:00 2001 From: Simon Hofmann Date: Tue, 26 Sep 2023 15:34:04 +0200 Subject: [PATCH 04/36] write layout metadata --- .../fiction/io/write_gate_level_layout.hpp | 14 +++-- test/io/write_gate_level_layout.cpp | 58 +++++++++++++++++++ 2 files changed, 68 insertions(+), 4 deletions(-) create mode 100644 test/io/write_gate_level_layout.cpp diff --git a/include/fiction/io/write_gate_level_layout.hpp b/include/fiction/io/write_gate_level_layout.hpp index a0aa24daf..ddf02d124 100644 --- a/include/fiction/io/write_gate_level_layout.hpp +++ b/include/fiction/io/write_gate_level_layout.hpp @@ -30,9 +30,9 @@ namespace detail namespace fcn { -inline constexpr const char* FCN_HEADER = "\n"; -inline constexpr const char* OPEN_FCN = "\n"; -inline constexpr const char* CLOSE_FCN = "\n"; +inline constexpr const char* FCN_HEADER = "\n"; +inline constexpr const char* OPEN_FCN = "\n"; +inline constexpr const char* CLOSE_FCN = "\n"; inline constexpr const char* FICTION_METADATA = " \n" " {}\n" " {}\n" @@ -60,7 +60,7 @@ class write_gate_level_layout_impl void run() { - std::stringstream header{}; + std::stringstream header{}, layout_metadata{}; header << fcn::FCN_HEADER << fcn::OPEN_FCN; @@ -68,8 +68,14 @@ class write_gate_level_layout_impl header << fmt::format(fcn::FICTION_METADATA, FICTION_VERSION, FICTION_REPO, time_str); + const auto clocking_scheme = lyt.get_clocking_scheme().name(); + + layout_metadata << fmt::format(get_name(lyt), "Cartesian", clocking_scheme, lyt.x(), lyt.y(), lyt.z()); + os << header.str(); + os << layout_metadata.str(); + os << fcn::CLOSE_FCN; } diff --git a/test/io/write_gate_level_layout.cpp b/test/io/write_gate_level_layout.cpp new file mode 100644 index 000000000..56863866f --- /dev/null +++ b/test/io/write_gate_level_layout.cpp @@ -0,0 +1,58 @@ +// +// Created by Simon Hofmann on 26.09.23. +// + +#include + +#include "utils/blueprints/layout_blueprints.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +using namespace fiction; + +template +void compare_written_and_read_layout(const WLyt& wlyt, const RLyt& rlyt) noexcept +{ + CHECK(wlyt.get_layout_name() == rlyt.get_layout_name()); + + const bounding_box_2d wbb{wlyt}; + const bounding_box_2d rbb{wlyt}; + + CHECK(wbb.get_min() == rbb.get_min()); + CHECK(wbb.get_max() == rbb.get_max()); + + CHECK(wbb.get_x_size() == rbb.get_x_size()); + CHECK(wbb.get_y_size() == rbb.get_y_size()); + + CHECK(wlyt.num_pis() == rlyt.num_pis()); + CHECK(wlyt.num_pos() == rlyt.num_pos()); +} + +TEST_CASE("Write empty gate_level layout", "[sqd]") +{ + using gate_layout = gate_level_layout>>>; + + const gate_layout layout{{}, "empty"}; + + std::stringstream layout_stream{}; + + write_gate_level_layout(layout, layout_stream); + + const auto read_layout = read_gate_level_layout(layout_stream, "empty"); + + compare_written_and_read_layout(layout, read_layout); +} From 680cc01c9d69b5a718c01f6bb8a9a3ff91dfa821 Mon Sep 17 00:00:00 2001 From: Simon Hofmann Date: Tue, 26 Sep 2023 15:35:43 +0200 Subject: [PATCH 05/36] small fix --- include/fiction/io/write_gate_level_layout.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/fiction/io/write_gate_level_layout.hpp b/include/fiction/io/write_gate_level_layout.hpp index ddf02d124..6e88cde97 100644 --- a/include/fiction/io/write_gate_level_layout.hpp +++ b/include/fiction/io/write_gate_level_layout.hpp @@ -70,7 +70,7 @@ class write_gate_level_layout_impl const auto clocking_scheme = lyt.get_clocking_scheme().name(); - layout_metadata << fmt::format(get_name(lyt), "Cartesian", clocking_scheme, lyt.x(), lyt.y(), lyt.z()); + layout_metadata << fmt::format(fcn::LAYOUT_METADATA, get_name(lyt), "Cartesian", clocking_scheme, lyt.x(), lyt.y(), lyt.z()); os << header.str(); From 7805678b0b60044824088b7b11ef10fba9e22c92 Mon Sep 17 00:00:00 2001 From: Simon Hofmann Date: Tue, 26 Sep 2023 17:34:08 +0200 Subject: [PATCH 06/36] extend write capabilities --- include/fiction/io/read_gate_level_layout.hpp | 108 +++++++++--------- .../fiction/io/write_gate_level_layout.hpp | 42 ++++++- test/io/write_gate_level_layout.cpp | 72 +++++++++++- 3 files changed, 166 insertions(+), 56 deletions(-) diff --git a/include/fiction/io/read_gate_level_layout.hpp b/include/fiction/io/read_gate_level_layout.hpp index 3af47e036..b5ad06f6f 100644 --- a/include/fiction/io/read_gate_level_layout.hpp +++ b/include/fiction/io/read_gate_level_layout.hpp @@ -81,7 +81,8 @@ class read_gate_level_layout_impl auto* const name = layout->FirstChildElement("name"); if (name != nullptr) { - set_name(lyt, name->GetText()); + std::string layout_name = name->GetText(); + set_name(lyt, layout_name); } auto* const clocking = layout->FirstChildElement("clocking"); @@ -138,75 +139,76 @@ class read_gate_level_layout_impl gates.push_back(gate); } - } - std::sort(gates.begin(), gates.end(), Gate::compareById); - for (const Gate& gate : gates) - { - tile location{gate.loc.x, gate.loc.y, gate.loc.z}; - for (tile i : gate.incoming) std::cout << i << std::endl; - if (gate.type == "PI") - { - lyt.create_pi(gate.name, location); - } + std::sort(gates.begin(), gates.end(), Gate::compareById); - else if (gate.incoming.size() == 1) + for (const Gate& gate : gates) { - auto incoming_tile = gate.incoming.front(); - auto incoming_signal = lyt.make_signal(lyt.get_node(incoming_tile)); - - if (gate.type == "PO") + tile location{gate.loc.x, gate.loc.y, gate.loc.z}; + for (tile i : gate.incoming) std::cout << i << std::endl; + if (gate.type == "PI") { - lyt.create_po(lyt.make_signal(lyt.get_node(incoming_tile)), gate.name, location); + lyt.create_pi(gate.name, location); } - else if (gate.type == "BUF") + else if (gate.incoming.size() == 1) { - lyt.create_buf(incoming_signal, location); - } + auto incoming_tile = gate.incoming.front(); + auto incoming_signal = lyt.make_signal(lyt.get_node(incoming_tile)); - else if (gate.type == "INV") - { - lyt.create_not(incoming_signal, location); - } - } - - else if (gate.incoming.size() == 2) - { - auto incoming_tile_1 = gate.incoming.front(); - auto incoming_tile_2 = gate.incoming.back(); + if (gate.type == "PO") + { + lyt.create_po(lyt.make_signal(lyt.get_node(incoming_tile)), gate.name, location); + } - auto incoming_signal_1 = lyt.make_signal(lyt.get_node(incoming_tile_1)); - auto incoming_signal_2 = lyt.make_signal(lyt.get_node(incoming_tile_2)); + else if (gate.type == "BUF") + { + lyt.create_buf(incoming_signal, location); + } - if (gate.type == "AND") - { - lyt.create_and(incoming_signal_1, incoming_signal_2, location); + else if (gate.type == "INV") + { + lyt.create_not(incoming_signal, location); + } } - else if (gate.type == "NAND") + else if (gate.incoming.size() == 2) { - lyt.create_nand(incoming_signal_1, incoming_signal_2, location); - } + auto incoming_tile_1 = gate.incoming.front(); + auto incoming_tile_2 = gate.incoming.back(); - else if (gate.type == "OR") - { - lyt.create_or(incoming_signal_1, incoming_signal_2, location); - } + auto incoming_signal_1 = lyt.make_signal(lyt.get_node(incoming_tile_1)); + auto incoming_signal_2 = lyt.make_signal(lyt.get_node(incoming_tile_2)); - else if (gate.type == "NOR") - { - lyt.create_nor(incoming_signal_1, incoming_signal_2, location); - } + if (gate.type == "AND") + { + lyt.create_and(incoming_signal_1, incoming_signal_2, location); + } - else if (gate.type == "XOR") - { - lyt.create_xor(incoming_signal_1, incoming_signal_2, location); - } + else if (gate.type == "NAND") + { + lyt.create_nand(incoming_signal_1, incoming_signal_2, location); + } - else if (gate.type == "XNOR") - { - lyt.create_xnor(incoming_signal_1, incoming_signal_2, location); + else if (gate.type == "OR") + { + lyt.create_or(incoming_signal_1, incoming_signal_2, location); + } + + else if (gate.type == "NOR") + { + lyt.create_nor(incoming_signal_1, incoming_signal_2, location); + } + + else if (gate.type == "XOR") + { + lyt.create_xor(incoming_signal_1, incoming_signal_2, location); + } + + else if (gate.type == "XNOR") + { + lyt.create_xnor(incoming_signal_1, incoming_signal_2, location); + } } } } diff --git a/include/fiction/io/write_gate_level_layout.hpp b/include/fiction/io/write_gate_level_layout.hpp index 6e88cde97..5f4304ed9 100644 --- a/include/fiction/io/write_gate_level_layout.hpp +++ b/include/fiction/io/write_gate_level_layout.hpp @@ -6,10 +6,13 @@ #define FICTION_WRITE_GATE_LEVEL_LAYOUT_HPP #include "fiction/traits.hpp" +#include +#include #include "utils/version_info.hpp" #include #include +#include #include #include @@ -49,6 +52,18 @@ inline constexpr const char* LAYOUT_METADATA = " \n" " {}\n" " \n" " \n"; +inline constexpr const char* OPEN_GATES = "\n"; +inline constexpr const char* CLOSE_GATES = "\n"; +inline constexpr const char* PI_GATE = " \n" + " {}\n" + " PI\n" + " {}\n" + " \n" + " {}\n" + " {}\n" + " {}\n" + " \n" + " \n"; } // namespace fcn @@ -68,14 +83,37 @@ class write_gate_level_layout_impl header << fmt::format(fcn::FICTION_METADATA, FICTION_VERSION, FICTION_REPO, time_str); - const auto clocking_scheme = lyt.get_clocking_scheme().name(); + std::string layout_name = get_name(lyt); + if (layout_name == "") + { + layout_name = "X"; + } - layout_metadata << fmt::format(fcn::LAYOUT_METADATA, get_name(lyt), "Cartesian", clocking_scheme, lyt.x(), lyt.y(), lyt.z()); + const auto clocking_scheme = lyt.get_clocking_scheme().name; + + layout_metadata << fmt::format(fcn::LAYOUT_METADATA, layout_name, "Cartesian", clocking_scheme, lyt.x(), lyt.y(), lyt.z()); os << header.str(); os << layout_metadata.str(); + os << fcn::OPEN_GATES; + + mockturtle::topo_view layout_topo{lyt}; + + layout_topo.foreach_pi([&](const auto& gate){ + const tile coord = lyt.get_tile(gate); + std::stringstream pi_tile{}; + pi_tile << fmt::format(fcn::PI_GATE, "0", lyt.get_name(gate), coord.x, coord.y, coord.z); + os << pi_tile.str(); + }); + + layout_topo.foreach_gate([&](const auto& gate){ + const tile old_coord = lyt.get_tile(gate); + std::cout << old_coord; + }); + + os << fcn::CLOSE_GATES; os << fcn::CLOSE_FCN; } diff --git a/test/io/write_gate_level_layout.cpp b/test/io/write_gate_level_layout.cpp index 56863866f..5608ea2eb 100644 --- a/test/io/write_gate_level_layout.cpp +++ b/test/io/write_gate_level_layout.cpp @@ -5,7 +5,10 @@ #include #include "utils/blueprints/layout_blueprints.hpp" +#include "utils/blueprints/network_blueprints.hpp" +#include "utils/equivalence_checking_utils.hpp" +#include #include #include #include @@ -15,9 +18,13 @@ #include #include #include +#include #include #include +#include +#include + #include #include #include @@ -42,6 +49,62 @@ void compare_written_and_read_layout(const WLyt& wlyt, const RLyt& rlyt) noexcep CHECK(wlyt.num_pos() == rlyt.num_pos()); } +template +void check_parsing_equiv(const Ntk& ntk) +{ + const auto layout = orthogonal(ntk, {}); + + std::stringstream layout_stream{}; + write_gate_level_layout(layout, layout_stream); + + std::cout << layout_stream.str(); + const auto read_layout = read_gate_level_layout(layout_stream, get_name(layout)); + + compare_written_and_read_layout(layout, read_layout); + + check_eq(ntk, layout); + check_eq(ntk, read_layout); + check_eq(layout, read_layout); +} + +template +void check_parsing_equiv_layout(const Lyt& lyt) +{ + std::stringstream layout_stream{}; + write_gate_level_layout(lyt, layout_stream); + const auto read_layout = read_gate_level_layout(layout_stream, lyt.get_layout_name()); + + compare_written_and_read_layout(lyt, read_layout); + + check_eq(lyt, read_layout); + CHECK(lyt.get_layout_name() == read_layout.get_layout_name()); +} + +template +void check_parsing_equiv_all() +{ + check_parsing_equiv(blueprints::maj1_network()); + check_parsing_equiv(blueprints::maj4_network()); + check_parsing_equiv(blueprints::unbalanced_and_inv_network()); + check_parsing_equiv(blueprints::and_or_network()); + check_parsing_equiv(blueprints::nary_operation_network()); + check_parsing_equiv(blueprints::constant_gate_input_maj_network()); + check_parsing_equiv(blueprints::half_adder_network()); + check_parsing_equiv(blueprints::full_adder_network()); + check_parsing_equiv(blueprints::mux21_network()); + check_parsing_equiv(blueprints::se_coloring_corner_case_network()); + check_parsing_equiv(blueprints::fanout_substitution_corner_case_network()); + check_parsing_equiv(blueprints::inverter_network()); + check_parsing_equiv(blueprints::clpl()); + check_parsing_equiv(blueprints::one_to_five_path_difference_network()); + check_parsing_equiv(blueprints::nand_xnor_network()); + + check_parsing_equiv_layout(blueprints::straight_wire_gate_layout()); + check_parsing_equiv_layout(blueprints::or_not_gate_layout()); + check_parsing_equiv_layout(blueprints::crossing_layout()); + check_parsing_equiv_layout(blueprints::tautology_gate_layout()); +} + TEST_CASE("Write empty gate_level layout", "[sqd]") { using gate_layout = gate_level_layout>>>; @@ -52,7 +115,14 @@ TEST_CASE("Write empty gate_level layout", "[sqd]") write_gate_level_layout(layout, layout_stream); - const auto read_layout = read_gate_level_layout(layout_stream, "empty"); + const auto read_layout = read_gate_level_layout(layout_stream, "empty"); compare_written_and_read_layout(layout, read_layout); } + +TEST_CASE("Write and read layouts") +{ + using gate_layout = gate_level_layout>>>; + + check_parsing_equiv_all(); +} From 9393d687301442e49cad5b98268fe4acffdf77a8 Mon Sep 17 00:00:00 2001 From: Simon Hofmann Date: Tue, 26 Sep 2023 17:37:14 +0200 Subject: [PATCH 07/36] fix layout name error --- include/fiction/io/read_gate_level_layout.hpp | 2 +- include/fiction/io/write_gate_level_layout.hpp | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/include/fiction/io/read_gate_level_layout.hpp b/include/fiction/io/read_gate_level_layout.hpp index b5ad06f6f..2e42f9d1a 100644 --- a/include/fiction/io/read_gate_level_layout.hpp +++ b/include/fiction/io/read_gate_level_layout.hpp @@ -79,7 +79,7 @@ class read_gate_level_layout_impl } auto* const name = layout->FirstChildElement("name"); - if (name != nullptr) + if (name != nullptr and name->GetText()) { std::string layout_name = name->GetText(); set_name(lyt, layout_name); diff --git a/include/fiction/io/write_gate_level_layout.hpp b/include/fiction/io/write_gate_level_layout.hpp index 5f4304ed9..fe146f5bf 100644 --- a/include/fiction/io/write_gate_level_layout.hpp +++ b/include/fiction/io/write_gate_level_layout.hpp @@ -84,10 +84,6 @@ class write_gate_level_layout_impl header << fmt::format(fcn::FICTION_METADATA, FICTION_VERSION, FICTION_REPO, time_str); std::string layout_name = get_name(lyt); - if (layout_name == "") - { - layout_name = "X"; - } const auto clocking_scheme = lyt.get_clocking_scheme().name; From 5d9c2d25c54ee1d9a16e4d937464b881e45f2d4d Mon Sep 17 00:00:00 2001 From: Simon Hofmann Date: Tue, 26 Sep 2023 17:39:25 +0200 Subject: [PATCH 08/36] remove debug output --- include/fiction/io/read_gate_level_layout.hpp | 2 +- .../fiction/io/write_gate_level_layout.hpp | 51 ++++++++++--------- test/io/write_gate_level_layout.cpp | 1 - 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/include/fiction/io/read_gate_level_layout.hpp b/include/fiction/io/read_gate_level_layout.hpp index 2e42f9d1a..5c6a0db36 100644 --- a/include/fiction/io/read_gate_level_layout.hpp +++ b/include/fiction/io/read_gate_level_layout.hpp @@ -145,7 +145,7 @@ class read_gate_level_layout_impl for (const Gate& gate : gates) { tile location{gate.loc.x, gate.loc.y, gate.loc.z}; - for (tile i : gate.incoming) std::cout << i << std::endl; + if (gate.type == "PI") { lyt.create_pi(gate.name, location); diff --git a/include/fiction/io/write_gate_level_layout.hpp b/include/fiction/io/write_gate_level_layout.hpp index fe146f5bf..4290f2772 100644 --- a/include/fiction/io/write_gate_level_layout.hpp +++ b/include/fiction/io/write_gate_level_layout.hpp @@ -6,9 +6,10 @@ #define FICTION_WRITE_GATE_LEVEL_LAYOUT_HPP #include "fiction/traits.hpp" +#include "utils/version_info.hpp" + #include #include -#include "utils/version_info.hpp" #include #include @@ -52,18 +53,18 @@ inline constexpr const char* LAYOUT_METADATA = " \n" " {}\n" " \n" " \n"; -inline constexpr const char* OPEN_GATES = "\n"; -inline constexpr const char* CLOSE_GATES = "\n"; -inline constexpr const char* PI_GATE = " \n" - " {}\n" - " PI\n" - " {}\n" - " \n" - " {}\n" - " {}\n" - " {}\n" - " \n" - " \n"; +inline constexpr const char* OPEN_GATES = "\n"; +inline constexpr const char* CLOSE_GATES = "\n"; +inline constexpr const char* PI_GATE = " \n" + " {}\n" + " PI\n" + " {}\n" + " \n" + " {}\n" + " {}\n" + " {}\n" + " \n" + " \n"; } // namespace fcn @@ -87,7 +88,8 @@ class write_gate_level_layout_impl const auto clocking_scheme = lyt.get_clocking_scheme().name; - layout_metadata << fmt::format(fcn::LAYOUT_METADATA, layout_name, "Cartesian", clocking_scheme, lyt.x(), lyt.y(), lyt.z()); + layout_metadata << fmt::format(fcn::LAYOUT_METADATA, layout_name, "Cartesian", clocking_scheme, lyt.x(), + lyt.y(), lyt.z()); os << header.str(); @@ -97,17 +99,16 @@ class write_gate_level_layout_impl mockturtle::topo_view layout_topo{lyt}; - layout_topo.foreach_pi([&](const auto& gate){ - const tile coord = lyt.get_tile(gate); - std::stringstream pi_tile{}; - pi_tile << fmt::format(fcn::PI_GATE, "0", lyt.get_name(gate), coord.x, coord.y, coord.z); - os << pi_tile.str(); - }); - - layout_topo.foreach_gate([&](const auto& gate){ - const tile old_coord = lyt.get_tile(gate); - std::cout << old_coord; - }); + layout_topo.foreach_pi( + [&](const auto& gate) + { + const tile coord = lyt.get_tile(gate); + std::stringstream pi_tile{}; + pi_tile << fmt::format(fcn::PI_GATE, "0", lyt.get_name(gate), coord.x, coord.y, coord.z); + os << pi_tile.str(); + }); + + layout_topo.foreach_gate([&](const auto& gate) { const tile old_coord = lyt.get_tile(gate); }); os << fcn::CLOSE_GATES; os << fcn::CLOSE_FCN; diff --git a/test/io/write_gate_level_layout.cpp b/test/io/write_gate_level_layout.cpp index 5608ea2eb..75a8ff213 100644 --- a/test/io/write_gate_level_layout.cpp +++ b/test/io/write_gate_level_layout.cpp @@ -57,7 +57,6 @@ void check_parsing_equiv(const Ntk& ntk) std::stringstream layout_stream{}; write_gate_level_layout(layout, layout_stream); - std::cout << layout_stream.str(); const auto read_layout = read_gate_level_layout(layout_stream, get_name(layout)); compare_written_and_read_layout(layout, read_layout); From 25d2534113794d8fec5daa67d542a028256b885d Mon Sep 17 00:00:00 2001 From: Simon Date: Wed, 27 Sep 2023 12:20:21 +0200 Subject: [PATCH 09/36] Extend writing capabilities --- include/fiction/io/read_gate_level_layout.hpp | 13 +- .../fiction/io/write_gate_level_layout.hpp | 139 ++++++++++++++---- test/io/write_gate_level_layout.cpp | 2 +- 3 files changed, 119 insertions(+), 35 deletions(-) diff --git a/include/fiction/io/read_gate_level_layout.hpp b/include/fiction/io/read_gate_level_layout.hpp index 5c6a0db36..119e57664 100644 --- a/include/fiction/io/read_gate_level_layout.hpp +++ b/include/fiction/io/read_gate_level_layout.hpp @@ -113,7 +113,7 @@ class read_gate_level_layout_impl gate.type = gate_xml->FirstChildElement("type")->GetText(); auto* const pi_name = gate_xml->FirstChildElement("name"); - if (pi_name != nullptr) + if (pi_name != nullptr and pi_name->GetText()) { gate.name = pi_name->GetText(); } @@ -153,12 +153,12 @@ class read_gate_level_layout_impl else if (gate.incoming.size() == 1) { - auto incoming_tile = gate.incoming.front(); - auto incoming_signal = lyt.make_signal(lyt.get_node(incoming_tile)); + tile incoming_tile{gate.incoming.front().x, gate.incoming.front().y, gate.incoming.front().z}; + auto incoming_signal = lyt.make_signal(lyt.get_node(incoming_tile)); if (gate.type == "PO") { - lyt.create_po(lyt.make_signal(lyt.get_node(incoming_tile)), gate.name, location); + lyt.create_po(incoming_signal, gate.name, location); } else if (gate.type == "BUF") @@ -174,8 +174,9 @@ class read_gate_level_layout_impl else if (gate.incoming.size() == 2) { - auto incoming_tile_1 = gate.incoming.front(); - auto incoming_tile_2 = gate.incoming.back(); + tile incoming_tile_1{gate.incoming.front().x, gate.incoming.front().y, + gate.incoming.front().z}; + tile incoming_tile_2{gate.incoming.back().x, gate.incoming.back().y, gate.incoming.back().z}; auto incoming_signal_1 = lyt.make_signal(lyt.get_node(incoming_tile_1)); auto incoming_signal_2 = lyt.make_signal(lyt.get_node(incoming_tile_2)); diff --git a/include/fiction/io/write_gate_level_layout.hpp b/include/fiction/io/write_gate_level_layout.hpp index 4290f2772..894c4e33d 100644 --- a/include/fiction/io/write_gate_level_layout.hpp +++ b/include/fiction/io/write_gate_level_layout.hpp @@ -37,34 +37,41 @@ namespace fcn inline constexpr const char* FCN_HEADER = "\n"; inline constexpr const char* OPEN_FCN = "\n"; inline constexpr const char* CLOSE_FCN = "\n"; -inline constexpr const char* FICTION_METADATA = " \n" - " {}\n" - " {}\n" - " {}\n" - " \n"; - -inline constexpr const char* LAYOUT_METADATA = " \n" - " {}\n" - " {}\n" - " {}\n" - " \n" - " {}\n" - " {}\n" - " {}\n" - " \n" - " \n"; -inline constexpr const char* OPEN_GATES = "\n"; -inline constexpr const char* CLOSE_GATES = "\n"; -inline constexpr const char* PI_GATE = " \n" - " {}\n" - " PI\n" +inline constexpr const char* FICTION_METADATA = " \n" + " {}\n" + " {}\n" + " {}\n" + " \n"; + +inline constexpr const char* LAYOUT_METADATA = " \n" + " {}\n" + " {}\n" + " {}\n" + " \n" + " {}\n" + " {}\n" + " {}\n" + " \n" + " \n"; +inline constexpr const char* OPEN_GATES = " \n"; +inline constexpr const char* CLOSE_GATES = " \n"; +inline constexpr const char* OPEN_GATE = " \n"; +inline constexpr const char* CLOSE_GATE = " \n"; +inline constexpr const char* GATE = " {}\n" + " {}\n" " {}\n" " \n" " {}\n" " {}\n" " {}\n" - " \n" - " \n"; + " \n"; +inline constexpr const char* OPEN_INCOMING = " \n"; +inline constexpr const char* CLOSE_INCOMING = " \n"; +inline constexpr const char* SIGNAL = " \n" + " {}\n" + " {}\n" + " {}\n" + " \n"; } // namespace fcn @@ -98,17 +105,93 @@ class write_gate_level_layout_impl os << fcn::OPEN_GATES; mockturtle::topo_view layout_topo{lyt}; + int id = 0; layout_topo.foreach_pi( [&](const auto& gate) { - const tile coord = lyt.get_tile(gate); - std::stringstream pi_tile{}; - pi_tile << fmt::format(fcn::PI_GATE, "0", lyt.get_name(gate), coord.x, coord.y, coord.z); - os << pi_tile.str(); + const tile coord = lyt.get_tile(gate); + os << fcn::OPEN_GATE; + os << fmt::format(fcn::GATE, id, "PI", lyt.get_name(gate), coord.x, coord.y, coord.z); + os << fcn::CLOSE_GATE; + id++; }); - layout_topo.foreach_gate([&](const auto& gate) { const tile old_coord = lyt.get_tile(gate); }); + layout_topo.foreach_gate( + [&](const auto& gate) + { + const tile coord = lyt.get_tile(gate); + if (const auto signals = lyt.incoming_data_flow(coord); signals.size() == 1) + { + os << fcn::OPEN_GATE; + + const auto signal = signals[0]; + + if (lyt.is_po(gate)) + { + os << fmt::format(fcn::GATE, id, "PO", lyt.get_name(gate), coord.x, coord.y, coord.z); + } + else if (lyt.is_wire(gate)) + { + os << fmt::format(fcn::GATE, id, "BUF", "", coord.x, coord.y, coord.z); + } + else if (lyt.is_inv(gate)) + { + os << fmt::format(fcn::GATE, id, "INV", "", coord.x, coord.y, coord.z); + } + + os << fcn::OPEN_INCOMING; + os << fmt::format(fcn::SIGNAL, signal.x, signal.y, signal.z); + os << fcn::CLOSE_INCOMING; + os << fcn::CLOSE_GATE; + id++; + } + else if (signals.size() == 2) + { + os << fcn::OPEN_GATE; + + const auto signal_a = signals[0]; + const auto signal_b = signals[1]; + + if (lyt.is_and(gate)) + { + os << fmt::format(fcn::GATE, id, "AND", "", coord.x, coord.y, coord.z); + } + else if (lyt.is_nand(gate)) + { + os << fmt::format(fcn::GATE, id, "NAND", "", coord.x, coord.y, coord.z); + } + else if (lyt.is_or(gate)) + { + os << fmt::format(fcn::GATE, id, "OR", "", coord.x, coord.y, coord.z); + } + else if (lyt.is_nor(gate)) + { + os << fmt::format(fcn::GATE, id, "NOR", "", coord.x, coord.y, coord.z); + } + else if (lyt.is_xor(gate)) + { + os << fmt::format(fcn::GATE, id, "XOR", "", coord.x, coord.y, coord.z); + } + else if (lyt.is_xnor(gate)) + { + os << fmt::format(fcn::GATE, id, "XNOR", "", coord.x, coord.y, coord.z); + } + // else if (lyt.is_function(node)) + //{ + // + // const auto node_fun = lyt.node_function(node); + + // hex_layout.create_node({hex_signal_a, hex_signal_b}, node_fun, hex); + //} + os << fcn::OPEN_INCOMING; + os << fmt::format(fcn::SIGNAL, signal_a.x, signal_a.y, signal_a.z); + os << fmt::format(fcn::SIGNAL, signal_b.x, signal_b.y, signal_b.z); + os << fcn::CLOSE_INCOMING; + os << fcn::CLOSE_GATE; + id++; + } + }); os << fcn::CLOSE_GATES; os << fcn::CLOSE_FCN; diff --git a/test/io/write_gate_level_layout.cpp b/test/io/write_gate_level_layout.cpp index 75a8ff213..38520e40b 100644 --- a/test/io/write_gate_level_layout.cpp +++ b/test/io/write_gate_level_layout.cpp @@ -101,7 +101,7 @@ void check_parsing_equiv_all() check_parsing_equiv_layout(blueprints::straight_wire_gate_layout()); check_parsing_equiv_layout(blueprints::or_not_gate_layout()); check_parsing_equiv_layout(blueprints::crossing_layout()); - check_parsing_equiv_layout(blueprints::tautology_gate_layout()); + // check_parsing_equiv_layout(blueprints::tautology_gate_layout()); } TEST_CASE("Write empty gate_level layout", "[sqd]") From 15ae87638abd48a341cbcab0db90f719c6ce8f74 Mon Sep 17 00:00:00 2001 From: Simon Date: Wed, 27 Sep 2023 12:48:52 +0200 Subject: [PATCH 10/36] add node functions --- include/fiction/io/read_gate_level_layout.hpp | 7 +++++++ include/fiction/io/write_gate_level_layout.hpp | 13 +++++++------ test/io/write_gate_level_layout.cpp | 2 +- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/include/fiction/io/read_gate_level_layout.hpp b/include/fiction/io/read_gate_level_layout.hpp index 119e57664..c5eefbaba 100644 --- a/include/fiction/io/read_gate_level_layout.hpp +++ b/include/fiction/io/read_gate_level_layout.hpp @@ -13,6 +13,7 @@ #include #include +#include #include #include @@ -210,6 +211,12 @@ class read_gate_level_layout_impl { lyt.create_xnor(incoming_signal_1, incoming_signal_2, location); } + else + { + kitty::dynamic_truth_table tt_t(2u); + kitty::create_from_binary_string(tt_t, gate.type); + lyt.create_node({incoming_signal_1, incoming_signal_2}, tt_t, location); + } } } } diff --git a/include/fiction/io/write_gate_level_layout.hpp b/include/fiction/io/write_gate_level_layout.hpp index 894c4e33d..19d5f2850 100644 --- a/include/fiction/io/write_gate_level_layout.hpp +++ b/include/fiction/io/write_gate_level_layout.hpp @@ -13,6 +13,7 @@ #include #include +#include #include #include @@ -177,13 +178,13 @@ class write_gate_level_layout_impl { os << fmt::format(fcn::GATE, id, "XNOR", "", coord.x, coord.y, coord.z); } - // else if (lyt.is_function(node)) - //{ - // - // const auto node_fun = lyt.node_function(node); + else if (lyt.is_function(gate)) + { + const auto node_fun = lyt.node_function(gate); - // hex_layout.create_node({hex_signal_a, hex_signal_b}, node_fun, hex); - //} + os << fmt::format(fcn::GATE, id, kitty::to_binary(node_fun), "", coord.x, coord.y, coord.z); + // hex_layout.create_node({hex_signal_a, hex_signal_b}, node_fun, hex); + } os << fcn::OPEN_INCOMING; os << fmt::format(fcn::SIGNAL, signal_a.x, signal_a.y, signal_a.z); os << fmt::format(fcn::SIGNAL, signal_b.x, signal_b.y, signal_b.z); diff --git a/test/io/write_gate_level_layout.cpp b/test/io/write_gate_level_layout.cpp index 38520e40b..75a8ff213 100644 --- a/test/io/write_gate_level_layout.cpp +++ b/test/io/write_gate_level_layout.cpp @@ -101,7 +101,7 @@ void check_parsing_equiv_all() check_parsing_equiv_layout(blueprints::straight_wire_gate_layout()); check_parsing_equiv_layout(blueprints::or_not_gate_layout()); check_parsing_equiv_layout(blueprints::crossing_layout()); - // check_parsing_equiv_layout(blueprints::tautology_gate_layout()); + check_parsing_equiv_layout(blueprints::tautology_gate_layout()); } TEST_CASE("Write empty gate_level layout", "[sqd]") From 6a502cdaabb0830109e1a5baabbde58af4a3087d Mon Sep 17 00:00:00 2001 From: Simon Date: Wed, 27 Sep 2023 19:32:08 +0200 Subject: [PATCH 11/36] =?UTF-8?q?clang-tidy=20=C3=A1nd=20100%=20test=20cov?= =?UTF-8?q?erage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/fiction/io/read_gate_level_layout.hpp | 25 ++++++----- .../fiction/io/write_gate_level_layout.hpp | 1 - test/io/read_gate_level_layout.cpp | 45 +++++++++++++++++++ 3 files changed, 58 insertions(+), 13 deletions(-) diff --git a/include/fiction/io/read_gate_level_layout.hpp b/include/fiction/io/read_gate_level_layout.hpp index c5eefbaba..ec2e6eb4f 100644 --- a/include/fiction/io/read_gate_level_layout.hpp +++ b/include/fiction/io/read_gate_level_layout.hpp @@ -98,18 +98,19 @@ class read_gate_level_layout_impl int x = std::stoi(size->FirstChildElement("x")->GetText()); int y = std::stoi(size->FirstChildElement("y")->GetText()); int z = std::stoi(size->FirstChildElement("z")->GetText()); - tile max_pos{x, y, z}; + tile max_pos; + max_pos = {x, y, z}; lyt.resize(max_pos); } - std::vector gates{}; - auto* const gates_xml = fcn_root->FirstChildElement("gates"); + std::vector gates; + auto* const gates_xml = fcn_root->FirstChildElement("gates"); if (gates_xml != nullptr) { for (const auto* gate_xml = gates_xml->FirstChildElement("gate"); gate_xml != nullptr; gate_xml = gate_xml->NextSiblingElement("gate")) { - Gate gate; + gate_storage gate; gate.id = std::stoi(gate_xml->FirstChildElement("id")->GetText()); gate.type = gate_xml->FirstChildElement("type")->GetText(); @@ -130,7 +131,7 @@ class read_gate_level_layout_impl for (const auto* signal = incoming_signals->FirstChildElement("signal"); signal != nullptr; signal = signal->NextSiblingElement("signal")) { - tile incoming_signal{}; + tile incoming_signal; incoming_signal.x = std::stoull(signal->FirstChildElement("x")->GetText()); incoming_signal.y = std::stoull(signal->FirstChildElement("y")->GetText()); incoming_signal.z = std::stoull(signal->FirstChildElement("z")->GetText()); @@ -141,9 +142,9 @@ class read_gate_level_layout_impl gates.push_back(gate); } - std::sort(gates.begin(), gates.end(), Gate::compareById); + std::sort(gates.begin(), gates.end(), gate_storage::compare_by_id); - for (const Gate& gate : gates) + for (const gate_storage& gate : gates) { tile location{gate.loc.x, gate.loc.y, gate.loc.z}; @@ -234,15 +235,15 @@ class read_gate_level_layout_impl */ std::istream& is; - struct Gate + struct gate_storage { - int id; + int id{}; std::string type; std::string name; - tile loc; - std::vector> incoming; + tile loc{}; + std::vector> incoming{}; - static bool compareById(const Gate& gate1, const Gate& gate2) + static bool compare_by_id(const gate_storage& gate1, const gate_storage& gate2) { return gate1.id < gate2.id; } diff --git a/include/fiction/io/write_gate_level_layout.hpp b/include/fiction/io/write_gate_level_layout.hpp index 19d5f2850..0df808328 100644 --- a/include/fiction/io/write_gate_level_layout.hpp +++ b/include/fiction/io/write_gate_level_layout.hpp @@ -183,7 +183,6 @@ class write_gate_level_layout_impl const auto node_fun = lyt.node_function(gate); os << fmt::format(fcn::GATE, id, kitty::to_binary(node_fun), "", coord.x, coord.y, coord.z); - // hex_layout.create_node({hex_signal_a, hex_signal_b}, node_fun, hex); } os << fcn::OPEN_INCOMING; os << fmt::format(fcn::SIGNAL, signal_a.x, signal_a.y, signal_a.z); diff --git a/test/io/read_gate_level_layout.cpp b/test/io/read_gate_level_layout.cpp index 74f61fa2f..3ceb2187e 100644 --- a/test/io/read_gate_level_layout.cpp +++ b/test/io/read_gate_level_layout.cpp @@ -141,4 +141,49 @@ TEST_CASE("Read simple FCN layout", "[fcn]") using gate_layout = gate_level_layout>>>; check(read_gate_level_layout(layout_stream)); +} + +TEST_CASE("Parsing error: malformed xml", "[fcn]") +{ + static constexpr const char* fcn_layout = "\n" + "\n" + " \n" + " Test\n" + " cartesian\n" + " 2DDWave\n" + " \n"; + + std::istringstream layout_stream{fcn_layout}; + + using gate_layout = gate_level_layout>>>; + CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); +} + +TEST_CASE("Parsing error: no root element 'fcn'", "[fcn]") +{ + static constexpr const char* fcn_layout = "\n" + " \n" + " Test\n" + " cartesian\n" + " 2DDWave\n" + " \n"; + + std::istringstream layout_stream{fcn_layout}; + + using gate_layout = gate_level_layout>>>; + CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); +} + +TEST_CASE("Parsing error: no element 'layout'", "[fcn]") +{ + static constexpr const char* fcn_layout = "\n" + "\n" + " Test\n" + " cartesian\n" + " 2DDWave\n"; + + std::istringstream layout_stream{fcn_layout}; + + using gate_layout = gate_level_layout>>>; + CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } \ No newline at end of file From 5a9484c5ba4898ee008374bec355d7a3d72a76ce Mon Sep 17 00:00:00 2001 From: Simon Date: Wed, 27 Sep 2023 19:38:37 +0200 Subject: [PATCH 12/36] more tests --- include/fiction/io/read_gate_level_layout.hpp | 10 ++- test/io/read_gate_level_layout.cpp | 80 +++++++++++++++++++ 2 files changed, 87 insertions(+), 3 deletions(-) diff --git a/include/fiction/io/read_gate_level_layout.hpp b/include/fiction/io/read_gate_level_layout.hpp index ec2e6eb4f..21cfdf487 100644 --- a/include/fiction/io/read_gate_level_layout.hpp +++ b/include/fiction/io/read_gate_level_layout.hpp @@ -121,9 +121,13 @@ class read_gate_level_layout_impl } auto* const loc = gate_xml->FirstChildElement("loc"); - gate.loc.x = std::stoull(loc->FirstChildElement("x")->GetText()); - gate.loc.y = std::stoull(loc->FirstChildElement("y")->GetText()); - gate.loc.z = std::stoull(loc->FirstChildElement("z")->GetText()); + if (loc == nullptr) + { + throw gate_level_parsing_error("Error parsing gate_level file: no element 'loc'"); + } + gate.loc.x = std::stoull(loc->FirstChildElement("x")->GetText()); + gate.loc.y = std::stoull(loc->FirstChildElement("y")->GetText()); + gate.loc.z = std::stoull(loc->FirstChildElement("z")->GetText()); auto* const incoming_signals = gate_xml->FirstChildElement("incoming"); if (incoming_signals != nullptr) diff --git a/test/io/read_gate_level_layout.cpp b/test/io/read_gate_level_layout.cpp index 3ceb2187e..22dc2d03c 100644 --- a/test/io/read_gate_level_layout.cpp +++ b/test/io/read_gate_level_layout.cpp @@ -184,6 +184,86 @@ TEST_CASE("Parsing error: no element 'layout'", "[fcn]") std::istringstream layout_stream{fcn_layout}; + using gate_layout = gate_level_layout>>>; + CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); +} + +TEST_CASE("Parsing error: no root element 'loc'", "[fcn]") +{ + static constexpr const char* fcn_layout = "\n" + "\n" + " \n" + " Test\n" + " cartesian\n" + " 2DDWave\n" + " \n" + " 2\n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" + " \n" + " 0\n" + " PI\n" + " pi0\n" + " \n" + " 0\n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" + " 1\n" + " PI\n" + " pi1\n" + " \n" + " 1\n" + " 0\n" + " 0\n" + " \n" + " \n" + " \n" + " 2\n" + " AND\n" + " 1\n" + " 1\n" + " 0\n" + " \n" + " \n" + " 0\n" + " 1\n" + " 0\n" + " \n" + " \n" + " 1\n" + " 0\n" + " 0\n" + " \n" + " \n" + " \n" + " \n" + " 3\n" + " PO\n" + " po0\n" + " \n" + " 2\n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" + " 1\n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" + " \n" + "\n"; + + std::istringstream layout_stream{fcn_layout}; + using gate_layout = gate_level_layout>>>; CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } \ No newline at end of file From 9ead80a2dd704c0b72d87ec2677fbb83dc2627e5 Mon Sep 17 00:00:00 2001 From: Simon Date: Wed, 27 Sep 2023 19:43:01 +0200 Subject: [PATCH 13/36] clang-tidy --- include/fiction/io/read_gate_level_layout.hpp | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/include/fiction/io/read_gate_level_layout.hpp b/include/fiction/io/read_gate_level_layout.hpp index 21cfdf487..a33ffee47 100644 --- a/include/fiction/io/read_gate_level_layout.hpp +++ b/include/fiction/io/read_gate_level_layout.hpp @@ -95,11 +95,11 @@ class read_gate_level_layout_impl auto* const size = layout->FirstChildElement("size"); if (size != nullptr) { - int x = std::stoi(size->FirstChildElement("x")->GetText()); - int y = std::stoi(size->FirstChildElement("y")->GetText()); - int z = std::stoi(size->FirstChildElement("z")->GetText()); - tile max_pos; - max_pos = {x, y, z}; + int x = std::stoi(size->FirstChildElement("x")->GetText()); + int y = std::stoi(size->FirstChildElement("y")->GetText()); + int z = std::stoi(size->FirstChildElement("z")->GetText()); + tile max_pos = {}; + max_pos = {x, y, z}; lyt.resize(max_pos); } @@ -110,9 +110,9 @@ class read_gate_level_layout_impl for (const auto* gate_xml = gates_xml->FirstChildElement("gate"); gate_xml != nullptr; gate_xml = gate_xml->NextSiblingElement("gate")) { - gate_storage gate; - gate.id = std::stoi(gate_xml->FirstChildElement("id")->GetText()); - gate.type = gate_xml->FirstChildElement("type")->GetText(); + gate_storage gate = {}; + gate.id = std::stoi(gate_xml->FirstChildElement("id")->GetText()); + gate.type = gate_xml->FirstChildElement("type")->GetText(); auto* const pi_name = gate_xml->FirstChildElement("name"); if (pi_name != nullptr and pi_name->GetText()) @@ -135,10 +135,10 @@ class read_gate_level_layout_impl for (const auto* signal = incoming_signals->FirstChildElement("signal"); signal != nullptr; signal = signal->NextSiblingElement("signal")) { - tile incoming_signal; - incoming_signal.x = std::stoull(signal->FirstChildElement("x")->GetText()); - incoming_signal.y = std::stoull(signal->FirstChildElement("y")->GetText()); - incoming_signal.z = std::stoull(signal->FirstChildElement("z")->GetText()); + tile incoming_signal = {}; + incoming_signal.x = std::stoull(signal->FirstChildElement("x")->GetText()); + incoming_signal.y = std::stoull(signal->FirstChildElement("y")->GetText()); + incoming_signal.z = std::stoull(signal->FirstChildElement("z")->GetText()); gate.incoming.push_back(incoming_signal); } } From 1585cdc860a655cb8a6f9dd9678c67fd67243d2e Mon Sep 17 00:00:00 2001 From: Simon Date: Wed, 27 Sep 2023 19:47:08 +0200 Subject: [PATCH 14/36] clang-tidy --- include/fiction/io/read_gate_level_layout.hpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/include/fiction/io/read_gate_level_layout.hpp b/include/fiction/io/read_gate_level_layout.hpp index a33ffee47..49d536ccb 100644 --- a/include/fiction/io/read_gate_level_layout.hpp +++ b/include/fiction/io/read_gate_level_layout.hpp @@ -98,8 +98,7 @@ class read_gate_level_layout_impl int x = std::stoi(size->FirstChildElement("x")->GetText()); int y = std::stoi(size->FirstChildElement("y")->GetText()); int z = std::stoi(size->FirstChildElement("z")->GetText()); - tile max_pos = {}; - max_pos = {x, y, z}; + tile max_pos{x, y, z}; lyt.resize(max_pos); } @@ -135,7 +134,7 @@ class read_gate_level_layout_impl for (const auto* signal = incoming_signals->FirstChildElement("signal"); signal != nullptr; signal = signal->NextSiblingElement("signal")) { - tile incoming_signal = {}; + tile incoming_signal; incoming_signal.x = std::stoull(signal->FirstChildElement("x")->GetText()); incoming_signal.y = std::stoull(signal->FirstChildElement("y")->GetText()); incoming_signal.z = std::stoull(signal->FirstChildElement("z")->GetText()); From 7784e8f5ccbf84b9d20067e0e116e4dd5950429d Mon Sep 17 00:00:00 2001 From: Simon Date: Wed, 27 Sep 2023 19:49:22 +0200 Subject: [PATCH 15/36] clang format --- include/fiction/io/read_gate_level_layout.hpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/include/fiction/io/read_gate_level_layout.hpp b/include/fiction/io/read_gate_level_layout.hpp index 49d536ccb..88f279d19 100644 --- a/include/fiction/io/read_gate_level_layout.hpp +++ b/include/fiction/io/read_gate_level_layout.hpp @@ -95,9 +95,9 @@ class read_gate_level_layout_impl auto* const size = layout->FirstChildElement("size"); if (size != nullptr) { - int x = std::stoi(size->FirstChildElement("x")->GetText()); - int y = std::stoi(size->FirstChildElement("y")->GetText()); - int z = std::stoi(size->FirstChildElement("z")->GetText()); + int x = std::stoi(size->FirstChildElement("x")->GetText()); + int y = std::stoi(size->FirstChildElement("y")->GetText()); + int z = std::stoi(size->FirstChildElement("z")->GetText()); tile max_pos{x, y, z}; lyt.resize(max_pos); } @@ -135,9 +135,9 @@ class read_gate_level_layout_impl signal = signal->NextSiblingElement("signal")) { tile incoming_signal; - incoming_signal.x = std::stoull(signal->FirstChildElement("x")->GetText()); - incoming_signal.y = std::stoull(signal->FirstChildElement("y")->GetText()); - incoming_signal.z = std::stoull(signal->FirstChildElement("z")->GetText()); + incoming_signal.x = std::stoull(signal->FirstChildElement("x")->GetText()); + incoming_signal.y = std::stoull(signal->FirstChildElement("y")->GetText()); + incoming_signal.z = std::stoull(signal->FirstChildElement("z")->GetText()); gate.incoming.push_back(incoming_signal); } } From fd716cf21a20713cad453a644ce058a22e49dadf Mon Sep 17 00:00:00 2001 From: Simon Date: Wed, 27 Sep 2023 20:29:28 +0200 Subject: [PATCH 16/36] 100% coverage --- test/io/read_gate_level_layout.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/io/read_gate_level_layout.cpp b/test/io/read_gate_level_layout.cpp index 22dc2d03c..82e88fee1 100644 --- a/test/io/read_gate_level_layout.cpp +++ b/test/io/read_gate_level_layout.cpp @@ -180,7 +180,8 @@ TEST_CASE("Parsing error: no element 'layout'", "[fcn]") "\n" " Test\n" " cartesian\n" - " 2DDWave\n"; + " 2DDWave\n" + "\n"; std::istringstream layout_stream{fcn_layout}; From 7c6db2000cc68c45147730ac0b7fbaa1de5e3abf Mon Sep 17 00:00:00 2001 From: simon1hofmann <119581649+simon1hofmann@users.noreply.github.com> Date: Fri, 29 Sep 2023 12:58:37 +0200 Subject: [PATCH 17/36] Apply suggestions from code review Co-authored-by: Marcel Walter --- include/fiction/io/read_gate_level_layout.hpp | 44 +++++++++---------- .../fiction/io/write_gate_level_layout.hpp | 13 +++--- 2 files changed, 29 insertions(+), 28 deletions(-) diff --git a/include/fiction/io/read_gate_level_layout.hpp b/include/fiction/io/read_gate_level_layout.hpp index 88f279d19..fdb1461d9 100644 --- a/include/fiction/io/read_gate_level_layout.hpp +++ b/include/fiction/io/read_gate_level_layout.hpp @@ -8,10 +8,10 @@ #include "fiction/traits.hpp" #include "fiction/utils/name_utils.hpp" -#include -#include -#include -#include +#include "fiction/layouts/cartesian_layout.hpp" +#include "fiction/layouts/clocked_layout.hpp" +#include "fiction/layouts/gate_level_layout.hpp" +#include "fiction/layouts/tile_based_layout.hpp" #include #include @@ -80,7 +80,7 @@ class read_gate_level_layout_impl } auto* const name = layout->FirstChildElement("name"); - if (name != nullptr and name->GetText()) + if (name != nullptr && name->GetText()) { std::string layout_name = name->GetText(); set_name(lyt, layout_name); @@ -98,23 +98,23 @@ class read_gate_level_layout_impl int x = std::stoi(size->FirstChildElement("x")->GetText()); int y = std::stoi(size->FirstChildElement("y")->GetText()); int z = std::stoi(size->FirstChildElement("z")->GetText()); - tile max_pos{x, y, z}; + const tile max_pos{x, y, z}; lyt.resize(max_pos); } - std::vector gates; + std::vector gates{}; auto* const gates_xml = fcn_root->FirstChildElement("gates"); if (gates_xml != nullptr) { for (const auto* gate_xml = gates_xml->FirstChildElement("gate"); gate_xml != nullptr; gate_xml = gate_xml->NextSiblingElement("gate")) { - gate_storage gate = {}; + gate_storage gate{}; gate.id = std::stoi(gate_xml->FirstChildElement("id")->GetText()); gate.type = gate_xml->FirstChildElement("type")->GetText(); auto* const pi_name = gate_xml->FirstChildElement("name"); - if (pi_name != nullptr and pi_name->GetText()) + if (pi_name != nullptr && pi_name->GetText()) { gate.name = pi_name->GetText(); } @@ -134,7 +134,7 @@ class read_gate_level_layout_impl for (const auto* signal = incoming_signals->FirstChildElement("signal"); signal != nullptr; signal = signal->NextSiblingElement("signal")) { - tile incoming_signal; + tile incoming_signal{}; incoming_signal.x = std::stoull(signal->FirstChildElement("x")->GetText()); incoming_signal.y = std::stoull(signal->FirstChildElement("y")->GetText()); incoming_signal.z = std::stoull(signal->FirstChildElement("z")->GetText()); @@ -147,9 +147,9 @@ class read_gate_level_layout_impl std::sort(gates.begin(), gates.end(), gate_storage::compare_by_id); - for (const gate_storage& gate : gates) + for (const auto& gate : gates) { - tile location{gate.loc.x, gate.loc.y, gate.loc.z}; + const tile location{gate.loc.x, gate.loc.y, gate.loc.z}; if (gate.type == "PI") { @@ -158,8 +158,8 @@ class read_gate_level_layout_impl else if (gate.incoming.size() == 1) { - tile incoming_tile{gate.incoming.front().x, gate.incoming.front().y, gate.incoming.front().z}; - auto incoming_signal = lyt.make_signal(lyt.get_node(incoming_tile)); + const tile incoming_tile{gate.incoming.front().x, gate.incoming.front().y, gate.incoming.front().z}; + const auto incoming_signal = lyt.make_signal(lyt.get_node(incoming_tile)); if (gate.type == "PO") { @@ -179,12 +179,12 @@ class read_gate_level_layout_impl else if (gate.incoming.size() == 2) { - tile incoming_tile_1{gate.incoming.front().x, gate.incoming.front().y, + const tile incoming_tile_1{gate.incoming.front().x, gate.incoming.front().y, gate.incoming.front().z}; - tile incoming_tile_2{gate.incoming.back().x, gate.incoming.back().y, gate.incoming.back().z}; + const tile incoming_tile_2{gate.incoming.back().x, gate.incoming.back().y, gate.incoming.back().z}; - auto incoming_signal_1 = lyt.make_signal(lyt.get_node(incoming_tile_1)); - auto incoming_signal_2 = lyt.make_signal(lyt.get_node(incoming_tile_2)); + const auto incoming_signal_1 = lyt.make_signal(lyt.get_node(incoming_tile_1)); + const auto incoming_signal_2 = lyt.make_signal(lyt.get_node(incoming_tile_2)); if (gate.type == "AND") { @@ -234,7 +234,7 @@ class read_gate_level_layout_impl */ Lyt lyt; /** - * The input stream from which the gate_level file is read. + * The input stream from which the gate-level layout is read. */ std::istream& is; @@ -246,7 +246,7 @@ class read_gate_level_layout_impl tile loc{}; std::vector> incoming{}; - static bool compare_by_id(const gate_storage& gate1, const gate_storage& gate2) + static bool compare_by_id(const gate_storage& gate1, const gate_storage& gate2) noexcept { return gate1.id < gate2.id; } @@ -266,7 +266,7 @@ class read_gate_level_layout_impl * @param name The name to give to the generated layout. */ template -Lyt read_gate_level_layout(std::istream& is, const std::string_view& name = "") +[[nodiscard]] Lyt read_gate_level_layout(std::istream& is, const std::string_view& name = "") { detail::read_gate_level_layout_impl p{is, name}; @@ -304,7 +304,7 @@ void read_gate_level_layout(Lyt& lyt, std::istream& is) * @param name The name to give to the generated layout. */ template -Lyt read_gate_level_layout(const std::string_view& filename, const std::string_view& name = "") +[[nodiscard]] Lyt read_gate_level_layout(const std::string_view& filename, const std::string_view& name = "") { std::ifstream is{filename.data(), std::ifstream::in}; diff --git a/include/fiction/io/write_gate_level_layout.hpp b/include/fiction/io/write_gate_level_layout.hpp index 0df808328..219970036 100644 --- a/include/fiction/io/write_gate_level_layout.hpp +++ b/include/fiction/io/write_gate_level_layout.hpp @@ -8,8 +8,8 @@ #include "fiction/traits.hpp" #include "utils/version_info.hpp" -#include -#include +#include "fiction/layouts/clocked_layout.hpp" +#include "fiction/layouts/clocking_scheme.hpp" #include #include @@ -84,7 +84,8 @@ class write_gate_level_layout_impl void run() { - std::stringstream header{}, layout_metadata{}; + std::stringstream header{}; + std::stringstream layout_metadata{}; header << fcn::FCN_HEADER << fcn::OPEN_FCN; @@ -106,12 +107,12 @@ class write_gate_level_layout_impl os << fcn::OPEN_GATES; mockturtle::topo_view layout_topo{lyt}; - int id = 0; + uint32_t id = 0; layout_topo.foreach_pi( [&](const auto& gate) { - const tile coord = lyt.get_tile(gate); + const auto coord = lyt.get_tile(gate); os << fcn::OPEN_GATE; os << fmt::format(fcn::GATE, id, "PI", lyt.get_name(gate), coord.x, coord.y, coord.z); os << fcn::CLOSE_GATE; @@ -121,7 +122,7 @@ class write_gate_level_layout_impl layout_topo.foreach_gate( [&](const auto& gate) { - const tile coord = lyt.get_tile(gate); + const auto coord = lyt.get_tile(gate); if (const auto signals = lyt.incoming_data_flow(coord); signals.size() == 1) { os << fcn::OPEN_GATE; From 3e5d090ffec349712ac8c0ae66d61084332b7ffe Mon Sep 17 00:00:00 2001 From: Simon Date: Sat, 30 Sep 2023 14:25:23 +0200 Subject: [PATCH 18/36] fix first batch of todos --- docs/io/input.rst | 12 +++++ docs/io/physical_simulation.rst | 8 ++++ include/fiction/io/read_gate_level_layout.hpp | 44 ++++++++++++------- .../fiction/io/write_gate_level_layout.hpp | 18 +++++--- test/io/read_gate_level_layout.cpp | 33 ++++++++++++++ 5 files changed, 93 insertions(+), 22 deletions(-) diff --git a/docs/io/input.rst b/docs/io/input.rst index b75ca1aef..67841f9c2 100644 --- a/docs/io/input.rst +++ b/docs/io/input.rst @@ -19,6 +19,18 @@ Truth Tables .. doxygenclass:: fiction::tt_reader :members: +Gate-level Layouts +################## + +**Header:** ``fiction/io/read_gate_level_layout.hpp`` + +.. doxygenfunction:: fiction::read_gate_level_layout(std::istream& is, const std::string_view& name = "") +.. doxygenfunction:: fiction::read_gate_level_layout(Lyt& lyt, std::istream& is) +.. doxygenfunction:: fiction::read_gate_level_layout(const std::string_view& filename, const std::string_view& name = "") +.. doxygenfunction:: fiction::read_gate_level_layout(Lyt& lyt, const std::string_view& filename) + +.. doxygenclass:: fiction::gate_level_parsing_error + Cell-level Layouts ################## diff --git a/docs/io/physical_simulation.rst b/docs/io/physical_simulation.rst index 6f3af3f4d..216bbabad 100644 --- a/docs/io/physical_simulation.rst +++ b/docs/io/physical_simulation.rst @@ -87,3 +87,11 @@ SiDB Operational Domain :members: .. doxygenfunction:: fiction::write_operational_domain(const operational_domain& opdom, std::ostream& os, const write_operational_domain_params& params = {}) .. doxygenfunction:: fiction::write_operational_domain(const operational_domain& opdom, const std::string_view& filename, const write_operational_domain_params& params = {}) + +Technology-independent Gate-level Layouts +######################################### + +**Header:** ``fiction/io/write_gate_level_layout.hpp`` + +.. doxygenfunction:: fiction::write_gate_level_layout(const Lyt& lyt, std::ostream& os) +.. doxygenfunction:: fiction::write_gate_level_layout(const Lyt& lyt, const std::string_view& filename) diff --git a/include/fiction/io/read_gate_level_layout.hpp b/include/fiction/io/read_gate_level_layout.hpp index fdb1461d9..0f994c92d 100644 --- a/include/fiction/io/read_gate_level_layout.hpp +++ b/include/fiction/io/read_gate_level_layout.hpp @@ -5,13 +5,12 @@ #ifndef FICTION_READ_GATE_LEVEL_LAYOUT_HPP #define FICTION_READ_GATE_LEVEL_LAYOUT_HPP -#include "fiction/traits.hpp" -#include "fiction/utils/name_utils.hpp" - #include "fiction/layouts/cartesian_layout.hpp" #include "fiction/layouts/clocked_layout.hpp" #include "fiction/layouts/gate_level_layout.hpp" #include "fiction/layouts/tile_based_layout.hpp" +#include "fiction/traits.hpp" +#include "fiction/utils/name_utils.hpp" #include #include @@ -57,10 +56,10 @@ class read_gate_level_layout_impl // tinyXML2 does not support std::istream, so we have to read the whole file into a string first std::stringstream buffer{}; buffer << is.rdbuf(); - const std::string sqd_content{buffer.str()}; + const std::string gate_level_content{buffer.str()}; tinyxml2::XMLDocument xml_document{}; - xml_document.Parse(sqd_content.c_str()); + xml_document.Parse(gate_level_content.c_str()); if (xml_document.ErrorID() != 0) { @@ -89,15 +88,28 @@ class read_gate_level_layout_impl auto* const clocking = layout->FirstChildElement("clocking"); if (clocking != nullptr) { - lyt.replace_clocking_scheme(*get_clocking_scheme(clocking->GetText())); + const auto clocking_scheme = get_clocking_scheme(clocking->GetText()); + if (clocking_scheme.has_value()) + { + lyt.replace_clocking_scheme(*clocking_scheme); + } + else + { + throw gate_level_parsing_error("Error parsing gate_level file: unknown clocking scheme: " + + std::string(clocking->GetText())); + } + } + else + { + throw gate_level_parsing_error("Error parsing gate_level file: no element 'clocking'"); } auto* const size = layout->FirstChildElement("size"); if (size != nullptr) { - int x = std::stoi(size->FirstChildElement("x")->GetText()); - int y = std::stoi(size->FirstChildElement("y")->GetText()); - int z = std::stoi(size->FirstChildElement("z")->GetText()); + int x = std::stoi(size->FirstChildElement("x")->GetText()); + int y = std::stoi(size->FirstChildElement("y")->GetText()); + int z = std::stoi(size->FirstChildElement("z")->GetText()); const tile max_pos{x, y, z}; lyt.resize(max_pos); } @@ -110,8 +122,8 @@ class read_gate_level_layout_impl gate_xml = gate_xml->NextSiblingElement("gate")) { gate_storage gate{}; - gate.id = std::stoi(gate_xml->FirstChildElement("id")->GetText()); - gate.type = gate_xml->FirstChildElement("type")->GetText(); + gate.id = std::stoi(gate_xml->FirstChildElement("id")->GetText()); + gate.type = gate_xml->FirstChildElement("type")->GetText(); auto* const pi_name = gate_xml->FirstChildElement("name"); if (pi_name != nullptr && pi_name->GetText()) @@ -158,7 +170,8 @@ class read_gate_level_layout_impl else if (gate.incoming.size() == 1) { - const tile incoming_tile{gate.incoming.front().x, gate.incoming.front().y, gate.incoming.front().z}; + const tile incoming_tile{gate.incoming.front().x, gate.incoming.front().y, + gate.incoming.front().z}; const auto incoming_signal = lyt.make_signal(lyt.get_node(incoming_tile)); if (gate.type == "PO") @@ -180,8 +193,9 @@ class read_gate_level_layout_impl else if (gate.incoming.size() == 2) { const tile incoming_tile_1{gate.incoming.front().x, gate.incoming.front().y, - gate.incoming.front().z}; - const tile incoming_tile_2{gate.incoming.back().x, gate.incoming.back().y, gate.incoming.back().z}; + gate.incoming.front().z}; + const tile incoming_tile_2{gate.incoming.back().x, gate.incoming.back().y, + gate.incoming.back().z}; const auto incoming_signal_1 = lyt.make_signal(lyt.get_node(incoming_tile_1)); const auto incoming_signal_2 = lyt.make_signal(lyt.get_node(incoming_tile_2)); @@ -230,7 +244,7 @@ class read_gate_level_layout_impl private: /** - * The layout to which the parsed cells are added. + * The layout which will be altered based on the parsed information. */ Lyt lyt; /** diff --git a/include/fiction/io/write_gate_level_layout.hpp b/include/fiction/io/write_gate_level_layout.hpp index 219970036..f6c063fd9 100644 --- a/include/fiction/io/write_gate_level_layout.hpp +++ b/include/fiction/io/write_gate_level_layout.hpp @@ -5,11 +5,10 @@ #ifndef FICTION_WRITE_GATE_LEVEL_LAYOUT_HPP #define FICTION_WRITE_GATE_LEVEL_LAYOUT_HPP -#include "fiction/traits.hpp" -#include "utils/version_info.hpp" - #include "fiction/layouts/clocked_layout.hpp" #include "fiction/layouts/clocking_scheme.hpp" +#include "fiction/traits.hpp" +#include "utils/version_info.hpp" #include #include @@ -107,10 +106,10 @@ class write_gate_level_layout_impl os << fcn::OPEN_GATES; mockturtle::topo_view layout_topo{lyt}; - uint32_t id = 0; + uint32_t id = 0; layout_topo.foreach_pi( - [&](const auto& gate) + [&id, this](const auto& gate) { const auto coord = lyt.get_tile(gate); os << fcn::OPEN_GATE; @@ -120,7 +119,7 @@ class write_gate_level_layout_impl }); layout_topo.foreach_gate( - [&](const auto& gate) + [&id, this](const auto& gate) { const auto coord = lyt.get_tile(gate); if (const auto signals = lyt.incoming_data_flow(coord); signals.size() == 1) @@ -199,8 +198,13 @@ class write_gate_level_layout_impl } private: + /** + * The layout to be written. + */ Lyt lyt; - + /** + * The output stream to which the gate-level layout is written. + */ std::ostream& os; }; diff --git a/test/io/read_gate_level_layout.cpp b/test/io/read_gate_level_layout.cpp index 82e88fee1..c8ee40caa 100644 --- a/test/io/read_gate_level_layout.cpp +++ b/test/io/read_gate_level_layout.cpp @@ -265,6 +265,39 @@ TEST_CASE("Parsing error: no root element 'loc'", "[fcn]") std::istringstream layout_stream{fcn_layout}; + using gate_layout = gate_level_layout>>>; + CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); +} + +TEST_CASE("Parsing error: no element 'clocking'", "[fcn]") +{ + static constexpr const char* fcn_layout = "\n" + "\n" + " \n" + " Test\n" + " cartesian\n" + " \n" + "\n"; + + std::istringstream layout_stream{fcn_layout}; + + using gate_layout = gate_level_layout>>>; + CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); +} + +TEST_CASE("Parsing error: unknown clocking scheme", "[fcn]") +{ + static constexpr const char* fcn_layout = "\n" + "\n" + " \n" + " Test\n" + " cartesian\n" + " CoolClocking\n" + " \n" + "\n"; + + std::istringstream layout_stream{fcn_layout}; + using gate_layout = gate_level_layout>>>; CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } \ No newline at end of file From dec32a93bff6465e06f8e4a2973bec48811820f6 Mon Sep 17 00:00:00 2001 From: Simon Hofmann Date: Mon, 2 Oct 2023 10:58:25 +0200 Subject: [PATCH 19/36] fix second batch of todos --- include/fiction/io/read_gate_level_layout.hpp | 223 +++++- .../fiction/io/write_gate_level_layout.hpp | 26 + test/io/read_gate_level_layout.cpp | 640 ++++++++++++++++-- test/io/write_gate_level_layout.cpp | 18 +- test/utils/blueprints/layout_blueprints.hpp | 37 + 5 files changed, 884 insertions(+), 60 deletions(-) diff --git a/include/fiction/io/read_gate_level_layout.hpp b/include/fiction/io/read_gate_level_layout.hpp index 0f994c92d..e8b7ed35f 100644 --- a/include/fiction/io/read_gate_level_layout.hpp +++ b/include/fiction/io/read_gate_level_layout.hpp @@ -58,6 +58,7 @@ class read_gate_level_layout_impl buffer << is.rdbuf(); const std::string gate_level_content{buffer.str()}; + // parse xml file tinyxml2::XMLDocument xml_document{}; xml_document.Parse(gate_level_content.c_str()); @@ -78,6 +79,7 @@ class read_gate_level_layout_impl throw gate_level_parsing_error("Error parsing gate_level file: no element 'layout'"); } + // set layout name auto* const name = layout->FirstChildElement("name"); if (name != nullptr && name->GetText()) { @@ -85,6 +87,7 @@ class read_gate_level_layout_impl set_name(lyt, layout_name); } + // set clocking scheme auto* const clocking = layout->FirstChildElement("clocking"); if (clocking != nullptr) { @@ -104,16 +107,52 @@ class read_gate_level_layout_impl throw gate_level_parsing_error("Error parsing gate_level file: no element 'clocking'"); } + // set layout size auto* const size = layout->FirstChildElement("size"); if (size != nullptr) { - int x = std::stoi(size->FirstChildElement("x")->GetText()); - int y = std::stoi(size->FirstChildElement("y")->GetText()); - int z = std::stoi(size->FirstChildElement("z")->GetText()); + auto* const size_x = size->FirstChildElement("x"); + int x = 0; + if (size_x != nullptr and size_x->GetText()) + { + x = std::stoi(size_x->GetText()); + } + else + { + throw gate_level_parsing_error("Error parsing gate_level file: no element 'x' in 'size'"); + } + + auto* const size_y = size->FirstChildElement("y"); + int y = 0; + if (size_y != nullptr and size_y->GetText()) + { + y = std::stoi(size_y->GetText()); + } + else + { + throw gate_level_parsing_error("Error parsing gate_level file: no element 'y' in 'size'"); + } + + auto* const size_z = size->FirstChildElement("z"); + int z = 0; + if (size_z != nullptr and size_z->GetText()) + { + z = std::stoi(size_z->GetText()); + } + else + { + throw gate_level_parsing_error("Error parsing gate_level file: no element 'z' in 'size'"); + } + const tile max_pos{x, y, z}; lyt.resize(max_pos); } + else + { + throw gate_level_parsing_error("Error parsing gate_level file: no element 'size'"); + } + // parse layout gates std::vector gates{}; auto* const gates_xml = fcn_root->FirstChildElement("gates"); if (gates_xml != nullptr) @@ -122,13 +161,39 @@ class read_gate_level_layout_impl gate_xml = gate_xml->NextSiblingElement("gate")) { gate_storage gate{}; - gate.id = std::stoi(gate_xml->FirstChildElement("id")->GetText()); - gate.type = gate_xml->FirstChildElement("type")->GetText(); - auto* const pi_name = gate_xml->FirstChildElement("name"); - if (pi_name != nullptr && pi_name->GetText()) + auto* const gate_id = gate_xml->FirstChildElement("id"); + if (gate_id != nullptr and gate_id->GetText()) + { + gate.id = std::stoi(gate_id->GetText()); + } + else + { + throw gate_level_parsing_error("Error parsing gate_level file: no element 'id' in 'gate'"); + } + + auto* const gate_type = gate_xml->FirstChildElement("type"); + if (gate_type != nullptr and gate_type->GetText()) + { + gate.type = gate_type->GetText(); + } + else { - gate.name = pi_name->GetText(); + throw gate_level_parsing_error("Error parsing gate_level file: no element 'type' in 'gate'"); + } + + if (gate.type == "PI" || gate.type == "PO") + { + auto* const pi_po_name = gate_xml->FirstChildElement("name"); + if (pi_po_name != nullptr && pi_po_name->GetText()) + { + gate.name = pi_po_name->GetText(); + } + else + { + throw gate_level_parsing_error( + "Error parsing gate_level file: no element 'name' in 'gate' for input/output"); + } } auto* const loc = gate_xml->FirstChildElement("loc"); @@ -136,9 +201,39 @@ class read_gate_level_layout_impl { throw gate_level_parsing_error("Error parsing gate_level file: no element 'loc'"); } - gate.loc.x = std::stoull(loc->FirstChildElement("x")->GetText()); - gate.loc.y = std::stoull(loc->FirstChildElement("y")->GetText()); - gate.loc.z = std::stoull(loc->FirstChildElement("z")->GetText()); + + // get x-coordinate + auto* const loc_x = loc->FirstChildElement("x"); + if (loc_x != nullptr and loc_x->GetText()) + { + gate.loc.x = std::stoull(loc_x->GetText()); + } + else + { + throw gate_level_parsing_error("Error parsing gate_level file: no element 'x' in 'loc'"); + } + + // get y-coordinate + auto* const loc_y = loc->FirstChildElement("y"); + if (loc_y != nullptr and loc_y->GetText()) + { + gate.loc.y = std::stoull(loc_y->GetText()); + } + else + { + throw gate_level_parsing_error("Error parsing gate_level file: no element 'y' in 'loc'"); + } + + // get z-coordinate + auto* const loc_z = loc->FirstChildElement("z"); + if (loc_z != nullptr and loc_z->GetText()) + { + gate.loc.z = std::stoull(loc_z->GetText()); + } + else + { + throw gate_level_parsing_error("Error parsing gate_level file: no element 'z' in 'loc'"); + } auto* const incoming_signals = gate_xml->FirstChildElement("incoming"); if (incoming_signals != nullptr) @@ -147,9 +242,37 @@ class read_gate_level_layout_impl signal = signal->NextSiblingElement("signal")) { tile incoming_signal{}; - incoming_signal.x = std::stoull(signal->FirstChildElement("x")->GetText()); - incoming_signal.y = std::stoull(signal->FirstChildElement("y")->GetText()); - incoming_signal.z = std::stoull(signal->FirstChildElement("z")->GetText()); + + auto* const incoming_signal_x = signal->FirstChildElement("x"); + if (incoming_signal_x != nullptr and incoming_signal_x->GetText()) + { + incoming_signal.x = std::stoull(incoming_signal_x->GetText()); + } + else + { + throw gate_level_parsing_error("Error parsing gate_level file: no element 'x' in 'signal'"); + } + + auto* const incoming_signal_y = signal->FirstChildElement("y"); + if (incoming_signal_y != nullptr and incoming_signal_y->GetText()) + { + incoming_signal.y = std::stoull(incoming_signal_y->GetText()); + } + else + { + throw gate_level_parsing_error("Error parsing gate_level file: no element 'y' in 'signal'"); + } + + auto* const incoming_signal_z = signal->FirstChildElement("z"); + if (incoming_signal_z != nullptr and incoming_signal_z->GetText()) + { + incoming_signal.z = std::stoull(incoming_signal_z->GetText()); + } + else + { + throw gate_level_parsing_error("Error parsing gate_level file: no element 'z' in 'signal'"); + } + gate.incoming.push_back(incoming_signal); } } @@ -157,6 +280,7 @@ class read_gate_level_layout_impl gates.push_back(gate); } + // sort gates ascending based on id std::sort(gates.begin(), gates.end(), gate_storage::compare_by_id); for (const auto& gate : gates) @@ -188,6 +312,12 @@ class read_gate_level_layout_impl { lyt.create_not(incoming_signal, location); } + + else + { + throw gate_level_parsing_error("Error parsing gate_level file: unknown gate type: " + + std::string(gate.type)); + } } else if (gate.incoming.size() == 2) @@ -236,6 +366,34 @@ class read_gate_level_layout_impl lyt.create_node({incoming_signal_1, incoming_signal_2}, tt_t, location); } } + else if (gate.incoming.size() == 3) + { + const tile incoming_tile_1{gate.incoming.front().x, gate.incoming.front().y, + gate.incoming.front().z}; + const tile incoming_tile_2{gate.incoming[1].x, gate.incoming[1].y, gate.incoming[1].z}; + const tile incoming_tile_3{gate.incoming.back().x, gate.incoming.back().y, + gate.incoming.back().z}; + + const auto incoming_signal_1 = lyt.make_signal(lyt.get_node(incoming_tile_1)); + const auto incoming_signal_2 = lyt.make_signal(lyt.get_node(incoming_tile_2)); + const auto incoming_signal_3 = lyt.make_signal(lyt.get_node(incoming_tile_3)); + + if (gate.type == "MAJ") + { + lyt.create_maj(incoming_signal_1, incoming_signal_2, incoming_signal_3, location); + } + else + { + kitty::dynamic_truth_table tt_t(3u); + kitty::create_from_binary_string(tt_t, gate.type); + lyt.create_node({incoming_signal_1, incoming_signal_2, incoming_signal_3}, tt_t, location); + } + } + else + { + throw gate_level_parsing_error( + "Error parsing gate_level file: gate has more than 3 incoming signals"); + } } } @@ -251,15 +409,42 @@ class read_gate_level_layout_impl * The input stream from which the gate-level layout is read. */ std::istream& is; - + /** + * @struct gate_storage + * + * Represents a gate in a fcn layout, storing its unique ID, type, name, location, and incoming connections. + */ struct gate_storage { - int id{}; - std::string type; - std::string name; - tile loc{}; + /** + * Unique identifier for the gate. + */ + int id{}; + /** + * Type of the gate, can be an alias (AND, OR, PI, ..) or the implemented function in a binary or hexadecimal + * form. + */ + std::string type; + /** + * Name of the gate (for inputs and outputs). + */ + std::string name; + /** + * Location of the gate represented its x-, y- and z-coordinate. + */ + tile loc{}; + /** + * List of incoming connections to the gate. + */ std::vector> incoming{}; + /** + * Static member function to compare gate_storage objects by their IDs. + * + * @param gate1 First gate to be compared. + * @param gate2 Second gate to be compared. + * @return True if gate1's ID is less than gate2's ID, false otherwise. + */ static bool compare_by_id(const gate_storage& gate1, const gate_storage& gate2) noexcept { return gate1.id < gate2.id; diff --git a/include/fiction/io/write_gate_level_layout.hpp b/include/fiction/io/write_gate_level_layout.hpp index f6c063fd9..6ca6271bf 100644 --- a/include/fiction/io/write_gate_level_layout.hpp +++ b/include/fiction/io/write_gate_level_layout.hpp @@ -191,6 +191,32 @@ class write_gate_level_layout_impl os << fcn::CLOSE_GATE; id++; } + else if (signals.size() == 3) + { + os << fcn::OPEN_GATE; + + const auto signal_a = signals[0]; + const auto signal_b = signals[1]; + const auto signal_c = signals[2]; + + if (lyt.is_maj(gate)) + { + os << fmt::format(fcn::GATE, id, "MAJ", "", coord.x, coord.y, coord.z); + } + else if (lyt.is_function(gate)) + { + const auto node_fun = lyt.node_function(gate); + + os << fmt::format(fcn::GATE, id, kitty::to_binary(node_fun), "", coord.x, coord.y, coord.z); + } + os << fcn::OPEN_INCOMING; + os << fmt::format(fcn::SIGNAL, signal_a.x, signal_a.y, signal_a.z); + os << fmt::format(fcn::SIGNAL, signal_b.x, signal_b.y, signal_b.z); + os << fmt::format(fcn::SIGNAL, signal_c.x, signal_c.y, signal_c.z); + os << fcn::CLOSE_INCOMING; + os << fcn::CLOSE_GATE; + id++; + } }); os << fcn::CLOSE_GATES; diff --git a/test/io/read_gate_level_layout.cpp b/test/io/read_gate_level_layout.cpp index c8ee40caa..29e89e786 100644 --- a/test/io/read_gate_level_layout.cpp +++ b/test/io/read_gate_level_layout.cpp @@ -27,6 +27,11 @@ TEST_CASE("Read empty FCN layout", "[fcn]") " Test\n" " cartesian\n" " 2DDWave\n" + " \n" + " 0\n" + " 0\n" + " 0\n" + " \n" " \n" "\n"; @@ -174,13 +179,129 @@ TEST_CASE("Parsing error: no root element 'fcn'", "[fcn]") CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } -TEST_CASE("Parsing error: no element 'layout'", "[fcn]") +TEST_CASE("Parsing error: no element 'layout' in 'fcn'", "[fcn]") +{ + static constexpr const char* fcn_layout = "\n" + "\n" + " Test\n" + " cartesian\n" + " 2DDWave\n" + "\n"; + + std::istringstream layout_stream{fcn_layout}; + + using gate_layout = gate_level_layout>>>; + CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); +} + +TEST_CASE("Parsing error: no element 'clocking' in 'layout'", "[fcn]") +{ + static constexpr const char* fcn_layout = "\n" + "\n" + " \n" + " Test\n" + " cartesian\n" + " \n" + "\n"; + + std::istringstream layout_stream{fcn_layout}; + + using gate_layout = gate_level_layout>>>; + CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); +} + +TEST_CASE("Parsing error: unknown clocking scheme", "[fcn]") +{ + static constexpr const char* fcn_layout = "\n" + "\n" + " \n" + " Test\n" + " cartesian\n" + " CoolClocking\n" + " \n" + "\n"; + + std::istringstream layout_stream{fcn_layout}; + + using gate_layout = gate_level_layout>>>; + CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); +} + +TEST_CASE("Parsing error: no element 'size' in 'layout'", "[fcn]") +{ + static constexpr const char* fcn_layout = "\n" + "\n" + " \n" + " Test\n" + " cartesian\n" + " 2DDWave\n" + " 2\n" + " 1\n" + " 0\n" + " \n" + "\n"; + + std::istringstream layout_stream{fcn_layout}; + + using gate_layout = gate_level_layout>>>; + CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); +} + +TEST_CASE("Parsing error: no element 'x' in 'size'", "[fcn]") +{ + static constexpr const char* fcn_layout = "\n" + "\n" + " \n" + " Test\n" + " cartesian\n" + " 2DDWave\n" + " \n" + " 1\n" + " 0\n" + " \n" + " \n" + "\n"; + + std::istringstream layout_stream{fcn_layout}; + + using gate_layout = gate_level_layout>>>; + CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); +} + +TEST_CASE("Parsing error: no element 'y' in 'size'", "[fcn]") +{ + static constexpr const char* fcn_layout = "\n" + "\n" + " \n" + " Test\n" + " cartesian\n" + " 2DDWave\n" + " \n" + " 2\n" + " 0\n" + " \n" + " \n" + "\n"; + + std::istringstream layout_stream{fcn_layout}; + + using gate_layout = gate_level_layout>>>; + CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); +} + +TEST_CASE("Parsing error: no element 'z' in 'size'", "[fcn]") { static constexpr const char* fcn_layout = "\n" "\n" + " \n" " Test\n" " cartesian\n" " 2DDWave\n" + " \n" + " 2\n" + " 1\n" + " \n" + " \n" "\n"; std::istringstream layout_stream{fcn_layout}; @@ -189,7 +310,7 @@ TEST_CASE("Parsing error: no element 'layout'", "[fcn]") CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } -TEST_CASE("Parsing error: no root element 'loc'", "[fcn]") +TEST_CASE("Parsing error: no element 'id' in 'gate", "[fcn]") { static constexpr const char* fcn_layout = "\n" "\n" @@ -205,7 +326,6 @@ TEST_CASE("Parsing error: no root element 'loc'", "[fcn]") " \n" " \n" " \n" - " 0\n" " PI\n" " pi0\n" " \n" @@ -214,51 +334,103 @@ TEST_CASE("Parsing error: no root element 'loc'", "[fcn]") " 0\n" " \n" " \n" + " \n" + "\n"; + + std::istringstream layout_stream{fcn_layout}; + + using gate_layout = gate_level_layout>>>; + CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); +} + +TEST_CASE("Parsing error: no element 'type' in 'gate", "[fcn]") +{ + static constexpr const char* fcn_layout = "\n" + "\n" + " \n" + " Test\n" + " cartesian\n" + " 2DDWave\n" + " \n" + " 2\n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" " \n" - " 1\n" - " PI\n" - " pi1\n" + " 0\n" + " pi0\n" " \n" - " 1\n" - " 0\n" + " 0\n" + " 1\n" " 0\n" " \n" " \n" + " \n" + "\n"; + + std::istringstream layout_stream{fcn_layout}; + + using gate_layout = gate_level_layout>>>; + CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); +} + +TEST_CASE("Parsing error: no element 'name' in 'gate", "[fcn]") +{ + static constexpr const char* fcn_layout = "\n" + "\n" + " \n" + " Test\n" + " cartesian\n" + " 2DDWave\n" + " \n" + " 2\n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" " \n" - " 2\n" - " AND\n" - " 1\n" + " 0\n" + " PI\n" + " \n" + " 0\n" " 1\n" " 0\n" - " \n" - " \n" - " 0\n" - " 1\n" - " 0\n" - " \n" - " \n" - " 1\n" - " 0\n" - " 0\n" - " \n" - " \n" + " \n" " \n" + " \n" + "\n"; + + std::istringstream layout_stream{fcn_layout}; + + using gate_layout = gate_level_layout>>>; + CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); +} + +TEST_CASE("Parsing error: no element 'loc' in 'gate'", "[fcn]") +{ + static constexpr const char* fcn_layout = "\n" + "\n" + " \n" + " Test\n" + " cartesian\n" + " 2DDWave\n" + " \n" + " 2\n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" " \n" - " 3\n" - " PO\n" - " po0\n" - " \n" - " 2\n" + " 0\n" + " PI\n" + " pi0\n" + " 0\n" " 1\n" " 0\n" - " \n" - " \n" - " \n" - " 1\n" - " 1\n" - " 0\n" - " \n" - " \n" " \n" " \n" "\n"; @@ -269,14 +441,31 @@ TEST_CASE("Parsing error: no root element 'loc'", "[fcn]") CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } -TEST_CASE("Parsing error: no element 'clocking'", "[fcn]") +TEST_CASE("Parsing error: no element 'x' in 'loc'", "[fcn]") { static constexpr const char* fcn_layout = "\n" "\n" " \n" " Test\n" " cartesian\n" + " 2DDWave\n" + " \n" + " 2\n" + " 1\n" + " 0\n" + " \n" " \n" + " \n" + " \n" + " 0\n" + " PI\n" + " pi0\n" + " \n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" "\n"; std::istringstream layout_stream{fcn_layout}; @@ -285,15 +474,388 @@ TEST_CASE("Parsing error: no element 'clocking'", "[fcn]") CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } -TEST_CASE("Parsing error: unknown clocking scheme", "[fcn]") +TEST_CASE("Parsing error: no element 'y' in 'loc'", "[fcn]") { static constexpr const char* fcn_layout = "\n" "\n" " \n" " Test\n" " cartesian\n" - " CoolClocking\n" + " 2DDWave\n" + " \n" + " 2\n" + " 1\n" + " 0\n" + " \n" " \n" + " \n" + " \n" + " 0\n" + " PI\n" + " pi0\n" + " \n" + " 0\n" + " 0\n" + " \n" + " \n" + " \n" + "\n"; + + std::istringstream layout_stream{fcn_layout}; + + using gate_layout = gate_level_layout>>>; + CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); +} + +TEST_CASE("Parsing error: no element 'z' in 'loc'", "[fcn]") +{ + static constexpr const char* fcn_layout = "\n" + "\n" + " \n" + " Test\n" + " cartesian\n" + " 2DDWave\n" + " \n" + " 2\n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" + " \n" + " 0\n" + " PI\n" + " pi0\n" + " \n" + " 0\n" + " 1\n" + " \n" + " \n" + " \n" + "\n"; + + std::istringstream layout_stream{fcn_layout}; + + using gate_layout = gate_level_layout>>>; + CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); +} + +TEST_CASE("Parsing error: unknown gate type", "[fcn]") +{ + static constexpr const char* fcn_layout = "\n" + "\n" + " \n" + " Test\n" + " cartesian\n" + " 2DDWave\n" + " \n" + " 2\n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" + " \n" + " 0\n" + " PI\n" + " pi0\n" + " \n" + " 0\n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" + " 1\n" + " PI\n" + " pi1\n" + " \n" + " 1\n" + " 0\n" + " 0\n" + " \n" + " \n" + " \n" + " 2\n" + " AND\n" + " \n" + " 1\n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" + " 0\n" + " 1\n" + " 0\n" + " \n" + " \n" + " 1\n" + " 0\n" + " 0\n" + " \n" + " \n" + " \n" + " \n" + " 3\n" + " unknown\n" + " \n" + " 2\n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" + " 1\n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" + " \n" + "\n"; + + std::istringstream layout_stream{fcn_layout}; + + using gate_layout = gate_level_layout>>>; + CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); +} + +TEST_CASE("Parsing error: no element 'x' in 'signal'", "[fcn]") +{ + static constexpr const char* fcn_layout = "\n" + "\n" + " \n" + " Test\n" + " cartesian\n" + " 2DDWave\n" + " \n" + " 2\n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" + " \n" + " 0\n" + " PI\n" + " pi0\n" + " \n" + " 0\n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" + " 1\n" + " PI\n" + " pi1\n" + " \n" + " 1\n" + " 0\n" + " 0\n" + " \n" + " \n" + " \n" + " 2\n" + " AND\n" + " \n" + " 1\n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" + " 1\n" + " 0\n" + " \n" + " \n" + " 1\n" + " 0\n" + " 0\n" + " \n" + " \n" + " \n" + " \n" + " 3\n" + " PO\n" + " po0\n" + " \n" + " 2\n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" + " 1\n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" + " \n" + "\n"; + + std::istringstream layout_stream{fcn_layout}; + + using gate_layout = gate_level_layout>>>; + CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); +} + +TEST_CASE("Parsing error: no element 'y' in 'signal'", "[fcn]") +{ + static constexpr const char* fcn_layout = "\n" + "\n" + " \n" + " Test\n" + " cartesian\n" + " 2DDWave\n" + " \n" + " 2\n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" + " \n" + " 0\n" + " PI\n" + " pi0\n" + " \n" + " 0\n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" + " 1\n" + " PI\n" + " pi1\n" + " \n" + " 1\n" + " 0\n" + " 0\n" + " \n" + " \n" + " \n" + " 2\n" + " AND\n" + " \n" + " 1\n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" + " 0\n" + " 0\n" + " \n" + " \n" + " 1\n" + " 0\n" + " 0\n" + " \n" + " \n" + " \n" + " \n" + " 3\n" + " PO\n" + " po0\n" + " \n" + " 2\n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" + " 1\n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" + " \n" + "\n"; + + std::istringstream layout_stream{fcn_layout}; + + using gate_layout = gate_level_layout>>>; + CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); +} + +TEST_CASE("Parsing error: no element 'z' in 'signal'", "[fcn]") +{ + static constexpr const char* fcn_layout = "\n" + "\n" + " \n" + " Test\n" + " cartesian\n" + " 2DDWave\n" + " \n" + " 2\n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" + " \n" + " 0\n" + " PI\n" + " pi0\n" + " \n" + " 0\n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" + " 1\n" + " PI\n" + " pi1\n" + " \n" + " 1\n" + " 0\n" + " 0\n" + " \n" + " \n" + " \n" + " 2\n" + " AND\n" + " \n" + " 1\n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" + " 0\n" + " 1\n" + " \n" + " \n" + " 1\n" + " 0\n" + " 0\n" + " \n" + " \n" + " \n" + " \n" + " 3\n" + " PO\n" + " po0\n" + " \n" + " 2\n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" + " 1\n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" + " \n" "\n"; std::istringstream layout_stream{fcn_layout}; diff --git a/test/io/write_gate_level_layout.cpp b/test/io/write_gate_level_layout.cpp index 75a8ff213..658571f0b 100644 --- a/test/io/write_gate_level_layout.cpp +++ b/test/io/write_gate_level_layout.cpp @@ -97,11 +97,25 @@ void check_parsing_equiv_all() check_parsing_equiv(blueprints::clpl()); check_parsing_equiv(blueprints::one_to_five_path_difference_network()); check_parsing_equiv(blueprints::nand_xnor_network()); - check_parsing_equiv_layout(blueprints::straight_wire_gate_layout()); + check_parsing_equiv_layout(blueprints::three_wire_paths_gate_layout()); + // check_parsing_equiv_layout(blueprints::xor_maj_gate_layout()); + check_parsing_equiv_layout(blueprints::tautology_gate_layout()); + // check_parsing_equiv_layout(blueprints::and_or_gate_layout()); + // check_parsing_equiv_layout(blueprints::and_not_gate_layout()); check_parsing_equiv_layout(blueprints::or_not_gate_layout()); + check_parsing_equiv_layout(blueprints::use_and_gate_layout()); + check_parsing_equiv_layout(blueprints::res_maj_gate_layout()); + check_parsing_equiv_layout(blueprints::res_tautology_gate_layout()); check_parsing_equiv_layout(blueprints::crossing_layout()); - check_parsing_equiv_layout(blueprints::tautology_gate_layout()); + // check_parsing_equiv_layout(blueprints::fanout_layout()); + // check_parsing_equiv_layout(blueprints::unbalanced_and_layout()); + // check_parsing_equiv_layout(blueprints::non_structural_all_function_gate_layout()); + check_parsing_equiv_layout(blueprints::shifted_cart_and_or_inv_gate_layout()); + check_parsing_equiv_layout(blueprints::row_clocked_and_xor_gate_layout()); + check_parsing_equiv_layout(blueprints::optimization_layout()); + check_parsing_equiv_layout(blueprints::optimization_layout_corner_case_outputs_1()); + check_parsing_equiv_layout(blueprints::optimization_layout_corner_case_outputs_2()); } TEST_CASE("Write empty gate_level layout", "[sqd]") diff --git a/test/utils/blueprints/layout_blueprints.hpp b/test/utils/blueprints/layout_blueprints.hpp index 61abe322b..42e1d63e5 100644 --- a/test/utils/blueprints/layout_blueprints.hpp +++ b/test/utils/blueprints/layout_blueprints.hpp @@ -190,6 +190,43 @@ GateLyt use_and_gate_layout() noexcept return layout; } +template +GateLyt res_maj_gate_layout() noexcept +{ + GateLyt layout{typename GateLyt::aspect_ratio{2, 2, 0}, fiction::res_clocking()}; + + const auto x1 = layout.create_pi("x1", {0, 1}); + const auto x2 = layout.create_pi("x2", {1, 0}); + const auto x3 = layout.create_pi("x3", {2, 1}); + + const auto maj = layout.create_maj(x1, x2, x3, {1, 1}); + + layout.create_po(maj, "f1", {1, 2}); + + return layout; +} + +template +GateLyt res_tautology_gate_layout() noexcept +{ + REQUIRE(mockturtle::has_create_node_v); + + GateLyt layout{typename GateLyt::aspect_ratio{2, 2, 0}, fiction::res_clocking()}; + + const auto x1 = layout.create_pi("x1", {0, 1}); + const auto x2 = layout.create_pi("x2", {1, 0}); + const auto x3 = layout.create_pi("x3", {2, 1}); + + kitty::dynamic_truth_table tt_t(3u); + kitty::create_from_hex_string(tt_t, "FF"); + + const auto n = layout.create_node({x1, x2, x3}, tt_t, {1, 1}); + + layout.create_po(n, "f1", {1, 2}); + + return layout; +} + template GateLyt crossing_layout() noexcept { From ffbe883eca8b9b6d81de2d94723f9637ed8a1cb8 Mon Sep 17 00:00:00 2001 From: Simon Hofmann Date: Mon, 2 Oct 2023 16:34:14 +0200 Subject: [PATCH 20/36] fix third batch of todos --- include/fiction/io/read_gate_level_layout.hpp | 165 ++++- .../fiction/io/write_gate_level_layout.hpp | 140 ++-- test/io/read_gate_level_layout.cpp | 636 +++++++++++++++++- test/io/write_gate_level_layout.cpp | 12 +- test/utils/blueprints/layout_blueprints.hpp | 32 + 5 files changed, 877 insertions(+), 108 deletions(-) diff --git a/include/fiction/io/read_gate_level_layout.hpp b/include/fiction/io/read_gate_level_layout.hpp index e8b7ed35f..bda28ffb0 100644 --- a/include/fiction/io/read_gate_level_layout.hpp +++ b/include/fiction/io/read_gate_level_layout.hpp @@ -87,26 +87,6 @@ class read_gate_level_layout_impl set_name(lyt, layout_name); } - // set clocking scheme - auto* const clocking = layout->FirstChildElement("clocking"); - if (clocking != nullptr) - { - const auto clocking_scheme = get_clocking_scheme(clocking->GetText()); - if (clocking_scheme.has_value()) - { - lyt.replace_clocking_scheme(*clocking_scheme); - } - else - { - throw gate_level_parsing_error("Error parsing gate_level file: unknown clocking scheme: " + - std::string(clocking->GetText())); - } - } - else - { - throw gate_level_parsing_error("Error parsing gate_level file: no element 'clocking'"); - } - // set layout size auto* const size = layout->FirstChildElement("size"); if (size != nullptr) @@ -152,6 +132,90 @@ class read_gate_level_layout_impl throw gate_level_parsing_error("Error parsing gate_level file: no element 'size'"); } + // set clocking scheme + auto* const clocking = layout->FirstChildElement("clocking"); + if (clocking != nullptr) + { + auto* const clocking_scheme_name = clocking->FirstChildElement("name"); + if (clocking_scheme_name != nullptr and clocking_scheme_name->GetText()) + { + const auto clocking_scheme = get_clocking_scheme(clocking_scheme_name->GetText()); + if (clocking_scheme.has_value()) + { + if (strcmp(clocking_scheme_name->GetText(), "OPEN") == 0) + { + auto* const clock_zones = clocking->FirstChildElement("zones"); + if (clock_zones != nullptr) + { + for (const auto* clock_zone = clock_zones->FirstChildElement("zone"); clock_zone != nullptr; + clock_zone = clock_zone->NextSiblingElement("zone")) + { + auto* const clocking_zone_x = clock_zone->FirstChildElement("x"); + int x_coord = 0; + if (clocking_zone_x != nullptr and clocking_zone_x->GetText()) + { + x_coord = std::stoi(clocking_zone_x->GetText()); + } + else + { + throw gate_level_parsing_error( + "Error parsing gate_level file: no element 'x' in 'zone'"); + } + + auto* const clocking_zone_y = clock_zone->FirstChildElement("y"); + int y_coord = 0; + if (clocking_zone_y != nullptr and clocking_zone_y->GetText()) + { + y_coord = std::stoi(clocking_zone_y->GetText()); + } + else + { + throw gate_level_parsing_error( + "Error parsing gate_level file: no element 'y' in 'zone'"); + } + + auto* const clocking_zone_clock = clock_zone->FirstChildElement("clock"); + uint8_t clock = 0; + if (clocking_zone_clock != nullptr and clocking_zone_clock->GetText()) + { + clock = static_cast(*clocking_zone_clock->GetText()); + } + else + { + throw gate_level_parsing_error( + "Error parsing gate_level file: no element 'clock' in 'zone'"); + } + + lyt.assign_clock_number({x_coord, y_coord}, clock); + } + } + else + { + throw gate_level_parsing_error( + "Error parsing gate_level file: no element 'zones' in 'clocking'"); + } + } + else + { + lyt.replace_clocking_scheme(*clocking_scheme); + } + } + else + { + throw gate_level_parsing_error("Error parsing gate_level file: unknown clocking scheme: " + + std::string(clocking_scheme_name->GetText())); + } + } + else + { + throw gate_level_parsing_error("Error parsing gate_level file: no element 'name' in 'clocking'"); + } + } + else + { + throw gate_level_parsing_error("Error parsing gate_level file: no element 'clocking'"); + } + // parse layout gates std::vector gates{}; auto* const gates_xml = fcn_root->FirstChildElement("gates"); @@ -243,6 +307,7 @@ class read_gate_level_layout_impl { tile incoming_signal{}; + // get x-coordinate of incoming signal auto* const incoming_signal_x = signal->FirstChildElement("x"); if (incoming_signal_x != nullptr and incoming_signal_x->GetText()) { @@ -253,6 +318,7 @@ class read_gate_level_layout_impl throw gate_level_parsing_error("Error parsing gate_level file: no element 'x' in 'signal'"); } + // get y-coordinate of incoming signal auto* const incoming_signal_y = signal->FirstChildElement("y"); if (incoming_signal_y != nullptr and incoming_signal_y->GetText()) { @@ -263,6 +329,7 @@ class read_gate_level_layout_impl throw gate_level_parsing_error("Error parsing gate_level file: no element 'y' in 'signal'"); } + // get z-coordinate of incoming signal auto* const incoming_signal_z = signal->FirstChildElement("z"); if (incoming_signal_z != nullptr and incoming_signal_z->GetText()) { @@ -287,9 +354,17 @@ class read_gate_level_layout_impl { const tile location{gate.loc.x, gate.loc.y, gate.loc.z}; - if (gate.type == "PI") + if (gate.incoming.size() == 0) { - lyt.create_pi(gate.name, location); + if (gate.type == "PI") + { + lyt.create_pi(gate.name, location); + } + else + { + throw gate_level_parsing_error("Error parsing gate_level file: unknown gate type: " + + std::string(gate.type)); + } } else if (gate.incoming.size() == 1) @@ -359,12 +434,17 @@ class read_gate_level_layout_impl { lyt.create_xnor(incoming_signal_1, incoming_signal_2, location); } - else + else if (std::all_of(gate.type.begin(), gate.type.end(), ::isxdigit)) { kitty::dynamic_truth_table tt_t(2u); - kitty::create_from_binary_string(tt_t, gate.type); + kitty::create_from_hex_string(tt_t, gate.type); lyt.create_node({incoming_signal_1, incoming_signal_2}, tt_t, location); } + else + { + throw gate_level_parsing_error("Error parsing gate_level file: unknown gate type: " + + std::string(gate.type)); + } } else if (gate.incoming.size() == 3) { @@ -382,17 +462,36 @@ class read_gate_level_layout_impl { lyt.create_maj(incoming_signal_1, incoming_signal_2, incoming_signal_3, location); } - else + else if (std::all_of(gate.type.begin(), gate.type.end(), ::isxdigit)) { kitty::dynamic_truth_table tt_t(3u); - kitty::create_from_binary_string(tt_t, gate.type); + kitty::create_from_hex_string(tt_t, gate.type); lyt.create_node({incoming_signal_1, incoming_signal_2, incoming_signal_3}, tt_t, location); } + else + { + throw gate_level_parsing_error("Error parsing gate_level file: unknown gate type: " + + std::string(gate.type)); + } + } + else if (std::all_of(gate.type.begin(), gate.type.end(), ::isxdigit)) + { + auto num_incoming_signals = static_cast(gate.incoming.size()); + std::vector> incoming_signals{}; + for (uint32_t i = 0; i < num_incoming_signals; i++) + { + tile incoming_tile_i{gate.incoming[i].x, gate.incoming[i].y, gate.incoming[i].z}; + auto incoming_signal_i = lyt.make_signal(lyt.get_node(incoming_tile_i)); + incoming_signals.push_back(incoming_signal_i); + } + kitty::dynamic_truth_table tt_t(num_incoming_signals); + kitty::create_from_hex_string(tt_t, gate.type); + lyt.create_node({incoming_signals}, tt_t, location); } else { - throw gate_level_parsing_error( - "Error parsing gate_level file: gate has more than 3 incoming signals"); + throw gate_level_parsing_error("Error parsing gate_level file: unknown gate type: " + + std::string(gate.type)); } } } @@ -467,6 +566,11 @@ class read_gate_level_layout_impl template [[nodiscard]] Lyt read_gate_level_layout(std::istream& is, const std::string_view& name = "") { + static_assert(is_coordinate_layout_v, "Lyt is not a coordinate layout"); + static_assert(is_tile_based_layout_v, "Lyt is not a tile-based layout"); + static_assert(is_clocked_layout_v, "Lyt is not a clocked layout"); + static_assert(is_gate_level_layout_v, "Lyt is not a gate-level layout"); + detail::read_gate_level_layout_impl p{is, name}; const auto lyt = p.run(); @@ -488,6 +592,11 @@ template template void read_gate_level_layout(Lyt& lyt, std::istream& is) { + static_assert(is_coordinate_layout_v, "Lyt is not a coordinate layout"); + static_assert(is_tile_based_layout_v, "Lyt is not a tile-based layout"); + static_assert(is_clocked_layout_v, "Lyt is not a clocked layout"); + static_assert(is_gate_level_layout_v, "Lyt is not a gate-level layout"); + detail::read_gate_level_layout_impl p{lyt, is}; lyt = p.run(); diff --git a/include/fiction/io/write_gate_level_layout.hpp b/include/fiction/io/write_gate_level_layout.hpp index 6ca6271bf..186768659 100644 --- a/include/fiction/io/write_gate_level_layout.hpp +++ b/include/fiction/io/write_gate_level_layout.hpp @@ -43,35 +43,45 @@ inline constexpr const char* FICTION_METADATA = " \n" " {}\n" " \n"; -inline constexpr const char* LAYOUT_METADATA = " \n" - " {}\n" - " {}\n" - " {}\n" - " \n" - " {}\n" - " {}\n" - " {}\n" - " \n" - " \n"; -inline constexpr const char* OPEN_GATES = " \n"; -inline constexpr const char* CLOSE_GATES = " \n"; -inline constexpr const char* OPEN_GATE = " \n"; -inline constexpr const char* CLOSE_GATE = " \n"; -inline constexpr const char* GATE = " {}\n" - " {}\n" - " {}\n" - " \n" - " {}\n" - " {}\n" - " {}\n" - " \n"; -inline constexpr const char* OPEN_INCOMING = " \n"; -inline constexpr const char* CLOSE_INCOMING = " \n"; -inline constexpr const char* SIGNAL = " \n" - " {}\n" - " {}\n" - " {}\n" - " \n"; +inline constexpr const char* OPEN_LAYOUT_METADATA = " \n"; +inline constexpr const char* CLOSE_LAYOUT_METADATA = " \n"; +inline constexpr const char* LAYOUT_METADATA = " {}\n" + " {}\n" + " \n" + " {}\n" + " {}\n" + " {}\n" + " \n"; +inline constexpr const char* OPEN_CLOCKING = " \n"; +inline constexpr const char* CLOSE_CLOCKING = " \n"; +inline constexpr const char* CLOCKING_SCHEME_NAME = " {}\n"; +inline constexpr const char* OPEN_CLOCK_ZONES = " \n"; +inline constexpr const char* CLOSE_CLOCK_ZONES = " \n"; +inline constexpr const char* CLOCK_ZONE = " \n" + " {}\n" + " {}\n" + " {}\n" + " \n"; + +inline constexpr const char* OPEN_GATES = " \n"; +inline constexpr const char* CLOSE_GATES = " \n"; +inline constexpr const char* OPEN_GATE = " \n"; +inline constexpr const char* CLOSE_GATE = " \n"; +inline constexpr const char* GATE = " {}\n" + " {}\n" + " {}\n" + " \n" + " {}\n" + " {}\n" + " {}\n" + " \n"; +inline constexpr const char* OPEN_INCOMING = " \n"; +inline constexpr const char* CLOSE_INCOMING = " \n"; +inline constexpr const char* SIGNAL = " \n" + " {}\n" + " {}\n" + " {}\n" + " \n"; } // namespace fcn @@ -86,28 +96,44 @@ class write_gate_level_layout_impl std::stringstream header{}; std::stringstream layout_metadata{}; + // metadata header << fcn::FCN_HEADER << fcn::OPEN_FCN; - const auto time_str = fmt::format("{:%Y-%m-%d %H:%M:%S}", fmt::localtime(std::time(nullptr))); - header << fmt::format(fcn::FICTION_METADATA, FICTION_VERSION, FICTION_REPO, time_str); + os << header.str(); + os << fcn::OPEN_LAYOUT_METADATA; std::string layout_name = get_name(lyt); + layout_metadata << fmt::format(fcn::LAYOUT_METADATA, layout_name, "Cartesian", lyt.x(), lyt.y(), lyt.z()); + os << layout_metadata.str(); - const auto clocking_scheme = lyt.get_clocking_scheme().name; - - layout_metadata << fmt::format(fcn::LAYOUT_METADATA, layout_name, "Cartesian", clocking_scheme, lyt.x(), - lyt.y(), lyt.z()); - - os << header.str(); + os << fcn::OPEN_CLOCKING; + const auto clocking_scheme = lyt.get_clocking_scheme(); + os << fmt::format(fcn::CLOCKING_SCHEME_NAME, clocking_scheme.name); - os << layout_metadata.str(); + if (clocking_scheme.name == "OPEN") + { + os << fcn::OPEN_CLOCK_ZONES; + for (uint64_t x = 0; x <= lyt.x(); ++x) + { + for (uint64_t y = 0; y <= lyt.y(); ++y) + { + int clock = clocking_scheme({x, y}); + os << fmt::format(fcn::CLOCK_ZONE, x, y, clock); + } + } + os << fcn::CLOSE_CLOCK_ZONES; + } + os << fcn::CLOSE_CLOCKING; + os << fcn::CLOSE_LAYOUT_METADATA; os << fcn::OPEN_GATES; + // create topological ordering mockturtle::topo_view layout_topo{lyt}; uint32_t id = 0; + // inputs layout_topo.foreach_pi( [&id, this](const auto& gate) { @@ -118,14 +144,14 @@ class write_gate_level_layout_impl id++; }); + // gates layout_topo.foreach_gate( [&id, this](const auto& gate) { + os << fcn::OPEN_GATE; const auto coord = lyt.get_tile(gate); if (const auto signals = lyt.incoming_data_flow(coord); signals.size() == 1) { - os << fcn::OPEN_GATE; - const auto signal = signals[0]; if (lyt.is_po(gate)) @@ -144,13 +170,9 @@ class write_gate_level_layout_impl os << fcn::OPEN_INCOMING; os << fmt::format(fcn::SIGNAL, signal.x, signal.y, signal.z); os << fcn::CLOSE_INCOMING; - os << fcn::CLOSE_GATE; - id++; } else if (signals.size() == 2) { - os << fcn::OPEN_GATE; - const auto signal_a = signals[0]; const auto signal_b = signals[1]; @@ -182,19 +204,15 @@ class write_gate_level_layout_impl { const auto node_fun = lyt.node_function(gate); - os << fmt::format(fcn::GATE, id, kitty::to_binary(node_fun), "", coord.x, coord.y, coord.z); + os << fmt::format(fcn::GATE, id, kitty::to_hex(node_fun), "", coord.x, coord.y, coord.z); } os << fcn::OPEN_INCOMING; os << fmt::format(fcn::SIGNAL, signal_a.x, signal_a.y, signal_a.z); os << fmt::format(fcn::SIGNAL, signal_b.x, signal_b.y, signal_b.z); os << fcn::CLOSE_INCOMING; - os << fcn::CLOSE_GATE; - id++; } else if (signals.size() == 3) { - os << fcn::OPEN_GATE; - const auto signal_a = signals[0]; const auto signal_b = signals[1]; const auto signal_c = signals[2]; @@ -207,16 +225,29 @@ class write_gate_level_layout_impl { const auto node_fun = lyt.node_function(gate); - os << fmt::format(fcn::GATE, id, kitty::to_binary(node_fun), "", coord.x, coord.y, coord.z); + os << fmt::format(fcn::GATE, id, kitty::to_hex(node_fun), "", coord.x, coord.y, coord.z); } os << fcn::OPEN_INCOMING; os << fmt::format(fcn::SIGNAL, signal_a.x, signal_a.y, signal_a.z); os << fmt::format(fcn::SIGNAL, signal_b.x, signal_b.y, signal_b.z); os << fmt::format(fcn::SIGNAL, signal_c.x, signal_c.y, signal_c.z); os << fcn::CLOSE_INCOMING; - os << fcn::CLOSE_GATE; - id++; } + else if (lyt.is_function(gate)) + { + const auto node_fun = lyt.node_function(gate); + + os << fmt::format(fcn::GATE, id, kitty::to_hex(node_fun), "", coord.x, coord.y, coord.z); + + os << fcn::OPEN_INCOMING; + for (uint i = 0; i <= signals.size(); i++) + { + os << fmt::format(fcn::SIGNAL, signals[i].x, signals[i].y, signals[i].z); + } + os << fcn::CLOSE_INCOMING; + } + os << fcn::CLOSE_GATE; + id++; }); os << fcn::CLOSE_GATES; @@ -248,6 +279,11 @@ class write_gate_level_layout_impl template void write_gate_level_layout(const Lyt& lyt, std::ostream& os) { + static_assert(is_coordinate_layout_v, "Lyt is not a coordinate layout"); + static_assert(is_tile_based_layout_v, "Lyt is not a tile-based layout"); + static_assert(is_clocked_layout_v, "Lyt is not a clocked layout"); + static_assert(is_gate_level_layout_v, "Lyt is not a gate-level layout"); + detail::write_gate_level_layout_impl p{lyt, os}; p.run(); diff --git a/test/io/read_gate_level_layout.cpp b/test/io/read_gate_level_layout.cpp index 29e89e786..8acaf7d3f 100644 --- a/test/io/read_gate_level_layout.cpp +++ b/test/io/read_gate_level_layout.cpp @@ -26,12 +26,14 @@ TEST_CASE("Read empty FCN layout", "[fcn]") " \n" " Test\n" " cartesian\n" - " 2DDWave\n" " \n" " 0\n" " 0\n" " 0\n" " \n" + " \n" + " 2DDWave\n" + " \n" " \n" "\n"; @@ -57,12 +59,14 @@ TEST_CASE("Read simple FCN layout", "[fcn]") " \n" " Test\n" " cartesian\n" - " 2DDWave\n" " \n" " 2\n" " 1\n" " 0\n" " \n" + " \n" + " 2DDWave\n" + " \n" " \n" " \n" " \n" @@ -155,7 +159,14 @@ TEST_CASE("Parsing error: malformed xml", "[fcn]") " \n" " Test\n" " cartesian\n" - " 2DDWave\n" + " \n" + " 0\n" + " 0\n" + " 0\n" + " \n" + " \n" + " 2DDWave\n" + " \n" " \n"; std::istringstream layout_stream{fcn_layout}; @@ -170,7 +181,14 @@ TEST_CASE("Parsing error: no root element 'fcn'", "[fcn]") " \n" " Test\n" " cartesian\n" - " 2DDWave\n" + " \n" + " 0\n" + " 0\n" + " 0\n" + " \n" + " \n" + " 2DDWave\n" + " \n" " \n"; std::istringstream layout_stream{fcn_layout}; @@ -185,7 +203,14 @@ TEST_CASE("Parsing error: no element 'layout' in 'fcn'", "[fcn]") "\n" " Test\n" " cartesian\n" - " 2DDWave\n" + " \n" + " 0\n" + " 0\n" + " 0\n" + " \n" + " \n" + " 2DDWave\n" + " \n" "\n"; std::istringstream layout_stream{fcn_layout}; @@ -201,6 +226,34 @@ TEST_CASE("Parsing error: no element 'clocking' in 'layout'", "[fcn]") " \n" " Test\n" " cartesian\n" + " \n" + " 0\n" + " 0\n" + " 0\n" + " \n" + " \n" + "\n"; + + std::istringstream layout_stream{fcn_layout}; + + using gate_layout = gate_level_layout>>>; + CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); +} + +TEST_CASE("Parsing error: no element 'name' in 'clocking'", "[fcn]") +{ + static constexpr const char* fcn_layout = "\n" + "\n" + " \n" + " Test\n" + " cartesian\n" + " \n" + " 0\n" + " 0\n" + " 0\n" + " \n" + " \n" + " \n" " \n" "\n"; @@ -217,7 +270,128 @@ TEST_CASE("Parsing error: unknown clocking scheme", "[fcn]") " \n" " Test\n" " cartesian\n" - " CoolClocking\n" + " \n" + " 0\n" + " 0\n" + " 0\n" + " \n" + " \n" + " CoolClocking\n" + " \n" + " \n" + "\n"; + + std::istringstream layout_stream{fcn_layout}; + + using gate_layout = gate_level_layout>>>; + CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); +} + +TEST_CASE("Parsing error: no element 'zones' in 'clocking'", "[fcn]") +{ + static constexpr const char* fcn_layout = "\n" + "\n" + " \n" + " Test\n" + " cartesian\n" + " \n" + " 0\n" + " 0\n" + " 0\n" + " \n" + " \n" + " OPEN\n" + " \n" + " \n" + "\n"; + + std::istringstream layout_stream{fcn_layout}; + + using gate_layout = gate_level_layout>>>; + CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); +} + +TEST_CASE("Parsing error: no element 'x' in 'zone'", "[fcn]") +{ + static constexpr const char* fcn_layout = "\n" + "\n" + " \n" + " Test\n" + " cartesian\n" + " \n" + " 0\n" + " 0\n" + " 0\n" + " \n" + " \n" + " OPEN\n" + " \n" + " \n" + " 0\n" + " 0\n" + " \n" + " \n" + " \n" + " \n" + "\n"; + + std::istringstream layout_stream{fcn_layout}; + + using gate_layout = gate_level_layout>>>; + CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); +} + +TEST_CASE("Parsing error: no element 'y' in 'zone'", "[fcn]") +{ + static constexpr const char* fcn_layout = "\n" + "\n" + " \n" + " Test\n" + " cartesian\n" + " \n" + " 0\n" + " 0\n" + " 0\n" + " \n" + " \n" + " OPEN\n" + " \n" + " \n" + " 0\n" + " 0\n" + " \n" + " \n" + " \n" + " \n" + "\n"; + + std::istringstream layout_stream{fcn_layout}; + + using gate_layout = gate_level_layout>>>; + CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); +} + +TEST_CASE("Parsing error: no element 'clock' in 'zone'", "[fcn]") +{ + static constexpr const char* fcn_layout = "\n" + "\n" + " \n" + " Test\n" + " cartesian\n" + " \n" + " 0\n" + " 0\n" + " 0\n" + " \n" + " \n" + " OPEN\n" + " \n" + " \n" + " 0\n" + " 0\n" + " \n" + " \n" + " \n" " \n" "\n"; @@ -234,10 +408,12 @@ TEST_CASE("Parsing error: no element 'size' in 'layout'", "[fcn]") " \n" " Test\n" " cartesian\n" - " 2DDWave\n" " 2\n" " 1\n" " 0\n" + " \n" + " 2DDWave\n" + " \n" " \n" "\n"; @@ -254,11 +430,13 @@ TEST_CASE("Parsing error: no element 'x' in 'size'", "[fcn]") " \n" " Test\n" " cartesian\n" - " 2DDWave\n" " \n" " 1\n" " 0\n" " \n" + " \n" + " 2DDWave\n" + " \n" " \n" "\n"; @@ -275,11 +453,13 @@ TEST_CASE("Parsing error: no element 'y' in 'size'", "[fcn]") " \n" " Test\n" " cartesian\n" - " 2DDWave\n" " \n" " 2\n" " 0\n" " \n" + " \n" + " 2DDWave\n" + " \n" " \n" "\n"; @@ -296,11 +476,13 @@ TEST_CASE("Parsing error: no element 'z' in 'size'", "[fcn]") " \n" " Test\n" " cartesian\n" - " 2DDWave\n" " \n" " 2\n" " 1\n" " \n" + " \n" + " 2DDWave\n" + " \n" " \n" "\n"; @@ -317,12 +499,14 @@ TEST_CASE("Parsing error: no element 'id' in 'gate", "[fcn]") " \n" " Test\n" " cartesian\n" - " 2DDWave\n" " \n" " 2\n" " 1\n" " 0\n" " \n" + " \n" + " 2DDWave\n" + " \n" " \n" " \n" " \n" @@ -350,12 +534,14 @@ TEST_CASE("Parsing error: no element 'type' in 'gate", "[fcn]") " \n" " Test\n" " cartesian\n" - " 2DDWave\n" " \n" " 2\n" " 1\n" " 0\n" " \n" + " \n" + " 2DDWave\n" + " \n" " \n" " \n" " \n" @@ -383,12 +569,14 @@ TEST_CASE("Parsing error: no element 'name' in 'gate", "[fcn]") " \n" " Test\n" " cartesian\n" - " 2DDWave\n" " \n" " 2\n" " 1\n" " 0\n" " \n" + " \n" + " 2DDWave\n" + " \n" " \n" " \n" " \n" @@ -416,12 +604,14 @@ TEST_CASE("Parsing error: no element 'loc' in 'gate'", "[fcn]") " \n" " Test\n" " cartesian\n" - " 2DDWave\n" " \n" " 2\n" " 1\n" " 0\n" " \n" + " \n" + " 2DDWave\n" + " \n" " \n" " \n" " \n" @@ -448,12 +638,14 @@ TEST_CASE("Parsing error: no element 'x' in 'loc'", "[fcn]") " \n" " Test\n" " cartesian\n" - " 2DDWave\n" " \n" " 2\n" " 1\n" " 0\n" " \n" + " \n" + " 2DDWave\n" + " \n" " \n" " \n" " \n" @@ -481,12 +673,14 @@ TEST_CASE("Parsing error: no element 'y' in 'loc'", "[fcn]") " \n" " Test\n" " cartesian\n" - " 2DDWave\n" " \n" " 2\n" " 1\n" " 0\n" " \n" + " \n" + " 2DDWave\n" + " \n" " \n" " \n" " \n" @@ -514,12 +708,14 @@ TEST_CASE("Parsing error: no element 'z' in 'loc'", "[fcn]") " \n" " Test\n" " cartesian\n" - " 2DDWave\n" " \n" " 2\n" " 1\n" " 0\n" " \n" + " \n" + " 2DDWave\n" + " \n" " \n" " \n" " \n" @@ -540,19 +736,104 @@ TEST_CASE("Parsing error: no element 'z' in 'loc'", "[fcn]") CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } -TEST_CASE("Parsing error: unknown gate type", "[fcn]") +TEST_CASE("Parsing error: unknown gate type with 0 incoming signals", "[fcn]") { static constexpr const char* fcn_layout = "\n" "\n" " \n" " Test\n" " cartesian\n" - " 2DDWave\n" " \n" " 2\n" " 1\n" " 0\n" " \n" + " \n" + " 2DDWave\n" + " \n" + " \n" + " \n" + " \n" + " 0\n" + " unknown\n" + " pi0\n" + " \n" + " 0\n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" + " 1\n" + " PI\n" + " pi1\n" + " \n" + " 1\n" + " 0\n" + " 0\n" + " \n" + " \n" + " \n" + " 2\n" + " AND\n" + " \n" + " 1\n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" + " 0\n" + " 1\n" + " 0\n" + " \n" + " \n" + " 1\n" + " 0\n" + " 0\n" + " \n" + " \n" + " \n" + " \n" + " 3\n" + " PO\n" + " \n" + " 2\n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" + " 1\n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" + " \n" + "\n"; + + std::istringstream layout_stream{fcn_layout}; + + using gate_layout = gate_level_layout>>>; + CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); +} + +TEST_CASE("Parsing error: unknown gate type with 1 incoming signal", "[fcn]") +{ + static constexpr const char* fcn_layout = "\n" + "\n" + " \n" + " Test\n" + " cartesian\n" + " \n" + " 2\n" + " 1\n" + " 0\n" + " \n" + " \n" + " 2DDWave\n" + " \n" " \n" " \n" " \n" @@ -621,6 +902,311 @@ TEST_CASE("Parsing error: unknown gate type", "[fcn]") CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } +TEST_CASE("Parsing error: unknown gate type with 2 incoming signals", "[fcn]") +{ + static constexpr const char* fcn_layout = "\n" + "\n" + " \n" + " Test\n" + " cartesian\n" + " \n" + " 2\n" + " 1\n" + " 0\n" + " \n" + " \n" + " 2DDWave\n" + " \n" + " \n" + " \n" + " \n" + " 0\n" + " PI\n" + " pi0\n" + " \n" + " 0\n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" + " 1\n" + " PI\n" + " pi1\n" + " \n" + " 1\n" + " 0\n" + " 0\n" + " \n" + " \n" + " \n" + " 2\n" + " unknown\n" + " \n" + " 1\n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" + " 0\n" + " 1\n" + " 0\n" + " \n" + " \n" + " 1\n" + " 0\n" + " 0\n" + " \n" + " \n" + " \n" + " \n" + " 3\n" + " PO\n" + " \n" + " 2\n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" + " 1\n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" + " \n" + "\n"; + + std::istringstream layout_stream{fcn_layout}; + + using gate_layout = gate_level_layout>>>; + CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); +} + +TEST_CASE("Parsing error: unknown gate type with 3 incoming signals", "[fcn]") +{ + static constexpr const char* fcn_layout = "\n" + "\n" + " \n" + " Test\n" + " cartesian\n" + " \n" + " 2\n" + " 2\n" + " 0\n" + " \n" + " \n" + " RES\n" + " \n" + " \n" + " \n" + " \n" + " 0\n" + " PI\n" + " pi0\n" + " \n" + " 0\n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" + " 1\n" + " PI\n" + " pi1\n" + " \n" + " 1\n" + " 0\n" + " 0\n" + " \n" + " \n" + " \n" + " 2\n" + " PI\n" + " pi2\n" + " \n" + " 2\n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" + " 3\n" + " unknown\n" + " \n" + " 1\n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" + " 0\n" + " 1\n" + " 0\n" + " \n" + " \n" + " 1\n" + " 0\n" + " 0\n" + " \n" + " \n" + " 2\n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" + " \n" + " 4\n" + " PO\n" + " \n" + " 1\n" + " 2\n" + " 0\n" + " \n" + " \n" + " \n" + " 1\n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" + " \n" + "\n"; + + std::istringstream layout_stream{fcn_layout}; + + using gate_layout = gate_level_layout>>>; + CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); +} + +TEST_CASE("Parsing error: unknown gate type with more than 3 incoming signals", "[fcn]") +{ + static constexpr const char* fcn_layout = "\n" + "\n" + " \n" + " Test\n" + " cartesian\n" + " \n" + " 2\n" + " 2\n" + " 0\n" + " \n" + " \n" + " OPEN\n" + " \n" + " \n" + " 0\n" + " 1\n" + " 0\n" + " \n" + " \n" + " 1\n" + " 0\n" + " 0\n" + " \n" + " \n" + " 2\n" + " 1\n" + " 0\n" + " \n" + " \n" + " 1\n" + " 2\n" + " 0\n" + " \n" + " \n" + " 1\n" + " 1\n" + " 1\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " 0\n" + " PI\n" + " pi0\n" + " \n" + " 0\n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" + " 1\n" + " PI\n" + " pi1\n" + " \n" + " 1\n" + " 0\n" + " 0\n" + " \n" + " \n" + " \n" + " 2\n" + " PI\n" + " pi2\n" + " \n" + " 2\n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" + " 3\n" + " PI\n" + " pi3\n" + " \n" + " 1\n" + " 2\n" + " 0\n" + " \n" + " \n" + " \n" + " 4\n" + " unknown\n" + " \n" + " 1\n" + " 1\n" + " 0\n" + " \n" + " \n" + " \n" + " 0\n" + " 1\n" + " 0\n" + " \n" + " \n" + " 1\n" + " 0\n" + " 0\n" + " \n" + " \n" + " 2\n" + " 1\n" + " 0\n" + " \n" + " \n" + " 1\n" + " 2\n" + " 0\n" + " \n" + " \n" + " \n" + " \n" + "\n"; + + std::istringstream layout_stream{fcn_layout}; + + using gate_layout = gate_level_layout>>>; + CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); +} + TEST_CASE("Parsing error: no element 'x' in 'signal'", "[fcn]") { static constexpr const char* fcn_layout = "\n" @@ -628,12 +1214,14 @@ TEST_CASE("Parsing error: no element 'x' in 'signal'", "[fcn]") " \n" " Test\n" " cartesian\n" - " 2DDWave\n" " \n" " 2\n" " 1\n" " 0\n" " \n" + " \n" + " 2DDWave\n" + " \n" " \n" " \n" " \n" @@ -709,12 +1297,14 @@ TEST_CASE("Parsing error: no element 'y' in 'signal'", "[fcn]") " \n" " Test\n" " cartesian\n" - " 2DDWave\n" " \n" " 2\n" " 1\n" " 0\n" " \n" + " \n" + " 2DDWave\n" + " \n" " \n" " \n" " \n" @@ -790,12 +1380,14 @@ TEST_CASE("Parsing error: no element 'z' in 'signal'", "[fcn]") " \n" " Test\n" " cartesian\n" - " 2DDWave\n" " \n" " 2\n" " 1\n" " 0\n" " \n" + " \n" + " 2DDWave\n" + " \n" " \n" " \n" " \n" diff --git a/test/io/write_gate_level_layout.cpp b/test/io/write_gate_level_layout.cpp index 658571f0b..1bfc85bae 100644 --- a/test/io/write_gate_level_layout.cpp +++ b/test/io/write_gate_level_layout.cpp @@ -99,18 +99,18 @@ void check_parsing_equiv_all() check_parsing_equiv(blueprints::nand_xnor_network()); check_parsing_equiv_layout(blueprints::straight_wire_gate_layout()); check_parsing_equiv_layout(blueprints::three_wire_paths_gate_layout()); - // check_parsing_equiv_layout(blueprints::xor_maj_gate_layout()); + check_parsing_equiv_layout(blueprints::xor_maj_gate_layout()); check_parsing_equiv_layout(blueprints::tautology_gate_layout()); - // check_parsing_equiv_layout(blueprints::and_or_gate_layout()); - // check_parsing_equiv_layout(blueprints::and_not_gate_layout()); + check_parsing_equiv_layout(blueprints::and_or_gate_layout()); + check_parsing_equiv_layout(blueprints::and_not_gate_layout()); check_parsing_equiv_layout(blueprints::or_not_gate_layout()); check_parsing_equiv_layout(blueprints::use_and_gate_layout()); check_parsing_equiv_layout(blueprints::res_maj_gate_layout()); check_parsing_equiv_layout(blueprints::res_tautology_gate_layout()); + // check_parsing_equiv_layout(blueprints::open_tautology_gate_layout()); check_parsing_equiv_layout(blueprints::crossing_layout()); - // check_parsing_equiv_layout(blueprints::fanout_layout()); - // check_parsing_equiv_layout(blueprints::unbalanced_and_layout()); - // check_parsing_equiv_layout(blueprints::non_structural_all_function_gate_layout()); + check_parsing_equiv_layout(blueprints::fanout_layout()); + check_parsing_equiv_layout(blueprints::unbalanced_and_layout()); check_parsing_equiv_layout(blueprints::shifted_cart_and_or_inv_gate_layout()); check_parsing_equiv_layout(blueprints::row_clocked_and_xor_gate_layout()); check_parsing_equiv_layout(blueprints::optimization_layout()); diff --git a/test/utils/blueprints/layout_blueprints.hpp b/test/utils/blueprints/layout_blueprints.hpp index 42e1d63e5..d4332a2f8 100644 --- a/test/utils/blueprints/layout_blueprints.hpp +++ b/test/utils/blueprints/layout_blueprints.hpp @@ -227,6 +227,38 @@ GateLyt res_tautology_gate_layout() noexcept return layout; } +template +GateLyt open_tautology_gate_layout() noexcept +{ + REQUIRE(mockturtle::has_create_node_v); + + GateLyt layout{typename GateLyt::aspect_ratio{2, 2, 0}, fiction::open_clocking()}; + + layout.assign_clock_number({0, 0}, static_cast(0)); + layout.assign_clock_number({1, 0}, static_cast(0)); + layout.assign_clock_number({2, 0}, static_cast(0)); + + layout.assign_clock_number({0, 1}, static_cast(0)); + layout.assign_clock_number({1, 1}, static_cast(1)); + layout.assign_clock_number({2, 1}, static_cast(0)); + + layout.assign_clock_number({0, 2}, static_cast(0)); + layout.assign_clock_number({1, 2}, static_cast(0)); + layout.assign_clock_number({2, 2}, static_cast(0)); + + const auto x1 = layout.create_pi("x1", {0, 1}); + const auto x2 = layout.create_pi("x2", {1, 0}); + const auto x3 = layout.create_pi("x3", {2, 1}); + const auto x4 = layout.create_pi("x4", {1, 2}); + + kitty::dynamic_truth_table tt_t(4u); + kitty::create_from_hex_string(tt_t, "FFF"); + + layout.create_node({x1, x2, x3, x4}, tt_t, {1, 1}); + + return layout; +} + template GateLyt crossing_layout() noexcept { From 16311bdb150fb30973fb4f5be567e332a34d867c Mon Sep 17 00:00:00 2001 From: Simon Hofmann Date: Mon, 2 Oct 2023 17:13:51 +0200 Subject: [PATCH 21/36] small fix --- include/fiction/io/read_gate_level_layout.hpp | 6 +++--- include/fiction/io/write_gate_level_layout.hpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/fiction/io/read_gate_level_layout.hpp b/include/fiction/io/read_gate_level_layout.hpp index bda28ffb0..9894bacd7 100644 --- a/include/fiction/io/read_gate_level_layout.hpp +++ b/include/fiction/io/read_gate_level_layout.hpp @@ -476,15 +476,15 @@ class read_gate_level_layout_impl } else if (std::all_of(gate.type.begin(), gate.type.end(), ::isxdigit)) { - auto num_incoming_signals = static_cast(gate.incoming.size()); + const auto num_incoming_signals = gate.incoming.size(); std::vector> incoming_signals{}; - for (uint32_t i = 0; i < num_incoming_signals; i++) + for (std::size_t i = 0; i < num_incoming_signals; i++) { tile incoming_tile_i{gate.incoming[i].x, gate.incoming[i].y, gate.incoming[i].z}; auto incoming_signal_i = lyt.make_signal(lyt.get_node(incoming_tile_i)); incoming_signals.push_back(incoming_signal_i); } - kitty::dynamic_truth_table tt_t(num_incoming_signals); + kitty::dynamic_truth_table tt_t(static_cast(num_incoming_signals)); kitty::create_from_hex_string(tt_t, gate.type); lyt.create_node({incoming_signals}, tt_t, location); } diff --git a/include/fiction/io/write_gate_level_layout.hpp b/include/fiction/io/write_gate_level_layout.hpp index 186768659..71a1eafb3 100644 --- a/include/fiction/io/write_gate_level_layout.hpp +++ b/include/fiction/io/write_gate_level_layout.hpp @@ -240,7 +240,7 @@ class write_gate_level_layout_impl os << fmt::format(fcn::GATE, id, kitty::to_hex(node_fun), "", coord.x, coord.y, coord.z); os << fcn::OPEN_INCOMING; - for (uint i = 0; i <= signals.size(); i++) + for (std::size_t i = 0; i <= signals.size(); i++) { os << fmt::format(fcn::SIGNAL, signals[i].x, signals[i].y, signals[i].z); } From b4fa61e0f598064a7d6e68aef6a27c33aec0aa24 Mon Sep 17 00:00:00 2001 From: Simon Hofmann Date: Mon, 2 Oct 2023 17:28:48 +0200 Subject: [PATCH 22/36] coverage --- include/fiction/io/write_gate_level_layout.hpp | 3 ++- test/io/read_gate_level_layout.cpp | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/include/fiction/io/write_gate_level_layout.hpp b/include/fiction/io/write_gate_level_layout.hpp index 71a1eafb3..155541a41 100644 --- a/include/fiction/io/write_gate_level_layout.hpp +++ b/include/fiction/io/write_gate_level_layout.hpp @@ -233,6 +233,7 @@ class write_gate_level_layout_impl os << fmt::format(fcn::SIGNAL, signal_c.x, signal_c.y, signal_c.z); os << fcn::CLOSE_INCOMING; } + /* else if (lyt.is_function(gate)) { const auto node_fun = lyt.node_function(gate); @@ -245,7 +246,7 @@ class write_gate_level_layout_impl os << fmt::format(fcn::SIGNAL, signals[i].x, signals[i].y, signals[i].z); } os << fcn::CLOSE_INCOMING; - } + }*/ os << fcn::CLOSE_GATE; id++; }); diff --git a/test/io/read_gate_level_layout.cpp b/test/io/read_gate_level_layout.cpp index 8acaf7d3f..d457d8308 100644 --- a/test/io/read_gate_level_layout.cpp +++ b/test/io/read_gate_level_layout.cpp @@ -797,6 +797,7 @@ TEST_CASE("Parsing error: unknown gate type with 0 incoming signals", "[fcn]") " \n" " 3\n" " PO\n" + " po0\n" " \n" " 2\n" " 1\n" @@ -963,6 +964,7 @@ TEST_CASE("Parsing error: unknown gate type with 2 incoming signals", "[fcn]") " \n" " 3\n" " PO\n" + " po0\n" " \n" " 2\n" " 1\n" @@ -1061,6 +1063,7 @@ TEST_CASE("Parsing error: unknown gate type with 3 incoming signals", "[fcn]") " \n" " 4\n" " PO\n" + " po0\n" " \n" " 1\n" " 2\n" From 369f468cad7bb05ed7e1ec9027b877e94ee0e572 Mon Sep 17 00:00:00 2001 From: Simon Date: Tue, 3 Oct 2023 12:05:01 +0200 Subject: [PATCH 23/36] increase coverage --- include/fiction/io/read_gate_level_layout.hpp | 2 +- .../fiction/io/write_gate_level_layout.hpp | 5 ++--- test/io/write_gate_level_layout.cpp | 2 +- test/utils/blueprints/layout_blueprints.hpp | 19 ++++++++----------- 4 files changed, 12 insertions(+), 16 deletions(-) diff --git a/include/fiction/io/read_gate_level_layout.hpp b/include/fiction/io/read_gate_level_layout.hpp index 9894bacd7..416ef782c 100644 --- a/include/fiction/io/read_gate_level_layout.hpp +++ b/include/fiction/io/read_gate_level_layout.hpp @@ -29,7 +29,7 @@ namespace fiction { /** - * Exception thrown when an error occurs during parsing of an gate_level file. + * Exception thrown when an error occurs during parsing of a gate_level file. */ class gate_level_parsing_error : public std::runtime_error { diff --git a/include/fiction/io/write_gate_level_layout.hpp b/include/fiction/io/write_gate_level_layout.hpp index 155541a41..a4d9a4171 100644 --- a/include/fiction/io/write_gate_level_layout.hpp +++ b/include/fiction/io/write_gate_level_layout.hpp @@ -233,7 +233,6 @@ class write_gate_level_layout_impl os << fmt::format(fcn::SIGNAL, signal_c.x, signal_c.y, signal_c.z); os << fcn::CLOSE_INCOMING; } - /* else if (lyt.is_function(gate)) { const auto node_fun = lyt.node_function(gate); @@ -241,12 +240,12 @@ class write_gate_level_layout_impl os << fmt::format(fcn::GATE, id, kitty::to_hex(node_fun), "", coord.x, coord.y, coord.z); os << fcn::OPEN_INCOMING; - for (std::size_t i = 0; i <= signals.size(); i++) + for (std::size_t i = 0; i < signals.size(); i++) { os << fmt::format(fcn::SIGNAL, signals[i].x, signals[i].y, signals[i].z); } os << fcn::CLOSE_INCOMING; - }*/ + } os << fcn::CLOSE_GATE; id++; }); diff --git a/test/io/write_gate_level_layout.cpp b/test/io/write_gate_level_layout.cpp index 1bfc85bae..94d6afbfa 100644 --- a/test/io/write_gate_level_layout.cpp +++ b/test/io/write_gate_level_layout.cpp @@ -107,7 +107,7 @@ void check_parsing_equiv_all() check_parsing_equiv_layout(blueprints::use_and_gate_layout()); check_parsing_equiv_layout(blueprints::res_maj_gate_layout()); check_parsing_equiv_layout(blueprints::res_tautology_gate_layout()); - // check_parsing_equiv_layout(blueprints::open_tautology_gate_layout()); + check_parsing_equiv_layout(blueprints::open_tautology_gate_layout()); check_parsing_equiv_layout(blueprints::crossing_layout()); check_parsing_equiv_layout(blueprints::fanout_layout()); check_parsing_equiv_layout(blueprints::unbalanced_and_layout()); diff --git a/test/utils/blueprints/layout_blueprints.hpp b/test/utils/blueprints/layout_blueprints.hpp index d4332a2f8..275fb3069 100644 --- a/test/utils/blueprints/layout_blueprints.hpp +++ b/test/utils/blueprints/layout_blueprints.hpp @@ -236,25 +236,22 @@ GateLyt open_tautology_gate_layout() noexcept layout.assign_clock_number({0, 0}, static_cast(0)); layout.assign_clock_number({1, 0}, static_cast(0)); - layout.assign_clock_number({2, 0}, static_cast(0)); - - layout.assign_clock_number({0, 1}, static_cast(0)); - layout.assign_clock_number({1, 1}, static_cast(1)); - layout.assign_clock_number({2, 1}, static_cast(0)); - layout.assign_clock_number({0, 2}, static_cast(0)); layout.assign_clock_number({1, 2}, static_cast(0)); - layout.assign_clock_number({2, 2}, static_cast(0)); + layout.assign_clock_number({1, 1}, static_cast(1)); + layout.assign_clock_number({2, 1}, static_cast(2)); - const auto x1 = layout.create_pi("x1", {0, 1}); + const auto x1 = layout.create_pi("x1", {0, 0}); const auto x2 = layout.create_pi("x2", {1, 0}); - const auto x3 = layout.create_pi("x3", {2, 1}); + const auto x3 = layout.create_pi("x3", {0, 2}); const auto x4 = layout.create_pi("x4", {1, 2}); kitty::dynamic_truth_table tt_t(4u); - kitty::create_from_hex_string(tt_t, "FFF"); + kitty::create_from_hex_string(tt_t, "FFFF"); + + const auto n = layout.create_node({x1, x2, x3, x4}, tt_t, {1, 1}); - layout.create_node({x1, x2, x3, x4}, tt_t, {1, 1}); + layout.create_po(n, "f1", {2, 1}); return layout; } From ffeabff255ef5045b9c677bd2078737e17f20693 Mon Sep 17 00:00:00 2001 From: Simon Date: Tue, 3 Oct 2023 12:12:45 +0200 Subject: [PATCH 24/36] typos --- include/fiction/io/read_gate_level_layout.hpp | 24 ++++++++----------- .../fiction/io/write_gate_level_layout.hpp | 6 ++--- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/include/fiction/io/read_gate_level_layout.hpp b/include/fiction/io/read_gate_level_layout.hpp index 416ef782c..b9213e1e6 100644 --- a/include/fiction/io/read_gate_level_layout.hpp +++ b/include/fiction/io/read_gate_level_layout.hpp @@ -554,10 +554,9 @@ class read_gate_level_layout_impl } // namespace detail /** - * Reads a gate-level layout from a gate_level file provided as an input stream. The format is used by fiction - * (https://github.com/cda-tum/fiction). + * Reads a gate-level layout from a gate_level file provided as an input stream. * - * May throw an `gate_level_parsing_exception` if the gate_level file is malformed. + * May throw a `gate_level_parsing_exception` if the gate_level file is malformed. * * @tparam Lyt The layout type to be created from an input. * @param is The input stream to read from. @@ -578,10 +577,9 @@ template return lyt; } /** - * Reads a gate-level layout from an gate_level file provided as an input stream. The format is used by fiction - * (https://github.com/cda-tum/fiction). + * Reads a gate-level layout from an gate_level file provided as an input stream. * - * May throw an `gate_level_parsing_exception` if the gate_level file is malformed. + * May throw a `gate_level_parsing_exception` if the gate_level file is malformed. * * This is an in-place version of read_gate_level_layout that utilizes the given layout as a target to write to. * @@ -602,10 +600,9 @@ void read_gate_level_layout(Lyt& lyt, std::istream& is) lyt = p.run(); } /** - * Reads a gate-level layout from a gate_level file provided as an input stream. The format is used by fiction - * (https://github.com/cda-tum/fiction). + * Reads a gate-level layout from a gate_level file provided as an input stream. * - * May throw an `gate_level_parsing_exception` if the gate_level file is malformed. + * May throw a `gate_level_parsing_exception` if the gate_level file is malformed. * * @tparam Lyt The layout type to be created from an input. * @param filename The file name to open and read from. @@ -627,14 +624,13 @@ template return lyt; } /** - * Reads a gate-level layout from an gate_level file provided as an input stream. The format is used by fiction - * (https://github.com/cda-tum/fiction). - - * May throw an `gate_level_parsing_exception` if the gate_level file is malformed. + * Reads a gate-level layout from an gate_level file provided as an input stream. + * + * May throw a `gate_level_parsing_exception` if the gate_level file is malformed. * * This is an in-place version of `read_gate_level_layout` that utilizes the given layout as a target to write to. * - * @tparam Lyt The layout type to be used as input. Must be a cell-level SiDB layout. + * @tparam Lyt The layout type to be used as input. * @param lyt The layout to write to. * @param filename The file name to open and read from. */ diff --git a/include/fiction/io/write_gate_level_layout.hpp b/include/fiction/io/write_gate_level_layout.hpp index a4d9a4171..5671fc1ed 100644 --- a/include/fiction/io/write_gate_level_layout.hpp +++ b/include/fiction/io/write_gate_level_layout.hpp @@ -268,7 +268,7 @@ class write_gate_level_layout_impl } // namespace detail /** - * Writes a gate-level layout to a fcn file that is used by Fiction (https://github.com/cda-tum/fiction). + * Writes a gate-level layout to a file. * * This overload uses an output stream to write into. * @@ -289,13 +289,13 @@ void write_gate_level_layout(const Lyt& lyt, std::ostream& os) p.run(); } /** - * Writes a gate-level layout to a fcn file that is used by Fiction (https://github.com/cda-tum/fiction). + * Writes a gate-level layout to a file. * * This overload uses a file name to create and write into. * * @tparam Lyt Layout. * @param lyt The layout to be written. - * @param filename The file name to create and write into. Should preferably use the `.fcn` extension. + * @param filename The file name to create and write into. */ template void write_gate_level_layout(const Lyt& lyt, const std::string_view& filename) From 400fb1f66cc66972ebbe03efd19c6aeea474014c Mon Sep 17 00:00:00 2001 From: Simon Hofmann Date: Wed, 4 Oct 2023 13:12:34 +0200 Subject: [PATCH 25/36] check topology --- include/fiction/io/read_gate_level_layout.hpp | 124 ++++++- .../fiction/io/write_gate_level_layout.hpp | 53 ++- test/io/read_gate_level_layout.cpp | 321 ++++++++++++++++++ test/io/write_gate_level_layout.cpp | 13 +- test/utils/blueprints/layout_blueprints.hpp | 59 ++-- 5 files changed, 544 insertions(+), 26 deletions(-) diff --git a/include/fiction/io/read_gate_level_layout.hpp b/include/fiction/io/read_gate_level_layout.hpp index b9213e1e6..5da5fb0a4 100644 --- a/include/fiction/io/read_gate_level_layout.hpp +++ b/include/fiction/io/read_gate_level_layout.hpp @@ -24,6 +24,7 @@ #include #include #include +#include namespace fiction { @@ -87,6 +88,118 @@ class read_gate_level_layout_impl set_name(lyt, layout_name); } + // check topology + auto* const topology = layout->FirstChildElement("topology"); + if (topology != nullptr && topology->GetText()) + { + const auto topology_name = topology->GetText(); + std::unordered_set shifted_cartesian{"odd_row_cartesian", "even_row_cartesian", + "odd_column_cartesian", "even_column_cartesian"}; + std::unordered_set hex{"odd_row_hex", "even_row_hex", "odd_column_hex", "even_column_hex"}; + + if (std::strcmp(topology_name, "cartesian") == 0) + { + if constexpr (!is_cartesian_layout_v) + { + throw gate_level_parsing_error("Error parsing gate_level file: Lyt is not a cartesian layout"); + } + } + else if (shifted_cartesian.find(topology_name) != shifted_cartesian.end()) + { + if constexpr (is_shifted_cartesian_layout_v) + { + if (std::strcmp(topology_name, "odd_row_cartesian") == 0) + { + if constexpr (!has_odd_row_cartesian_arrangement_v) + { + throw gate_level_parsing_error( + "Error parsing gate_level file: Lyt is not an odd_row_cartesian layout"); + } + } + else if (std::strcmp(topology_name, "even_row_cartesian") == 0) + { + if constexpr (!has_even_row_cartesian_arrangement_v) + { + throw gate_level_parsing_error( + "Error parsing gate_level file: Lyt is not an even_row_cartesian layout"); + } + } + else if (std::strcmp(topology_name, "odd_column_cartesian") == 0) + { + if constexpr (!has_odd_column_cartesian_arrangement_v) + { + throw gate_level_parsing_error( + "Error parsing gate_level file: Lyt is not an odd_column_cartesian layout"); + } + } + else if (std::strcmp(topology_name, "even_column_cartesian") == 0) + { + if constexpr (!has_even_column_cartesian_arrangement_v) + { + throw gate_level_parsing_error( + "Error parsing gate_level file: Lyt is not an even_column_cartesian layout"); + } + } + } + else + { + throw gate_level_parsing_error( + "Error parsing gate_level file: Lyt is not a shifted_cartesian layout"); + } + } + else if (hex.find(topology_name) != hex.end()) + { + if constexpr (is_hexagonal_layout_v) + { + if (std::strcmp(topology_name, "odd_row_hex") == 0) + { + if constexpr (!has_odd_row_hex_arrangement_v) + { + throw gate_level_parsing_error( + "Error parsing gate_level file: Lyt is not an odd_row_hex layout"); + } + } + else if (std::strcmp(topology_name, "even_row_hex") == 0) + { + if constexpr (!has_even_row_hex_arrangement_v) + { + throw gate_level_parsing_error( + "Error parsing gate_level file: Lyt is not an even_row_hex layout"); + } + } + else if (std::strcmp(topology_name, "odd_column_hex") == 0) + { + if constexpr (!has_odd_column_hex_arrangement_v) + { + throw gate_level_parsing_error( + "Error parsing gate_level file: Lyt is not an odd_column_hex layout"); + } + } + else if (std::strcmp(topology_name, "even_column_hex") == 0) + { + if constexpr (!has_even_column_hex_arrangement_v) + { + throw gate_level_parsing_error( + "Error parsing gate_level file: Lyt is not an even_column_hex layout"); + } + } + } + else + { + throw gate_level_parsing_error("Error parsing gate_level file: Lyt is not a hexagonal layout"); + } + } + else + { + throw gate_level_parsing_error("Error parsing gate_level file: unknown topology: " + + std::string(topology_name)); + } + } + else + { + throw gate_level_parsing_error("Error parsing gate_level file: no element 'topology' in 'layout'"); + } + // set layout size auto* const size = layout->FirstChildElement("size"); if (size != nullptr) @@ -129,7 +242,7 @@ class read_gate_level_layout_impl } else { - throw gate_level_parsing_error("Error parsing gate_level file: no element 'size'"); + throw gate_level_parsing_error("Error parsing gate_level file: no element 'size' in 'layout'"); } // set clocking scheme @@ -213,7 +326,7 @@ class read_gate_level_layout_impl } else { - throw gate_level_parsing_error("Error parsing gate_level file: no element 'clocking'"); + throw gate_level_parsing_error("Error parsing gate_level file: no element 'clocking' in 'layout'"); } // parse layout gates @@ -387,7 +500,12 @@ class read_gate_level_layout_impl { lyt.create_not(incoming_signal, location); } - + else if (std::all_of(gate.type.begin(), gate.type.end(), ::isxdigit)) + { + kitty::dynamic_truth_table tt_t(1u); + kitty::create_from_hex_string(tt_t, gate.type); + lyt.create_node({incoming_signal}, tt_t, location); + } else { throw gate_level_parsing_error("Error parsing gate_level file: unknown gate type: " + diff --git a/include/fiction/io/write_gate_level_layout.hpp b/include/fiction/io/write_gate_level_layout.hpp index 5671fc1ed..39b64b253 100644 --- a/include/fiction/io/write_gate_level_layout.hpp +++ b/include/fiction/io/write_gate_level_layout.hpp @@ -104,7 +104,52 @@ class write_gate_level_layout_impl os << fcn::OPEN_LAYOUT_METADATA; std::string layout_name = get_name(lyt); - layout_metadata << fmt::format(fcn::LAYOUT_METADATA, layout_name, "Cartesian", lyt.x(), lyt.y(), lyt.z()); + + std::string topology = ""; + if constexpr (is_cartesian_layout_v) + { + topology = "cartesian"; + } + else if constexpr (is_shifted_cartesian_layout_v) + { + if constexpr (has_odd_row_cartesian_arrangement_v) + { + topology = "odd_row_cartesian"; + } + else if constexpr (has_even_row_cartesian_arrangement_v) + { + topology = "even_row_cartesian"; + } + else if constexpr (has_odd_column_cartesian_arrangement_v) + { + topology = "odd_column_cartesian"; + } + else if constexpr (has_even_column_cartesian_arrangement_v) + { + topology = "even_column_cartesian"; + } + } + else if constexpr (is_hexagonal_layout_v) + { + if constexpr (has_odd_row_hex_arrangement_v) + { + topology = "odd_row_hex"; + } + else if constexpr (has_even_row_hex_arrangement_v) + { + topology = "even_row_hex"; + } + else if constexpr (has_odd_column_hex_arrangement_v) + { + topology = "odd_column_hex"; + } + else if constexpr (has_even_column_hex_arrangement_v) + { + topology = "even_column_hex"; + } + } + + layout_metadata << fmt::format(fcn::LAYOUT_METADATA, layout_name, topology, lyt.x(), lyt.y(), lyt.z()); os << layout_metadata.str(); os << fcn::OPEN_CLOCKING; @@ -166,6 +211,12 @@ class write_gate_level_layout_impl { os << fmt::format(fcn::GATE, id, "INV", "", coord.x, coord.y, coord.z); } + else if (lyt.is_function(gate)) + { + const auto node_fun = lyt.node_function(gate); + + os << fmt::format(fcn::GATE, id, kitty::to_hex(node_fun), "", coord.x, coord.y, coord.z); + } os << fcn::OPEN_INCOMING; os << fmt::format(fcn::SIGNAL, signal.x, signal.y, signal.z); diff --git a/test/io/read_gate_level_layout.cpp b/test/io/read_gate_level_layout.cpp index d457d8308..5ed0bb776 100644 --- a/test/io/read_gate_level_layout.cpp +++ b/test/io/read_gate_level_layout.cpp @@ -401,6 +401,327 @@ TEST_CASE("Parsing error: no element 'clock' in 'zone'", "[fcn]") CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } +TEST_CASE("Parsing error: no element 'topology' in 'layout'", "[fcn]") +{ + static constexpr const char* fcn_layout = "\n" + "\n" + " \n" + " Test\n" + " \n" + " 0\n" + " 0\n" + " 0\n" + " \n" + " \n" + " 2DDWave\n" + " \n" + " \n" + "\n"; + + std::istringstream layout_stream{fcn_layout}; + + using gate_layout = gate_level_layout>>>; + CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); +} + +TEST_CASE("Parsing error: unknown topology", "[fcn]") +{ + static constexpr const char* fcn_layout = "\n" + "\n" + " \n" + " Test\n" + " unknown\n" + " \n" + " 0\n" + " 0\n" + " 0\n" + " \n" + " \n" + " 2DDWave\n" + " \n" + " \n" + "\n"; + + std::istringstream layout_stream{fcn_layout}; + + using gate_layout = gate_level_layout>>>; + CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); +} + +TEST_CASE("Parsing error: Lyt is not a cartesian layout", "[fcn]") +{ + static constexpr const char* fcn_layout = "\n" + "\n" + " \n" + " Test\n" + " cartesian\n" + " \n" + " 0\n" + " 0\n" + " 0\n" + " \n" + " \n" + " 2DDWave\n" + " \n" + " \n" + "\n"; + + std::istringstream layout_stream{fcn_layout}; + + using gate_layout = gate_level_layout< + clocked_layout>>>; + CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); +} + +TEST_CASE("Parsing error: Lyt is not a shifted_cartesian layout", "[fcn]") +{ + static constexpr const char* fcn_layout = "\n" + "\n" + " \n" + " Test\n" + " odd_row_cartesian\n" + " \n" + " 0\n" + " 0\n" + " 0\n" + " \n" + " \n" + " 2DDWave\n" + " \n" + " \n" + "\n"; + + std::istringstream layout_stream{fcn_layout}; + + using gate_layout = gate_level_layout>>>; + CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); +} + +TEST_CASE("Parsing error: Lyt is not an odd_row_cartesian layout", "[fcn]") +{ + static constexpr const char* fcn_layout = "\n" + "\n" + " \n" + " Test\n" + " odd_row_cartesian\n" + " \n" + " 0\n" + " 0\n" + " 0\n" + " \n" + " \n" + " 2DDWave\n" + " \n" + " \n" + "\n"; + + std::istringstream layout_stream{fcn_layout}; + + using gate_layout = gate_level_layout< + clocked_layout>>>; + CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); +} + +TEST_CASE("Parsing error: Lyt is not an even_row_cartesian layout", "[fcn]") +{ + static constexpr const char* fcn_layout = "\n" + "\n" + " \n" + " Test\n" + " even_row_cartesian\n" + " \n" + " 0\n" + " 0\n" + " 0\n" + " \n" + " \n" + " 2DDWave\n" + " \n" + " \n" + "\n"; + + std::istringstream layout_stream{fcn_layout}; + + using gate_layout = gate_level_layout< + clocked_layout>>>; + CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); +} + +TEST_CASE("Parsing error: Lyt is not an odd_column_cartesian layout", "[fcn]") +{ + static constexpr const char* fcn_layout = "\n" + "\n" + " \n" + " Test\n" + " odd_column_cartesian\n" + " \n" + " 0\n" + " 0\n" + " 0\n" + " \n" + " \n" + " 2DDWave\n" + " \n" + " \n" + "\n"; + + std::istringstream layout_stream{fcn_layout}; + + using gate_layout = gate_level_layout< + clocked_layout>>>; + CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); +} + +TEST_CASE("Parsing error: Lyt is not an even_column_cartesian layout", "[fcn]") +{ + static constexpr const char* fcn_layout = "\n" + "\n" + " \n" + " Test\n" + " even_column_cartesian\n" + " \n" + " 0\n" + " 0\n" + " 0\n" + " \n" + " \n" + " 2DDWave\n" + " \n" + " \n" + "\n"; + + std::istringstream layout_stream{fcn_layout}; + + using gate_layout = gate_level_layout< + clocked_layout>>>; + CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); +} + +TEST_CASE("Parsing error: Lyt is not a hexagonal layout", "[fcn]") +{ + static constexpr const char* fcn_layout = "\n" + "\n" + " \n" + " Test\n" + " odd_row_hex\n" + " \n" + " 0\n" + " 0\n" + " 0\n" + " \n" + " \n" + " 2DDWave\n" + " \n" + " \n" + "\n"; + + std::istringstream layout_stream{fcn_layout}; + + using gate_layout = gate_level_layout< + clocked_layout>>>; + CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); +} + +TEST_CASE("Parsing error: Lyt is not an odd_row_hex layout", "[fcn]") +{ + static constexpr const char* fcn_layout = "\n" + "\n" + " \n" + " Test\n" + " odd_row_hex\n" + " \n" + " 0\n" + " 0\n" + " 0\n" + " \n" + " \n" + " 2DDWave\n" + " \n" + " \n" + "\n"; + + std::istringstream layout_stream{fcn_layout}; + + using gate_layout = + gate_level_layout>>>; + CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); +} + +TEST_CASE("Parsing error: Lyt is not an even_row_hex layout", "[fcn]") +{ + static constexpr const char* fcn_layout = "\n" + "\n" + " \n" + " Test\n" + " even_row_hex\n" + " \n" + " 0\n" + " 0\n" + " 0\n" + " \n" + " \n" + " 2DDWave\n" + " \n" + " \n" + "\n"; + + std::istringstream layout_stream{fcn_layout}; + + using gate_layout = + gate_level_layout>>>; + CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); +} + +TEST_CASE("Parsing error: Lyt is not an odd_column_hex layout", "[fcn]") +{ + static constexpr const char* fcn_layout = "\n" + "\n" + " \n" + " Test\n" + " odd_column_hex\n" + " \n" + " 0\n" + " 0\n" + " 0\n" + " \n" + " \n" + " 2DDWave\n" + " \n" + " \n" + "\n"; + + std::istringstream layout_stream{fcn_layout}; + + using gate_layout = + gate_level_layout>>>; + CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); +} + +TEST_CASE("Parsing error: Lyt is not an even_column_hex layout", "[fcn]") +{ + static constexpr const char* fcn_layout = "\n" + "\n" + " \n" + " Test\n" + " even_column_hex\n" + " \n" + " 0\n" + " 0\n" + " 0\n" + " \n" + " \n" + " 2DDWave\n" + " \n" + " \n" + "\n"; + + std::istringstream layout_stream{fcn_layout}; + + using gate_layout = + gate_level_layout>>>; + CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); +} + TEST_CASE("Parsing error: no element 'size' in 'layout'", "[fcn]") { static constexpr const char* fcn_layout = "\n" diff --git a/test/io/write_gate_level_layout.cpp b/test/io/write_gate_level_layout.cpp index 94d6afbfa..677953b39 100644 --- a/test/io/write_gate_level_layout.cpp +++ b/test/io/write_gate_level_layout.cpp @@ -100,8 +100,17 @@ void check_parsing_equiv_all() check_parsing_equiv_layout(blueprints::straight_wire_gate_layout()); check_parsing_equiv_layout(blueprints::three_wire_paths_gate_layout()); check_parsing_equiv_layout(blueprints::xor_maj_gate_layout()); + check_parsing_equiv_layout(blueprints::single_input_tautology_gate_layout()); check_parsing_equiv_layout(blueprints::tautology_gate_layout()); check_parsing_equiv_layout(blueprints::and_or_gate_layout()); + check_parsing_equiv_layout(blueprints::and_or_gate_layout()); + check_parsing_equiv_layout(blueprints::and_or_gate_layout()); + check_parsing_equiv_layout(blueprints::and_or_gate_layout()); + check_parsing_equiv_layout(blueprints::and_or_gate_layout()); + check_parsing_equiv_layout(blueprints::and_or_gate_layout()); + check_parsing_equiv_layout(blueprints::and_or_gate_layout()); + check_parsing_equiv_layout(blueprints::and_or_gate_layout()); + check_parsing_equiv_layout(blueprints::and_or_gate_layout()); check_parsing_equiv_layout(blueprints::and_not_gate_layout()); check_parsing_equiv_layout(blueprints::or_not_gate_layout()); check_parsing_equiv_layout(blueprints::use_and_gate_layout()); @@ -118,7 +127,7 @@ void check_parsing_equiv_all() check_parsing_equiv_layout(blueprints::optimization_layout_corner_case_outputs_2()); } -TEST_CASE("Write empty gate_level layout", "[sqd]") +TEST_CASE("Write empty gate_level layout", "[fcn]") { using gate_layout = gate_level_layout>>>; @@ -133,7 +142,7 @@ TEST_CASE("Write empty gate_level layout", "[sqd]") compare_written_and_read_layout(layout, read_layout); } -TEST_CASE("Write and read layouts") +TEST_CASE("Write and read layouts", "[fcn]") { using gate_layout = gate_level_layout>>>; diff --git a/test/utils/blueprints/layout_blueprints.hpp b/test/utils/blueprints/layout_blueprints.hpp index 275fb3069..efb7532b2 100644 --- a/test/utils/blueprints/layout_blueprints.hpp +++ b/test/utils/blueprints/layout_blueprints.hpp @@ -84,26 +84,6 @@ GateLyt xor_maj_gate_layout() noexcept return layout; } -template -GateLyt tautology_gate_layout() noexcept -{ - REQUIRE(mockturtle::has_create_node_v); - - GateLyt layout{typename GateLyt::aspect_ratio{2, 2, 1}, fiction::twoddwave_clocking()}; - - const auto x1 = layout.create_pi("x1", {1, 0}); - const auto x2 = layout.create_pi("x2", {0, 1}); - - kitty::dynamic_truth_table tt_t(2u); - kitty::create_from_hex_string(tt_t, "F"); - - const auto n_xor = layout.create_node({x1, x2}, tt_t, {1, 1}); - - layout.create_po(n_xor, "f1", {2, 1}); - - return layout; -} - template GateLyt and_or_gate_layout() noexcept { @@ -206,6 +186,45 @@ GateLyt res_maj_gate_layout() noexcept return layout; } +template +GateLyt single_input_tautology_gate_layout() noexcept +{ + REQUIRE(mockturtle::has_create_node_v); + + GateLyt layout{typename GateLyt::aspect_ratio{2, 0, 0}, fiction::twoddwave_clocking()}; + + const auto x1 = layout.create_pi("x1", {0, 0}); + + kitty::dynamic_truth_table tt_t(1u); + kitty::create_from_hex_string(tt_t, "3"); + + const auto n = layout.create_node({x1}, tt_t, {1, 0}); + + layout.create_po(n, "f1", {2, 0}); + + return layout; +} + +template +GateLyt tautology_gate_layout() noexcept +{ + REQUIRE(mockturtle::has_create_node_v); + + GateLyt layout{typename GateLyt::aspect_ratio{2, 2, 1}, fiction::twoddwave_clocking()}; + + const auto x1 = layout.create_pi("x1", {1, 0}); + const auto x2 = layout.create_pi("x2", {0, 1}); + + kitty::dynamic_truth_table tt_t(2u); + kitty::create_from_hex_string(tt_t, "F"); + + const auto n_xor = layout.create_node({x1, x2}, tt_t, {1, 1}); + + layout.create_po(n_xor, "f1", {2, 1}); + + return layout; +} + template GateLyt res_tautology_gate_layout() noexcept { From a93e412b850dd6701ca0410ea5e1f4de7cefb918 Mon Sep 17 00:00:00 2001 From: Simon Hofmann Date: Wed, 4 Oct 2023 17:10:28 +0200 Subject: [PATCH 26/36] first batch of todos --- include/fiction/io/read_gate_level_layout.hpp | 93 ++++++++++--------- .../fiction/io/write_gate_level_layout.hpp | 76 +++++++-------- test/io/read_gate_level_layout.cpp | 88 +++++++++--------- test/io/write_gate_level_layout.cpp | 72 ++++++++------ 4 files changed, 172 insertions(+), 157 deletions(-) diff --git a/include/fiction/io/read_gate_level_layout.hpp b/include/fiction/io/read_gate_level_layout.hpp index 5da5fb0a4..30f88bdc0 100644 --- a/include/fiction/io/read_gate_level_layout.hpp +++ b/include/fiction/io/read_gate_level_layout.hpp @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -25,16 +26,22 @@ #include #include #include +#include namespace fiction { /** - * Exception thrown when an error occurs during parsing of a gate_level file. + * Exception thrown when an error occurs during parsing of a file containing a gate_level layout. */ class gate_level_parsing_error : public std::runtime_error { public: + /** + * Constructs a gate_level_parsing_error object with the given error message. + * + * @param msg The error message describing the parsing error. + */ explicit gate_level_parsing_error(const std::string_view& msg) noexcept : std::runtime_error(msg.data()) {} }; @@ -65,7 +72,7 @@ class read_gate_level_layout_impl if (xml_document.ErrorID() != 0) { - throw gate_level_parsing_error("Error parsing gate_level file: " + std::string(xml_document.ErrorName())); + throw gate_level_parsing_error(fmt::format("Error parsing gate_level file: {}", xml_document.ErrorName())); } auto* const fcn_root = xml_document.FirstChildElement("fcn"); @@ -191,8 +198,8 @@ class read_gate_level_layout_impl } else { - throw gate_level_parsing_error("Error parsing gate_level file: unknown topology: " + - std::string(topology_name)); + throw gate_level_parsing_error( + fmt::format("Error parsing gate_level file: unknown topology: {}", topology_name)); } } else @@ -206,7 +213,7 @@ class read_gate_level_layout_impl { auto* const size_x = size->FirstChildElement("x"); int x = 0; - if (size_x != nullptr and size_x->GetText()) + if (size_x != nullptr && size_x->GetText()) { x = std::stoi(size_x->GetText()); } @@ -217,7 +224,7 @@ class read_gate_level_layout_impl auto* const size_y = size->FirstChildElement("y"); int y = 0; - if (size_y != nullptr and size_y->GetText()) + if (size_y != nullptr && size_y->GetText()) { y = std::stoi(size_y->GetText()); } @@ -228,7 +235,7 @@ class read_gate_level_layout_impl auto* const size_z = size->FirstChildElement("z"); int z = 0; - if (size_z != nullptr and size_z->GetText()) + if (size_z != nullptr && size_z->GetText()) { z = std::stoi(size_z->GetText()); } @@ -237,8 +244,8 @@ class read_gate_level_layout_impl throw gate_level_parsing_error("Error parsing gate_level file: no element 'z' in 'size'"); } - const tile max_pos{x, y, z}; - lyt.resize(max_pos); + const aspect_ratio ar{x, y, z}; + lyt.resize(ar); } else { @@ -250,7 +257,7 @@ class read_gate_level_layout_impl if (clocking != nullptr) { auto* const clocking_scheme_name = clocking->FirstChildElement("name"); - if (clocking_scheme_name != nullptr and clocking_scheme_name->GetText()) + if (clocking_scheme_name != nullptr && clocking_scheme_name->GetText()) { const auto clocking_scheme = get_clocking_scheme(clocking_scheme_name->GetText()); if (clocking_scheme.has_value()) @@ -265,7 +272,7 @@ class read_gate_level_layout_impl { auto* const clocking_zone_x = clock_zone->FirstChildElement("x"); int x_coord = 0; - if (clocking_zone_x != nullptr and clocking_zone_x->GetText()) + if (clocking_zone_x != nullptr && clocking_zone_x->GetText()) { x_coord = std::stoi(clocking_zone_x->GetText()); } @@ -277,7 +284,7 @@ class read_gate_level_layout_impl auto* const clocking_zone_y = clock_zone->FirstChildElement("y"); int y_coord = 0; - if (clocking_zone_y != nullptr and clocking_zone_y->GetText()) + if (clocking_zone_y != nullptr && clocking_zone_y->GetText()) { y_coord = std::stoi(clocking_zone_y->GetText()); } @@ -289,7 +296,7 @@ class read_gate_level_layout_impl auto* const clocking_zone_clock = clock_zone->FirstChildElement("clock"); uint8_t clock = 0; - if (clocking_zone_clock != nullptr and clocking_zone_clock->GetText()) + if (clocking_zone_clock != nullptr && clocking_zone_clock->GetText()) { clock = static_cast(*clocking_zone_clock->GetText()); } @@ -315,8 +322,8 @@ class read_gate_level_layout_impl } else { - throw gate_level_parsing_error("Error parsing gate_level file: unknown clocking scheme: " + - std::string(clocking_scheme_name->GetText())); + throw gate_level_parsing_error(fmt::format( + "Error parsing gate_level file: unknown clocking scheme: {}", clocking_scheme_name->GetText())); } } else @@ -340,7 +347,7 @@ class read_gate_level_layout_impl gate_storage gate{}; auto* const gate_id = gate_xml->FirstChildElement("id"); - if (gate_id != nullptr and gate_id->GetText()) + if (gate_id != nullptr && gate_id->GetText()) { gate.id = std::stoi(gate_id->GetText()); } @@ -350,7 +357,7 @@ class read_gate_level_layout_impl } auto* const gate_type = gate_xml->FirstChildElement("type"); - if (gate_type != nullptr and gate_type->GetText()) + if (gate_type != nullptr && gate_type->GetText()) { gate.type = gate_type->GetText(); } @@ -381,7 +388,7 @@ class read_gate_level_layout_impl // get x-coordinate auto* const loc_x = loc->FirstChildElement("x"); - if (loc_x != nullptr and loc_x->GetText()) + if (loc_x != nullptr && loc_x->GetText()) { gate.loc.x = std::stoull(loc_x->GetText()); } @@ -392,7 +399,7 @@ class read_gate_level_layout_impl // get y-coordinate auto* const loc_y = loc->FirstChildElement("y"); - if (loc_y != nullptr and loc_y->GetText()) + if (loc_y != nullptr && loc_y->GetText()) { gate.loc.y = std::stoull(loc_y->GetText()); } @@ -403,7 +410,7 @@ class read_gate_level_layout_impl // get z-coordinate auto* const loc_z = loc->FirstChildElement("z"); - if (loc_z != nullptr and loc_z->GetText()) + if (loc_z != nullptr && loc_z->GetText()) { gate.loc.z = std::stoull(loc_z->GetText()); } @@ -415,16 +422,16 @@ class read_gate_level_layout_impl auto* const incoming_signals = gate_xml->FirstChildElement("incoming"); if (incoming_signals != nullptr) { - for (const auto* signal = incoming_signals->FirstChildElement("signal"); signal != nullptr; - signal = signal->NextSiblingElement("signal")) + for (const auto* incoming_signal = incoming_signals->FirstChildElement("signal"); + incoming_signal != nullptr; incoming_signal = incoming_signal->NextSiblingElement("signal")) { - tile incoming_signal{}; + tile incoming{}; // get x-coordinate of incoming signal - auto* const incoming_signal_x = signal->FirstChildElement("x"); - if (incoming_signal_x != nullptr and incoming_signal_x->GetText()) + auto* const incoming_signal_x = incoming_signal->FirstChildElement("x"); + if (incoming_signal_x != nullptr && incoming_signal_x->GetText()) { - incoming_signal.x = std::stoull(incoming_signal_x->GetText()); + incoming.x = std::stoull(incoming_signal_x->GetText()); } else { @@ -432,10 +439,10 @@ class read_gate_level_layout_impl } // get y-coordinate of incoming signal - auto* const incoming_signal_y = signal->FirstChildElement("y"); - if (incoming_signal_y != nullptr and incoming_signal_y->GetText()) + auto* const incoming_signal_y = incoming_signal->FirstChildElement("y"); + if (incoming_signal_y != nullptr && incoming_signal_y->GetText()) { - incoming_signal.y = std::stoull(incoming_signal_y->GetText()); + incoming.y = std::stoull(incoming_signal_y->GetText()); } else { @@ -443,17 +450,17 @@ class read_gate_level_layout_impl } // get z-coordinate of incoming signal - auto* const incoming_signal_z = signal->FirstChildElement("z"); - if (incoming_signal_z != nullptr and incoming_signal_z->GetText()) + auto* const incoming_signal_z = incoming_signal->FirstChildElement("z"); + if (incoming_signal_z != nullptr && incoming_signal_z->GetText()) { - incoming_signal.z = std::stoull(incoming_signal_z->GetText()); + incoming.z = std::stoull(incoming_signal_z->GetText()); } else { throw gate_level_parsing_error("Error parsing gate_level file: no element 'z' in 'signal'"); } - gate.incoming.push_back(incoming_signal); + gate.incoming.push_back(incoming); } } @@ -475,8 +482,8 @@ class read_gate_level_layout_impl } else { - throw gate_level_parsing_error("Error parsing gate_level file: unknown gate type: " + - std::string(gate.type)); + throw gate_level_parsing_error( + fmt::format("Error parsing gate_level file: unknown gate type: {}", gate.type)); } } @@ -508,8 +515,8 @@ class read_gate_level_layout_impl } else { - throw gate_level_parsing_error("Error parsing gate_level file: unknown gate type: " + - std::string(gate.type)); + throw gate_level_parsing_error( + fmt::format("Error parsing gate_level file: unknown gate type: {}", gate.type)); } } @@ -560,8 +567,8 @@ class read_gate_level_layout_impl } else { - throw gate_level_parsing_error("Error parsing gate_level file: unknown gate type: " + - std::string(gate.type)); + throw gate_level_parsing_error( + fmt::format("Error parsing gate_level file: unknown gate type: {}", gate.type)); } } else if (gate.incoming.size() == 3) @@ -588,8 +595,8 @@ class read_gate_level_layout_impl } else { - throw gate_level_parsing_error("Error parsing gate_level file: unknown gate type: " + - std::string(gate.type)); + throw gate_level_parsing_error( + fmt::format("Error parsing gate_level file: unknown gate type: {}", gate.type)); } } else if (std::all_of(gate.type.begin(), gate.type.end(), ::isxdigit)) @@ -608,8 +615,8 @@ class read_gate_level_layout_impl } else { - throw gate_level_parsing_error("Error parsing gate_level file: unknown gate type: " + - std::string(gate.type)); + throw gate_level_parsing_error( + fmt::format("Error parsing gate_level file: unknown gate type: {}", gate.type)); } } } diff --git a/include/fiction/io/write_gate_level_layout.hpp b/include/fiction/io/write_gate_level_layout.hpp index 39b64b253..0cc174075 100644 --- a/include/fiction/io/write_gate_level_layout.hpp +++ b/include/fiction/io/write_gate_level_layout.hpp @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -93,14 +94,10 @@ class write_gate_level_layout_impl void run() { - std::stringstream header{}; - std::stringstream layout_metadata{}; - // metadata - header << fcn::FCN_HEADER << fcn::OPEN_FCN; + os << fcn::FCN_HEADER << fcn::OPEN_FCN; const auto time_str = fmt::format("{:%Y-%m-%d %H:%M:%S}", fmt::localtime(std::time(nullptr))); - header << fmt::format(fcn::FICTION_METADATA, FICTION_VERSION, FICTION_REPO, time_str); - os << header.str(); + os << fmt::format(fcn::FICTION_METADATA, FICTION_VERSION, FICTION_REPO, time_str); os << fcn::OPEN_LAYOUT_METADATA; std::string layout_name = get_name(lyt); @@ -149,8 +146,7 @@ class write_gate_level_layout_impl } } - layout_metadata << fmt::format(fcn::LAYOUT_METADATA, layout_name, topology, lyt.x(), lyt.y(), lyt.z()); - os << layout_metadata.str(); + os << fmt::format(fcn::LAYOUT_METADATA, layout_name, topology, lyt.x(), lyt.y(), lyt.z()); os << fcn::OPEN_CLOCKING; const auto clocking_scheme = lyt.get_clocking_scheme(); @@ -176,119 +172,119 @@ class write_gate_level_layout_impl // create topological ordering mockturtle::topo_view layout_topo{lyt}; - uint32_t id = 0; + uint32_t gate_id = 0; // inputs layout_topo.foreach_pi( - [&id, this](const auto& gate) + [&gate_id, this](const auto& gate) { const auto coord = lyt.get_tile(gate); os << fcn::OPEN_GATE; - os << fmt::format(fcn::GATE, id, "PI", lyt.get_name(gate), coord.x, coord.y, coord.z); + os << fmt::format(fcn::GATE, gate_id, "PI", lyt.get_name(gate), coord.x, coord.y, coord.z); os << fcn::CLOSE_GATE; - id++; + gate_id++; }); // gates layout_topo.foreach_gate( - [&id, this](const auto& gate) + [&gate_id, this](const auto& gate) { os << fcn::OPEN_GATE; const auto coord = lyt.get_tile(gate); if (const auto signals = lyt.incoming_data_flow(coord); signals.size() == 1) { - const auto signal = signals[0]; + const auto incoming_signal = signals[0]; if (lyt.is_po(gate)) { - os << fmt::format(fcn::GATE, id, "PO", lyt.get_name(gate), coord.x, coord.y, coord.z); + os << fmt::format(fcn::GATE, gate_id, "PO", lyt.get_name(gate), coord.x, coord.y, coord.z); } else if (lyt.is_wire(gate)) { - os << fmt::format(fcn::GATE, id, "BUF", "", coord.x, coord.y, coord.z); + os << fmt::format(fcn::GATE, gate_id, "BUF", "", coord.x, coord.y, coord.z); } else if (lyt.is_inv(gate)) { - os << fmt::format(fcn::GATE, id, "INV", "", coord.x, coord.y, coord.z); + os << fmt::format(fcn::GATE, gate_id, "INV", "", coord.x, coord.y, coord.z); } else if (lyt.is_function(gate)) { const auto node_fun = lyt.node_function(gate); - os << fmt::format(fcn::GATE, id, kitty::to_hex(node_fun), "", coord.x, coord.y, coord.z); + os << fmt::format(fcn::GATE, gate_id, kitty::to_hex(node_fun), "", coord.x, coord.y, coord.z); } os << fcn::OPEN_INCOMING; - os << fmt::format(fcn::SIGNAL, signal.x, signal.y, signal.z); + os << fmt::format(fcn::SIGNAL, incoming_signal.x, incoming_signal.y, incoming_signal.z); os << fcn::CLOSE_INCOMING; } else if (signals.size() == 2) { - const auto signal_a = signals[0]; - const auto signal_b = signals[1]; + const auto incoming_signal_a = signals[0]; + const auto incoming_signal_b = signals[1]; if (lyt.is_and(gate)) { - os << fmt::format(fcn::GATE, id, "AND", "", coord.x, coord.y, coord.z); + os << fmt::format(fcn::GATE, gate_id, "AND", "", coord.x, coord.y, coord.z); } else if (lyt.is_nand(gate)) { - os << fmt::format(fcn::GATE, id, "NAND", "", coord.x, coord.y, coord.z); + os << fmt::format(fcn::GATE, gate_id, "NAND", "", coord.x, coord.y, coord.z); } else if (lyt.is_or(gate)) { - os << fmt::format(fcn::GATE, id, "OR", "", coord.x, coord.y, coord.z); + os << fmt::format(fcn::GATE, gate_id, "OR", "", coord.x, coord.y, coord.z); } else if (lyt.is_nor(gate)) { - os << fmt::format(fcn::GATE, id, "NOR", "", coord.x, coord.y, coord.z); + os << fmt::format(fcn::GATE, gate_id, "NOR", "", coord.x, coord.y, coord.z); } else if (lyt.is_xor(gate)) { - os << fmt::format(fcn::GATE, id, "XOR", "", coord.x, coord.y, coord.z); + os << fmt::format(fcn::GATE, gate_id, "XOR", "", coord.x, coord.y, coord.z); } else if (lyt.is_xnor(gate)) { - os << fmt::format(fcn::GATE, id, "XNOR", "", coord.x, coord.y, coord.z); + os << fmt::format(fcn::GATE, gate_id, "XNOR", "", coord.x, coord.y, coord.z); } else if (lyt.is_function(gate)) { const auto node_fun = lyt.node_function(gate); - os << fmt::format(fcn::GATE, id, kitty::to_hex(node_fun), "", coord.x, coord.y, coord.z); + os << fmt::format(fcn::GATE, gate_id, kitty::to_hex(node_fun), "", coord.x, coord.y, coord.z); } os << fcn::OPEN_INCOMING; - os << fmt::format(fcn::SIGNAL, signal_a.x, signal_a.y, signal_a.z); - os << fmt::format(fcn::SIGNAL, signal_b.x, signal_b.y, signal_b.z); + os << fmt::format(fcn::SIGNAL, incoming_signal_a.x, incoming_signal_a.y, incoming_signal_a.z); + os << fmt::format(fcn::SIGNAL, incoming_signal_b.x, incoming_signal_b.y, incoming_signal_b.z); os << fcn::CLOSE_INCOMING; } else if (signals.size() == 3) { - const auto signal_a = signals[0]; - const auto signal_b = signals[1]; - const auto signal_c = signals[2]; + const auto incoming_signal_a = signals[0]; + const auto incoming_signal_b = signals[1]; + const auto incoming_signal_c = signals[2]; if (lyt.is_maj(gate)) { - os << fmt::format(fcn::GATE, id, "MAJ", "", coord.x, coord.y, coord.z); + os << fmt::format(fcn::GATE, gate_id, "MAJ", "", coord.x, coord.y, coord.z); } else if (lyt.is_function(gate)) { const auto node_fun = lyt.node_function(gate); - os << fmt::format(fcn::GATE, id, kitty::to_hex(node_fun), "", coord.x, coord.y, coord.z); + os << fmt::format(fcn::GATE, gate_id, kitty::to_hex(node_fun), "", coord.x, coord.y, coord.z); } os << fcn::OPEN_INCOMING; - os << fmt::format(fcn::SIGNAL, signal_a.x, signal_a.y, signal_a.z); - os << fmt::format(fcn::SIGNAL, signal_b.x, signal_b.y, signal_b.z); - os << fmt::format(fcn::SIGNAL, signal_c.x, signal_c.y, signal_c.z); + os << fmt::format(fcn::SIGNAL, incoming_signal_a.x, incoming_signal_a.y, incoming_signal_a.z); + os << fmt::format(fcn::SIGNAL, incoming_signal_b.x, incoming_signal_b.y, incoming_signal_b.z); + os << fmt::format(fcn::SIGNAL, incoming_signal_c.x, incoming_signal_c.y, incoming_signal_c.z); os << fcn::CLOSE_INCOMING; } else if (lyt.is_function(gate)) { const auto node_fun = lyt.node_function(gate); - os << fmt::format(fcn::GATE, id, kitty::to_hex(node_fun), "", coord.x, coord.y, coord.z); + os << fmt::format(fcn::GATE, gate_id, kitty::to_hex(node_fun), "", coord.x, coord.y, coord.z); os << fcn::OPEN_INCOMING; for (std::size_t i = 0; i < signals.size(); i++) @@ -298,7 +294,7 @@ class write_gate_level_layout_impl os << fcn::CLOSE_INCOMING; } os << fcn::CLOSE_GATE; - id++; + gate_id++; }); os << fcn::CLOSE_GATES; diff --git a/test/io/read_gate_level_layout.cpp b/test/io/read_gate_level_layout.cpp index 5ed0bb776..027229fdc 100644 --- a/test/io/read_gate_level_layout.cpp +++ b/test/io/read_gate_level_layout.cpp @@ -19,7 +19,7 @@ using namespace fiction; -TEST_CASE("Read empty FCN layout", "[fcn]") +TEST_CASE("Read empty FCN layout", "[read-gate-level-layout]") { static constexpr const char* fcn_layout = "\n" "\n" @@ -52,7 +52,7 @@ TEST_CASE("Read empty FCN layout", "[fcn]") check(read_gate_level_layout(layout_stream)); } -TEST_CASE("Read simple FCN layout", "[fcn]") +TEST_CASE("Read simple FCN layout", "[read-gate-level-layout]") { static constexpr const char* fcn_layout = "\n" "\n" @@ -152,7 +152,7 @@ TEST_CASE("Read simple FCN layout", "[fcn]") check(read_gate_level_layout(layout_stream)); } -TEST_CASE("Parsing error: malformed xml", "[fcn]") +TEST_CASE("Parsing error: malformed xml", "[read-gate-level-layout]") { static constexpr const char* fcn_layout = "\n" "\n" @@ -175,7 +175,7 @@ TEST_CASE("Parsing error: malformed xml", "[fcn]") CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } -TEST_CASE("Parsing error: no root element 'fcn'", "[fcn]") +TEST_CASE("Parsing error: no root element 'fcn'", "[read-gate-level-layout]") { static constexpr const char* fcn_layout = "\n" " \n" @@ -197,7 +197,7 @@ TEST_CASE("Parsing error: no root element 'fcn'", "[fcn]") CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } -TEST_CASE("Parsing error: no element 'layout' in 'fcn'", "[fcn]") +TEST_CASE("Parsing error: no element 'layout' in 'fcn'", "[read-gate-level-layout]") { static constexpr const char* fcn_layout = "\n" "\n" @@ -219,7 +219,7 @@ TEST_CASE("Parsing error: no element 'layout' in 'fcn'", "[fcn]") CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } -TEST_CASE("Parsing error: no element 'clocking' in 'layout'", "[fcn]") +TEST_CASE("Parsing error: no element 'clocking' in 'layout'", "[read-gate-level-layout]") { static constexpr const char* fcn_layout = "\n" "\n" @@ -240,7 +240,7 @@ TEST_CASE("Parsing error: no element 'clocking' in 'layout'", "[fcn]") CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } -TEST_CASE("Parsing error: no element 'name' in 'clocking'", "[fcn]") +TEST_CASE("Parsing error: no element 'name' in 'clocking'", "[read-gate-level-layout]") { static constexpr const char* fcn_layout = "\n" "\n" @@ -263,7 +263,7 @@ TEST_CASE("Parsing error: no element 'name' in 'clocking'", "[fcn]") CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } -TEST_CASE("Parsing error: unknown clocking scheme", "[fcn]") +TEST_CASE("Parsing error: unknown clocking scheme", "[read-gate-level-layout]") { static constexpr const char* fcn_layout = "\n" "\n" @@ -287,7 +287,7 @@ TEST_CASE("Parsing error: unknown clocking scheme", "[fcn]") CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } -TEST_CASE("Parsing error: no element 'zones' in 'clocking'", "[fcn]") +TEST_CASE("Parsing error: no element 'zones' in 'clocking'", "[read-gate-level-layout]") { static constexpr const char* fcn_layout = "\n" "\n" @@ -311,7 +311,7 @@ TEST_CASE("Parsing error: no element 'zones' in 'clocking'", "[fcn]") CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } -TEST_CASE("Parsing error: no element 'x' in 'zone'", "[fcn]") +TEST_CASE("Parsing error: no element 'x' in 'zone'", "[read-gate-level-layout]") { static constexpr const char* fcn_layout = "\n" "\n" @@ -341,7 +341,7 @@ TEST_CASE("Parsing error: no element 'x' in 'zone'", "[fcn]") CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } -TEST_CASE("Parsing error: no element 'y' in 'zone'", "[fcn]") +TEST_CASE("Parsing error: no element 'y' in 'zone'", "[read-gate-level-layout]") { static constexpr const char* fcn_layout = "\n" "\n" @@ -371,7 +371,7 @@ TEST_CASE("Parsing error: no element 'y' in 'zone'", "[fcn]") CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } -TEST_CASE("Parsing error: no element 'clock' in 'zone'", "[fcn]") +TEST_CASE("Parsing error: no element 'clock' in 'zone'", "[read-gate-level-layout]") { static constexpr const char* fcn_layout = "\n" "\n" @@ -401,7 +401,7 @@ TEST_CASE("Parsing error: no element 'clock' in 'zone'", "[fcn]") CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } -TEST_CASE("Parsing error: no element 'topology' in 'layout'", "[fcn]") +TEST_CASE("Parsing error: no element 'topology' in 'layout'", "[read-gate-level-layout]") { static constexpr const char* fcn_layout = "\n" "\n" @@ -424,7 +424,7 @@ TEST_CASE("Parsing error: no element 'topology' in 'layout'", "[fcn]") CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } -TEST_CASE("Parsing error: unknown topology", "[fcn]") +TEST_CASE("Parsing error: unknown topology", "[read-gate-level-layout]") { static constexpr const char* fcn_layout = "\n" "\n" @@ -448,7 +448,7 @@ TEST_CASE("Parsing error: unknown topology", "[fcn]") CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } -TEST_CASE("Parsing error: Lyt is not a cartesian layout", "[fcn]") +TEST_CASE("Parsing error: Lyt is not a cartesian layout", "[read-gate-level-layout]") { static constexpr const char* fcn_layout = "\n" "\n" @@ -473,7 +473,7 @@ TEST_CASE("Parsing error: Lyt is not a cartesian layout", "[fcn]") CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } -TEST_CASE("Parsing error: Lyt is not a shifted_cartesian layout", "[fcn]") +TEST_CASE("Parsing error: Lyt is not a shifted_cartesian layout", "[read-gate-level-layout]") { static constexpr const char* fcn_layout = "\n" "\n" @@ -497,7 +497,7 @@ TEST_CASE("Parsing error: Lyt is not a shifted_cartesian layout", "[fcn]") CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } -TEST_CASE("Parsing error: Lyt is not an odd_row_cartesian layout", "[fcn]") +TEST_CASE("Parsing error: Lyt is not an odd_row_cartesian layout", "[read-gate-level-layout]") { static constexpr const char* fcn_layout = "\n" "\n" @@ -522,7 +522,7 @@ TEST_CASE("Parsing error: Lyt is not an odd_row_cartesian layout", "[fcn]") CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } -TEST_CASE("Parsing error: Lyt is not an even_row_cartesian layout", "[fcn]") +TEST_CASE("Parsing error: Lyt is not an even_row_cartesian layout", "[read-gate-level-layout]") { static constexpr const char* fcn_layout = "\n" "\n" @@ -547,7 +547,7 @@ TEST_CASE("Parsing error: Lyt is not an even_row_cartesian layout", "[fcn]") CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } -TEST_CASE("Parsing error: Lyt is not an odd_column_cartesian layout", "[fcn]") +TEST_CASE("Parsing error: Lyt is not an odd_column_cartesian layout", "[read-gate-level-layout]") { static constexpr const char* fcn_layout = "\n" "\n" @@ -572,7 +572,7 @@ TEST_CASE("Parsing error: Lyt is not an odd_column_cartesian layout", "[fcn]") CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } -TEST_CASE("Parsing error: Lyt is not an even_column_cartesian layout", "[fcn]") +TEST_CASE("Parsing error: Lyt is not an even_column_cartesian layout", "[read-gate-level-layout]") { static constexpr const char* fcn_layout = "\n" "\n" @@ -597,7 +597,7 @@ TEST_CASE("Parsing error: Lyt is not an even_column_cartesian layout", "[fcn]") CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } -TEST_CASE("Parsing error: Lyt is not a hexagonal layout", "[fcn]") +TEST_CASE("Parsing error: Lyt is not a hexagonal layout", "[read-gate-level-layout]") { static constexpr const char* fcn_layout = "\n" "\n" @@ -622,7 +622,7 @@ TEST_CASE("Parsing error: Lyt is not a hexagonal layout", "[fcn]") CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } -TEST_CASE("Parsing error: Lyt is not an odd_row_hex layout", "[fcn]") +TEST_CASE("Parsing error: Lyt is not an odd_row_hex layout", "[read-gate-level-layout]") { static constexpr const char* fcn_layout = "\n" "\n" @@ -647,7 +647,7 @@ TEST_CASE("Parsing error: Lyt is not an odd_row_hex layout", "[fcn]") CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } -TEST_CASE("Parsing error: Lyt is not an even_row_hex layout", "[fcn]") +TEST_CASE("Parsing error: Lyt is not an even_row_hex layout", "[read-gate-level-layout]") { static constexpr const char* fcn_layout = "\n" "\n" @@ -672,7 +672,7 @@ TEST_CASE("Parsing error: Lyt is not an even_row_hex layout", "[fcn]") CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } -TEST_CASE("Parsing error: Lyt is not an odd_column_hex layout", "[fcn]") +TEST_CASE("Parsing error: Lyt is not an odd_column_hex layout", "[read-gate-level-layout]") { static constexpr const char* fcn_layout = "\n" "\n" @@ -697,7 +697,7 @@ TEST_CASE("Parsing error: Lyt is not an odd_column_hex layout", "[fcn]") CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } -TEST_CASE("Parsing error: Lyt is not an even_column_hex layout", "[fcn]") +TEST_CASE("Parsing error: Lyt is not an even_column_hex layout", "[read-gate-level-layout]") { static constexpr const char* fcn_layout = "\n" "\n" @@ -722,7 +722,7 @@ TEST_CASE("Parsing error: Lyt is not an even_column_hex layout", "[fcn]") CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } -TEST_CASE("Parsing error: no element 'size' in 'layout'", "[fcn]") +TEST_CASE("Parsing error: no element 'size' in 'layout'", "[read-gate-level-layout]") { static constexpr const char* fcn_layout = "\n" "\n" @@ -744,7 +744,7 @@ TEST_CASE("Parsing error: no element 'size' in 'layout'", "[fcn]") CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } -TEST_CASE("Parsing error: no element 'x' in 'size'", "[fcn]") +TEST_CASE("Parsing error: no element 'x' in 'size'", "[read-gate-level-layout]") { static constexpr const char* fcn_layout = "\n" "\n" @@ -767,7 +767,7 @@ TEST_CASE("Parsing error: no element 'x' in 'size'", "[fcn]") CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } -TEST_CASE("Parsing error: no element 'y' in 'size'", "[fcn]") +TEST_CASE("Parsing error: no element 'y' in 'size'", "[read-gate-level-layout]") { static constexpr const char* fcn_layout = "\n" "\n" @@ -790,7 +790,7 @@ TEST_CASE("Parsing error: no element 'y' in 'size'", "[fcn]") CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } -TEST_CASE("Parsing error: no element 'z' in 'size'", "[fcn]") +TEST_CASE("Parsing error: no element 'z' in 'size'", "[read-gate-level-layout]") { static constexpr const char* fcn_layout = "\n" "\n" @@ -813,7 +813,7 @@ TEST_CASE("Parsing error: no element 'z' in 'size'", "[fcn]") CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } -TEST_CASE("Parsing error: no element 'id' in 'gate", "[fcn]") +TEST_CASE("Parsing error: no element 'id' in 'gate", "[read-gate-level-layout]") { static constexpr const char* fcn_layout = "\n" "\n" @@ -848,7 +848,7 @@ TEST_CASE("Parsing error: no element 'id' in 'gate", "[fcn]") CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } -TEST_CASE("Parsing error: no element 'type' in 'gate", "[fcn]") +TEST_CASE("Parsing error: no element 'type' in 'gate", "[read-gate-level-layout]") { static constexpr const char* fcn_layout = "\n" "\n" @@ -883,7 +883,7 @@ TEST_CASE("Parsing error: no element 'type' in 'gate", "[fcn]") CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } -TEST_CASE("Parsing error: no element 'name' in 'gate", "[fcn]") +TEST_CASE("Parsing error: no element 'name' in 'gate", "[read-gate-level-layout]") { static constexpr const char* fcn_layout = "\n" "\n" @@ -918,7 +918,7 @@ TEST_CASE("Parsing error: no element 'name' in 'gate", "[fcn]") CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } -TEST_CASE("Parsing error: no element 'loc' in 'gate'", "[fcn]") +TEST_CASE("Parsing error: no element 'loc' in 'gate'", "[read-gate-level-layout]") { static constexpr const char* fcn_layout = "\n" "\n" @@ -952,7 +952,7 @@ TEST_CASE("Parsing error: no element 'loc' in 'gate'", "[fcn]") CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } -TEST_CASE("Parsing error: no element 'x' in 'loc'", "[fcn]") +TEST_CASE("Parsing error: no element 'x' in 'loc'", "[read-gate-level-layout]") { static constexpr const char* fcn_layout = "\n" "\n" @@ -987,7 +987,7 @@ TEST_CASE("Parsing error: no element 'x' in 'loc'", "[fcn]") CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } -TEST_CASE("Parsing error: no element 'y' in 'loc'", "[fcn]") +TEST_CASE("Parsing error: no element 'y' in 'loc'", "[read-gate-level-layout]") { static constexpr const char* fcn_layout = "\n" "\n" @@ -1022,7 +1022,7 @@ TEST_CASE("Parsing error: no element 'y' in 'loc'", "[fcn]") CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } -TEST_CASE("Parsing error: no element 'z' in 'loc'", "[fcn]") +TEST_CASE("Parsing error: no element 'z' in 'loc'", "[read-gate-level-layout]") { static constexpr const char* fcn_layout = "\n" "\n" @@ -1057,7 +1057,7 @@ TEST_CASE("Parsing error: no element 'z' in 'loc'", "[fcn]") CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } -TEST_CASE("Parsing error: unknown gate type with 0 incoming signals", "[fcn]") +TEST_CASE("Parsing error: unknown gate type with 0 incoming signals", "[read-gate-level-layout]") { static constexpr const char* fcn_layout = "\n" "\n" @@ -1141,7 +1141,7 @@ TEST_CASE("Parsing error: unknown gate type with 0 incoming signals", "[fcn]") CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } -TEST_CASE("Parsing error: unknown gate type with 1 incoming signal", "[fcn]") +TEST_CASE("Parsing error: unknown gate type with 1 incoming signal", "[read-gate-level-layout]") { static constexpr const char* fcn_layout = "\n" "\n" @@ -1224,7 +1224,7 @@ TEST_CASE("Parsing error: unknown gate type with 1 incoming signal", "[fcn]") CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } -TEST_CASE("Parsing error: unknown gate type with 2 incoming signals", "[fcn]") +TEST_CASE("Parsing error: unknown gate type with 2 incoming signals", "[read-gate-level-layout]") { static constexpr const char* fcn_layout = "\n" "\n" @@ -1308,7 +1308,7 @@ TEST_CASE("Parsing error: unknown gate type with 2 incoming signals", "[fcn]") CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } -TEST_CASE("Parsing error: unknown gate type with 3 incoming signals", "[fcn]") +TEST_CASE("Parsing error: unknown gate type with 3 incoming signals", "[read-gate-level-layout]") { static constexpr const char* fcn_layout = "\n" "\n" @@ -1407,7 +1407,7 @@ TEST_CASE("Parsing error: unknown gate type with 3 incoming signals", "[fcn]") CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } -TEST_CASE("Parsing error: unknown gate type with more than 3 incoming signals", "[fcn]") +TEST_CASE("Parsing error: unknown gate type with more than 3 incoming signals", "[read-gate-level-layout]") { static constexpr const char* fcn_layout = "\n" "\n" @@ -1531,7 +1531,7 @@ TEST_CASE("Parsing error: unknown gate type with more than 3 incoming signals", CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } -TEST_CASE("Parsing error: no element 'x' in 'signal'", "[fcn]") +TEST_CASE("Parsing error: no element 'x' in 'signal'", "[read-gate-level-layout]") { static constexpr const char* fcn_layout = "\n" "\n" @@ -1614,7 +1614,7 @@ TEST_CASE("Parsing error: no element 'x' in 'signal'", "[fcn]") CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } -TEST_CASE("Parsing error: no element 'y' in 'signal'", "[fcn]") +TEST_CASE("Parsing error: no element 'y' in 'signal'", "[read-gate-level-layout]") { static constexpr const char* fcn_layout = "\n" "\n" @@ -1697,7 +1697,7 @@ TEST_CASE("Parsing error: no element 'y' in 'signal'", "[fcn]") CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); } -TEST_CASE("Parsing error: no element 'z' in 'signal'", "[fcn]") +TEST_CASE("Parsing error: no element 'z' in 'signal'", "[read-gate-level-layout]") { static constexpr const char* fcn_layout = "\n" "\n" diff --git a/test/io/write_gate_level_layout.cpp b/test/io/write_gate_level_layout.cpp index 677953b39..e3ef6a7ff 100644 --- a/test/io/write_gate_level_layout.cpp +++ b/test/io/write_gate_level_layout.cpp @@ -97,37 +97,48 @@ void check_parsing_equiv_all() check_parsing_equiv(blueprints::clpl()); check_parsing_equiv(blueprints::one_to_five_path_difference_network()); check_parsing_equiv(blueprints::nand_xnor_network()); - check_parsing_equiv_layout(blueprints::straight_wire_gate_layout()); - check_parsing_equiv_layout(blueprints::three_wire_paths_gate_layout()); - check_parsing_equiv_layout(blueprints::xor_maj_gate_layout()); - check_parsing_equiv_layout(blueprints::single_input_tautology_gate_layout()); - check_parsing_equiv_layout(blueprints::tautology_gate_layout()); - check_parsing_equiv_layout(blueprints::and_or_gate_layout()); - check_parsing_equiv_layout(blueprints::and_or_gate_layout()); - check_parsing_equiv_layout(blueprints::and_or_gate_layout()); - check_parsing_equiv_layout(blueprints::and_or_gate_layout()); - check_parsing_equiv_layout(blueprints::and_or_gate_layout()); - check_parsing_equiv_layout(blueprints::and_or_gate_layout()); - check_parsing_equiv_layout(blueprints::and_or_gate_layout()); - check_parsing_equiv_layout(blueprints::and_or_gate_layout()); - check_parsing_equiv_layout(blueprints::and_or_gate_layout()); - check_parsing_equiv_layout(blueprints::and_not_gate_layout()); - check_parsing_equiv_layout(blueprints::or_not_gate_layout()); - check_parsing_equiv_layout(blueprints::use_and_gate_layout()); - check_parsing_equiv_layout(blueprints::res_maj_gate_layout()); - check_parsing_equiv_layout(blueprints::res_tautology_gate_layout()); - check_parsing_equiv_layout(blueprints::open_tautology_gate_layout()); - check_parsing_equiv_layout(blueprints::crossing_layout()); - check_parsing_equiv_layout(blueprints::fanout_layout()); - check_parsing_equiv_layout(blueprints::unbalanced_and_layout()); - check_parsing_equiv_layout(blueprints::shifted_cart_and_or_inv_gate_layout()); - check_parsing_equiv_layout(blueprints::row_clocked_and_xor_gate_layout()); - check_parsing_equiv_layout(blueprints::optimization_layout()); - check_parsing_equiv_layout(blueprints::optimization_layout_corner_case_outputs_1()); - check_parsing_equiv_layout(blueprints::optimization_layout_corner_case_outputs_2()); } -TEST_CASE("Write empty gate_level layout", "[fcn]") +void check_parsing_equiv_layout_all() +{ + check_parsing_equiv_layout(blueprints::straight_wire_gate_layout()); + check_parsing_equiv_layout(blueprints::three_wire_paths_gate_layout()); + check_parsing_equiv_layout(blueprints::xor_maj_gate_layout()); + check_parsing_equiv_layout(blueprints::single_input_tautology_gate_layout()); + check_parsing_equiv_layout(blueprints::tautology_gate_layout()); + check_parsing_equiv_layout(blueprints::and_or_gate_layout()); + check_parsing_equiv_layout(blueprints::and_or_gate_layout()); + check_parsing_equiv_layout( + blueprints::and_or_gate_layout()); + check_parsing_equiv_layout(blueprints::and_or_gate_layout()); + check_parsing_equiv_layout( + blueprints::and_or_gate_layout()); + check_parsing_equiv_layout(blueprints::and_or_gate_layout()); + check_parsing_equiv_layout(blueprints::and_or_gate_layout()); + check_parsing_equiv_layout(blueprints::and_or_gate_layout()); + check_parsing_equiv_layout(blueprints::and_or_gate_layout()); + check_parsing_equiv_layout(blueprints::and_not_gate_layout()); + check_parsing_equiv_layout(blueprints::or_not_gate_layout()); + check_parsing_equiv_layout(blueprints::use_and_gate_layout()); + check_parsing_equiv_layout(blueprints::res_maj_gate_layout()); + check_parsing_equiv_layout(blueprints::res_tautology_gate_layout()); + check_parsing_equiv_layout( + blueprints::open_tautology_gate_layout()); + check_parsing_equiv_layout(blueprints::crossing_layout()); + check_parsing_equiv_layout(blueprints::fanout_layout()); + check_parsing_equiv_layout(blueprints::unbalanced_and_layout()); + check_parsing_equiv_layout( + blueprints::shifted_cart_and_or_inv_gate_layout()); + check_parsing_equiv_layout( + blueprints::row_clocked_and_xor_gate_layout()); + check_parsing_equiv_layout(blueprints::optimization_layout()); + check_parsing_equiv_layout( + blueprints::optimization_layout_corner_case_outputs_1()); + check_parsing_equiv_layout( + blueprints::optimization_layout_corner_case_outputs_2()); +} + +TEST_CASE("Write empty gate_level layout", "[write-gate-level-layout]") { using gate_layout = gate_level_layout>>>; @@ -142,9 +153,10 @@ TEST_CASE("Write empty gate_level layout", "[fcn]") compare_written_and_read_layout(layout, read_layout); } -TEST_CASE("Write and read layouts", "[fcn]") +TEST_CASE("Write and read layouts", "[write-gate-level-layout]") { using gate_layout = gate_level_layout>>>; check_parsing_equiv_all(); + check_parsing_equiv_layout_all(); } From 22f44b85077c31ce9e5d447fc1e4c6cb80b69d9c Mon Sep 17 00:00:00 2001 From: Simon Hofmann Date: Thu, 5 Oct 2023 09:49:03 +0200 Subject: [PATCH 27/36] second batch of todos --- include/fiction/io/read_gate_level_layout.hpp | 209 +++++++++++------- .../fiction/io/write_gate_level_layout.hpp | 2 +- test/utils/blueprints/layout_blueprints.hpp | 1 + 3 files changed, 127 insertions(+), 85 deletions(-) diff --git a/include/fiction/io/read_gate_level_layout.hpp b/include/fiction/io/read_gate_level_layout.hpp index 30f88bdc0..fa26c0534 100644 --- a/include/fiction/io/read_gate_level_layout.hpp +++ b/include/fiction/io/read_gate_level_layout.hpp @@ -99,10 +99,11 @@ class read_gate_level_layout_impl auto* const topology = layout->FirstChildElement("topology"); if (topology != nullptr && topology->GetText()) { - const auto topology_name = topology->GetText(); - std::unordered_set shifted_cartesian{"odd_row_cartesian", "even_row_cartesian", - "odd_column_cartesian", "even_column_cartesian"}; - std::unordered_set hex{"odd_row_hex", "even_row_hex", "odd_column_hex", "even_column_hex"}; + const auto topology_name = topology->GetText(); + static const std::array shifted_cartesian{"odd_row_cartesian", "even_row_cartesian", + "odd_column_cartesian", "even_column_cartesian"}; + static const std::array hex{"odd_row_hex", "even_row_hex", "odd_column_hex", + "even_column_hex"}; if (std::strcmp(topology_name, "cartesian") == 0) { @@ -111,7 +112,8 @@ class read_gate_level_layout_impl throw gate_level_parsing_error("Error parsing gate_level file: Lyt is not a cartesian layout"); } } - else if (shifted_cartesian.find(topology_name) != shifted_cartesian.end()) + else if (std::find(std::begin(shifted_cartesian), std::end(shifted_cartesian), topology_name) != + shifted_cartesian.end()) { if constexpr (is_shifted_cartesian_layout_v) { @@ -154,7 +156,7 @@ class read_gate_level_layout_impl "Error parsing gate_level file: Lyt is not a shifted_cartesian layout"); } } - else if (hex.find(topology_name) != hex.end()) + else if (std::find(std::begin(hex), std::end(hex), topology_name) != hex.end()) { if constexpr (is_hexagonal_layout_v) { @@ -262,62 +264,56 @@ class read_gate_level_layout_impl const auto clocking_scheme = get_clocking_scheme(clocking_scheme_name->GetText()); if (clocking_scheme.has_value()) { - if (strcmp(clocking_scheme_name->GetText(), "OPEN") == 0) + lyt.replace_clocking_scheme(*clocking_scheme); + auto* const clock_zones = clocking->FirstChildElement("zones"); + if (clock_zones != nullptr) { - auto* const clock_zones = clocking->FirstChildElement("zones"); - if (clock_zones != nullptr) + for (const auto* clock_zone = clock_zones->FirstChildElement("zone"); clock_zone != nullptr; + clock_zone = clock_zone->NextSiblingElement("zone")) { - for (const auto* clock_zone = clock_zones->FirstChildElement("zone"); clock_zone != nullptr; - clock_zone = clock_zone->NextSiblingElement("zone")) + auto* const clocking_zone_x = clock_zone->FirstChildElement("x"); + int x_coord = 0; + if (clocking_zone_x != nullptr && clocking_zone_x->GetText()) { - auto* const clocking_zone_x = clock_zone->FirstChildElement("x"); - int x_coord = 0; - if (clocking_zone_x != nullptr && clocking_zone_x->GetText()) - { - x_coord = std::stoi(clocking_zone_x->GetText()); - } - else - { - throw gate_level_parsing_error( - "Error parsing gate_level file: no element 'x' in 'zone'"); - } - - auto* const clocking_zone_y = clock_zone->FirstChildElement("y"); - int y_coord = 0; - if (clocking_zone_y != nullptr && clocking_zone_y->GetText()) - { - y_coord = std::stoi(clocking_zone_y->GetText()); - } - else - { - throw gate_level_parsing_error( - "Error parsing gate_level file: no element 'y' in 'zone'"); - } - - auto* const clocking_zone_clock = clock_zone->FirstChildElement("clock"); - uint8_t clock = 0; - if (clocking_zone_clock != nullptr && clocking_zone_clock->GetText()) - { - clock = static_cast(*clocking_zone_clock->GetText()); - } - else - { - throw gate_level_parsing_error( - "Error parsing gate_level file: no element 'clock' in 'zone'"); - } - - lyt.assign_clock_number({x_coord, y_coord}, clock); + x_coord = std::stoi(clocking_zone_x->GetText()); } - } - else - { - throw gate_level_parsing_error( - "Error parsing gate_level file: no element 'zones' in 'clocking'"); + else + { + throw gate_level_parsing_error( + "Error parsing gate_level file: no element 'x' in 'zone'"); + } + + auto* const clocking_zone_y = clock_zone->FirstChildElement("y"); + int y_coord = 0; + if (clocking_zone_y != nullptr && clocking_zone_y->GetText()) + { + y_coord = std::stoi(clocking_zone_y->GetText()); + } + else + { + throw gate_level_parsing_error( + "Error parsing gate_level file: no element 'y' in 'zone'"); + } + + auto* const clocking_zone_clock = clock_zone->FirstChildElement("clock"); + uint8_t clock = 0; + if (clocking_zone_clock != nullptr && clocking_zone_clock->GetText()) + { + clock = static_cast(*clocking_zone_clock->GetText()); + } + else + { + throw gate_level_parsing_error( + "Error parsing gate_level file: no element 'clock' in 'zone'"); + } + + lyt.assign_clock_number({x_coord, y_coord}, clock); } } - else + else if (strcmp(clocking_scheme_name->GetText(), "OPEN") == 0) { - lyt.replace_clocking_scheme(*clocking_scheme); + throw gate_level_parsing_error( + "Error parsing gate_level file: no element 'zones' in 'clocking'"); } } else @@ -478,7 +474,10 @@ class read_gate_level_layout_impl { if (gate.type == "PI") { - lyt.create_pi(gate.name, location); + if constexpr (mockturtle::has_create_pi_v) + { + lyt.create_pi(gate.name, location); + } } else { @@ -495,23 +494,35 @@ class read_gate_level_layout_impl if (gate.type == "PO") { - lyt.create_po(incoming_signal, gate.name, location); + if constexpr (mockturtle::has_create_po_v) + { + lyt.create_po(incoming_signal, gate.name, location); + } } else if (gate.type == "BUF") { - lyt.create_buf(incoming_signal, location); + if constexpr (mockturtle::has_create_buf_v) + { + lyt.create_buf(incoming_signal, location); + } } else if (gate.type == "INV") { - lyt.create_not(incoming_signal, location); + if constexpr (mockturtle::has_create_not_v) + { + lyt.create_not(incoming_signal, location); + } } else if (std::all_of(gate.type.begin(), gate.type.end(), ::isxdigit)) { - kitty::dynamic_truth_table tt_t(1u); - kitty::create_from_hex_string(tt_t, gate.type); - lyt.create_node({incoming_signal}, tt_t, location); + if constexpr (mockturtle::has_create_node_v) + { + kitty::dynamic_truth_table tt_t(1u); + kitty::create_from_hex_string(tt_t, gate.type); + lyt.create_node({incoming_signal}, tt_t, location); + } } else { @@ -532,38 +543,59 @@ class read_gate_level_layout_impl if (gate.type == "AND") { - lyt.create_and(incoming_signal_1, incoming_signal_2, location); + if constexpr (mockturtle::has_create_and_v) + { + lyt.create_and(incoming_signal_1, incoming_signal_2, location); + } } else if (gate.type == "NAND") { - lyt.create_nand(incoming_signal_1, incoming_signal_2, location); + if constexpr (mockturtle::has_create_nand_v) + { + lyt.create_nand(incoming_signal_1, incoming_signal_2, location); + } } else if (gate.type == "OR") { - lyt.create_or(incoming_signal_1, incoming_signal_2, location); + if constexpr (mockturtle::has_create_or_v) + { + lyt.create_or(incoming_signal_1, incoming_signal_2, location); + } } else if (gate.type == "NOR") { - lyt.create_nor(incoming_signal_1, incoming_signal_2, location); + if constexpr (mockturtle::has_create_nor_v) + { + lyt.create_nor(incoming_signal_1, incoming_signal_2, location); + } } else if (gate.type == "XOR") { - lyt.create_xor(incoming_signal_1, incoming_signal_2, location); + if constexpr (mockturtle::has_create_xor_v) + { + lyt.create_xor(incoming_signal_1, incoming_signal_2, location); + } } else if (gate.type == "XNOR") { - lyt.create_xnor(incoming_signal_1, incoming_signal_2, location); + if constexpr (mockturtle::has_create_xnor_v) + { + lyt.create_xnor(incoming_signal_1, incoming_signal_2, location); + } } else if (std::all_of(gate.type.begin(), gate.type.end(), ::isxdigit)) { - kitty::dynamic_truth_table tt_t(2u); - kitty::create_from_hex_string(tt_t, gate.type); - lyt.create_node({incoming_signal_1, incoming_signal_2}, tt_t, location); + if constexpr (mockturtle::has_create_node_v) + { + kitty::dynamic_truth_table tt_t(2u); + kitty::create_from_hex_string(tt_t, gate.type); + lyt.create_node({incoming_signal_1, incoming_signal_2}, tt_t, location); + } } else { @@ -585,13 +617,19 @@ class read_gate_level_layout_impl if (gate.type == "MAJ") { - lyt.create_maj(incoming_signal_1, incoming_signal_2, incoming_signal_3, location); + if constexpr (mockturtle::has_create_maj_v) + { + lyt.create_maj(incoming_signal_1, incoming_signal_2, incoming_signal_3, location); + } } else if (std::all_of(gate.type.begin(), gate.type.end(), ::isxdigit)) { - kitty::dynamic_truth_table tt_t(3u); - kitty::create_from_hex_string(tt_t, gate.type); - lyt.create_node({incoming_signal_1, incoming_signal_2, incoming_signal_3}, tt_t, location); + if constexpr (mockturtle::has_create_node_v) + { + kitty::dynamic_truth_table tt_t(3u); + kitty::create_from_hex_string(tt_t, gate.type); + lyt.create_node({incoming_signal_1, incoming_signal_2, incoming_signal_3}, tt_t, location); + } } else { @@ -601,17 +639,20 @@ class read_gate_level_layout_impl } else if (std::all_of(gate.type.begin(), gate.type.end(), ::isxdigit)) { - const auto num_incoming_signals = gate.incoming.size(); - std::vector> incoming_signals{}; - for (std::size_t i = 0; i < num_incoming_signals; i++) + if constexpr (mockturtle::has_create_node_v) { - tile incoming_tile_i{gate.incoming[i].x, gate.incoming[i].y, gate.incoming[i].z}; - auto incoming_signal_i = lyt.make_signal(lyt.get_node(incoming_tile_i)); - incoming_signals.push_back(incoming_signal_i); + const auto num_incoming_signals = gate.incoming.size(); + std::vector> incoming_signals{}; + for (std::size_t i = 0; i < num_incoming_signals; i++) + { + tile incoming_tile_i{gate.incoming[i].x, gate.incoming[i].y, gate.incoming[i].z}; + auto incoming_signal_i = lyt.make_signal(lyt.get_node(incoming_tile_i)); + incoming_signals.push_back(incoming_signal_i); + } + kitty::dynamic_truth_table tt_t(static_cast(num_incoming_signals)); + kitty::create_from_hex_string(tt_t, gate.type); + lyt.create_node({incoming_signals}, tt_t, location); } - kitty::dynamic_truth_table tt_t(static_cast(num_incoming_signals)); - kitty::create_from_hex_string(tt_t, gate.type); - lyt.create_node({incoming_signals}, tt_t, location); } else { diff --git a/include/fiction/io/write_gate_level_layout.hpp b/include/fiction/io/write_gate_level_layout.hpp index 0cc174075..3477fc13c 100644 --- a/include/fiction/io/write_gate_level_layout.hpp +++ b/include/fiction/io/write_gate_level_layout.hpp @@ -152,7 +152,7 @@ class write_gate_level_layout_impl const auto clocking_scheme = lyt.get_clocking_scheme(); os << fmt::format(fcn::CLOCKING_SCHEME_NAME, clocking_scheme.name); - if (clocking_scheme.name == "OPEN") + if (clocking_scheme.name == "OPEN" || !clocking_scheme.is_regular()) { os << fcn::OPEN_CLOCK_ZONES; for (uint64_t x = 0; x <= lyt.x(); ++x) diff --git a/test/utils/blueprints/layout_blueprints.hpp b/test/utils/blueprints/layout_blueprints.hpp index efb7532b2..82302a4bd 100644 --- a/test/utils/blueprints/layout_blueprints.hpp +++ b/test/utils/blueprints/layout_blueprints.hpp @@ -174,6 +174,7 @@ template GateLyt res_maj_gate_layout() noexcept { GateLyt layout{typename GateLyt::aspect_ratio{2, 2, 0}, fiction::res_clocking()}; + layout.assign_clock_number({0, 0}, static_cast(0)); const auto x1 = layout.create_pi("x1", {0, 1}); const auto x2 = layout.create_pi("x2", {1, 0}); From cbed85c475559e0c8a63fc99af01ccce0236c8df Mon Sep 17 00:00:00 2001 From: Simon Hofmann Date: Thu, 5 Oct 2023 12:42:52 +0200 Subject: [PATCH 28/36] use .fgl file extension --- ...e_level_layout.hpp => read_fgl_layout.hpp} | 185 +++---- ..._level_layout.hpp => write_fgl_layout.hpp} | 36 +- ...e_level_layout.cpp => read_fgl_layout.cpp} | 524 +++++++++--------- ..._level_layout.cpp => write_fgl_layout.cpp} | 23 +- 4 files changed, 377 insertions(+), 391 deletions(-) rename include/fiction/io/{read_gate_level_layout.hpp => read_fgl_layout.hpp} (75%) rename include/fiction/io/{write_gate_level_layout.hpp => write_fgl_layout.hpp} (93%) rename test/io/{read_gate_level_layout.cpp => read_fgl_layout.cpp} (84%) rename test/io/{write_gate_level_layout.cpp => write_fgl_layout.cpp} (91%) diff --git a/include/fiction/io/read_gate_level_layout.hpp b/include/fiction/io/read_fgl_layout.hpp similarity index 75% rename from include/fiction/io/read_gate_level_layout.hpp rename to include/fiction/io/read_fgl_layout.hpp index fa26c0534..5188af57c 100644 --- a/include/fiction/io/read_gate_level_layout.hpp +++ b/include/fiction/io/read_fgl_layout.hpp @@ -2,8 +2,8 @@ // Created by simon on 25.09.23. // -#ifndef FICTION_READ_GATE_LEVEL_LAYOUT_HPP -#define FICTION_READ_GATE_LEVEL_LAYOUT_HPP +#ifndef FICTION_READ_FGL_LAYOUT_HPP +#define FICTION_READ_FGL_LAYOUT_HPP #include "fiction/layouts/cartesian_layout.hpp" #include "fiction/layouts/clocked_layout.hpp" @@ -32,59 +32,59 @@ namespace fiction { /** - * Exception thrown when an error occurs during parsing of a file containing a gate_level layout. + * Exception thrown when an error occurs during parsing of a .fgl file containing a gate-level layout. */ -class gate_level_parsing_error : public std::runtime_error +class fgl_parsing_error : public std::runtime_error { public: /** - * Constructs a gate_level_parsing_error object with the given error message. + * Constructs a fgl_parsing_error object with the given error message. * * @param msg The error message describing the parsing error. */ - explicit gate_level_parsing_error(const std::string_view& msg) noexcept : std::runtime_error(msg.data()) {} + explicit fgl_parsing_error(const std::string_view& msg) noexcept : std::runtime_error(msg.data()) {} }; namespace detail { template -class read_gate_level_layout_impl +class read_fgl_layout_impl { public: - read_gate_level_layout_impl(std::istream& s, const std::string_view& name) : lyt{}, is{s} + read_fgl_layout_impl(std::istream& s, const std::string_view& name) : lyt{}, is{s} { set_name(lyt, name); } - read_gate_level_layout_impl(Lyt& tgt, std::istream& s) : lyt{tgt}, is{s} {} + read_fgl_layout_impl(Lyt& tgt, std::istream& s) : lyt{tgt}, is{s} {} Lyt run() { // tinyXML2 does not support std::istream, so we have to read the whole file into a string first std::stringstream buffer{}; buffer << is.rdbuf(); - const std::string gate_level_content{buffer.str()}; + const std::string fgl_content{buffer.str()}; // parse xml file tinyxml2::XMLDocument xml_document{}; - xml_document.Parse(gate_level_content.c_str()); + xml_document.Parse(fgl_content.c_str()); if (xml_document.ErrorID() != 0) { - throw gate_level_parsing_error(fmt::format("Error parsing gate_level file: {}", xml_document.ErrorName())); + throw fgl_parsing_error(fmt::format("Error parsing FGL file: {}", xml_document.ErrorName())); } - auto* const fcn_root = xml_document.FirstChildElement("fcn"); - if (fcn_root == nullptr) + auto* const fgl_root = xml_document.FirstChildElement("fgl"); + if (fgl_root == nullptr) { - throw gate_level_parsing_error("Error parsing gate_level file: no root element 'fcn'"); + throw fgl_parsing_error("Error parsing FGL file: no root element 'fgl'"); } - auto* const layout = fcn_root->FirstChildElement("layout"); + auto* const layout = fgl_root->FirstChildElement("layout"); if (layout == nullptr) { - throw gate_level_parsing_error("Error parsing gate_level file: no element 'layout'"); + throw fgl_parsing_error("Error parsing FGL file: no element 'layout'"); } // set layout name @@ -109,7 +109,7 @@ class read_gate_level_layout_impl { if constexpr (!is_cartesian_layout_v) { - throw gate_level_parsing_error("Error parsing gate_level file: Lyt is not a cartesian layout"); + throw fgl_parsing_error("Error parsing FGL file: Lyt is not a cartesian layout"); } } else if (std::find(std::begin(shifted_cartesian), std::end(shifted_cartesian), topology_name) != @@ -121,39 +121,36 @@ class read_gate_level_layout_impl { if constexpr (!has_odd_row_cartesian_arrangement_v) { - throw gate_level_parsing_error( - "Error parsing gate_level file: Lyt is not an odd_row_cartesian layout"); + throw fgl_parsing_error("Error parsing FGL file: Lyt is not an odd_row_cartesian layout"); } } else if (std::strcmp(topology_name, "even_row_cartesian") == 0) { if constexpr (!has_even_row_cartesian_arrangement_v) { - throw gate_level_parsing_error( - "Error parsing gate_level file: Lyt is not an even_row_cartesian layout"); + throw fgl_parsing_error("Error parsing FGL file: Lyt is not an even_row_cartesian layout"); } } else if (std::strcmp(topology_name, "odd_column_cartesian") == 0) { if constexpr (!has_odd_column_cartesian_arrangement_v) { - throw gate_level_parsing_error( - "Error parsing gate_level file: Lyt is not an odd_column_cartesian layout"); + throw fgl_parsing_error( + "Error parsing FGL file: Lyt is not an odd_column_cartesian layout"); } } else if (std::strcmp(topology_name, "even_column_cartesian") == 0) { if constexpr (!has_even_column_cartesian_arrangement_v) { - throw gate_level_parsing_error( - "Error parsing gate_level file: Lyt is not an even_column_cartesian layout"); + throw fgl_parsing_error( + "Error parsing FGL file: Lyt is not an even_column_cartesian layout"); } } } else { - throw gate_level_parsing_error( - "Error parsing gate_level file: Lyt is not a shifted_cartesian layout"); + throw fgl_parsing_error("Error parsing FGL file: Lyt is not a shifted_cartesian layout"); } } else if (std::find(std::begin(hex), std::end(hex), topology_name) != hex.end()) @@ -164,49 +161,44 @@ class read_gate_level_layout_impl { if constexpr (!has_odd_row_hex_arrangement_v) { - throw gate_level_parsing_error( - "Error parsing gate_level file: Lyt is not an odd_row_hex layout"); + throw fgl_parsing_error("Error parsing FGL file: Lyt is not an odd_row_hex layout"); } } else if (std::strcmp(topology_name, "even_row_hex") == 0) { if constexpr (!has_even_row_hex_arrangement_v) { - throw gate_level_parsing_error( - "Error parsing gate_level file: Lyt is not an even_row_hex layout"); + throw fgl_parsing_error("Error parsing FGL file: Lyt is not an even_row_hex layout"); } } else if (std::strcmp(topology_name, "odd_column_hex") == 0) { if constexpr (!has_odd_column_hex_arrangement_v) { - throw gate_level_parsing_error( - "Error parsing gate_level file: Lyt is not an odd_column_hex layout"); + throw fgl_parsing_error("Error parsing FGL file: Lyt is not an odd_column_hex layout"); } } else if (std::strcmp(topology_name, "even_column_hex") == 0) { if constexpr (!has_even_column_hex_arrangement_v) { - throw gate_level_parsing_error( - "Error parsing gate_level file: Lyt is not an even_column_hex layout"); + throw fgl_parsing_error("Error parsing FGL file: Lyt is not an even_column_hex layout"); } } } else { - throw gate_level_parsing_error("Error parsing gate_level file: Lyt is not a hexagonal layout"); + throw fgl_parsing_error("Error parsing FGL file: Lyt is not a hexagonal layout"); } } else { - throw gate_level_parsing_error( - fmt::format("Error parsing gate_level file: unknown topology: {}", topology_name)); + throw fgl_parsing_error(fmt::format("Error parsing FGL file: unknown topology: {}", topology_name)); } } else { - throw gate_level_parsing_error("Error parsing gate_level file: no element 'topology' in 'layout'"); + throw fgl_parsing_error("Error parsing FGL file: no element 'topology' in 'layout'"); } // set layout size @@ -221,7 +213,7 @@ class read_gate_level_layout_impl } else { - throw gate_level_parsing_error("Error parsing gate_level file: no element 'x' in 'size'"); + throw fgl_parsing_error("Error parsing FGL file: no element 'x' in 'size'"); } auto* const size_y = size->FirstChildElement("y"); @@ -232,7 +224,7 @@ class read_gate_level_layout_impl } else { - throw gate_level_parsing_error("Error parsing gate_level file: no element 'y' in 'size'"); + throw fgl_parsing_error("Error parsing FGL file: no element 'y' in 'size'"); } auto* const size_z = size->FirstChildElement("z"); @@ -243,7 +235,7 @@ class read_gate_level_layout_impl } else { - throw gate_level_parsing_error("Error parsing gate_level file: no element 'z' in 'size'"); + throw fgl_parsing_error("Error parsing FGL file: no element 'z' in 'size'"); } const aspect_ratio ar{x, y, z}; @@ -251,7 +243,7 @@ class read_gate_level_layout_impl } else { - throw gate_level_parsing_error("Error parsing gate_level file: no element 'size' in 'layout'"); + throw fgl_parsing_error("Error parsing FGL file: no element 'size' in 'layout'"); } // set clocking scheme @@ -265,6 +257,8 @@ class read_gate_level_layout_impl if (clocking_scheme.has_value()) { lyt.replace_clocking_scheme(*clocking_scheme); + static const std::array open_clocking_schemes{"OPEN", "OPEN3", "OPEN4"}; + auto* const clock_zones = clocking->FirstChildElement("zones"); if (clock_zones != nullptr) { @@ -279,8 +273,7 @@ class read_gate_level_layout_impl } else { - throw gate_level_parsing_error( - "Error parsing gate_level file: no element 'x' in 'zone'"); + throw fgl_parsing_error("Error parsing FGL file: no element 'x' in 'zone'"); } auto* const clocking_zone_y = clock_zone->FirstChildElement("y"); @@ -291,8 +284,7 @@ class read_gate_level_layout_impl } else { - throw gate_level_parsing_error( - "Error parsing gate_level file: no element 'y' in 'zone'"); + throw fgl_parsing_error("Error parsing FGL file: no element 'y' in 'zone'"); } auto* const clocking_zone_clock = clock_zone->FirstChildElement("clock"); @@ -303,38 +295,37 @@ class read_gate_level_layout_impl } else { - throw gate_level_parsing_error( - "Error parsing gate_level file: no element 'clock' in 'zone'"); + throw fgl_parsing_error("Error parsing FGL file: no element 'clock' in 'zone'"); } lyt.assign_clock_number({x_coord, y_coord}, clock); } } - else if (strcmp(clocking_scheme_name->GetText(), "OPEN") == 0) + else if (std::find(std::begin(open_clocking_schemes), std::end(open_clocking_schemes), + clocking_scheme_name->GetText()) != open_clocking_schemes.end()) { - throw gate_level_parsing_error( - "Error parsing gate_level file: no element 'zones' in 'clocking'"); + throw fgl_parsing_error("Error parsing FGL file: no element 'zones' in 'clocking'"); } } else { - throw gate_level_parsing_error(fmt::format( - "Error parsing gate_level file: unknown clocking scheme: {}", clocking_scheme_name->GetText())); + throw fgl_parsing_error(fmt::format("Error parsing FGL file: unknown clocking scheme: {}", + clocking_scheme_name->GetText())); } } else { - throw gate_level_parsing_error("Error parsing gate_level file: no element 'name' in 'clocking'"); + throw fgl_parsing_error("Error parsing FGL file: no element 'name' in 'clocking'"); } } else { - throw gate_level_parsing_error("Error parsing gate_level file: no element 'clocking' in 'layout'"); + throw fgl_parsing_error("Error parsing FGL file: no element 'clocking' in 'layout'"); } // parse layout gates std::vector gates{}; - auto* const gates_xml = fcn_root->FirstChildElement("gates"); + auto* const gates_xml = fgl_root->FirstChildElement("gates"); if (gates_xml != nullptr) { for (const auto* gate_xml = gates_xml->FirstChildElement("gate"); gate_xml != nullptr; @@ -349,7 +340,7 @@ class read_gate_level_layout_impl } else { - throw gate_level_parsing_error("Error parsing gate_level file: no element 'id' in 'gate'"); + throw fgl_parsing_error("Error parsing FGL file: no element 'id' in 'gate'"); } auto* const gate_type = gate_xml->FirstChildElement("type"); @@ -359,7 +350,7 @@ class read_gate_level_layout_impl } else { - throw gate_level_parsing_error("Error parsing gate_level file: no element 'type' in 'gate'"); + throw fgl_parsing_error("Error parsing FGL file: no element 'type' in 'gate'"); } if (gate.type == "PI" || gate.type == "PO") @@ -371,15 +362,14 @@ class read_gate_level_layout_impl } else { - throw gate_level_parsing_error( - "Error parsing gate_level file: no element 'name' in 'gate' for input/output"); + throw fgl_parsing_error("Error parsing FGL file: no element 'name' in 'gate' for input/output"); } } auto* const loc = gate_xml->FirstChildElement("loc"); if (loc == nullptr) { - throw gate_level_parsing_error("Error parsing gate_level file: no element 'loc'"); + throw fgl_parsing_error("Error parsing FGL file: no element 'loc'"); } // get x-coordinate @@ -390,7 +380,7 @@ class read_gate_level_layout_impl } else { - throw gate_level_parsing_error("Error parsing gate_level file: no element 'x' in 'loc'"); + throw fgl_parsing_error("Error parsing FGL file: no element 'x' in 'loc'"); } // get y-coordinate @@ -401,7 +391,7 @@ class read_gate_level_layout_impl } else { - throw gate_level_parsing_error("Error parsing gate_level file: no element 'y' in 'loc'"); + throw fgl_parsing_error("Error parsing FGL file: no element 'y' in 'loc'"); } // get z-coordinate @@ -412,7 +402,7 @@ class read_gate_level_layout_impl } else { - throw gate_level_parsing_error("Error parsing gate_level file: no element 'z' in 'loc'"); + throw fgl_parsing_error("Error parsing FGL file: no element 'z' in 'loc'"); } auto* const incoming_signals = gate_xml->FirstChildElement("incoming"); @@ -431,7 +421,7 @@ class read_gate_level_layout_impl } else { - throw gate_level_parsing_error("Error parsing gate_level file: no element 'x' in 'signal'"); + throw fgl_parsing_error("Error parsing FGL file: no element 'x' in 'signal'"); } // get y-coordinate of incoming signal @@ -442,7 +432,7 @@ class read_gate_level_layout_impl } else { - throw gate_level_parsing_error("Error parsing gate_level file: no element 'y' in 'signal'"); + throw fgl_parsing_error("Error parsing FGL file: no element 'y' in 'signal'"); } // get z-coordinate of incoming signal @@ -453,7 +443,7 @@ class read_gate_level_layout_impl } else { - throw gate_level_parsing_error("Error parsing gate_level file: no element 'z' in 'signal'"); + throw fgl_parsing_error("Error parsing FGL file: no element 'z' in 'signal'"); } gate.incoming.push_back(incoming); @@ -481,8 +471,8 @@ class read_gate_level_layout_impl } else { - throw gate_level_parsing_error( - fmt::format("Error parsing gate_level file: unknown gate type: {}", gate.type)); + throw fgl_parsing_error( + fmt::format("Error parsing FGL file: unknown gate type: {}", gate.type)); } } @@ -526,8 +516,8 @@ class read_gate_level_layout_impl } else { - throw gate_level_parsing_error( - fmt::format("Error parsing gate_level file: unknown gate type: {}", gate.type)); + throw fgl_parsing_error( + fmt::format("Error parsing FGL file: unknown gate type: {}", gate.type)); } } @@ -599,8 +589,8 @@ class read_gate_level_layout_impl } else { - throw gate_level_parsing_error( - fmt::format("Error parsing gate_level file: unknown gate type: {}", gate.type)); + throw fgl_parsing_error( + fmt::format("Error parsing FGL file: unknown gate type: {}", gate.type)); } } else if (gate.incoming.size() == 3) @@ -633,8 +623,8 @@ class read_gate_level_layout_impl } else { - throw gate_level_parsing_error( - fmt::format("Error parsing gate_level file: unknown gate type: {}", gate.type)); + throw fgl_parsing_error( + fmt::format("Error parsing FGL file: unknown gate type: {}", gate.type)); } } else if (std::all_of(gate.type.begin(), gate.type.end(), ::isxdigit)) @@ -656,8 +646,7 @@ class read_gate_level_layout_impl } else { - throw gate_level_parsing_error( - fmt::format("Error parsing gate_level file: unknown gate type: {}", gate.type)); + throw fgl_parsing_error(fmt::format("Error parsing FGL file: unknown gate type: {}", gate.type)); } } } @@ -720,62 +709,62 @@ class read_gate_level_layout_impl } // namespace detail /** - * Reads a gate-level layout from a gate_level file provided as an input stream. + * Reads a gate-level layout from an FGL file provided as an input stream. * - * May throw a `gate_level_parsing_exception` if the gate_level file is malformed. + * May throw a `fgl_parsing_exception` if the FGL file is malformed. * * @tparam Lyt The layout type to be created from an input. * @param is The input stream to read from. * @param name The name to give to the generated layout. */ template -[[nodiscard]] Lyt read_gate_level_layout(std::istream& is, const std::string_view& name = "") +[[nodiscard]] Lyt read_fgl_layout(std::istream& is, const std::string_view& name = "") { static_assert(is_coordinate_layout_v, "Lyt is not a coordinate layout"); static_assert(is_tile_based_layout_v, "Lyt is not a tile-based layout"); static_assert(is_clocked_layout_v, "Lyt is not a clocked layout"); static_assert(is_gate_level_layout_v, "Lyt is not a gate-level layout"); - detail::read_gate_level_layout_impl p{is, name}; + detail::read_fgl_layout_impl p{is, name}; const auto lyt = p.run(); return lyt; } /** - * Reads a gate-level layout from an gate_level file provided as an input stream. + * Reads a gate-level layout from an FGL file provided as an input stream. * - * May throw a `gate_level_parsing_exception` if the gate_level file is malformed. + * May throw a `fgl_parsing_exception` if the FGL file is malformed. * - * This is an in-place version of read_gate_level_layout that utilizes the given layout as a target to write to. + * This is an in-place version of read_fgl_layout that utilizes the given layout as a target to write to. * * @tparam Lyt The layout type to be used as input. * @param lyt The layout to write to. * @param is The input stream to read from. */ template -void read_gate_level_layout(Lyt& lyt, std::istream& is) +void read_fgl_layout(Lyt& lyt, std::istream& is) { static_assert(is_coordinate_layout_v, "Lyt is not a coordinate layout"); static_assert(is_tile_based_layout_v, "Lyt is not a tile-based layout"); static_assert(is_clocked_layout_v, "Lyt is not a clocked layout"); static_assert(is_gate_level_layout_v, "Lyt is not a gate-level layout"); - detail::read_gate_level_layout_impl p{lyt, is}; + detail::read_fgl_layout_impl p{lyt, is}; lyt = p.run(); } /** - * Reads a gate-level layout from a gate_level file provided as an input stream. + * Reads a gate-level layout from an FGL file provided as an input stream. * - * May throw a `gate_level_parsing_exception` if the gate_level file is malformed. + * May throw a `fgl_parsing_exception` if the FGL file is malformed. * * @tparam Lyt The layout type to be created from an input. * @param filename The file name to open and read from. * @param name The name to give to the generated layout. */ template -[[nodiscard]] Lyt read_gate_level_layout(const std::string_view& filename, const std::string_view& name = "") +[[nodiscard]] Lyt read_fgl_layout(const std::string_view& filename, const std::string_view& name = "") { std::ifstream is{filename.data(), std::ifstream::in}; @@ -784,24 +773,24 @@ template throw std::ifstream::failure("could not open file"); } - const auto lyt = read_gate_level_layout(is, name); + const auto lyt = read_fgl_layout(is, name); is.close(); return lyt; } /** - * Reads a gate-level layout from an gate_level file provided as an input stream. + * Reads a gate-level layout from an FGL file provided as an input stream. * - * May throw a `gate_level_parsing_exception` if the gate_level file is malformed. + * May throw a `fgl_parsing_exception` if the FGL file is malformed. * - * This is an in-place version of `read_gate_level_layout` that utilizes the given layout as a target to write to. + * This is an in-place version of `read_fgl_layout` that utilizes the given layout as a target to write to. * * @tparam Lyt The layout type to be used as input. * @param lyt The layout to write to. * @param filename The file name to open and read from. */ template -void read_gate_level_layout(Lyt& lyt, const std::string_view& filename) +void read_fgl_layout(Lyt& lyt, const std::string_view& filename) { std::ifstream is{filename.data(), std::ifstream::in}; @@ -810,10 +799,10 @@ void read_gate_level_layout(Lyt& lyt, const std::string_view& filename) throw std::ifstream::failure("could not open file"); } - read_gate_level_layout(lyt, is); + read_fgl_layout(lyt, is); is.close(); } } // namespace fiction -#endif // FICTION_READ_GATE_LEVEL_LAYOUT_HPP +#endif // FICTION_READ_FGL_LAYOUT_HPP diff --git a/include/fiction/io/write_gate_level_layout.hpp b/include/fiction/io/write_fgl_layout.hpp similarity index 93% rename from include/fiction/io/write_gate_level_layout.hpp rename to include/fiction/io/write_fgl_layout.hpp index 3477fc13c..c9fef4a8d 100644 --- a/include/fiction/io/write_gate_level_layout.hpp +++ b/include/fiction/io/write_fgl_layout.hpp @@ -2,8 +2,8 @@ // Created by simon on 25.09.23. // -#ifndef FICTION_WRITE_GATE_LEVEL_LAYOUT_HPP -#define FICTION_WRITE_GATE_LEVEL_LAYOUT_HPP +#ifndef FICTION_WRITE_FGL_LAYOUT_HPP +#define FICTION_WRITE_FGL_LAYOUT_HPP #include "fiction/layouts/clocked_layout.hpp" #include "fiction/layouts/clocking_scheme.hpp" @@ -35,9 +35,9 @@ namespace detail namespace fcn { -inline constexpr const char* FCN_HEADER = "\n"; -inline constexpr const char* OPEN_FCN = "\n"; -inline constexpr const char* CLOSE_FCN = "\n"; +inline constexpr const char* FGL_HEADER = "\n"; +inline constexpr const char* OPEN_FGL = "\n"; +inline constexpr const char* CLOSE_FGL = "\n"; inline constexpr const char* FICTION_METADATA = " \n" " {}\n" " {}\n" @@ -87,15 +87,15 @@ inline constexpr const char* SIGNAL = " \n" } // namespace fcn template -class write_gate_level_layout_impl +class write_fgl_layout_impl { public: - write_gate_level_layout_impl(const Lyt& src, std::ostream& s) : lyt{src}, os{s} {} + write_fgl_layout_impl(const Lyt& src, std::ostream& s) : lyt{src}, os{s} {} void run() { // metadata - os << fcn::FCN_HEADER << fcn::OPEN_FCN; + os << fcn::FGL_HEADER << fcn::OPEN_FGL; const auto time_str = fmt::format("{:%Y-%m-%d %H:%M:%S}", fmt::localtime(std::time(nullptr))); os << fmt::format(fcn::FICTION_METADATA, FICTION_VERSION, FICTION_REPO, time_str); @@ -152,7 +152,7 @@ class write_gate_level_layout_impl const auto clocking_scheme = lyt.get_clocking_scheme(); os << fmt::format(fcn::CLOCKING_SCHEME_NAME, clocking_scheme.name); - if (clocking_scheme.name == "OPEN" || !clocking_scheme.is_regular()) + if (!clocking_scheme.is_regular()) { os << fcn::OPEN_CLOCK_ZONES; for (uint64_t x = 0; x <= lyt.x(); ++x) @@ -298,7 +298,7 @@ class write_gate_level_layout_impl }); os << fcn::CLOSE_GATES; - os << fcn::CLOSE_FCN; + os << fcn::CLOSE_FGL; } private: @@ -315,7 +315,7 @@ class write_gate_level_layout_impl } // namespace detail /** - * Writes a gate-level layout to a file. + * Writes an FGL layout to a file. * * This overload uses an output stream to write into. * @@ -324,28 +324,28 @@ class write_gate_level_layout_impl * @param os The output stream to write into. */ template -void write_gate_level_layout(const Lyt& lyt, std::ostream& os) +void write_fgl_layout(const Lyt& lyt, std::ostream& os) { static_assert(is_coordinate_layout_v, "Lyt is not a coordinate layout"); static_assert(is_tile_based_layout_v, "Lyt is not a tile-based layout"); static_assert(is_clocked_layout_v, "Lyt is not a clocked layout"); static_assert(is_gate_level_layout_v, "Lyt is not a gate-level layout"); - detail::write_gate_level_layout_impl p{lyt, os}; + detail::write_fgl_layout_impl p{lyt, os}; p.run(); } /** - * Writes a gate-level layout to a file. + * Writes an FGL layout to a file. * * This overload uses a file name to create and write into. * * @tparam Lyt Layout. * @param lyt The layout to be written. - * @param filename The file name to create and write into. + * @param filename The file name to create and write into. Should preferably use the .fgl extension. */ template -void write_gate_level_layout(const Lyt& lyt, const std::string_view& filename) +void write_fgl_layout(const Lyt& lyt, const std::string_view& filename) { std::ofstream os{filename.data(), std::ofstream::out}; @@ -354,10 +354,10 @@ void write_gate_level_layout(const Lyt& lyt, const std::string_view& filename) throw std::ofstream::failure("could not open file"); } - write_gate_level_layout(lyt, os); + write_fgl_layout(lyt, os); os.close(); } } // namespace fiction -#endif // FICTION_WRITE_GATE_LEVEL_LAYOUT_HPP +#endif // FICTION_WRITE_FGL_LAYOUT_HPP diff --git a/test/io/read_gate_level_layout.cpp b/test/io/read_fgl_layout.cpp similarity index 84% rename from test/io/read_gate_level_layout.cpp rename to test/io/read_fgl_layout.cpp index 027229fdc..e2ba0425f 100644 --- a/test/io/read_gate_level_layout.cpp +++ b/test/io/read_fgl_layout.cpp @@ -4,7 +4,7 @@ #include -#include +#include #include #include #include @@ -19,10 +19,10 @@ using namespace fiction; -TEST_CASE("Read empty FCN layout", "[read-gate-level-layout]") +TEST_CASE("Read empty FGL layout", "[read-fgl-layout]") { - static constexpr const char* fcn_layout = "\n" - "\n" + static constexpr const char* fgl_layout = "\n" + "\n" " \n" " Test\n" " cartesian\n" @@ -35,9 +35,9 @@ TEST_CASE("Read empty FCN layout", "[read-gate-level-layout]") " 2DDWave\n" " \n" " \n" - "\n"; + "\n"; - std::istringstream layout_stream{fcn_layout}; + std::istringstream layout_stream{fgl_layout}; const auto check = [](const auto& lyt) { @@ -49,13 +49,13 @@ TEST_CASE("Read empty FCN layout", "[read-gate-level-layout]") }; using gate_layout = gate_level_layout>>>; - check(read_gate_level_layout(layout_stream)); + check(read_fgl_layout(layout_stream)); } -TEST_CASE("Read simple FCN layout", "[read-gate-level-layout]") +TEST_CASE("Read simple FGL layout", "[read-fgl-layout]") { - static constexpr const char* fcn_layout = "\n" - "\n" + static constexpr const char* fgl_layout = "\n" + "\n" " \n" " Test\n" " cartesian\n" @@ -128,9 +128,9 @@ TEST_CASE("Read simple FCN layout", "[read-gate-level-layout]") " \n" " \n" " \n" - "\n"; + "\n"; - std::istringstream layout_stream{fcn_layout}; + std::istringstream layout_stream{fgl_layout}; const auto check = [](const auto& lyt) { @@ -149,13 +149,13 @@ TEST_CASE("Read simple FCN layout", "[read-gate-level-layout]") }; using gate_layout = gate_level_layout>>>; - check(read_gate_level_layout(layout_stream)); + check(read_fgl_layout(layout_stream)); } -TEST_CASE("Parsing error: malformed xml", "[read-gate-level-layout]") +TEST_CASE("Parsing error: malformed xml", "[read-fgl-layout]") { - static constexpr const char* fcn_layout = "\n" - "\n" + static constexpr const char* fgl_layout = "\n" + "\n" " \n" " Test\n" " cartesian\n" @@ -169,15 +169,15 @@ TEST_CASE("Parsing error: malformed xml", "[read-gate-level-layout]") " \n" " \n"; - std::istringstream layout_stream{fcn_layout}; + std::istringstream layout_stream{fgl_layout}; using gate_layout = gate_level_layout>>>; - CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); + CHECK_THROWS_AS(read_fgl_layout(layout_stream), fgl_parsing_error); } -TEST_CASE("Parsing error: no root element 'fcn'", "[read-gate-level-layout]") +TEST_CASE("Parsing error: no root element 'fgl'", "[read-fgl-layout]") { - static constexpr const char* fcn_layout = "\n" + static constexpr const char* fgl_layout = "\n" " \n" " Test\n" " cartesian\n" @@ -191,16 +191,16 @@ TEST_CASE("Parsing error: no root element 'fcn'", "[read-gate-level-layout]") " \n" " \n"; - std::istringstream layout_stream{fcn_layout}; + std::istringstream layout_stream{fgl_layout}; using gate_layout = gate_level_layout>>>; - CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); + CHECK_THROWS_AS(read_fgl_layout(layout_stream), fgl_parsing_error); } -TEST_CASE("Parsing error: no element 'layout' in 'fcn'", "[read-gate-level-layout]") +TEST_CASE("Parsing error: no element 'layout' in 'fgl'", "[read-fgl-layout]") { - static constexpr const char* fcn_layout = "\n" - "\n" + static constexpr const char* fgl_layout = "\n" + "\n" " Test\n" " cartesian\n" " \n" @@ -211,18 +211,18 @@ TEST_CASE("Parsing error: no element 'layout' in 'fcn'", "[read-gate-level-layou " \n" " 2DDWave\n" " \n" - "\n"; + "\n"; - std::istringstream layout_stream{fcn_layout}; + std::istringstream layout_stream{fgl_layout}; using gate_layout = gate_level_layout>>>; - CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); + CHECK_THROWS_AS(read_fgl_layout(layout_stream), fgl_parsing_error); } -TEST_CASE("Parsing error: no element 'clocking' in 'layout'", "[read-gate-level-layout]") +TEST_CASE("Parsing error: no element 'clocking' in 'layout'", "[read-fgl-layout]") { - static constexpr const char* fcn_layout = "\n" - "\n" + static constexpr const char* fgl_layout = "\n" + "\n" " \n" " Test\n" " cartesian\n" @@ -232,18 +232,18 @@ TEST_CASE("Parsing error: no element 'clocking' in 'layout'", "[read-gate-level- " 0\n" " \n" " \n" - "\n"; + "\n"; - std::istringstream layout_stream{fcn_layout}; + std::istringstream layout_stream{fgl_layout}; using gate_layout = gate_level_layout>>>; - CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); + CHECK_THROWS_AS(read_fgl_layout(layout_stream), fgl_parsing_error); } -TEST_CASE("Parsing error: no element 'name' in 'clocking'", "[read-gate-level-layout]") +TEST_CASE("Parsing error: no element 'name' in 'clocking'", "[read-fgl-layout]") { - static constexpr const char* fcn_layout = "\n" - "\n" + static constexpr const char* fgl_layout = "\n" + "\n" " \n" " Test\n" " cartesian\n" @@ -255,18 +255,18 @@ TEST_CASE("Parsing error: no element 'name' in 'clocking'", "[read-gate-level-la " \n" " \n" " \n" - "\n"; + "\n"; - std::istringstream layout_stream{fcn_layout}; + std::istringstream layout_stream{fgl_layout}; using gate_layout = gate_level_layout>>>; - CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); + CHECK_THROWS_AS(read_fgl_layout(layout_stream), fgl_parsing_error); } -TEST_CASE("Parsing error: unknown clocking scheme", "[read-gate-level-layout]") +TEST_CASE("Parsing error: unknown clocking scheme", "[read-fgl-layout]") { - static constexpr const char* fcn_layout = "\n" - "\n" + static constexpr const char* fgl_layout = "\n" + "\n" " \n" " Test\n" " cartesian\n" @@ -279,18 +279,18 @@ TEST_CASE("Parsing error: unknown clocking scheme", "[read-gate-level-layout]") " CoolClocking\n" " \n" " \n" - "\n"; + "\n"; - std::istringstream layout_stream{fcn_layout}; + std::istringstream layout_stream{fgl_layout}; using gate_layout = gate_level_layout>>>; - CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); + CHECK_THROWS_AS(read_fgl_layout(layout_stream), fgl_parsing_error); } -TEST_CASE("Parsing error: no element 'zones' in 'clocking'", "[read-gate-level-layout]") +TEST_CASE("Parsing error: no element 'zones' in 'clocking'", "[read-fgl-layout]") { - static constexpr const char* fcn_layout = "\n" - "\n" + static constexpr const char* fgl_layout = "\n" + "\n" " \n" " Test\n" " cartesian\n" @@ -303,18 +303,18 @@ TEST_CASE("Parsing error: no element 'zones' in 'clocking'", "[read-gate-level-l " OPEN\n" " \n" " \n" - "\n"; + "\n"; - std::istringstream layout_stream{fcn_layout}; + std::istringstream layout_stream{fgl_layout}; using gate_layout = gate_level_layout>>>; - CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); + CHECK_THROWS_AS(read_fgl_layout(layout_stream), fgl_parsing_error); } -TEST_CASE("Parsing error: no element 'x' in 'zone'", "[read-gate-level-layout]") +TEST_CASE("Parsing error: no element 'x' in 'zone'", "[read-fgl-layout]") { - static constexpr const char* fcn_layout = "\n" - "\n" + static constexpr const char* fgl_layout = "\n" + "\n" " \n" " Test\n" " cartesian\n" @@ -333,18 +333,18 @@ TEST_CASE("Parsing error: no element 'x' in 'zone'", "[read-gate-level-layout]") " \n" " \n" " \n" - "\n"; + "\n"; - std::istringstream layout_stream{fcn_layout}; + std::istringstream layout_stream{fgl_layout}; using gate_layout = gate_level_layout>>>; - CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); + CHECK_THROWS_AS(read_fgl_layout(layout_stream), fgl_parsing_error); } -TEST_CASE("Parsing error: no element 'y' in 'zone'", "[read-gate-level-layout]") +TEST_CASE("Parsing error: no element 'y' in 'zone'", "[read-fgl-layout]") { - static constexpr const char* fcn_layout = "\n" - "\n" + static constexpr const char* fgl_layout = "\n" + "\n" " \n" " Test\n" " cartesian\n" @@ -363,18 +363,18 @@ TEST_CASE("Parsing error: no element 'y' in 'zone'", "[read-gate-level-layout]") " \n" " \n" " \n" - "\n"; + "\n"; - std::istringstream layout_stream{fcn_layout}; + std::istringstream layout_stream{fgl_layout}; using gate_layout = gate_level_layout>>>; - CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); + CHECK_THROWS_AS(read_fgl_layout(layout_stream), fgl_parsing_error); } -TEST_CASE("Parsing error: no element 'clock' in 'zone'", "[read-gate-level-layout]") +TEST_CASE("Parsing error: no element 'clock' in 'zone'", "[read-fgl-layout]") { - static constexpr const char* fcn_layout = "\n" - "\n" + static constexpr const char* fgl_layout = "\n" + "\n" " \n" " Test\n" " cartesian\n" @@ -393,18 +393,18 @@ TEST_CASE("Parsing error: no element 'clock' in 'zone'", "[read-gate-level-layou " \n" " \n" " \n" - "\n"; + "\n"; - std::istringstream layout_stream{fcn_layout}; + std::istringstream layout_stream{fgl_layout}; using gate_layout = gate_level_layout>>>; - CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); + CHECK_THROWS_AS(read_fgl_layout(layout_stream), fgl_parsing_error); } -TEST_CASE("Parsing error: no element 'topology' in 'layout'", "[read-gate-level-layout]") +TEST_CASE("Parsing error: no element 'topology' in 'layout'", "[read-fgl-layout]") { - static constexpr const char* fcn_layout = "\n" - "\n" + static constexpr const char* fgl_layout = "\n" + "\n" " \n" " Test\n" " \n" @@ -416,18 +416,18 @@ TEST_CASE("Parsing error: no element 'topology' in 'layout'", "[read-gate-level- " 2DDWave\n" " \n" " \n" - "\n"; + "\n"; - std::istringstream layout_stream{fcn_layout}; + std::istringstream layout_stream{fgl_layout}; using gate_layout = gate_level_layout>>>; - CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); + CHECK_THROWS_AS(read_fgl_layout(layout_stream), fgl_parsing_error); } -TEST_CASE("Parsing error: unknown topology", "[read-gate-level-layout]") +TEST_CASE("Parsing error: unknown topology", "[read-fgl-layout]") { - static constexpr const char* fcn_layout = "\n" - "\n" + static constexpr const char* fgl_layout = "\n" + "\n" " \n" " Test\n" " unknown\n" @@ -440,18 +440,18 @@ TEST_CASE("Parsing error: unknown topology", "[read-gate-level-layout]") " 2DDWave\n" " \n" " \n" - "\n"; + "\n"; - std::istringstream layout_stream{fcn_layout}; + std::istringstream layout_stream{fgl_layout}; using gate_layout = gate_level_layout>>>; - CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); + CHECK_THROWS_AS(read_fgl_layout(layout_stream), fgl_parsing_error); } -TEST_CASE("Parsing error: Lyt is not a cartesian layout", "[read-gate-level-layout]") +TEST_CASE("Parsing error: Lyt is not a cartesian layout", "[read-fgl-layout]") { - static constexpr const char* fcn_layout = "\n" - "\n" + static constexpr const char* fgl_layout = "\n" + "\n" " \n" " Test\n" " cartesian\n" @@ -464,19 +464,19 @@ TEST_CASE("Parsing error: Lyt is not a cartesian layout", "[read-gate-level-layo " 2DDWave\n" " \n" " \n" - "\n"; + "\n"; - std::istringstream layout_stream{fcn_layout}; + std::istringstream layout_stream{fgl_layout}; using gate_layout = gate_level_layout< clocked_layout>>>; - CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); + CHECK_THROWS_AS(read_fgl_layout(layout_stream), fgl_parsing_error); } -TEST_CASE("Parsing error: Lyt is not a shifted_cartesian layout", "[read-gate-level-layout]") +TEST_CASE("Parsing error: Lyt is not a shifted_cartesian layout", "[read-fgl-layout]") { - static constexpr const char* fcn_layout = "\n" - "\n" + static constexpr const char* fgl_layout = "\n" + "\n" " \n" " Test\n" " odd_row_cartesian\n" @@ -489,18 +489,18 @@ TEST_CASE("Parsing error: Lyt is not a shifted_cartesian layout", "[read-gate-le " 2DDWave\n" " \n" " \n" - "\n"; + "\n"; - std::istringstream layout_stream{fcn_layout}; + std::istringstream layout_stream{fgl_layout}; using gate_layout = gate_level_layout>>>; - CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); + CHECK_THROWS_AS(read_fgl_layout(layout_stream), fgl_parsing_error); } -TEST_CASE("Parsing error: Lyt is not an odd_row_cartesian layout", "[read-gate-level-layout]") +TEST_CASE("Parsing error: Lyt is not an odd_row_cartesian layout", "[read-fgl-layout]") { - static constexpr const char* fcn_layout = "\n" - "\n" + static constexpr const char* fgl_layout = "\n" + "\n" " \n" " Test\n" " odd_row_cartesian\n" @@ -513,19 +513,19 @@ TEST_CASE("Parsing error: Lyt is not an odd_row_cartesian layout", "[read-gate-l " 2DDWave\n" " \n" " \n" - "\n"; + "\n"; - std::istringstream layout_stream{fcn_layout}; + std::istringstream layout_stream{fgl_layout}; using gate_layout = gate_level_layout< clocked_layout>>>; - CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); + CHECK_THROWS_AS(read_fgl_layout(layout_stream), fgl_parsing_error); } -TEST_CASE("Parsing error: Lyt is not an even_row_cartesian layout", "[read-gate-level-layout]") +TEST_CASE("Parsing error: Lyt is not an even_row_cartesian layout", "[read-fgl-layout]") { - static constexpr const char* fcn_layout = "\n" - "\n" + static constexpr const char* fgl_layout = "\n" + "\n" " \n" " Test\n" " even_row_cartesian\n" @@ -538,19 +538,19 @@ TEST_CASE("Parsing error: Lyt is not an even_row_cartesian layout", "[read-gate- " 2DDWave\n" " \n" " \n" - "\n"; + "\n"; - std::istringstream layout_stream{fcn_layout}; + std::istringstream layout_stream{fgl_layout}; using gate_layout = gate_level_layout< clocked_layout>>>; - CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); + CHECK_THROWS_AS(read_fgl_layout(layout_stream), fgl_parsing_error); } -TEST_CASE("Parsing error: Lyt is not an odd_column_cartesian layout", "[read-gate-level-layout]") +TEST_CASE("Parsing error: Lyt is not an odd_column_cartesian layout", "[read-fgl-layout]") { - static constexpr const char* fcn_layout = "\n" - "\n" + static constexpr const char* fgl_layout = "\n" + "\n" " \n" " Test\n" " odd_column_cartesian\n" @@ -563,19 +563,19 @@ TEST_CASE("Parsing error: Lyt is not an odd_column_cartesian layout", "[read-gat " 2DDWave\n" " \n" " \n" - "\n"; + "\n"; - std::istringstream layout_stream{fcn_layout}; + std::istringstream layout_stream{fgl_layout}; using gate_layout = gate_level_layout< clocked_layout>>>; - CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); + CHECK_THROWS_AS(read_fgl_layout(layout_stream), fgl_parsing_error); } -TEST_CASE("Parsing error: Lyt is not an even_column_cartesian layout", "[read-gate-level-layout]") +TEST_CASE("Parsing error: Lyt is not an even_column_cartesian layout", "[read-fgl-layout]") { - static constexpr const char* fcn_layout = "\n" - "\n" + static constexpr const char* fgl_layout = "\n" + "\n" " \n" " Test\n" " even_column_cartesian\n" @@ -588,19 +588,19 @@ TEST_CASE("Parsing error: Lyt is not an even_column_cartesian layout", "[read-ga " 2DDWave\n" " \n" " \n" - "\n"; + "\n"; - std::istringstream layout_stream{fcn_layout}; + std::istringstream layout_stream{fgl_layout}; using gate_layout = gate_level_layout< clocked_layout>>>; - CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); + CHECK_THROWS_AS(read_fgl_layout(layout_stream), fgl_parsing_error); } -TEST_CASE("Parsing error: Lyt is not a hexagonal layout", "[read-gate-level-layout]") +TEST_CASE("Parsing error: Lyt is not a hexagonal layout", "[read-fgl-layout]") { - static constexpr const char* fcn_layout = "\n" - "\n" + static constexpr const char* fgl_layout = "\n" + "\n" " \n" " Test\n" " odd_row_hex\n" @@ -613,19 +613,19 @@ TEST_CASE("Parsing error: Lyt is not a hexagonal layout", "[read-gate-level-layo " 2DDWave\n" " \n" " \n" - "\n"; + "\n"; - std::istringstream layout_stream{fcn_layout}; + std::istringstream layout_stream{fgl_layout}; using gate_layout = gate_level_layout< clocked_layout>>>; - CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); + CHECK_THROWS_AS(read_fgl_layout(layout_stream), fgl_parsing_error); } -TEST_CASE("Parsing error: Lyt is not an odd_row_hex layout", "[read-gate-level-layout]") +TEST_CASE("Parsing error: Lyt is not an odd_row_hex layout", "[read-fgl-layout]") { - static constexpr const char* fcn_layout = "\n" - "\n" + static constexpr const char* fgl_layout = "\n" + "\n" " \n" " Test\n" " odd_row_hex\n" @@ -638,19 +638,19 @@ TEST_CASE("Parsing error: Lyt is not an odd_row_hex layout", "[read-gate-level-l " 2DDWave\n" " \n" " \n" - "\n"; + "\n"; - std::istringstream layout_stream{fcn_layout}; + std::istringstream layout_stream{fgl_layout}; using gate_layout = gate_level_layout>>>; - CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); + CHECK_THROWS_AS(read_fgl_layout(layout_stream), fgl_parsing_error); } -TEST_CASE("Parsing error: Lyt is not an even_row_hex layout", "[read-gate-level-layout]") +TEST_CASE("Parsing error: Lyt is not an even_row_hex layout", "[read-fgl-layout]") { - static constexpr const char* fcn_layout = "\n" - "\n" + static constexpr const char* fgl_layout = "\n" + "\n" " \n" " Test\n" " even_row_hex\n" @@ -663,19 +663,19 @@ TEST_CASE("Parsing error: Lyt is not an even_row_hex layout", "[read-gate-level- " 2DDWave\n" " \n" " \n" - "\n"; + "\n"; - std::istringstream layout_stream{fcn_layout}; + std::istringstream layout_stream{fgl_layout}; using gate_layout = gate_level_layout>>>; - CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); + CHECK_THROWS_AS(read_fgl_layout(layout_stream), fgl_parsing_error); } -TEST_CASE("Parsing error: Lyt is not an odd_column_hex layout", "[read-gate-level-layout]") +TEST_CASE("Parsing error: Lyt is not an odd_column_hex layout", "[read-fgl-layout]") { - static constexpr const char* fcn_layout = "\n" - "\n" + static constexpr const char* fgl_layout = "\n" + "\n" " \n" " Test\n" " odd_column_hex\n" @@ -688,19 +688,19 @@ TEST_CASE("Parsing error: Lyt is not an odd_column_hex layout", "[read-gate-leve " 2DDWave\n" " \n" " \n" - "\n"; + "\n"; - std::istringstream layout_stream{fcn_layout}; + std::istringstream layout_stream{fgl_layout}; using gate_layout = gate_level_layout>>>; - CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); + CHECK_THROWS_AS(read_fgl_layout(layout_stream), fgl_parsing_error); } -TEST_CASE("Parsing error: Lyt is not an even_column_hex layout", "[read-gate-level-layout]") +TEST_CASE("Parsing error: Lyt is not an even_column_hex layout", "[read-fgl-layout]") { - static constexpr const char* fcn_layout = "\n" - "\n" + static constexpr const char* fgl_layout = "\n" + "\n" " \n" " Test\n" " even_column_hex\n" @@ -713,19 +713,19 @@ TEST_CASE("Parsing error: Lyt is not an even_column_hex layout", "[read-gate-lev " 2DDWave\n" " \n" " \n" - "\n"; + "\n"; - std::istringstream layout_stream{fcn_layout}; + std::istringstream layout_stream{fgl_layout}; using gate_layout = gate_level_layout>>>; - CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); + CHECK_THROWS_AS(read_fgl_layout(layout_stream), fgl_parsing_error); } -TEST_CASE("Parsing error: no element 'size' in 'layout'", "[read-gate-level-layout]") +TEST_CASE("Parsing error: no element 'size' in 'layout'", "[read-fgl-layout]") { - static constexpr const char* fcn_layout = "\n" - "\n" + static constexpr const char* fgl_layout = "\n" + "\n" " \n" " Test\n" " cartesian\n" @@ -736,18 +736,18 @@ TEST_CASE("Parsing error: no element 'size' in 'layout'", "[read-gate-level-layo " 2DDWave\n" " \n" " \n" - "\n"; + "\n"; - std::istringstream layout_stream{fcn_layout}; + std::istringstream layout_stream{fgl_layout}; using gate_layout = gate_level_layout>>>; - CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); + CHECK_THROWS_AS(read_fgl_layout(layout_stream), fgl_parsing_error); } -TEST_CASE("Parsing error: no element 'x' in 'size'", "[read-gate-level-layout]") +TEST_CASE("Parsing error: no element 'x' in 'size'", "[read-fgl-layout]") { - static constexpr const char* fcn_layout = "\n" - "\n" + static constexpr const char* fgl_layout = "\n" + "\n" " \n" " Test\n" " cartesian\n" @@ -759,18 +759,18 @@ TEST_CASE("Parsing error: no element 'x' in 'size'", "[read-gate-level-layout]") " 2DDWave\n" " \n" " \n" - "\n"; + "\n"; - std::istringstream layout_stream{fcn_layout}; + std::istringstream layout_stream{fgl_layout}; using gate_layout = gate_level_layout>>>; - CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); + CHECK_THROWS_AS(read_fgl_layout(layout_stream), fgl_parsing_error); } -TEST_CASE("Parsing error: no element 'y' in 'size'", "[read-gate-level-layout]") +TEST_CASE("Parsing error: no element 'y' in 'size'", "[read-fgl-layout]") { - static constexpr const char* fcn_layout = "\n" - "\n" + static constexpr const char* fgl_layout = "\n" + "\n" " \n" " Test\n" " cartesian\n" @@ -782,18 +782,18 @@ TEST_CASE("Parsing error: no element 'y' in 'size'", "[read-gate-level-layout]") " 2DDWave\n" " \n" " \n" - "\n"; + "\n"; - std::istringstream layout_stream{fcn_layout}; + std::istringstream layout_stream{fgl_layout}; using gate_layout = gate_level_layout>>>; - CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); + CHECK_THROWS_AS(read_fgl_layout(layout_stream), fgl_parsing_error); } -TEST_CASE("Parsing error: no element 'z' in 'size'", "[read-gate-level-layout]") +TEST_CASE("Parsing error: no element 'z' in 'size'", "[read-fgl-layout]") { - static constexpr const char* fcn_layout = "\n" - "\n" + static constexpr const char* fgl_layout = "\n" + "\n" " \n" " Test\n" " cartesian\n" @@ -805,18 +805,18 @@ TEST_CASE("Parsing error: no element 'z' in 'size'", "[read-gate-level-layout]") " 2DDWave\n" " \n" " \n" - "\n"; + "\n"; - std::istringstream layout_stream{fcn_layout}; + std::istringstream layout_stream{fgl_layout}; using gate_layout = gate_level_layout>>>; - CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); + CHECK_THROWS_AS(read_fgl_layout(layout_stream), fgl_parsing_error); } -TEST_CASE("Parsing error: no element 'id' in 'gate", "[read-gate-level-layout]") +TEST_CASE("Parsing error: no element 'id' in 'gate", "[read-fgl-layout]") { - static constexpr const char* fcn_layout = "\n" - "\n" + static constexpr const char* fgl_layout = "\n" + "\n" " \n" " Test\n" " cartesian\n" @@ -840,18 +840,18 @@ TEST_CASE("Parsing error: no element 'id' in 'gate", "[read-gate-level-layout]") " \n" " \n" " \n" - "\n"; + "\n"; - std::istringstream layout_stream{fcn_layout}; + std::istringstream layout_stream{fgl_layout}; using gate_layout = gate_level_layout>>>; - CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); + CHECK_THROWS_AS(read_fgl_layout(layout_stream), fgl_parsing_error); } -TEST_CASE("Parsing error: no element 'type' in 'gate", "[read-gate-level-layout]") +TEST_CASE("Parsing error: no element 'type' in 'gate", "[read-fgl-layout]") { - static constexpr const char* fcn_layout = "\n" - "\n" + static constexpr const char* fgl_layout = "\n" + "\n" " \n" " Test\n" " cartesian\n" @@ -875,18 +875,18 @@ TEST_CASE("Parsing error: no element 'type' in 'gate", "[read-gate-level-layout] " \n" " \n" " \n" - "\n"; + "\n"; - std::istringstream layout_stream{fcn_layout}; + std::istringstream layout_stream{fgl_layout}; using gate_layout = gate_level_layout>>>; - CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); + CHECK_THROWS_AS(read_fgl_layout(layout_stream), fgl_parsing_error); } -TEST_CASE("Parsing error: no element 'name' in 'gate", "[read-gate-level-layout]") +TEST_CASE("Parsing error: no element 'name' in 'gate", "[read-fgl-layout]") { - static constexpr const char* fcn_layout = "\n" - "\n" + static constexpr const char* fgl_layout = "\n" + "\n" " \n" " Test\n" " cartesian\n" @@ -910,18 +910,18 @@ TEST_CASE("Parsing error: no element 'name' in 'gate", "[read-gate-level-layout] " \n" " \n" " \n" - "\n"; + "\n"; - std::istringstream layout_stream{fcn_layout}; + std::istringstream layout_stream{fgl_layout}; using gate_layout = gate_level_layout>>>; - CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); + CHECK_THROWS_AS(read_fgl_layout(layout_stream), fgl_parsing_error); } -TEST_CASE("Parsing error: no element 'loc' in 'gate'", "[read-gate-level-layout]") +TEST_CASE("Parsing error: no element 'loc' in 'gate'", "[read-fgl-layout]") { - static constexpr const char* fcn_layout = "\n" - "\n" + static constexpr const char* fgl_layout = "\n" + "\n" " \n" " Test\n" " cartesian\n" @@ -944,18 +944,18 @@ TEST_CASE("Parsing error: no element 'loc' in 'gate'", "[read-gate-level-layout] " 0\n" " \n" " \n" - "\n"; + "\n"; - std::istringstream layout_stream{fcn_layout}; + std::istringstream layout_stream{fgl_layout}; using gate_layout = gate_level_layout>>>; - CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); + CHECK_THROWS_AS(read_fgl_layout(layout_stream), fgl_parsing_error); } -TEST_CASE("Parsing error: no element 'x' in 'loc'", "[read-gate-level-layout]") +TEST_CASE("Parsing error: no element 'x' in 'loc'", "[read-fgl-layout]") { - static constexpr const char* fcn_layout = "\n" - "\n" + static constexpr const char* fgl_layout = "\n" + "\n" " \n" " Test\n" " cartesian\n" @@ -979,18 +979,18 @@ TEST_CASE("Parsing error: no element 'x' in 'loc'", "[read-gate-level-layout]") " \n" " \n" " \n" - "\n"; + "\n"; - std::istringstream layout_stream{fcn_layout}; + std::istringstream layout_stream{fgl_layout}; using gate_layout = gate_level_layout>>>; - CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); + CHECK_THROWS_AS(read_fgl_layout(layout_stream), fgl_parsing_error); } -TEST_CASE("Parsing error: no element 'y' in 'loc'", "[read-gate-level-layout]") +TEST_CASE("Parsing error: no element 'y' in 'loc'", "[read-fgl-layout]") { - static constexpr const char* fcn_layout = "\n" - "\n" + static constexpr const char* fgl_layout = "\n" + "\n" " \n" " Test\n" " cartesian\n" @@ -1014,18 +1014,18 @@ TEST_CASE("Parsing error: no element 'y' in 'loc'", "[read-gate-level-layout]") " \n" " \n" " \n" - "\n"; + "\n"; - std::istringstream layout_stream{fcn_layout}; + std::istringstream layout_stream{fgl_layout}; using gate_layout = gate_level_layout>>>; - CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); + CHECK_THROWS_AS(read_fgl_layout(layout_stream), fgl_parsing_error); } -TEST_CASE("Parsing error: no element 'z' in 'loc'", "[read-gate-level-layout]") +TEST_CASE("Parsing error: no element 'z' in 'loc'", "[read-fgl-layout]") { - static constexpr const char* fcn_layout = "\n" - "\n" + static constexpr const char* fgl_layout = "\n" + "\n" " \n" " Test\n" " cartesian\n" @@ -1049,18 +1049,18 @@ TEST_CASE("Parsing error: no element 'z' in 'loc'", "[read-gate-level-layout]") " \n" " \n" " \n" - "\n"; + "\n"; - std::istringstream layout_stream{fcn_layout}; + std::istringstream layout_stream{fgl_layout}; using gate_layout = gate_level_layout>>>; - CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); + CHECK_THROWS_AS(read_fgl_layout(layout_stream), fgl_parsing_error); } -TEST_CASE("Parsing error: unknown gate type with 0 incoming signals", "[read-gate-level-layout]") +TEST_CASE("Parsing error: unknown gate type with 0 incoming signals", "[read-fgl-layout]") { - static constexpr const char* fcn_layout = "\n" - "\n" + static constexpr const char* fgl_layout = "\n" + "\n" " \n" " Test\n" " cartesian\n" @@ -1133,18 +1133,18 @@ TEST_CASE("Parsing error: unknown gate type with 0 incoming signals", "[read-gat " \n" " \n" " \n" - "\n"; + "\n"; - std::istringstream layout_stream{fcn_layout}; + std::istringstream layout_stream{fgl_layout}; using gate_layout = gate_level_layout>>>; - CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); + CHECK_THROWS_AS(read_fgl_layout(layout_stream), fgl_parsing_error); } -TEST_CASE("Parsing error: unknown gate type with 1 incoming signal", "[read-gate-level-layout]") +TEST_CASE("Parsing error: unknown gate type with 1 incoming signal", "[read-fgl-layout]") { - static constexpr const char* fcn_layout = "\n" - "\n" + static constexpr const char* fgl_layout = "\n" + "\n" " \n" " Test\n" " cartesian\n" @@ -1216,18 +1216,18 @@ TEST_CASE("Parsing error: unknown gate type with 1 incoming signal", "[read-gate " \n" " \n" " \n" - "\n"; + "\n"; - std::istringstream layout_stream{fcn_layout}; + std::istringstream layout_stream{fgl_layout}; using gate_layout = gate_level_layout>>>; - CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); + CHECK_THROWS_AS(read_fgl_layout(layout_stream), fgl_parsing_error); } -TEST_CASE("Parsing error: unknown gate type with 2 incoming signals", "[read-gate-level-layout]") +TEST_CASE("Parsing error: unknown gate type with 2 incoming signals", "[read-fgl-layout]") { - static constexpr const char* fcn_layout = "\n" - "\n" + static constexpr const char* fgl_layout = "\n" + "\n" " \n" " Test\n" " cartesian\n" @@ -1300,18 +1300,18 @@ TEST_CASE("Parsing error: unknown gate type with 2 incoming signals", "[read-gat " \n" " \n" " \n" - "\n"; + "\n"; - std::istringstream layout_stream{fcn_layout}; + std::istringstream layout_stream{fgl_layout}; using gate_layout = gate_level_layout>>>; - CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); + CHECK_THROWS_AS(read_fgl_layout(layout_stream), fgl_parsing_error); } -TEST_CASE("Parsing error: unknown gate type with 3 incoming signals", "[read-gate-level-layout]") +TEST_CASE("Parsing error: unknown gate type with 3 incoming signals", "[read-fgl-layout]") { - static constexpr const char* fcn_layout = "\n" - "\n" + static constexpr const char* fgl_layout = "\n" + "\n" " \n" " Test\n" " cartesian\n" @@ -1399,18 +1399,18 @@ TEST_CASE("Parsing error: unknown gate type with 3 incoming signals", "[read-gat " \n" " \n" " \n" - "\n"; + "\n"; - std::istringstream layout_stream{fcn_layout}; + std::istringstream layout_stream{fgl_layout}; using gate_layout = gate_level_layout>>>; - CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); + CHECK_THROWS_AS(read_fgl_layout(layout_stream), fgl_parsing_error); } -TEST_CASE("Parsing error: unknown gate type with more than 3 incoming signals", "[read-gate-level-layout]") +TEST_CASE("Parsing error: unknown gate type with more than 3 incoming signals", "[read-fgl-layout]") { - static constexpr const char* fcn_layout = "\n" - "\n" + static constexpr const char* fgl_layout = "\n" + "\n" " \n" " Test\n" " cartesian\n" @@ -1523,18 +1523,18 @@ TEST_CASE("Parsing error: unknown gate type with more than 3 incoming signals", " \n" " \n" " \n" - "\n"; + "\n"; - std::istringstream layout_stream{fcn_layout}; + std::istringstream layout_stream{fgl_layout}; using gate_layout = gate_level_layout>>>; - CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); + CHECK_THROWS_AS(read_fgl_layout(layout_stream), fgl_parsing_error); } -TEST_CASE("Parsing error: no element 'x' in 'signal'", "[read-gate-level-layout]") +TEST_CASE("Parsing error: no element 'x' in 'signal'", "[read-fgl-layout]") { - static constexpr const char* fcn_layout = "\n" - "\n" + static constexpr const char* fgl_layout = "\n" + "\n" " \n" " Test\n" " cartesian\n" @@ -1606,18 +1606,18 @@ TEST_CASE("Parsing error: no element 'x' in 'signal'", "[read-gate-level-layout] " \n" " \n" " \n" - "\n"; + "\n"; - std::istringstream layout_stream{fcn_layout}; + std::istringstream layout_stream{fgl_layout}; using gate_layout = gate_level_layout>>>; - CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); + CHECK_THROWS_AS(read_fgl_layout(layout_stream), fgl_parsing_error); } -TEST_CASE("Parsing error: no element 'y' in 'signal'", "[read-gate-level-layout]") +TEST_CASE("Parsing error: no element 'y' in 'signal'", "[read-fgl-layout]") { - static constexpr const char* fcn_layout = "\n" - "\n" + static constexpr const char* fgl_layout = "\n" + "\n" " \n" " Test\n" " cartesian\n" @@ -1689,18 +1689,18 @@ TEST_CASE("Parsing error: no element 'y' in 'signal'", "[read-gate-level-layout] " \n" " \n" " \n" - "\n"; + "\n"; - std::istringstream layout_stream{fcn_layout}; + std::istringstream layout_stream{fgl_layout}; using gate_layout = gate_level_layout>>>; - CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); + CHECK_THROWS_AS(read_fgl_layout(layout_stream), fgl_parsing_error); } -TEST_CASE("Parsing error: no element 'z' in 'signal'", "[read-gate-level-layout]") +TEST_CASE("Parsing error: no element 'z' in 'signal'", "[read-fgl-layout]") { - static constexpr const char* fcn_layout = "\n" - "\n" + static constexpr const char* fgl_layout = "\n" + "\n" " \n" " Test\n" " cartesian\n" @@ -1772,10 +1772,10 @@ TEST_CASE("Parsing error: no element 'z' in 'signal'", "[read-gate-level-layout] " \n" " \n" " \n" - "\n"; + "\n"; - std::istringstream layout_stream{fcn_layout}; + std::istringstream layout_stream{fgl_layout}; using gate_layout = gate_level_layout>>>; - CHECK_THROWS_AS(read_gate_level_layout(layout_stream), gate_level_parsing_error); + CHECK_THROWS_AS(read_fgl_layout(layout_stream), fgl_parsing_error); } \ No newline at end of file diff --git a/test/io/write_gate_level_layout.cpp b/test/io/write_fgl_layout.cpp similarity index 91% rename from test/io/write_gate_level_layout.cpp rename to test/io/write_fgl_layout.cpp index e3ef6a7ff..780bfdc9d 100644 --- a/test/io/write_gate_level_layout.cpp +++ b/test/io/write_fgl_layout.cpp @@ -9,8 +9,8 @@ #include "utils/equivalence_checking_utils.hpp" #include -#include -#include +#include +#include #include #include #include @@ -55,9 +55,9 @@ void check_parsing_equiv(const Ntk& ntk) const auto layout = orthogonal(ntk, {}); std::stringstream layout_stream{}; - write_gate_level_layout(layout, layout_stream); + write_fgl_layout(layout, layout_stream); - const auto read_layout = read_gate_level_layout(layout_stream, get_name(layout)); + const auto read_layout = read_fgl_layout(layout_stream, get_name(layout)); compare_written_and_read_layout(layout, read_layout); @@ -70,8 +70,8 @@ template void check_parsing_equiv_layout(const Lyt& lyt) { std::stringstream layout_stream{}; - write_gate_level_layout(lyt, layout_stream); - const auto read_layout = read_gate_level_layout(layout_stream, lyt.get_layout_name()); + write_fgl_layout(lyt, layout_stream); + const auto read_layout = read_fgl_layout(layout_stream, lyt.get_layout_name()); compare_written_and_read_layout(lyt, read_layout); @@ -138,22 +138,19 @@ void check_parsing_equiv_layout_all() blueprints::optimization_layout_corner_case_outputs_2()); } -TEST_CASE("Write empty gate_level layout", "[write-gate-level-layout]") +TEST_CASE("Write empty gate_level layout", "[write-fgl-layout]") { using gate_layout = gate_level_layout>>>; - const gate_layout layout{{}, "empty"}; std::stringstream layout_stream{}; - - write_gate_level_layout(layout, layout_stream); - - const auto read_layout = read_gate_level_layout(layout_stream, "empty"); + write_fgl_layout(layout, layout_stream); + const auto read_layout = read_fgl_layout(layout_stream, "empty"); compare_written_and_read_layout(layout, read_layout); } -TEST_CASE("Write and read layouts", "[write-gate-level-layout]") +TEST_CASE("Write and read layouts", "[write-fgl-layout]") { using gate_layout = gate_level_layout>>>; From 2118b1cf98fc1e5bf986062ef289f158693ec220 Mon Sep 17 00:00:00 2001 From: Simon Hofmann Date: Thu, 5 Oct 2023 14:13:46 +0200 Subject: [PATCH 29/36] small fix --- include/fiction/io/read_fgl_layout.hpp | 37 +++++++++++++------------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/include/fiction/io/read_fgl_layout.hpp b/include/fiction/io/read_fgl_layout.hpp index 5188af57c..60d4e10a8 100644 --- a/include/fiction/io/read_fgl_layout.hpp +++ b/include/fiction/io/read_fgl_layout.hpp @@ -99,39 +99,39 @@ class read_fgl_layout_impl auto* const topology = layout->FirstChildElement("topology"); if (topology != nullptr && topology->GetText()) { - const auto topology_name = topology->GetText(); - static const std::array shifted_cartesian{"odd_row_cartesian", "even_row_cartesian", - "odd_column_cartesian", "even_column_cartesian"}; - static const std::array hex{"odd_row_hex", "even_row_hex", "odd_column_hex", - "even_column_hex"}; + const std::string topology_name = topology->GetText(); + static constexpr std::array shifted_cartesian{ + "odd_row_cartesian", "even_row_cartesian", "odd_column_cartesian", "even_column_cartesian"}; + static constexpr std::array hex{"odd_row_hex", "even_row_hex", "odd_column_hex", + "even_column_hex"}; - if (std::strcmp(topology_name, "cartesian") == 0) + if (topology_name == "cartesian") { if constexpr (!is_cartesian_layout_v) { throw fgl_parsing_error("Error parsing FGL file: Lyt is not a cartesian layout"); } } - else if (std::find(std::begin(shifted_cartesian), std::end(shifted_cartesian), topology_name) != + else if (std::find(shifted_cartesian.begin(), shifted_cartesian.end(), topology_name) != shifted_cartesian.end()) { if constexpr (is_shifted_cartesian_layout_v) { - if (std::strcmp(topology_name, "odd_row_cartesian") == 0) + if (topology_name == "odd_row_cartesian") { if constexpr (!has_odd_row_cartesian_arrangement_v) { throw fgl_parsing_error("Error parsing FGL file: Lyt is not an odd_row_cartesian layout"); } } - else if (std::strcmp(topology_name, "even_row_cartesian") == 0) + else if (topology_name == "even_row_cartesian") { if constexpr (!has_even_row_cartesian_arrangement_v) { throw fgl_parsing_error("Error parsing FGL file: Lyt is not an even_row_cartesian layout"); } } - else if (std::strcmp(topology_name, "odd_column_cartesian") == 0) + else if (topology_name == "odd_column_cartesian") { if constexpr (!has_odd_column_cartesian_arrangement_v) { @@ -139,7 +139,7 @@ class read_fgl_layout_impl "Error parsing FGL file: Lyt is not an odd_column_cartesian layout"); } } - else if (std::strcmp(topology_name, "even_column_cartesian") == 0) + else if (topology_name == "even_column_cartesian") { if constexpr (!has_even_column_cartesian_arrangement_v) { @@ -153,32 +153,32 @@ class read_fgl_layout_impl throw fgl_parsing_error("Error parsing FGL file: Lyt is not a shifted_cartesian layout"); } } - else if (std::find(std::begin(hex), std::end(hex), topology_name) != hex.end()) + else if (std::find(hex.begin(), hex.end(), topology_name) != hex.end()) { if constexpr (is_hexagonal_layout_v) { - if (std::strcmp(topology_name, "odd_row_hex") == 0) + if (topology_name == "odd_row_hex") { if constexpr (!has_odd_row_hex_arrangement_v) { throw fgl_parsing_error("Error parsing FGL file: Lyt is not an odd_row_hex layout"); } } - else if (std::strcmp(topology_name, "even_row_hex") == 0) + else if (topology_name == "even_row_hex") { if constexpr (!has_even_row_hex_arrangement_v) { throw fgl_parsing_error("Error parsing FGL file: Lyt is not an even_row_hex layout"); } } - else if (std::strcmp(topology_name, "odd_column_hex") == 0) + else if (topology_name == "odd_column_hex") { if constexpr (!has_odd_column_hex_arrangement_v) { throw fgl_parsing_error("Error parsing FGL file: Lyt is not an odd_column_hex layout"); } } - else if (std::strcmp(topology_name, "even_column_hex") == 0) + else if (topology_name == "even_column_hex") { if constexpr (!has_even_column_hex_arrangement_v) { @@ -257,7 +257,7 @@ class read_fgl_layout_impl if (clocking_scheme.has_value()) { lyt.replace_clocking_scheme(*clocking_scheme); - static const std::array open_clocking_schemes{"OPEN", "OPEN3", "OPEN4"}; + static constexpr std::array open_clocking_schemes{"OPEN", "OPEN3", "OPEN4"}; auto* const clock_zones = clocking->FirstChildElement("zones"); if (clock_zones != nullptr) @@ -302,7 +302,8 @@ class read_fgl_layout_impl } } else if (std::find(std::begin(open_clocking_schemes), std::end(open_clocking_schemes), - clocking_scheme_name->GetText()) != open_clocking_schemes.end()) + static_cast(clocking_scheme_name->GetText())) != + open_clocking_schemes.end()) { throw fgl_parsing_error("Error parsing FGL file: no element 'zones' in 'clocking'"); } From 8800c2fc1c101e177ba09a4e58e4abfb82621570 Mon Sep 17 00:00:00 2001 From: Simon Date: Thu, 5 Oct 2023 19:17:17 +0200 Subject: [PATCH 30/36] fix warnings --- include/fiction/io/read_fgl_layout.hpp | 12 ++++++------ include/fiction/io/write_fgl_layout.hpp | 2 ++ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/include/fiction/io/read_fgl_layout.hpp b/include/fiction/io/read_fgl_layout.hpp index 60d4e10a8..40b505e1f 100644 --- a/include/fiction/io/read_fgl_layout.hpp +++ b/include/fiction/io/read_fgl_layout.hpp @@ -377,7 +377,7 @@ class read_fgl_layout_impl auto* const loc_x = loc->FirstChildElement("x"); if (loc_x != nullptr && loc_x->GetText()) { - gate.loc.x = std::stoull(loc_x->GetText()); + gate.loc.x = static_cast(std::stoull(loc_x->GetText())); } else { @@ -388,7 +388,7 @@ class read_fgl_layout_impl auto* const loc_y = loc->FirstChildElement("y"); if (loc_y != nullptr && loc_y->GetText()) { - gate.loc.y = std::stoull(loc_y->GetText()); + gate.loc.y = static_cast(std::stoull(loc_y->GetText())); } else { @@ -399,7 +399,7 @@ class read_fgl_layout_impl auto* const loc_z = loc->FirstChildElement("z"); if (loc_z != nullptr && loc_z->GetText()) { - gate.loc.z = std::stoull(loc_z->GetText()); + gate.loc.z = static_cast(std::stoull(loc_z->GetText())); } else { @@ -418,7 +418,7 @@ class read_fgl_layout_impl auto* const incoming_signal_x = incoming_signal->FirstChildElement("x"); if (incoming_signal_x != nullptr && incoming_signal_x->GetText()) { - incoming.x = std::stoull(incoming_signal_x->GetText()); + incoming.x = static_cast(std::stoull(incoming_signal_x->GetText())); } else { @@ -429,7 +429,7 @@ class read_fgl_layout_impl auto* const incoming_signal_y = incoming_signal->FirstChildElement("y"); if (incoming_signal_y != nullptr && incoming_signal_y->GetText()) { - incoming.y = std::stoull(incoming_signal_y->GetText()); + incoming.y = static_cast(std::stoull(incoming_signal_y->GetText())); } else { @@ -440,7 +440,7 @@ class read_fgl_layout_impl auto* const incoming_signal_z = incoming_signal->FirstChildElement("z"); if (incoming_signal_z != nullptr && incoming_signal_z->GetText()) { - incoming.z = std::stoull(incoming_signal_z->GetText()); + incoming.z = static_cast(std::stoull(incoming_signal_z->GetText())); } else { diff --git a/include/fiction/io/write_fgl_layout.hpp b/include/fiction/io/write_fgl_layout.hpp index c9fef4a8d..4869e7cdc 100644 --- a/include/fiction/io/write_fgl_layout.hpp +++ b/include/fiction/io/write_fgl_layout.hpp @@ -102,6 +102,7 @@ class write_fgl_layout_impl os << fcn::OPEN_LAYOUT_METADATA; std::string layout_name = get_name(lyt); + // check if topology matches Lyt std::string topology = ""; if constexpr (is_cartesian_layout_v) { @@ -152,6 +153,7 @@ class write_fgl_layout_impl const auto clocking_scheme = lyt.get_clocking_scheme(); os << fmt::format(fcn::CLOCKING_SCHEME_NAME, clocking_scheme.name); + // if clocking scheme is irregular, overwrite clock zones if (!clocking_scheme.is_regular()) { os << fcn::OPEN_CLOCK_ZONES; From 2729bff2148d834be77084d1338c509d0f1c63db Mon Sep 17 00:00:00 2001 From: Simon Date: Thu, 5 Oct 2023 19:40:00 +0200 Subject: [PATCH 31/36] ignore warning --- include/fiction/io/read_fgl_layout.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/fiction/io/read_fgl_layout.hpp b/include/fiction/io/read_fgl_layout.hpp index 40b505e1f..9406f30d9 100644 --- a/include/fiction/io/read_fgl_layout.hpp +++ b/include/fiction/io/read_fgl_layout.hpp @@ -28,6 +28,9 @@ #include #include +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" + namespace fiction { @@ -805,5 +808,6 @@ void read_fgl_layout(Lyt& lyt, const std::string_view& filename) } } // namespace fiction +#pragma GCC diagnostic pop #endif // FICTION_READ_FGL_LAYOUT_HPP From 34166e87f710f97be0e4a013b317b398239ccdb4 Mon Sep 17 00:00:00 2001 From: Simon Hofmann Date: Fri, 6 Oct 2023 09:18:13 +0200 Subject: [PATCH 32/36] update docs --- docs/io/input.rst | 12 ++++++------ docs/io/physical_simulation.rst | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/io/input.rst b/docs/io/input.rst index 67841f9c2..db789e901 100644 --- a/docs/io/input.rst +++ b/docs/io/input.rst @@ -22,14 +22,14 @@ Truth Tables Gate-level Layouts ################## -**Header:** ``fiction/io/read_gate_level_layout.hpp`` +**Header:** ``fiction/io/read_fgl_layout.hpp`` -.. doxygenfunction:: fiction::read_gate_level_layout(std::istream& is, const std::string_view& name = "") -.. doxygenfunction:: fiction::read_gate_level_layout(Lyt& lyt, std::istream& is) -.. doxygenfunction:: fiction::read_gate_level_layout(const std::string_view& filename, const std::string_view& name = "") -.. doxygenfunction:: fiction::read_gate_level_layout(Lyt& lyt, const std::string_view& filename) +.. doxygenfunction:: fiction::read_fgl_layout(std::istream& is, const std::string_view& name = "") +.. doxygenfunction:: fiction::read_fgl_layout(Lyt& lyt, std::istream& is) +.. doxygenfunction:: fiction::read_fgl_layout(const std::string_view& filename, const std::string_view& name = "") +.. doxygenfunction:: fiction::read_fgl_layout(Lyt& lyt, const std::string_view& filename) -.. doxygenclass:: fiction::gate_level_parsing_error +.. doxygenclass:: fiction::fgl_parsing_error Cell-level Layouts ################## diff --git a/docs/io/physical_simulation.rst b/docs/io/physical_simulation.rst index 216bbabad..3aa01efb7 100644 --- a/docs/io/physical_simulation.rst +++ b/docs/io/physical_simulation.rst @@ -91,7 +91,7 @@ SiDB Operational Domain Technology-independent Gate-level Layouts ######################################### -**Header:** ``fiction/io/write_gate_level_layout.hpp`` +**Header:** ``fiction/io/write_fgl_layout.hpp`` -.. doxygenfunction:: fiction::write_gate_level_layout(const Lyt& lyt, std::ostream& os) -.. doxygenfunction:: fiction::write_gate_level_layout(const Lyt& lyt, const std::string_view& filename) +.. doxygenfunction:: fiction::write_fgl_layout(const Lyt& lyt, std::ostream& os) +.. doxygenfunction:: fiction::write_fgl_layout(const Lyt& lyt, const std::string_view& filename) From 5fcdd7bd64caef0e66b20512544168a2550b9df2 Mon Sep 17 00:00:00 2001 From: Simon Hofmann Date: Fri, 6 Oct 2023 10:36:12 +0200 Subject: [PATCH 33/36] add cli commands for reading and writing --- cli/cmd/io/fgl.hpp | 114 ++++++++++++++++++++++++++++++++++++++++++++ cli/cmd/io/read.hpp | 112 ++++++++++++++++++++++++++++++++++++++++++- cli/commands.hpp | 1 + 3 files changed, 225 insertions(+), 2 deletions(-) create mode 100644 cli/cmd/io/fgl.hpp diff --git a/cli/cmd/io/fgl.hpp b/cli/cmd/io/fgl.hpp new file mode 100644 index 000000000..ae769fc0b --- /dev/null +++ b/cli/cmd/io/fgl.hpp @@ -0,0 +1,114 @@ +// +// Created by simon on 06.10.2023 +// + +#ifndef FICTION_CMD_FGL_HPP +#define FICTION_CMD_FGL_HPP + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +namespace alice +{ +/** + * Generates a FGL file for the current gate-level layout in store and writes it to the given path. + */ +class fgl_command : public command +{ + public: + /** + * Standard constructor. Adds descriptive information, options, and flags. + * + * @param e alice::environment that specifies stores etc. + */ + explicit fgl_command(const environment::ptr& e) : + command(e, "Generates a FGL file for the current gate-level layout in store.") + { + add_option("filename", filename, "FGL file name"); + } + + protected: + /** + * Function to perform the output call. Generates a FGL file. + */ + void execute() override + { + auto& s = store(); + + // error case: empty gate-level layout store + if (s.empty()) + { + env->out() << "[w] no gate-level layout in store" << std::endl; + return; + } + + const auto get_name = [](auto&& lyt_ptr) -> std::string { return fiction::get_name(*lyt_ptr); }; + + const auto write_fgl = [this, &get_name](auto&& lyt_ptr) + { + using Lyt = typename std::decay_t::element_type; + + if constexpr (fiction::is_gate_level_layout_v) + { + fiction::write_fgl_layout(*lyt_ptr, filename); + } + else + { + env->out() << fmt::format("[e] {} is not a gate-level layout", get_name(lyt_ptr)) << std::endl; + } + }; + + const auto& lyt = s.current(); + + // error case: do not override directories + if (std::filesystem::is_directory(filename)) + { + env->out() << "[e] cannot override a directory" << std::endl; + return; + } + // if filename was not given, use stored layout name + if (filename.empty()) + { + filename = std::visit(get_name, lyt); + } + // add .fgl file extension if necessary + if (std::filesystem::path(filename).extension() != ".fgl") + { + filename += ".fgl"; + } + + try + { + std::visit(write_fgl, lyt); + } + catch (const std::ofstream::failure& e) + { + env->out() << fmt::format("[e] {}", e.what()) << std::endl; + } + catch (...) + { + env->out() << "[e] an error occurred while the file was being written; it could be corrupted" << std::endl; + } + } + + private: + /** + * File name to write the FGL file into. + */ + std::string filename; +}; + +ALICE_ADD_COMMAND(fgl, "I/O") + +} // namespace alice + +#endif // FICTION_CMD_FGL_HPP diff --git a/cli/cmd/io/read.hpp b/cli/cmd/io/read.hpp index 93e85e73f..b7b655c4d 100644 --- a/cli/cmd/io/read.hpp +++ b/cli/cmd/io/read.hpp @@ -6,6 +6,7 @@ #define FICTION_CMD_READ_HPP #include +#include #include #include @@ -22,7 +23,7 @@ namespace alice * * Currently parses Verilog, AIGER, and BLIF using the lorina parsers. * - * Parses FQCA via a custom reader function. + * Parses FGL and FQCA via custom reader functions. * * For more information see: https://github.com/hriener/lorina */ @@ -38,14 +39,17 @@ class read_command : public command command(e, "Reads a file or a directory of files and creates logic network or FCN layout objects " "which will be put into the respective store. Current supported file types are:\n" "Logic networks: Verilog, AIGER, BLIF.\n" + "Gate-level layouts: FGL.\n" "Cell-level layouts: FQCA.\n" "In a directory, only files with extension '.v', '.aig', '.blif' are considered.") { add_option("filename", filename, "Filename or directory")->required(); + add_option("topology", topology, "Topology for gate-level layouts"); add_flag("--aig,-a", "Parse file as AIG"); add_flag("--xag,-x", "Parse file as XAG"); add_flag("--mig,-m", "Parse file as MIG"); add_flag("--tec,-t", "Parse file as technology network"); + add_flag("--fgl,-f", "Parse file as fiction gate-level layout"); add_flag("--qca,-q", "Parse file as QCA cell-level layout"); add_flag("--sort,-s", sort, "Sort networks in given directory by vertex count prior to storing them"); } @@ -64,14 +68,22 @@ class read_command : public command } }; - if (!is_set("aig") && !is_set("xag") && !is_set("mig") && !is_set("tec") && !is_set("qca")) + if (!is_set("aig") && !is_set("xag") && !is_set("mig") && !is_set("tec") && !is_set("fgl") && !is_set("qca")) { env->out() << "[e] at least one network or layout type must be specified" << std::endl; } + else if ((is_set("aig") || is_set("xag") || is_set("mig") || is_set("tec")) && is_set("fql")) + { + env->out() << "[e] cannot parse files as both logic networks and gate-level layouts" << std::endl; + } else if ((is_set("aig") || is_set("xag") || is_set("mig") || is_set("tec")) && is_set("qca")) { env->out() << "[e] cannot parse files as both logic networks and cell-level layouts" << std::endl; } + else if (is_set("fql") && is_set("qca")) + { + env->out() << "[e] cannot parse files as both gate-level and cell-level layouts" << std::endl; + } else { try @@ -100,6 +112,98 @@ class read_command : public command store_ntks(reader); } + if (is_set("fgl")) + { + if (!topology.empty()) + { + if (std::filesystem::exists(filename)) + { + if (std::filesystem::is_regular_file(filename)) + { + try + { + if (topology == "cartesian") + { + store().extend() = + std::make_shared( + fiction::read_fgl_layout(filename)); + } + else if (topology == "odd_row_cartesian") + { + store().extend() = + std::make_shared( + fiction::read_fgl_layout(filename)); + } + else if (topology == "even_row_cartesian") + { + store().extend() = + std::make_shared( + fiction::read_fgl_layout( + filename)); + } + else if (topology == "odd_column_cartesian") + { + store().extend() = + std::make_shared( + fiction::read_fgl_layout(filename)); + } + else if (topology == "even_column_cartesian") + { + store().extend() = + std::make_shared( + fiction::read_fgl_layout( + filename)); + } + else if (topology == "odd_row_hex") + { + store().extend() = + std::make_shared( + fiction::read_fgl_layout(filename)); + } + else if (topology == "even_row_hex") + { + store().extend() = + std::make_shared( + fiction::read_fgl_layout(filename)); + } + else if (topology == "odd_column_hex") + { + store().extend() = + std::make_shared( + fiction::read_fgl_layout(filename)); + } + else if (topology == "even_column_hex") + { + store().extend() = + std::make_shared( + fiction::read_fgl_layout(filename)); + } + else + { + env->out() << fmt::format("[e] given topology does not exist: {}", topology) + << std::endl; + } + } + catch (const fiction::fgl_parsing_error& e) + { + env->out() << e.what() << std::endl; + } + } + else + { + env->out() << "[e] given file name does not point to a regular file" << std::endl; + } + } + else + { + env->out() << "[e] given file name does not exist" << std::endl; + } + } + else + { + env->out() << "[e] for reading gate-level layouts, the topology has to be set" << std::endl; + } + } if (is_set("qca")) { if (std::filesystem::exists(filename)) @@ -160,6 +264,10 @@ class read_command : public command * Verilog filename. */ std::string filename; + /** + * Gate-level layout topology. + */ + std::string topology; /** * Flag to indicate that files should be sorted by file size. */ diff --git a/cli/commands.hpp b/cli/commands.hpp index 7587c22e3..bd8222a60 100644 --- a/cli/commands.hpp +++ b/cli/commands.hpp @@ -8,6 +8,7 @@ #include "cmd/general/clear.hpp" #include "cmd/general/version.hpp" #include "cmd/io/blif.hpp" +#include "cmd/io/fgl.hpp" #include "cmd/io/fqca.hpp" #include "cmd/io/qca.hpp" #include "cmd/io/qcc.hpp" From 4960cc47dbbd45c17985a872d6ce937181754218 Mon Sep 17 00:00:00 2001 From: simon1hofmann <119581649+simon1hofmann@users.noreply.github.com> Date: Fri, 6 Oct 2023 14:00:41 +0200 Subject: [PATCH 34/36] Apply suggestions from code review Co-authored-by: Marcel Walter --- include/fiction/io/read_fgl_layout.hpp | 3 +-- test/io/read_fgl_layout.cpp | 3 --- test/io/write_fgl_layout.cpp | 2 -- 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/include/fiction/io/read_fgl_layout.hpp b/include/fiction/io/read_fgl_layout.hpp index 9406f30d9..0a7668084 100644 --- a/include/fiction/io/read_fgl_layout.hpp +++ b/include/fiction/io/read_fgl_layout.hpp @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -24,8 +25,6 @@ #include #include #include -#include -#include #include #pragma GCC diagnostic push diff --git a/test/io/read_fgl_layout.cpp b/test/io/read_fgl_layout.cpp index e2ba0425f..bfa787a22 100644 --- a/test/io/read_fgl_layout.cpp +++ b/test/io/read_fgl_layout.cpp @@ -13,9 +13,6 @@ #include #include -#include -#include -#include using namespace fiction; diff --git a/test/io/write_fgl_layout.cpp b/test/io/write_fgl_layout.cpp index 780bfdc9d..54df72566 100644 --- a/test/io/write_fgl_layout.cpp +++ b/test/io/write_fgl_layout.cpp @@ -25,9 +25,7 @@ #include #include -#include #include -#include using namespace fiction; From ddefb5fddca766023c845c8746cf022fe0fe5cde Mon Sep 17 00:00:00 2001 From: Simon Hofmann Date: Fri, 6 Oct 2023 14:23:02 +0200 Subject: [PATCH 35/36] fix todos from code review --- cli/cmd/io/read.hpp | 219 ++++++++++++------------ include/fiction/io/read_fgl_layout.hpp | 31 ++-- include/fiction/io/write_fgl_layout.hpp | 5 - test/io/read_fgl_layout.cpp | 2 +- 4 files changed, 122 insertions(+), 135 deletions(-) diff --git a/cli/cmd/io/read.hpp b/cli/cmd/io/read.hpp index b7b655c4d..40af5d29d 100644 --- a/cli/cmd/io/read.hpp +++ b/cli/cmd/io/read.hpp @@ -44,7 +44,9 @@ class read_command : public command "In a directory, only files with extension '.v', '.aig', '.blif' are considered.") { add_option("filename", filename, "Filename or directory")->required(); - add_option("topology", topology, "Topology for gate-level layouts"); + add_option("topology", topology, + "Topology for gate-level layouts. Can be 'cartesian' or of the form " + "'__"); add_flag("--aig,-a", "Parse file as AIG"); add_flag("--xag,-x", "Parse file as XAG"); add_flag("--mig,-m", "Parse file as MIG"); @@ -112,130 +114,127 @@ class read_command : public command store_ntks(reader); } - if (is_set("fgl")) + if (is_set("fgl") || is_set("qca")) { - if (!topology.empty()) + if (std::filesystem::exists(filename)) { - if (std::filesystem::exists(filename)) + if (std::filesystem::is_regular_file(filename)) { - if (std::filesystem::is_regular_file(filename)) + if (is_set("fgl")) { - try + if (!topology.empty()) { - if (topology == "cartesian") - { - store().extend() = - std::make_shared( - fiction::read_fgl_layout(filename)); - } - else if (topology == "odd_row_cartesian") - { - store().extend() = - std::make_shared( - fiction::read_fgl_layout(filename)); - } - else if (topology == "even_row_cartesian") - { - store().extend() = - std::make_shared( - fiction::read_fgl_layout( - filename)); - } - else if (topology == "odd_column_cartesian") - { - store().extend() = - std::make_shared( - fiction::read_fgl_layout(filename)); - } - else if (topology == "even_column_cartesian") - { - store().extend() = - std::make_shared( - fiction::read_fgl_layout( - filename)); - } - else if (topology == "odd_row_hex") + try { - store().extend() = - std::make_shared( - fiction::read_fgl_layout(filename)); + if (topology == "cartesian") + { + store().extend() = + std::make_shared( + fiction::read_fgl_layout(filename)); + } + else if (topology == "odd_row_cartesian") + { + store().extend() = + std::make_shared( + fiction::read_fgl_layout( + filename)); + } + else if (topology == "even_row_cartesian") + { + store().extend() = + std::make_shared( + fiction::read_fgl_layout( + filename)); + } + else if (topology == "odd_column_cartesian") + { + store().extend() = + std::make_shared( + fiction::read_fgl_layout( + filename)); + } + else if (topology == "even_column_cartesian") + { + store().extend() = + std::make_shared( + fiction::read_fgl_layout( + filename)); + } + else if (topology == "odd_row_hex") + { + store().extend() = + std::make_shared( + fiction::read_fgl_layout( + filename)); + } + else if (topology == "even_row_hex") + { + store().extend() = + std::make_shared( + fiction::read_fgl_layout( + filename)); + } + else if (topology == "odd_column_hex") + { + store().extend() = + std::make_shared( + fiction::read_fgl_layout( + filename)); + } + else if (topology == "even_column_hex") + { + store().extend() = + std::make_shared( + fiction::read_fgl_layout( + filename)); + } + else + { + env->out() << fmt::format("[e] given topology does not exist: {}", topology) + << std::endl; + } } - else if (topology == "even_row_hex") + catch (const fiction::fgl_parsing_error& e) { - store().extend() = - std::make_shared( - fiction::read_fgl_layout(filename)); - } - else if (topology == "odd_column_hex") - { - store().extend() = - std::make_shared( - fiction::read_fgl_layout(filename)); - } - else if (topology == "even_column_hex") - { - store().extend() = - std::make_shared( - fiction::read_fgl_layout(filename)); - } - else - { - env->out() << fmt::format("[e] given topology does not exist: {}", topology) - << std::endl; + env->out() << e.what() << std::endl; } } - catch (const fiction::fgl_parsing_error& e) + else { - env->out() << e.what() << std::endl; + env->out() << "[e] for reading gate-level layouts, the topology has to be set" + << std::endl; } } - else - { - env->out() << "[e] given file name does not point to a regular file" << std::endl; - } - } - else - { - env->out() << "[e] given file name does not exist" << std::endl; - } - } - else - { - env->out() << "[e] for reading gate-level layouts, the topology has to be set" << std::endl; - } - } - if (is_set("qca")) - { - if (std::filesystem::exists(filename)) - { - if (std::filesystem::is_regular_file(filename)) - { - try + if (is_set("qca")) { - const auto layout_name = std::filesystem::path{filename}.stem().string(); + try + { + const auto layout_name = std::filesystem::path{filename}.stem().string(); - store().extend() = - std::make_shared( - fiction::read_fqca_layout(filename, - layout_name)); - } - catch (const fiction::unsupported_character_exception& e) - { - env->out() - << fmt::format("character '{}' is not supported as a cell designator", e.which()) - << std::endl; - } - catch (const fiction::undefined_cell_label_exception& e) - { - env->out() << fmt::format("cell label '{}' was used in the cell definition section but " - "never defined above", - e.which()) - << std::endl; - } - catch (const fiction::unrecognized_cell_definition_exception& e) - { - env->out() - << fmt::format("unsupported cell definition in line {}", e.where()) << std::endl; + store().extend() = + std::make_shared( + fiction::read_fqca_layout(filename, + layout_name)); + } + catch (const fiction::unsupported_character_exception& e) + { + env->out() << fmt::format("character '{}' is not supported as a cell designator", + e.which()) + << std::endl; + } + catch (const fiction::undefined_cell_label_exception& e) + { + env->out() + << fmt::format("cell label '{}' was used in the cell definition section but " + "never defined above", + e.which()) + << std::endl; + } + catch (const fiction::unrecognized_cell_definition_exception& e) + { + env->out() << fmt::format("unsupported cell definition in line {}", e.where()) + << std::endl; + } } } else diff --git a/include/fiction/io/read_fgl_layout.hpp b/include/fiction/io/read_fgl_layout.hpp index 0a7668084..6f540eac4 100644 --- a/include/fiction/io/read_fgl_layout.hpp +++ b/include/fiction/io/read_fgl_layout.hpp @@ -27,9 +27,6 @@ #include #include -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wconversion" - namespace fiction { @@ -114,8 +111,8 @@ class read_fgl_layout_impl throw fgl_parsing_error("Error parsing FGL file: Lyt is not a cartesian layout"); } } - else if (std::find(shifted_cartesian.begin(), shifted_cartesian.end(), topology_name) != - shifted_cartesian.end()) + else if (std::find(shifted_cartesian.cbegin(), shifted_cartesian.cend(), topology_name) != + shifted_cartesian.cend()) { if constexpr (is_shifted_cartesian_layout_v) { @@ -155,7 +152,7 @@ class read_fgl_layout_impl throw fgl_parsing_error("Error parsing FGL file: Lyt is not a shifted_cartesian layout"); } } - else if (std::find(hex.begin(), hex.end(), topology_name) != hex.end()) + else if (std::find(hex.cbegin(), hex.cend(), topology_name) != hex.cend()) { if constexpr (is_hexagonal_layout_v) { @@ -303,9 +300,9 @@ class read_fgl_layout_impl lyt.assign_clock_number({x_coord, y_coord}, clock); } } - else if (std::find(std::begin(open_clocking_schemes), std::end(open_clocking_schemes), + else if (std::find(open_clocking_schemes.cbegin(), open_clocking_schemes.cend(), static_cast(clocking_scheme_name->GetText())) != - open_clocking_schemes.end()) + open_clocking_schemes.cend()) { throw fgl_parsing_error("Error parsing FGL file: no element 'zones' in 'clocking'"); } @@ -375,6 +372,8 @@ class read_fgl_layout_impl throw fgl_parsing_error("Error parsing FGL file: no element 'loc'"); } +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" // get x-coordinate auto* const loc_x = loc->FirstChildElement("x"); if (loc_x != nullptr && loc_x->GetText()) @@ -452,6 +451,7 @@ class read_fgl_layout_impl gate.incoming.push_back(incoming); } } +#pragma GCC diagnostic pop gates.push_back(gate); } @@ -714,7 +714,7 @@ class read_fgl_layout_impl /** * Reads a gate-level layout from an FGL file provided as an input stream. * - * May throw a `fgl_parsing_exception` if the FGL file is malformed. + * May throw an `fgl_parsing_exception` if the FGL file is malformed. * * @tparam Lyt The layout type to be created from an input. * @param is The input stream to read from. @@ -723,9 +723,6 @@ class read_fgl_layout_impl template [[nodiscard]] Lyt read_fgl_layout(std::istream& is, const std::string_view& name = "") { - static_assert(is_coordinate_layout_v, "Lyt is not a coordinate layout"); - static_assert(is_tile_based_layout_v, "Lyt is not a tile-based layout"); - static_assert(is_clocked_layout_v, "Lyt is not a clocked layout"); static_assert(is_gate_level_layout_v, "Lyt is not a gate-level layout"); detail::read_fgl_layout_impl p{is, name}; @@ -737,7 +734,7 @@ template /** * Reads a gate-level layout from an FGL file provided as an input stream. * - * May throw a `fgl_parsing_exception` if the FGL file is malformed. + * May throw an `fgl_parsing_exception` if the FGL file is malformed. * * This is an in-place version of read_fgl_layout that utilizes the given layout as a target to write to. * @@ -748,9 +745,6 @@ template template void read_fgl_layout(Lyt& lyt, std::istream& is) { - static_assert(is_coordinate_layout_v, "Lyt is not a coordinate layout"); - static_assert(is_tile_based_layout_v, "Lyt is not a tile-based layout"); - static_assert(is_clocked_layout_v, "Lyt is not a clocked layout"); static_assert(is_gate_level_layout_v, "Lyt is not a gate-level layout"); detail::read_fgl_layout_impl p{lyt, is}; @@ -760,7 +754,7 @@ void read_fgl_layout(Lyt& lyt, std::istream& is) /** * Reads a gate-level layout from an FGL file provided as an input stream. * - * May throw a `fgl_parsing_exception` if the FGL file is malformed. + * May throw an `fgl_parsing_exception` if the FGL file is malformed. * * @tparam Lyt The layout type to be created from an input. * @param filename The file name to open and read from. @@ -784,7 +778,7 @@ template /** * Reads a gate-level layout from an FGL file provided as an input stream. * - * May throw a `fgl_parsing_exception` if the FGL file is malformed. + * May throw an `fgl_parsing_exception` if the FGL file is malformed. * * This is an in-place version of `read_fgl_layout` that utilizes the given layout as a target to write to. * @@ -807,6 +801,5 @@ void read_fgl_layout(Lyt& lyt, const std::string_view& filename) } } // namespace fiction -#pragma GCC diagnostic pop #endif // FICTION_READ_FGL_LAYOUT_HPP diff --git a/include/fiction/io/write_fgl_layout.hpp b/include/fiction/io/write_fgl_layout.hpp index 4869e7cdc..ba93260c7 100644 --- a/include/fiction/io/write_fgl_layout.hpp +++ b/include/fiction/io/write_fgl_layout.hpp @@ -23,8 +23,6 @@ #include #include #include -#include -#include namespace fiction { @@ -328,9 +326,6 @@ class write_fgl_layout_impl template void write_fgl_layout(const Lyt& lyt, std::ostream& os) { - static_assert(is_coordinate_layout_v, "Lyt is not a coordinate layout"); - static_assert(is_tile_based_layout_v, "Lyt is not a tile-based layout"); - static_assert(is_clocked_layout_v, "Lyt is not a clocked layout"); static_assert(is_gate_level_layout_v, "Lyt is not a gate-level layout"); detail::write_fgl_layout_impl p{lyt, os}; diff --git a/test/io/read_fgl_layout.cpp b/test/io/read_fgl_layout.cpp index bfa787a22..cb6e30f6b 100644 --- a/test/io/read_fgl_layout.cpp +++ b/test/io/read_fgl_layout.cpp @@ -1775,4 +1775,4 @@ TEST_CASE("Parsing error: no element 'z' in 'signal'", "[read-fgl-layout]") using gate_layout = gate_level_layout>>>; CHECK_THROWS_AS(read_fgl_layout(layout_stream), fgl_parsing_error); -} \ No newline at end of file +} From d4c583b7882e792a1acfde15dfa5cb31e741a828 Mon Sep 17 00:00:00 2001 From: simon1hofmann <119581649+simon1hofmann@users.noreply.github.com> Date: Fri, 6 Oct 2023 18:14:17 +0200 Subject: [PATCH 36/36] Update read.hpp Co-authored-by: Marcel Walter --- cli/cmd/io/read.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/cmd/io/read.hpp b/cli/cmd/io/read.hpp index 40af5d29d..e28441c89 100644 --- a/cli/cmd/io/read.hpp +++ b/cli/cmd/io/read.hpp @@ -46,7 +46,7 @@ class read_command : public command add_option("filename", filename, "Filename or directory")->required(); add_option("topology", topology, "Topology for gate-level layouts. Can be 'cartesian' or of the form " - "'__"); + "'__'"); add_flag("--aig,-a", "Parse file as AIG"); add_flag("--xag,-x", "Parse file as XAG"); add_flag("--mig,-m", "Parse file as MIG");