Skip to content

Commit

Permalink
✨ Enable charge layout printing (#219)
Browse files Browse the repository at this point in the history
* ✨ Enable charge distribution surface printing

* 🚨 Remove code using a C++20 extension

* 🐛 Add missing import

* 🎨 Shorten name to "print_charge_layout"

* 🐛 Added missing import

* 🎨 Reformatted code

* ✅ Added test

* ✅ Updated test s.t. it passes on different operating systems

* 🐛 Round to 3 decimal places before comparing doubles

* ✨ Draw lattice background and crop output to gate dimensions

* 💡 Add comments and implement PR conversation suggestions

* ✅ Avoided division in a for loop bound

* ✅ Updated test in accord with the changes of the previous commit

* 💄 Changed the color of a negatively charged SiDB to cyan (was blue)

* ✅ Changed algorithmic charge state assignment into static assignments

* ✅ Changed a single charge assignment

* ✅ Added test for empty charge layout

* 🎨 Implemented const-correctness suggestions

* 🎨 Implemented suggestions from PR conversations

* ✨ Made lattice background drawing optional (opt-out)

* 🎨 Changed siqad::coord_t to coordinate<Lyt>

* 🎨 Made crop dimension coordinates const

* 🎨 Implemented suggestions from PR conversations

* 🎨 Implemented suggestions from PR conversations

* 📝 Added `print_charge_layout` to the RST documentation
  • Loading branch information
wlambooy authored May 22, 2023
1 parent 416b2ca commit cc6075b
Show file tree
Hide file tree
Showing 3 changed files with 228 additions and 3 deletions.
1 change: 1 addition & 0 deletions docs/io/visualization.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Layout Printing

.. doxygenfunction:: fiction::print_gate_level_layout
.. doxygenfunction:: fiction::print_cell_level_layout
.. doxygenfunction:: fiction::print_charge_layout

Graphviz (DOT) Drawers
######################
Expand Down
110 changes: 110 additions & 0 deletions include/fiction/io/print_layout.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,19 @@
#ifndef FICTION_PRINT_LAYOUT_HPP
#define FICTION_PRINT_LAYOUT_HPP

#include "fiction/technology/charge_distribution_surface.hpp"
#include "fiction/traits.hpp"
#include "fiction/types.hpp"

#include <fmt/color.h>
#include <fmt/format.h>

#include <algorithm>
#include <array>
#include <cmath>
#include <cstdint>
#include <iostream>
#include <limits>
#include <string>
#include <vector>

Expand All @@ -32,6 +38,16 @@ static const std::array<fmt::text_style, 4> CLOCK_COLOR{{fmt::fg(fmt::color::bla
fmt::fg(fmt::color::black) | fmt::bg(fmt::color::light_gray),
fmt::fg(fmt::color::white) | fmt::bg(fmt::color::gray),
fmt::fg(fmt::color::white) | fmt::bg(fmt::color::dark_gray)}};
// Escape color sequence for negatively charged SiDB colors (cyan).
static const auto SIDB_NEG_COLOR = fmt::fg(fmt::color::cyan);
// Escape color sequence for positively charged SiDB colors (red).
static const auto SIDB_POS_COLOR = fmt::fg(fmt::color::red);
// Escape color sequence for charge-neutral SiDB colors (white).
static const auto SIDB_NEUT_COLOR = fmt::fg(fmt::color::white);
// Escape color sequence for lattice background colors (grey).
static const auto SIDB_LAT_COLOR = fmt::fg(fmt::color::gray);
// Empty escape color sequence
inline constexpr auto NO_COLOR = fmt::text_style{};

} // namespace detail

Expand Down Expand Up @@ -222,6 +238,7 @@ void print_gate_level_layout(std::ostream& os, const Lyt& layout, const bool io_

++r_ctr;
}

// flush stream
os << std::endl;
}
Expand Down Expand Up @@ -304,6 +321,99 @@ void print_cell_level_layout(std::ostream& os, const Lyt& layout, const bool io_
}
os << '\n';
}

// flush stream
os << std::endl;
}
/**
* Writes a simplified 2D representation of an SiDB charge layout to an output stream.
*
* @tparam Lyt Cell-level layout based on SiQAD coordinates.
* @param os Output stream to write into.
* @param cds The charge distribution surface of which the charge layout is to be printed.
* @param cs_color Flag to utilize color escapes for charge states.
* @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 draw_lattice = true) noexcept
{
// empty layout
if (cds.is_empty())
{
os << "[i] empty layout" << std::endl;
return;
}

// obtain the crop dimensions
auto min_x = std::numeric_limits<decltype(cds.x())>::max();
auto max_x = std::numeric_limits<decltype(cds.x())>::min();

auto min_y = std::numeric_limits<decltype(cds.y())>::max();
auto max_y = std::numeric_limits<decltype(cds.y())>::min();

cds.foreach_cell(
[&cds, &min_x, &max_x, &min_y, &max_y](const cell<Lyt>& c)
{
if (!cds.is_empty_cell(c))
{
min_x = std::min(min_x, c.x);
max_x = std::max(max_x, c.x);

min_y = std::min(min_y, c.y);
max_y = std::max(max_y, c.y);
}
});

const coordinate<Lyt> min{std::max(min_x - 2, 0), std::max(min_y - 1, 0)};
const coordinate<Lyt> max{std::min(max_x + 2, cds.x()), std::min(max_y + 1, cds.y())};

// loop over dimer pairs
for (decltype(cds.y()) y_pos = min.y; y_pos <= max.y; ++y_pos)
{
// loop over rows of a dimer pair
for (uint8_t r = 0; r <= 1; ++r)
{
for (decltype(cds.x()) x_pos = min.x; x_pos <= max.x; ++x_pos)
{
const cell<Lyt> c{x_pos, y_pos, r};

if (cds.is_empty_cell(c))
{
os << (draw_lattice ? fmt::format(cs_color ? detail::SIDB_LAT_COLOR : detail::NO_COLOR, " · ") :
" ");
continue;
}

// switch over the charge state of the SiDB index associated with the current cell, and update count
switch (cds.get_charge_state(c))
{
case sidb_charge_state::NEGATIVE:
{
os << fmt::format(cs_color ? detail::SIDB_NEG_COLOR : detail::NO_COLOR, "");
continue;
}
case sidb_charge_state::POSITIVE:
{
os << fmt::format(cs_color ? detail::SIDB_POS_COLOR : detail::NO_COLOR, "");
continue;
}
case sidb_charge_state::NEUTRAL:
{
os << fmt::format(cs_color ? detail::SIDB_NEUT_COLOR : detail::NO_COLOR, "");
continue;
}
default: // NONE charge state case
{
os << fmt::format(cs_color ? detail::SIDB_LAT_COLOR : detail::NO_COLOR, "");
}
}
}
os << '\n';
}
os << '\n';
}

// flush stream
os << std::endl;
}
Expand Down
120 changes: 117 additions & 3 deletions test/io/print_layout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@

#include "utils/blueprints/layout_blueprints.hpp"

#include <fiction/algorithms/physical_design/apply_gate_library.hpp>
#include <fiction/io/print_layout.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/technology/charge_distribution_surface.hpp>
#include <fiction/technology/sidb_bestagon_library.hpp>

#include <sstream>

Expand All @@ -20,7 +23,7 @@ TEST_CASE("Print empty gate-level layout", "[print-gate-level-layout]")
{
using gate_layout = gate_level_layout<clocked_layout<tile_based_layout<cartesian_layout<offset::ucoord_t>>>>;

gate_layout layout{gate_layout::aspect_ratio{2, 2}, open_clocking<gate_layout>(num_clks::FOUR)};
const gate_layout layout{gate_layout::aspect_ratio{2, 2}, open_clocking<gate_layout>(num_clks::FOUR)};

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

Expand Down Expand Up @@ -103,12 +106,12 @@ TEST_CASE("Print crossing gate-level layout", "[print-gate-level-layout]")
CHECK(print_stream.str() == layout_print);
}

TEST_CASE("Print empty cell-level layout", "[print-gate-level-layout]")
TEST_CASE("Print empty cell-level layout", "[print-cell-level-layout]")
{
using cell_layout = fiction::cell_level_layout<fiction::qca_technology,
fiction::clocked_layout<cartesian_layout<offset::ucoord_t>>>;

cell_layout layout{cell_layout::aspect_ratio{2, 2}, "Empty"};
const cell_layout layout{cell_layout::aspect_ratio{2, 2}, "Empty"};

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

Expand Down Expand Up @@ -194,3 +197,114 @@ TEST_CASE("Print wire crossing cell-level layout", "[print-cell-level-layout]")

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

TEST_CASE("Print empty charge layout", "[print-charge-layout]")
{
using sqd_lyt = sidb_cell_clk_lyt_siqad;

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);

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

TEST_CASE("Print Bestagon OR-gate", "[print-charge-layout]")
{
using hex_gate_lyt = hex_even_row_gate_clk_lyt;

hex_gate_lyt layout{{1, 0}};

layout.create_or({}, {}, {0, 0});

const charge_distribution_surface<sidb_cell_clk_lyt_siqad> cl{
convert_to_siqad_coordinates(apply_gate_library<sidb_cell_clk_lyt, sidb_bestagon_library>(layout)),
sidb_simulation_parameters{3, -0.32}, sidb_charge_state::NEGATIVE};

cl.assign_charge_state({46, 3, 0}, sidb_charge_state::NEUTRAL);
cl.assign_charge_state({72, 3, 0}, sidb_charge_state::NEGATIVE);
cl.assign_charge_state({48, 4, 0}, sidb_charge_state::NONE);
cl.assign_charge_state({70, 4, 0}, sidb_charge_state::NEGATIVE);
cl.assign_charge_state({52, 5, 0}, sidb_charge_state::NEGATIVE);
cl.assign_charge_state({66, 5, 0}, sidb_charge_state::NEUTRAL);
cl.assign_charge_state({54, 6, 0}, sidb_charge_state::NEGATIVE);
cl.assign_charge_state({64, 6, 0}, sidb_charge_state::POSITIVE);
cl.assign_charge_state({57, 9, 0}, sidb_charge_state::NEGATIVE);
cl.assign_charge_state({57, 10, 1}, sidb_charge_state::NONE);
cl.assign_charge_state({62, 10, 0}, sidb_charge_state::POSITIVE);
cl.assign_charge_state({59, 11, 1}, sidb_charge_state::NEGATIVE);
cl.assign_charge_state({59, 14, 0}, sidb_charge_state::NEGATIVE);
cl.assign_charge_state({60, 15, 0}, sidb_charge_state::NEGATIVE);
cl.assign_charge_state({64, 16, 0}, sidb_charge_state::POSITIVE);
cl.assign_charge_state({66, 17, 0}, sidb_charge_state::NEUTRAL);
cl.assign_charge_state({70, 18, 0}, sidb_charge_state::NEGATIVE);
cl.assign_charge_state({72, 19, 0}, sidb_charge_state::NEGATIVE);

std::stringstream print_stream{};

print_charge_layout(print_stream, cl, false);

constexpr const char* layout_print =
" · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · \n"
" · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · \n"
"\n"
" · · ◯ · · · · · · · · · · · · · · · · · · · · · · · · · ● · · \n"
" · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · \n"
"\n"
" · · · · ◌ · · · · · · · · · · · · · · · · · · · · · ● · · · · \n"
" · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · \n"
"\n"
" · · · · · · · · ● · · · · · · · · · · · · · ◯ · · · · · · · · \n"
" · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · \n"
"\n"
" · · · · · · · · · · ● · · · · · · · · · ⨁ · · · · · · · · · · \n"
" · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · \n"
"\n"
" · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · \n"
" · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · \n"
"\n"
" · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · \n"
" · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · \n"
"\n"
" · · · · · · · · · · · · · ● · · · · · · · · · · · · · · · · · \n"
" · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · \n"
"\n"
" · · · · · · · · · · · · · · · · · · ⨁ · · · · · · · · · · · · \n"
" · · · · · · · · · · · · · ◌ · · · · · · · · · · · · · · · · · \n"
"\n"
" · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · \n"
" · · · · · · · · · · · · · · · ● · · · · · · · · · · · · · · · \n"
"\n"
" · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · \n"
" · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · \n"
"\n"
" · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · \n"
" · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · \n"
"\n"
" · · · · · · · · · · · · · · · ● · · · · · · · · · · · · · · · \n"
" · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · \n"
"\n"
" · · · · · · · · · · · · · · · · ● · · · · · · · · · · · · · · \n"
" · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · \n"
"\n"
" · · · · · · · · · · · · · · · · · · · · ⨁ · · · · · · · · · · \n"
" · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · \n"
"\n"
" · · · · · · · · · · · · · · · · · · · · · · ◯ · · · · · · · · \n"
" · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · \n"
"\n"
" · · · · · · · · · · · · · · · · · · · · · · · · · · ● · · · · \n"
" · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · \n"
"\n"
" · · · · · · · · · · · · · · · · · · · · · · · · · · · · ● · · \n"
" · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · \n"
"\n"
" · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · \n"
" · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · \n"
"\n"
"\n";

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

0 comments on commit cc6075b

Please sign in to comment.