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

✨ Support defects in the SiDB Gate Designer #289

Merged
merged 7 commits into from
Sep 26, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "fiction/algorithms/simulation/sidb/sidb_simulation_engine.hpp"
#include "fiction/algorithms/simulation/sidb/sidb_simulation_parameters.hpp"
#include "fiction/layouts/coordinates.hpp"
#include "fiction/technology/sidb_surface.hpp"
Drewniok marked this conversation as resolved.
Show resolved Hide resolved
#include "fiction/traits.hpp"
#include "fiction/types.hpp"
#include "fiction/utils/layout_utils.hpp"
Expand Down Expand Up @@ -123,7 +124,6 @@ class design_sidb_gates_impl
if (!are_sidbs_too_close(combination))
{
auto layout_with_added_cells = skeleton_layout_with_canvas_sidbs(combination);

if (const auto [status, sim_calls] =
is_operational(layout_with_added_cells, truth_table, params_is_operational);
status == operational_status::OPERATIONAL)
Expand Down Expand Up @@ -317,8 +317,8 @@ class design_sidb_gates_impl

/**
* The *SiDB Gate Designer* designs SiDB gate implementations based on a specified Boolean function, a
* skeleton structure, canvas size, and a predetermined number of canvas SiDBs. Two different design modes are
* implemented: `exhaustive` and `random design`.
* skeleton layout (can hold defects), canvas size, and a predetermined number of canvas SiDBs. Two different design
* modes are implemented: `exhaustive` and `random design`.
*
* The `exhaustive design` is composed of three steps:
* 1. In the initial step, all possible distributions of `number_of_sidbs` SiDBs within a given canvas are
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ Lyt generate_random_sidb_layout(const Lyt& lyt_skeleton, const generate_random_s
const auto random_coord = random_coordinate(params.coordinate_pair.first, params.coordinate_pair.second);

bool constraint_violation_positive_sidbs = false;
bool random_cell_is_identical_wih_defect = false;

if (params.positive_sidbs == generate_random_sidb_layout_params<Lyt>::positive_charges::FORBIDDEN)
{
Expand All @@ -129,8 +130,23 @@ Lyt generate_random_sidb_layout(const Lyt& lyt_skeleton, const generate_random_s
}
});
}
// if the constraint that no positive SiDBs occur is satisfied, the SiDB is added to the layout
if (!constraint_violation_positive_sidbs)
// check if a defect does not yet occupy random coordinate.
if constexpr (has_get_sidb_defect_v<Lyt>)
{
lyt.foreach_sidb_defect(
[&random_cell_is_identical_wih_defect, &random_coord](const auto& cd)
{
const auto& [cell, defect] = cd;
if (cell == random_coord)
{
random_cell_is_identical_wih_defect = true;
}
});
Drewniok marked this conversation as resolved.
Show resolved Hide resolved
}

// if the constraints that no positive SiDBs occur and the cell is not yet occupied by a defect are satisfied,
// the SiDB is added to the layout
if (!constraint_violation_positive_sidbs && !random_cell_is_identical_wih_defect)
{
lyt.assign_cell_type(random_coord, Lyt::cell_type::NORMAL);
Drewniok marked this conversation as resolved.
Show resolved Hide resolved
}
Expand Down
12 changes: 12 additions & 0 deletions include/fiction/technology/sidb_surface.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,18 @@ class sidb_surface<Lyt, false> : public Lyt

assert(strg->params.ignore.count(sidb_defect_type::NONE) == 0 && "The defect type 'NONE' cannot be ignored");
}
/**
* Clones the layout returning a deep copy.
*
* @return Deep copy of the layout.
*/
[[nodiscard]] sidb_surface clone() const noexcept
{
sidb_surface copy{Lyt::clone()};
copy.strg = std::make_shared<sidb_surface_storage>(*strg);

return copy;
}
/**
* Assigns a given defect type to the given coordinate.
*
Expand Down
65 changes: 57 additions & 8 deletions test/algorithms/physical_design/design_sidb_gates.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ TEST_CASE("Use SiQAD XNOR skeleton and generate SiQAD XNOR gate, exhaustive", "[

const design_sidb_gates_params params{sidb_simulation_parameters{2, -0.32},
design_sidb_gates_params::design_sidb_gates_mode::EXHAUSTIVE,
{{10, 4, 0}, {10, 5, 1}},
{{10, 4, 0}, {10, 4, 0}},
1,
sidb_simulation_engine::QUICKEXACT};

Expand Down Expand Up @@ -134,20 +134,45 @@ TEST_CASE("Use FO2 Bestagon gate without SiDB at {17, 11, 0} and generate origin
lyt.assign_cell_type({36, 19, 0}, sidb_technology::cell_type::NORMAL);
lyt.assign_cell_type({2, 19, 0}, sidb_technology::cell_type::NORMAL);

CHECK(lyt.get_cell_type({17, 11, 0}) == layout::technology::EMPTY);

// generate gate by placing one SiDB
const design_sidb_gates_params params{sidb_simulation_parameters{2, -0.32},
design_sidb_gates_params::design_sidb_gates_mode::EXHAUSTIVE,
{{17, 11, 0}, {17, 11, 0}},
1,
sidb_simulation_engine::QUICKEXACT};

const auto found_gate_layouts = design_sidb_gates(lyt, std::vector<tt>{create_fan_out_tt()}, params);
SECTION("generate original fo2")
Drewniok marked this conversation as resolved.
Show resolved Hide resolved
{
CHECK(lyt.get_cell_type({17, 11, 0}) == layout::technology::EMPTY);

REQUIRE(found_gate_layouts.size() == 1);
CHECK(found_gate_layouts[0].num_cells() == 21);
CHECK(found_gate_layouts[0].get_cell_type({17, 11, 0}) == layout::technology::NORMAL);
// generate gate by placing one SiDB

const auto found_gate_layouts = design_sidb_gates(lyt, std::vector<tt>{create_fan_out_tt()}, params);

REQUIRE(found_gate_layouts.size() == 1);
CHECK(found_gate_layouts[0].num_cells() == 21);
CHECK(found_gate_layouts[0].get_cell_type({17, 11, 0}) == layout::technology::NORMAL);
}

SECTION("replace the output perturbers by equivalent negatively charged defects")
{
sidb_defect_cell_clk_lyt_siqad defect_layout{lyt};
defect_layout.assign_cell_type({36, 19, 0}, sidb_technology::cell_type::EMPTY);
defect_layout.assign_cell_type({2, 19, 0}, sidb_technology::cell_type::EMPTY);
CHECK(defect_layout.get_cell_type({36, 19, 0}) == layout::technology::EMPTY);
CHECK(defect_layout.get_cell_type({2, 19, 0}) == layout::technology::EMPTY);
Drewniok marked this conversation as resolved.
Show resolved Hide resolved

defect_layout.assign_sidb_defect(
{36, 19, 0},
sidb_defect{sidb_defect_type::DB, -1, params.phys_params.epsilon_r, params.phys_params.lambda_tf});
defect_layout.assign_sidb_defect({2, 19, 0}, sidb_defect{sidb_defect_type::DB, -1, params.phys_params.epsilon_r,
params.phys_params.lambda_tf});

const auto found_gate_layouts = design_sidb_gates(defect_layout, std::vector<tt>{create_fan_out_tt()}, params);

REQUIRE(found_gate_layouts.size() == 1);
CHECK(found_gate_layouts[0].num_cells() == 19);
CHECK(found_gate_layouts[0].get_cell_type({17, 11, 0}) == layout::technology::NORMAL);
}
}

TEST_CASE("Design AND Bestagon shaped gate", "[design-sidb-gates]")
Expand Down Expand Up @@ -194,4 +219,28 @@ TEST_CASE("Design AND Bestagon shaped gate", "[design-sidb-gates]")
REQUIRE(!found_gate_layouts.empty());
CHECK(found_gate_layouts.front().num_cells() == lyt.num_cells() + 3);
}

SECTION("Random Generation with defects")
{
sidb_defect_cell_clk_lyt_siqad defect_layout{lyt};

defect_layout.assign_sidb_defect(
{15, 10, 0},
sidb_defect{sidb_defect_type::DB, -1, params.phys_params.epsilon_r, params.phys_params.lambda_tf});
defect_layout.assign_sidb_defect(
{20, 12, 0},
sidb_defect{sidb_defect_type::DB, -1, params.phys_params.epsilon_r, params.phys_params.lambda_tf});

const auto found_gate_layouts = design_sidb_gates(defect_layout, std::vector<tt>{create_and_tt()}, params);
REQUIRE(!found_gate_layouts.empty());
CHECK(found_gate_layouts.front().num_defects() == 2);
CHECK(found_gate_layouts.front().num_cells() == lyt.num_cells() + 3);

found_gate_layouts.front().foreach_cell(
[](const auto& cell)
{
CHECK(cell != siqad::coord_t{15, 10, 0});
CHECK(cell != siqad::coord_t{20, 12, 0});
});
}
}
140 changes: 121 additions & 19 deletions test/algorithms/simulation/sidb/random_sidb_layout_generator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@
#include <fiction/layouts/cartesian_layout.hpp>
#include <fiction/layouts/cell_level_layout.hpp>
#include <fiction/layouts/clocked_layout.hpp>
#include <fiction/layouts/coordinates.hpp>
#include <fiction/technology/cell_technologies.hpp>
#include <fiction/technology/sidb_defects.hpp>
#include <fiction/technology/sidb_surface.hpp>

using namespace fiction;

Expand Down Expand Up @@ -402,13 +405,13 @@
}
}

TEST_CASE("Random siqad::coord_t layout generation", "[generate_random_sidb_layout]")
TEST_CASE("Random siqad::coord_t layout generation", "[generate-random-sidb-layout]")
Dismissed Show dismissed Hide dismissed
{
SECTION("empty parameters")
{
const generate_random_sidb_layout_params<sidb_cell_clk_lyt> params{};
const generate_random_sidb_layout_params<sidb_cell_clk_lyt_siqad> params{};

const auto lyt = generate_random_sidb_layout<sidb_cell_clk_lyt>(sidb_cell_clk_lyt{}, params);
const auto lyt = generate_random_sidb_layout<sidb_cell_clk_lyt_siqad>(sidb_cell_clk_lyt_siqad{}, params);
Drewniok marked this conversation as resolved.
Show resolved Hide resolved

CHECK(lyt.num_cells() == 0);
CHECK(lyt.x() == 0);
Expand All @@ -417,9 +420,9 @@

SECTION("given two identical coordinates")
{
const generate_random_sidb_layout_params<sidb_cell_clk_lyt> params{{{5, 5, 1}, {5, 5, 1}}, 1};
const generate_random_sidb_layout_params<sidb_cell_clk_lyt_siqad> params{{{5, 5, 1}, {5, 5, 1}}, 1};

const auto result_lyt = generate_random_sidb_layout<sidb_cell_clk_lyt>(sidb_cell_clk_lyt{}, params);
const auto result_lyt = generate_random_sidb_layout<sidb_cell_clk_lyt_siqad>(sidb_cell_clk_lyt_siqad{}, params);

CHECK(result_lyt.num_cells() == 1);
result_lyt.foreach_cell(
Expand All @@ -433,9 +436,9 @@

SECTION("given corner coordinates")
{
const generate_random_sidb_layout_params<sidb_cell_clk_lyt> params{{{1, 1, 0}, {5, 7, 1}}};
const generate_random_sidb_layout_params<sidb_cell_clk_lyt_siqad> params{{{1, 1, 0}, {5, 7, 1}}};

const auto result_lyt = generate_random_sidb_layout<sidb_cell_clk_lyt>(sidb_cell_clk_lyt{}, params);
const auto result_lyt = generate_random_sidb_layout<sidb_cell_clk_lyt_siqad>(sidb_cell_clk_lyt_siqad{}, params);

CHECK(result_lyt.num_cells() == 0);
result_lyt.foreach_cell(
Expand All @@ -449,9 +452,9 @@

SECTION("given corner coordinates and number of placed SiDBs")
{
const generate_random_sidb_layout_params<sidb_cell_clk_lyt> params{{{1, 1, 0}, {50, 7, 1}}, 10};
const generate_random_sidb_layout_params<sidb_cell_clk_lyt_siqad> params{{{1, 1, 0}, {50, 7, 1}}, 10};

const auto result_lyt = generate_random_sidb_layout<sidb_cell_clk_lyt>(sidb_cell_clk_lyt{}, params);
const auto result_lyt = generate_random_sidb_layout<sidb_cell_clk_lyt_siqad>(sidb_cell_clk_lyt_siqad{}, params);

CHECK(result_lyt.num_cells() == 10);
result_lyt.foreach_cell(
Expand All @@ -467,12 +470,12 @@

SECTION("given corner coordinates and number of placed SiDBs, and allow positive charges")
{
const generate_random_sidb_layout_params<sidb_cell_clk_lyt> params{
const generate_random_sidb_layout_params<sidb_cell_clk_lyt_siqad> params{
{{0, 0, 0}, {90, 90, 0}},
100,
generate_random_sidb_layout_params<sidb_cell_clk_lyt>::positive_charges::ALLOWED};
generate_random_sidb_layout_params<sidb_cell_clk_lyt_siqad>::positive_charges::ALLOWED};

const auto result_lyt = generate_random_sidb_layout<sidb_cell_clk_lyt>(sidb_cell_clk_lyt{}, params);
const auto result_lyt = generate_random_sidb_layout<sidb_cell_clk_lyt_siqad>(sidb_cell_clk_lyt_siqad{}, params);

CHECK(result_lyt.num_cells() == 100);
result_lyt.foreach_cell(
Expand All @@ -485,12 +488,12 @@

SECTION("given corner coordinates and number of placed SiDBs, and forbid positive charges")
{
const generate_random_sidb_layout_params<sidb_cell_clk_lyt> params{
const generate_random_sidb_layout_params<sidb_cell_clk_lyt_siqad> params{
{{0, 0, 0}, {90, 90, 0}},
10,
generate_random_sidb_layout_params<sidb_cell_clk_lyt>::positive_charges::FORBIDDEN};
generate_random_sidb_layout_params<sidb_cell_clk_lyt_siqad>::positive_charges::FORBIDDEN};

const auto result_lyt = generate_random_sidb_layout<sidb_cell_clk_lyt>(sidb_cell_clk_lyt{}, params);
const auto result_lyt = generate_random_sidb_layout<sidb_cell_clk_lyt_siqad>(sidb_cell_clk_lyt_siqad{}, params);

CHECK(result_lyt.num_cells() == 10);
result_lyt.foreach_cell(
Expand All @@ -509,22 +512,23 @@
{
if (cell_one != cell_two)
{
CHECK(euclidean_distance<sidb_cell_clk_lyt>(result_lyt, cell_one, cell_two) >= 2);
CHECK(euclidean_distance<sidb_cell_clk_lyt_siqad>(result_lyt, cell_one, cell_two) >= 2);
}
});
});
}

SECTION("given previous layouts")
{
const generate_random_sidb_layout_params<sidb_cell_clk_lyt> params{
const generate_random_sidb_layout_params<sidb_cell_clk_lyt_siqad> params{
{{0, 0, 1}, {9, 9, 1}},
10,
generate_random_sidb_layout_params<sidb_cell_clk_lyt>::positive_charges::FORBIDDEN,
generate_random_sidb_layout_params<sidb_cell_clk_lyt_siqad>::positive_charges::FORBIDDEN,
2,
static_cast<uint64_t>(10E6),
3};
const auto result_lyts = generate_multiple_random_sidb_layouts<sidb_cell_clk_lyt>(sidb_cell_clk_lyt{}, params);
const auto result_lyts =
generate_multiple_random_sidb_layouts<sidb_cell_clk_lyt_siqad>(sidb_cell_clk_lyt_siqad{}, params);
CHECK(result_lyts.size() == 3);

for (const auto& lyt : result_lyts)
Expand All @@ -541,3 +545,101 @@
}
}
}

TEST_CASE("Random siqad::coord_t layout generation with defects", "[generate-random-sidb-layout]")
{

SECTION("given two identical coordinates")
{
const generate_random_sidb_layout_params<sidb_defect_cell_clk_lyt_siqad> params{{{5, 5, 1}, {5, 5, 1}}, 1};

const auto result_lyt =
generate_random_sidb_layout<sidb_defect_cell_clk_lyt_siqad>(sidb_defect_cell_clk_lyt_siqad{}, params);

CHECK(result_lyt.num_cells() == 1);
result_lyt.foreach_cell(
[](const auto& cell)
{
CHECK(cell.x == 5);
CHECK(cell.y == 5);
CHECK(cell.z == 1);
});
}

SECTION("region including only one cell and there is a defect")
{
// it is not possible to generate a random layout since the position where a SiDB could be placed is occupied by
// a defect.
const generate_random_sidb_layout_params<sidb_defect_cell_clk_lyt_siqad> params{
{{2, 1, 1}, {2, 1, 1}},
1,
generate_random_sidb_layout_params<sidb_defect_cell_clk_lyt_siqad>::positive_charges::FORBIDDEN,
2,
5u};

auto defect_layout = sidb_defect_cell_clk_lyt_siqad{};
defect_layout.assign_sidb_defect({2, 1, 1}, sidb_defect{sidb_defect_type::DB, -1, 5.6, 5});

const auto result_lyt = generate_random_sidb_layout<sidb_defect_cell_clk_lyt_siqad>(defect_layout, params);

CHECK(result_lyt.num_cells() == 0);
CHECK(result_lyt.num_defects() == 1);
}

SECTION("region including only one cell and there is no defect")
{
// it is not possible to generate a random layout since the position where a SiDB could be placed is occupied by
// a defect.
const generate_random_sidb_layout_params<sidb_defect_cell_clk_lyt_siqad> params{
{{2, 1, 1}, {2, 1, 1}},
1,
generate_random_sidb_layout_params<sidb_defect_cell_clk_lyt_siqad>::positive_charges::FORBIDDEN,
2,
5u};

auto defect_layout = sidb_defect_cell_clk_lyt_siqad{};
defect_layout.assign_sidb_defect({3, 1, 1}, sidb_defect{sidb_defect_type::DB, -1, 5.6, 5});
defect_layout.assign_sidb_defect({4, 1, 1}, sidb_defect{sidb_defect_type::SINGLE_DIHYDRIDE, 1, 7.6, 7});

const auto result_lyt = generate_random_sidb_layout<sidb_defect_cell_clk_lyt_siqad>(defect_layout, params);

CHECK(result_lyt.num_cells() == 1);
CHECK(result_lyt.num_defects() == 2);

CHECK(result_lyt.get_cell_type({2, 1, 1}) == sidb_defect_cell_clk_lyt_siqad::technology::cell_type::NORMAL);
CHECK(result_lyt.get_sidb_defect({3, 1, 1}) == sidb_defect{sidb_defect_type::DB, -1, 5.6, 5});
CHECK(result_lyt.get_sidb_defect({4, 1, 1}) == sidb_defect{sidb_defect_type::SINGLE_DIHYDRIDE, 1, 7.6, 7});
}

SECTION("given corner coordinates and number of placed SiDBs, and allow positive charges")
{
const generate_random_sidb_layout_params<sidb_defect_cell_clk_lyt_siqad> params{
{{0, 0, 0}, {10, 2, 0}},
10,
generate_random_sidb_layout_params<sidb_defect_cell_clk_lyt_siqad>::positive_charges::ALLOWED,
2};

auto defect_layout = sidb_defect_cell_clk_lyt_siqad{};
defect_layout.assign_sidb_defect({2, 2, 0}, sidb_defect{sidb_defect_type::DB, -1, 5.6, 5});
defect_layout.assign_sidb_defect({4, 1, 0}, sidb_defect{sidb_defect_type::SINGLE_DIHYDRIDE, 1, 7.6, 7});
defect_layout.assign_sidb_defect({5, 1, 0}, sidb_defect{sidb_defect_type::SINGLE_DIHYDRIDE, 1, 7.6, 9});
defect_layout.assign_sidb_defect({7, 1, 0}, sidb_defect{sidb_defect_type::SINGLE_DIHYDRIDE, 1, 2.6, 7});
defect_layout.assign_sidb_defect({2, 1, 0}, sidb_defect{sidb_defect_type::SINGLE_DIHYDRIDE, 1, 7.6, 4});

const auto result_lyt = generate_random_sidb_layout<sidb_defect_cell_clk_lyt_siqad>(defect_layout, params);

CHECK(result_lyt.num_cells() == 10);
CHECK(result_lyt.num_defects() == 5);

// check if all cells are not closer than two cells (Euclidean distance).
result_lyt.foreach_cell(
[](const auto& cell)
{
CHECK(cell != siqad::coord_t{2, 2, 0});
CHECK(cell != siqad::coord_t{4, 1, 0});
CHECK(cell != siqad::coord_t{5, 1, 0});
CHECK(cell != siqad::coord_t{7, 1, 0});
CHECK(cell != siqad::coord_t{2, 1, 0});
});
}
}
Loading