Skip to content

Commit

Permalink
✨ Added a unified print_layout function (#240)
Browse files Browse the repository at this point in the history
  • Loading branch information
marcelwa committed Jun 22, 2023
1 parent bfee388 commit b352aaf
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 13 deletions.
1 change: 1 addition & 0 deletions docs/io/visualization.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Layout Printing
.. doxygenfunction:: fiction::print_gate_level_layout
.. doxygenfunction:: fiction::print_cell_level_layout
.. doxygenfunction:: fiction::print_charge_layout
.. doxygenfunction:: fiction::print_layout

Graphviz (DOT) Drawers
######################
Expand Down
65 changes: 53 additions & 12 deletions include/fiction/io/print_layout.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ inline constexpr auto NO_COLOR = fmt::text_style{};
*/
template <typename Lyt>
void print_gate_level_layout(std::ostream& os, const Lyt& layout, const bool io_color = true,
const bool clk_color = false) noexcept
const bool clk_color = false)
{
static_assert(is_gate_level_layout_v<Lyt>, "Lyt is not a gate-level layout");

Expand Down Expand Up @@ -252,7 +252,7 @@ void print_gate_level_layout(std::ostream& os, const Lyt& layout, const bool io_
*/
template <typename Lyt>
void print_cell_level_layout(std::ostream& os, const Lyt& layout, const bool io_color = true,
const bool clk_color = false) noexcept
const bool clk_color = false)
{
static_assert(is_cell_level_layout_v<Lyt>, "Lyt is not a cell-level layout");

Expand Down Expand Up @@ -327,31 +327,37 @@ void print_cell_level_layout(std::ostream& os, const Lyt& layout, const bool io_
/**
* Writes a simplified 2D representation of an SiDB charge layout to an output stream.
*
* @tparam Lyt Cell-level layout based on SiQAD coordinates.
* @tparam Lyt SiDB cell-level layout with charge-information based on SiQAD coordinates, e.g., a
* charge_distribution_surface object.
* @param os Output stream to write into.
* @param cds The charge distribution surface of which the charge layout is to be printed.
* @param lyt The layout of which the charge distribution is to be printed.
* @param cs_color Flag to utilize color escapes for charge states.
* @param crop_layout Flag to print the 2D bounding box of the layout, while leaving a maximum padding of one dimer row
* and two columns.
* @param draw_lattice Flag to enable lattice background drawing.
*/
template <typename Lyt>
void print_charge_layout(std::ostream& os, const charge_distribution_surface<Lyt>& cds, const bool cs_color = true,
const bool crop_layout = false, const bool draw_lattice = true) noexcept
void print_charge_layout(std::ostream& os, const Lyt& lyt, const bool cs_color = true, const bool crop_layout = false,
const bool draw_lattice = true)
{
static_assert(is_cell_level_layout_v<Lyt>, "Lyt is not a cell-level layout");
static_assert(has_sidb_technology_v<Lyt>, "Lyt is not an SiDB layout");
static_assert(has_siqad_coord_v<Lyt>, "Lyt is not based on SiQAD coordinates");
static_assert(has_get_charge_state_v<Lyt>, "Lyt does not implement the get_charge_state function");

// empty layout
if (cds.is_empty())
if (lyt.is_empty())
{
os << "[i] empty layout" << std::endl;
return;
}

coordinate<Lyt> min{};
coordinate<Lyt> max{cds.x(), cds.y(), 1};
coordinate<Lyt> max{lyt.x(), lyt.y(), 1};

if (crop_layout)
{
const auto bb = bounding_box_2d{cds};
const auto bb = bounding_box_2d{lyt};

// apply padding of maximally one dimer row and two columns
min = bb.get_min() - coordinate<Lyt>{2, 1};
Expand All @@ -363,15 +369,15 @@ void print_charge_layout(std::ostream& os, const charge_distribution_surface<Lyt
}

// iterate over all coordinates in the rows determined by the vertical crop
cds.foreach_coordinate(
lyt.foreach_coordinate(
[&](const coordinate<Lyt>& c)
{
if (crop_layout && (c.x < min.x || c.x > max.x)) // apply horizontal crop
{
return;
}

switch (cds.get_charge_state(c)) // switch over the charge state of the SiDB at the current coordinate
switch (lyt.get_charge_state(c)) // switch over the charge state of the SiDB at the current coordinate
{
case sidb_charge_state::NEGATIVE:
{
Expand All @@ -390,7 +396,7 @@ void print_charge_layout(std::ostream& os, const charge_distribution_surface<Lyt
}
default: // NONE charge state case -> empty cell
{
os << (draw_lattice || !cds.is_empty_cell(c) ?
os << (draw_lattice || !lyt.is_empty_cell(c) ?
fmt::format(cs_color ? detail::SIDB_LAT_COLOR : detail::NO_COLOR, " · ") :
" ");
}
Expand All @@ -406,6 +412,41 @@ void print_charge_layout(std::ostream& os, const charge_distribution_surface<Lyt
// flush stream
os << std::endl;
}
/**
* A unified printer of the versions above. Depending on the passed layout type, this function will automatically select
* the appropriate printer to use. This simplifies printing by enabling the statement `print_layout(lyt)`.
*
* @note This function will use the respective function's default settings to print the layout.
*
* @tparam Lyt Any coordinate layout type.
* @param lyt The coordinate layout.
* @param os The output stream to write into.
*/
template <typename Lyt>
void print_layout(const Lyt& lyt, std::ostream& os = std::cout)
{
static_assert(is_coordinate_layout_v<Lyt>, "Lyt is not a coordinate layout");

if constexpr (is_gate_level_layout_v<Lyt>)
{
print_gate_level_layout(os, lyt);
}
else if constexpr (is_cell_level_layout_v<Lyt>)
{
if constexpr (has_sidb_technology_v<Lyt> && has_siqad_coord_v<Lyt> && has_get_charge_state_v<Lyt>)
{
print_charge_layout(os, lyt);
}
else
{
print_cell_level_layout(os, lyt);
}
}
else
{
os << "[e] unknown layout type" << std::endl;
}
}

} // namespace fiction

Expand Down
22 changes: 21 additions & 1 deletion test/io/print_layout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ TEST_CASE("Print empty gate-level layout", "[print-gate-level-layout]")
print_gate_level_layout(print_stream, layout, false, false);

CHECK(print_stream.str() == layout_print);

print_stream = {};

print_layout(layout, print_stream);

CHECK(print_stream.str() == layout_print);
}

TEST_CASE("Print simple gate-level layout", "[print-gate-level-layout]")
Expand Down Expand Up @@ -121,6 +127,12 @@ TEST_CASE("Print empty cell-level layout", "[print-cell-level-layout]")
print_cell_level_layout(print_stream, layout, false, false);

CHECK(print_stream.str() == layout_print);

print_stream = {};

print_layout(layout, print_stream);

CHECK(print_stream.str() == layout_print);
}

TEST_CASE("Print AND gate cell-level layout", "[print-cell-level-layout]")
Expand Down Expand Up @@ -203,11 +215,19 @@ TEST_CASE("Print empty charge layout", "[print-charge-layout]")
{
using sqd_lyt = sidb_cell_clk_lyt_siqad;

const charge_distribution_surface<sqd_lyt> layout{sqd_lyt{{2, 2}, "Empty"}};

constexpr const char* layout_print = "[i] empty layout\n";

std::stringstream print_stream{};

print_charge_layout(print_stream, charge_distribution_surface<sqd_lyt>{sqd_lyt{{2, 2}, "Empty"}}, false);
print_charge_layout(print_stream, layout, false);

CHECK(print_stream.str() == layout_print);

print_stream = {};

print_layout(layout, print_stream);

CHECK(print_stream.str() == layout_print);
}
Expand Down

0 comments on commit b352aaf

Please sign in to comment.