Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

✨ Gate-level layout file reader and writer #296

Merged
merged 43 commits into from
Oct 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
8546100
basic parser for gate level layouts
simon1hofmann Sep 25, 2023
c429ae6
implement gate_level_layout reader for simple layouts
simon1hofmann Sep 26, 2023
5306758
add missing gate types
simon1hofmann Sep 26, 2023
4973ad2
write layout metadata
simon1hofmann Sep 26, 2023
680cc01
small fix
simon1hofmann Sep 26, 2023
7805678
extend write capabilities
simon1hofmann Sep 26, 2023
9393d68
fix layout name error
simon1hofmann Sep 26, 2023
5d9c2d2
remove debug output
simon1hofmann Sep 26, 2023
20ffd2d
Merge branch 'cda-tum:main' into gate_level_layout_io
simon1hofmann Sep 27, 2023
25d2534
Extend writing capabilities
Sep 27, 2023
15ae876
add node functions
Sep 27, 2023
6a502cd
clang-tidy ánd 100% test coverage
Sep 27, 2023
5a9484c
more tests
Sep 27, 2023
9ead80a
clang-tidy
Sep 27, 2023
1585cdc
clang-tidy
Sep 27, 2023
7784e8f
clang format
Sep 27, 2023
fd716cf
100% coverage
Sep 27, 2023
7c6db20
Apply suggestions from code review
simon1hofmann Sep 29, 2023
3e5d090
fix first batch of todos
Sep 30, 2023
dec32a9
fix second batch of todos
simon1hofmann Oct 2, 2023
ffbe883
fix third batch of todos
simon1hofmann Oct 2, 2023
16311bd
small fix
simon1hofmann Oct 2, 2023
b4fa61e
coverage
simon1hofmann Oct 2, 2023
369f468
increase coverage
Oct 3, 2023
ffeabff
typos
Oct 3, 2023
400fb1f
check topology
simon1hofmann Oct 4, 2023
a93e412
first batch of todos
simon1hofmann Oct 4, 2023
ace4ad6
Merge branch 'main' into gate_level_layout_io
simon1hofmann Oct 4, 2023
22f44b8
second batch of todos
simon1hofmann Oct 5, 2023
d0e8238
Merge branch 'main' into gate_level_layout_io
simon1hofmann Oct 5, 2023
271f333
Merge branch 'main' into gate_level_layout_io
simon1hofmann Oct 5, 2023
cb16e3f
Merge branch 'main' into gate_level_layout_io
simon1hofmann Oct 5, 2023
cbed85c
use .fgl file extension
simon1hofmann Oct 5, 2023
2118b1c
small fix
simon1hofmann Oct 5, 2023
8800c2f
fix warnings
Oct 5, 2023
2729bff
ignore warning
Oct 5, 2023
5484320
Merge branch 'main' into gate_level_layout_io
simon1hofmann Oct 5, 2023
34166e8
update docs
simon1hofmann Oct 6, 2023
7f294c3
Merge branch 'main' into gate_level_layout_io
simon1hofmann Oct 6, 2023
5fcdd7b
add cli commands for reading and writing
simon1hofmann Oct 6, 2023
4960cc4
Apply suggestions from code review
simon1hofmann Oct 6, 2023
ddefb5f
fix todos from code review
simon1hofmann Oct 6, 2023
d4c583b
Update read.hpp
simon1hofmann Oct 6, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 114 additions & 0 deletions cli/cmd/io/fgl.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
//
// Created by simon on 06.10.2023
//

#ifndef FICTION_CMD_FGL_HPP
#define FICTION_CMD_FGL_HPP

#include <fiction/io/write_fgl_layout.hpp>
#include <fiction/traits.hpp>
#include <fiction/types.hpp>
#include <fiction/utils/name_utils.hpp>

#include <alice/alice.hpp>

#include <filesystem>
#include <ostream>
#include <string>
#include <variant>

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<fiction::gate_layout_t>();

// 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<decltype(lyt_ptr)>::element_type;

if constexpr (fiction::is_gate_level_layout_v<Lyt>)
{
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
159 changes: 133 additions & 26 deletions cli/cmd/io/read.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#define FICTION_CMD_READ_HPP

#include <fiction/io/network_reader.hpp>
#include <fiction/io/read_fgl_layout.hpp>
#include <fiction/io/read_fqca_layout.hpp>
#include <fiction/types.hpp>

Expand All @@ -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
*/
Expand All @@ -38,14 +39,19 @@ 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. Can be 'cartesian' or of the form "
"'<odd|even>_<row|column>_<cartesian|hex>'");
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");
}
Expand All @@ -64,14 +70,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"))
{
simon1hofmann marked this conversation as resolved.
Show resolved Hide resolved
simon1hofmann marked this conversation as resolved.
Show resolved Hide resolved
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
Expand Down Expand Up @@ -100,38 +114,127 @@ class read_command : public command

store_ntks(reader);
}
if (is_set("qca"))
if (is_set("fgl") || is_set("qca"))
{
if (std::filesystem::exists(filename))
{
if (std::filesystem::is_regular_file(filename))
{
try
{
const auto layout_name = std::filesystem::path{filename}.stem().string();

store<fiction::cell_layout_t>().extend() =
std::make_shared<fiction::stacked_qca_cell_clk_lyt>(
fiction::read_fqca_layout<fiction::stacked_qca_cell_clk_lyt>(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)
if (is_set("fgl"))
{
env->out() << fmt::format("cell label '{}' was used in the cell definition section but "
"never defined above",
e.which())
<< std::endl;
if (!topology.empty())
{
try
{
if (topology == "cartesian")
{
simon1hofmann marked this conversation as resolved.
Show resolved Hide resolved
store<fiction::gate_layout_t>().extend() =
std::make_shared<fiction::cart_gate_clk_lyt>(
fiction::read_fgl_layout<fiction::cart_gate_clk_lyt>(filename));
}
else if (topology == "odd_row_cartesian")
{
store<fiction::gate_layout_t>().extend() =
std::make_shared<fiction::cart_odd_row_gate_clk_lyt>(
fiction::read_fgl_layout<fiction::cart_odd_row_gate_clk_lyt>(
filename));
}
else if (topology == "even_row_cartesian")
{
store<fiction::gate_layout_t>().extend() =
std::make_shared<fiction::cart_even_row_gate_clk_lyt>(
fiction::read_fgl_layout<fiction::cart_even_row_gate_clk_lyt>(
filename));
}
else if (topology == "odd_column_cartesian")
{
store<fiction::gate_layout_t>().extend() =
std::make_shared<fiction::cart_odd_col_gate_clk_lyt>(
fiction::read_fgl_layout<fiction::cart_odd_col_gate_clk_lyt>(
filename));
}
else if (topology == "even_column_cartesian")
{
store<fiction::gate_layout_t>().extend() =
std::make_shared<fiction::cart_even_col_gate_clk_lyt>(
fiction::read_fgl_layout<fiction::cart_even_col_gate_clk_lyt>(
filename));
}
else if (topology == "odd_row_hex")
{
store<fiction::gate_layout_t>().extend() =
std::make_shared<fiction::hex_odd_row_gate_clk_lyt>(
fiction::read_fgl_layout<fiction::hex_odd_row_gate_clk_lyt>(
filename));
}
else if (topology == "even_row_hex")
{
store<fiction::gate_layout_t>().extend() =
std::make_shared<fiction::hex_even_row_gate_clk_lyt>(
fiction::read_fgl_layout<fiction::hex_even_row_gate_clk_lyt>(
filename));
}
else if (topology == "odd_column_hex")
{
store<fiction::gate_layout_t>().extend() =
std::make_shared<fiction::hex_odd_col_gate_clk_lyt>(
fiction::read_fgl_layout<fiction::hex_odd_col_gate_clk_lyt>(
filename));
}
else if (topology == "even_column_hex")
{
store<fiction::gate_layout_t>().extend() =
std::make_shared<fiction::hex_even_col_gate_clk_lyt>(
fiction::read_fgl_layout<fiction::hex_even_col_gate_clk_lyt>(
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] for reading gate-level layouts, the topology has to be set"
<< std::endl;
}
}
catch (const fiction::unrecognized_cell_definition_exception& e)
if (is_set("qca"))
{
env->out()
<< fmt::format("unsupported cell definition in line {}", e.where()) << std::endl;
try
{
const auto layout_name = std::filesystem::path{filename}.stem().string();

store<fiction::cell_layout_t>().extend() =
std::make_shared<fiction::stacked_qca_cell_clk_lyt>(
fiction::read_fqca_layout<fiction::stacked_qca_cell_clk_lyt>(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
Expand Down Expand Up @@ -160,6 +263,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.
*/
Expand Down
1 change: 1 addition & 0 deletions cli/commands.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
12 changes: 12 additions & 0 deletions docs/io/input.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,18 @@ Truth Tables
.. doxygenclass:: fiction::tt_reader
:members:

Gate-level Layouts
##################

**Header:** ``fiction/io/read_fgl_layout.hpp``

.. 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::fgl_parsing_error

Cell-level Layouts
##################

Expand Down
8 changes: 8 additions & 0 deletions docs/io/physical_simulation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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_fgl_layout.hpp``

.. doxygenfunction:: fiction::write_fgl_layout(const Lyt& lyt, std::ostream& os)
.. doxygenfunction:: fiction::write_fgl_layout(const Lyt& lyt, const std::string_view& filename)
Loading
Loading