diff options
-rw-r--r-- | generic/main.cc | 28 | ||||
-rw-r--r-- | gui/quadtree.cc | 122 | ||||
-rw-r--r-- | ice40/hx1k.cc | 106 | ||||
-rw-r--r-- | ice40/hx8k.cc | 106 | ||||
-rw-r--r-- | ice40/lp1k.cc | 106 | ||||
-rw-r--r-- | ice40/lp384.cc | 106 | ||||
-rw-r--r-- | ice40/lp8k.cc | 106 | ||||
-rw-r--r-- | ice40/main.cc | 27 | ||||
-rw-r--r-- | ice40/up5k.cc | 106 |
9 files changed, 813 insertions, 0 deletions
diff --git a/generic/main.cc b/generic/main.cc new file mode 100644 index 0000000..a263471 --- /dev/null +++ b/generic/main.cc @@ -0,0 +1,28 @@ +/* + * nextpnr -- Next Generation Place and Route + * + * Copyright (C) 2018 Miodrag Milanovic <miodrag@symbioticeda.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "gtest/gtest.h" + +#include <vector> + +int main(int argc, char **argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/gui/quadtree.cc b/gui/quadtree.cc new file mode 100644 index 0000000..6711e90 --- /dev/null +++ b/gui/quadtree.cc @@ -0,0 +1,122 @@ +/* + * nextpnr -- Next Generation Place and Route + * + * Copyright (C) 2018 Serge Bazanski <q3k@symbioticeda.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "gtest/gtest.h" +#include "nextpnr.h" + +#include "quadtree.h" + +USING_NEXTPNR_NAMESPACE + +using QT = QuadTree<int, int>; + +class QuadTreeTest : public ::testing::Test +{ + protected: + virtual void SetUp() { qt_ = new QT(QT::BoundingBox(0, 0, width_, height_)); } + virtual void TearDown() { delete qt_; } + + int width_ = 100; + int height_ = 100; + QT *qt_; +}; + +// Test that we're doing bound checking correctly. +TEST_F(QuadTreeTest, insert_bound_checking) +{ + ASSERT_TRUE(qt_->insert(QT::BoundingBox(10, 10, 20, 20), 10)); + ASSERT_TRUE(qt_->insert(QT::BoundingBox(0, 0, 100, 100), 10)); + ASSERT_FALSE(qt_->insert(QT::BoundingBox(10, 10, 101, 20), 10)); + ASSERT_FALSE(qt_->insert(QT::BoundingBox(-1, 10, 101, 20), 10)); + ASSERT_FALSE(qt_->insert(QT::BoundingBox(-1, -1, 20, 20), 10)); +} + +// Test whether we are not losing any elements. +TEST_F(QuadTreeTest, insert_count) +{ + auto rng = NEXTPNR_NAMESPACE::DeterministicRNG(); + + // Add 10000 random rectangles. + for (unsigned int i = 0; i < 10000; i++) { + int x0 = rng.rng(width_); + int y0 = rng.rng(height_); + int w = rng.rng(width_ - x0); + int h = rng.rng(width_ - y0); + int x1 = x0 + w; + int y1 = y0 + h; + ASSERT_TRUE(qt_->insert(QT::BoundingBox(x0, y0, x1, y1), i)); + ASSERT_EQ(qt_->size(), i + 1); + } + // Add 100000 random points. + for (unsigned int i = 0; i < 100000; i++) { + int x0 = rng.rng(width_); + int y0 = rng.rng(height_); + int x1 = x0; + int y1 = y0; + ASSERT_TRUE(qt_->insert(QT::BoundingBox(x0, y0, x1, y1), i)); + ASSERT_EQ(qt_->size(), i + 10001); + } +} + +// Test that we can insert and retrieve the same element. +TEST_F(QuadTreeTest, insert_retrieve_same) +{ + auto rng = NEXTPNR_NAMESPACE::DeterministicRNG(); + + // Add 10000 small random rectangles. + rng.rngseed(0); + for (int i = 0; i < 10000; i++) { + int x0 = rng.rng(width_); + int y0 = rng.rng(height_); + int w = rng.rng(width_ - x0); + int h = rng.rng(width_ - y0); + int x1 = x0 + w / 4; + int y1 = y0 + h / 4; + ASSERT_TRUE(qt_->insert(QT::BoundingBox(x0, y0, x1, y1), i)); + } + + // Restart RNG, make sure we get the same rectangles back. + rng.rngseed(0); + for (int i = 0; i < 10000; i++) { + int x0 = rng.rng(width_); + int y0 = rng.rng(height_); + int w = rng.rng(width_ - x0); + int h = rng.rng(width_ - y0); + int x1 = x0 + w / 4; + int y1 = y0 + h / 4; + + // try to find something in the middle of the square + int x = (x1 - x0) / 2 + x0; + int y = (y1 - y0) / 2 + y0; + + auto res = qt_->get(x, y); + // Somewhat arbirary test to make sure we don't return obscene + // amounts of data. + ASSERT_LT(res.size(), 200UL); + bool found = false; + for (auto elem : res) { + // Is this what we're looking for? + if (elem == i) { + found = true; + break; + } + } + ASSERT_TRUE(found); + } +} diff --git a/ice40/hx1k.cc b/ice40/hx1k.cc new file mode 100644 index 0000000..741c954 --- /dev/null +++ b/ice40/hx1k.cc @@ -0,0 +1,106 @@ +/* + * nextpnr -- Next Generation Place and Route + * + * Copyright (C) 2018 Clifford Wolf <clifford@symbioticeda.com> + * Copyright (C) 2018 Miodrag Milanovic <miodrag@symbioticeda.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include <vector> +#include "gtest/gtest.h" +#include "nextpnr.h" + +USING_NEXTPNR_NAMESPACE + +class HX1KTest : public ::testing::Test +{ + protected: + virtual void SetUp() + { + chipArgs.type = ArchArgs::HX1K; + chipArgs.package = "tq144"; + ctx = new Context(chipArgs); + } + + virtual void TearDown() { delete ctx; } + + ArchArgs chipArgs; + Context *ctx; +}; + +TEST_F(HX1KTest, bel_names) +{ + int bel_count = 0; + for (auto bel : ctx->getBels()) { + auto name = ctx->getBelName(bel); + ASSERT_EQ(bel, ctx->getBelByName(name)); + bel_count++; + } + ASSERT_EQ(bel_count, 1418); +} + +TEST_F(HX1KTest, wire_names) +{ + int wire_count = 0; + for (auto wire : ctx->getWires()) { + auto name = ctx->getWireName(wire); + assert(wire == ctx->getWireByName(name)); + wire_count++; + } + ASSERT_EQ(wire_count, 32802); +} + +TEST_F(HX1KTest, pip_names) +{ + int pip_count = 0; + for (auto pip : ctx->getPips()) { + auto name = ctx->getPipName(pip); + assert(pip == ctx->getPipByName(name)); + pip_count++; + } + ASSERT_EQ(pip_count, 345504); +} + +TEST_F(HX1KTest, uphill_to_downhill) +{ + for (auto dst : ctx->getWires()) { + for (auto uphill_pip : ctx->getPipsUphill(dst)) { + bool found_downhill = false; + for (auto downhill_pip : ctx->getPipsDownhill(ctx->getPipSrcWire(uphill_pip))) { + if (uphill_pip == downhill_pip) { + ASSERT_FALSE(found_downhill); + found_downhill = true; + } + } + ASSERT_TRUE(found_downhill); + } + } +} + +TEST_F(HX1KTest, downhill_to_uphill) +{ + for (auto dst : ctx->getWires()) { + for (auto downhill_pip : ctx->getPipsDownhill(dst)) { + bool found_uphill = false; + for (auto uphill_pip : ctx->getPipsUphill(ctx->getPipDstWire(downhill_pip))) { + if (uphill_pip == downhill_pip) { + ASSERT_FALSE(found_uphill); + found_uphill = true; + } + } + ASSERT_TRUE(found_uphill); + } + } +} diff --git a/ice40/hx8k.cc b/ice40/hx8k.cc new file mode 100644 index 0000000..517df0d --- /dev/null +++ b/ice40/hx8k.cc @@ -0,0 +1,106 @@ +/* + * nextpnr -- Next Generation Place and Route + * + * Copyright (C) 2018 Clifford Wolf <clifford@symbioticeda.com> + * Copyright (C) 2018 Miodrag Milanovic <miodrag@symbioticeda.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include <vector> +#include "gtest/gtest.h" +#include "nextpnr.h" + +USING_NEXTPNR_NAMESPACE + +class HX8KTest : public ::testing::Test +{ + protected: + virtual void SetUp() + { + chipArgs.type = ArchArgs::HX8K; + chipArgs.package = "ct256"; + ctx = new Context(chipArgs); + } + + virtual void TearDown() { delete ctx; } + + ArchArgs chipArgs; + Context *ctx; +}; + +TEST_F(HX8KTest, bel_names) +{ + int bel_count = 0; + for (auto bel : ctx->getBels()) { + auto name = ctx->getBelName(bel); + ASSERT_EQ(bel, ctx->getBelByName(name)); + bel_count++; + } + ASSERT_EQ(bel_count, 7979); +} + +TEST_F(HX8KTest, wire_names) +{ + int wire_count = 0; + for (auto wire : ctx->getWires()) { + auto name = ctx->getWireName(wire); + assert(wire == ctx->getWireByName(name)); + wire_count++; + } + ASSERT_EQ(wire_count, 165894); +} + +TEST_F(HX8KTest, pip_names) +{ + int pip_count = 0; + for (auto pip : ctx->getPips()) { + auto name = ctx->getPipName(pip); + assert(pip == ctx->getPipByName(name)); + pip_count++; + } + ASSERT_EQ(pip_count, 1806080); +} + +TEST_F(HX8KTest, uphill_to_downhill) +{ + for (auto dst : ctx->getWires()) { + for (auto uphill_pip : ctx->getPipsUphill(dst)) { + bool found_downhill = false; + for (auto downhill_pip : ctx->getPipsDownhill(ctx->getPipSrcWire(uphill_pip))) { + if (uphill_pip == downhill_pip) { + ASSERT_FALSE(found_downhill); + found_downhill = true; + } + } + ASSERT_TRUE(found_downhill); + } + } +} + +TEST_F(HX8KTest, downhill_to_uphill) +{ + for (auto dst : ctx->getWires()) { + for (auto downhill_pip : ctx->getPipsDownhill(dst)) { + bool found_uphill = false; + for (auto uphill_pip : ctx->getPipsUphill(ctx->getPipDstWire(downhill_pip))) { + if (uphill_pip == downhill_pip) { + ASSERT_FALSE(found_uphill); + found_uphill = true; + } + } + ASSERT_TRUE(found_uphill); + } + } +} diff --git a/ice40/lp1k.cc b/ice40/lp1k.cc new file mode 100644 index 0000000..2fdba08 --- /dev/null +++ b/ice40/lp1k.cc @@ -0,0 +1,106 @@ +/* + * nextpnr -- Next Generation Place and Route + * + * Copyright (C) 2018 Clifford Wolf <clifford@symbioticeda.com> + * Copyright (C) 2018 Miodrag Milanovic <miodrag@symbioticeda.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include <vector> +#include "gtest/gtest.h" +#include "nextpnr.h" + +USING_NEXTPNR_NAMESPACE + +class LP1KTest : public ::testing::Test +{ + protected: + virtual void SetUp() + { + chipArgs.type = ArchArgs::LP1K; + chipArgs.package = "tq144"; + ctx = new Context(chipArgs); + } + + virtual void TearDown() { delete ctx; } + + ArchArgs chipArgs; + Context *ctx; +}; + +TEST_F(LP1KTest, bel_names) +{ + int bel_count = 0; + for (auto bel : ctx->getBels()) { + auto name = ctx->getBelName(bel); + ASSERT_EQ(bel, ctx->getBelByName(name)); + bel_count++; + } + ASSERT_EQ(bel_count, 1418); +} + +TEST_F(LP1KTest, wire_names) +{ + int wire_count = 0; + for (auto wire : ctx->getWires()) { + auto name = ctx->getWireName(wire); + assert(wire == ctx->getWireByName(name)); + wire_count++; + } + ASSERT_EQ(wire_count, 32802); +} + +TEST_F(LP1KTest, pip_names) +{ + int pip_count = 0; + for (auto pip : ctx->getPips()) { + auto name = ctx->getPipName(pip); + assert(pip == ctx->getPipByName(name)); + pip_count++; + } + ASSERT_EQ(pip_count, 345504); +} + +TEST_F(LP1KTest, uphill_to_downhill) +{ + for (auto dst : ctx->getWires()) { + for (auto uphill_pip : ctx->getPipsUphill(dst)) { + bool found_downhill = false; + for (auto downhill_pip : ctx->getPipsDownhill(ctx->getPipSrcWire(uphill_pip))) { + if (uphill_pip == downhill_pip) { + ASSERT_FALSE(found_downhill); + found_downhill = true; + } + } + ASSERT_TRUE(found_downhill); + } + } +} + +TEST_F(LP1KTest, downhill_to_uphill) +{ + for (auto dst : ctx->getWires()) { + for (auto downhill_pip : ctx->getPipsDownhill(dst)) { + bool found_uphill = false; + for (auto uphill_pip : ctx->getPipsUphill(ctx->getPipDstWire(downhill_pip))) { + if (uphill_pip == downhill_pip) { + ASSERT_FALSE(found_uphill); + found_uphill = true; + } + } + ASSERT_TRUE(found_uphill); + } + } +} diff --git a/ice40/lp384.cc b/ice40/lp384.cc new file mode 100644 index 0000000..a030b77 --- /dev/null +++ b/ice40/lp384.cc @@ -0,0 +1,106 @@ +/* + * nextpnr -- Next Generation Place and Route + * + * Copyright (C) 2018 Clifford Wolf <clifford@symbioticeda.com> + * Copyright (C) 2018 Miodrag Milanovic <miodrag@symbioticeda.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include <vector> +#include "gtest/gtest.h" +#include "nextpnr.h" + +USING_NEXTPNR_NAMESPACE + +class LP384Test : public ::testing::Test +{ + protected: + virtual void SetUp() + { + chipArgs.type = ArchArgs::LP384; + chipArgs.package = "qn32"; + ctx = new Context(chipArgs); + } + + virtual void TearDown() { delete ctx; } + + ArchArgs chipArgs; + Context *ctx; +}; + +TEST_F(LP384Test, bel_names) +{ + int bel_count = 0; + for (auto bel : ctx->getBels()) { + auto name = ctx->getBelName(bel); + ASSERT_EQ(bel, ctx->getBelByName(name)); + bel_count++; + } + ASSERT_EQ(bel_count, 449); +} + +TEST_F(LP384Test, wire_names) +{ + int wire_count = 0; + for (auto wire : ctx->getWires()) { + auto name = ctx->getWireName(wire); + assert(wire == ctx->getWireByName(name)); + wire_count++; + } + ASSERT_EQ(wire_count, 9830); +} + +TEST_F(LP384Test, pip_names) +{ + int pip_count = 0; + for (auto pip : ctx->getPips()) { + auto name = ctx->getPipName(pip); + assert(pip == ctx->getPipByName(name)); + pip_count++; + } + ASSERT_EQ(pip_count, 94544); +} + +TEST_F(LP384Test, uphill_to_downhill) +{ + for (auto dst : ctx->getWires()) { + for (auto uphill_pip : ctx->getPipsUphill(dst)) { + bool found_downhill = false; + for (auto downhill_pip : ctx->getPipsDownhill(ctx->getPipSrcWire(uphill_pip))) { + if (uphill_pip == downhill_pip) { + ASSERT_FALSE(found_downhill); + found_downhill = true; + } + } + ASSERT_TRUE(found_downhill); + } + } +} + +TEST_F(LP384Test, downhill_to_uphill) +{ + for (auto dst : ctx->getWires()) { + for (auto downhill_pip : ctx->getPipsDownhill(dst)) { + bool found_uphill = false; + for (auto uphill_pip : ctx->getPipsUphill(ctx->getPipDstWire(downhill_pip))) { + if (uphill_pip == downhill_pip) { + ASSERT_FALSE(found_uphill); + found_uphill = true; + } + } + ASSERT_TRUE(found_uphill); + } + } +} diff --git a/ice40/lp8k.cc b/ice40/lp8k.cc new file mode 100644 index 0000000..7fe6ac3 --- /dev/null +++ b/ice40/lp8k.cc @@ -0,0 +1,106 @@ +/* + * nextpnr -- Next Generation Place and Route + * + * Copyright (C) 2018 Clifford Wolf <clifford@symbioticeda.com> + * Copyright (C) 2018 Miodrag Milanovic <miodrag@symbioticeda.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include <vector> +#include "gtest/gtest.h" +#include "nextpnr.h" + +USING_NEXTPNR_NAMESPACE + +class LP8KTest : public ::testing::Test +{ + protected: + virtual void SetUp() + { + chipArgs.type = ArchArgs::LP8K; + chipArgs.package = "ct256"; + ctx = new Context(chipArgs); + } + + virtual void TearDown() { delete ctx; } + + ArchArgs chipArgs; + Context *ctx; +}; + +TEST_F(LP8KTest, bel_names) +{ + int bel_count = 0; + for (auto bel : ctx->getBels()) { + auto name = ctx->getBelName(bel); + ASSERT_EQ(bel, ctx->getBelByName(name)); + bel_count++; + } + ASSERT_EQ(bel_count, 7979); +} + +TEST_F(LP8KTest, wire_names) +{ + int wire_count = 0; + for (auto wire : ctx->getWires()) { + auto name = ctx->getWireName(wire); + assert(wire == ctx->getWireByName(name)); + wire_count++; + } + ASSERT_EQ(wire_count, 165894); +} + +TEST_F(LP8KTest, pip_names) +{ + int pip_count = 0; + for (auto pip : ctx->getPips()) { + auto name = ctx->getPipName(pip); + assert(pip == ctx->getPipByName(name)); + pip_count++; + } + ASSERT_EQ(pip_count, 1806080); +} + +TEST_F(LP8KTest, uphill_to_downhill) +{ + for (auto dst : ctx->getWires()) { + for (auto uphill_pip : ctx->getPipsUphill(dst)) { + bool found_downhill = false; + for (auto downhill_pip : ctx->getPipsDownhill(ctx->getPipSrcWire(uphill_pip))) { + if (uphill_pip == downhill_pip) { + ASSERT_FALSE(found_downhill); + found_downhill = true; + } + } + ASSERT_TRUE(found_downhill); + } + } +} + +TEST_F(LP8KTest, downhill_to_uphill) +{ + for (auto dst : ctx->getWires()) { + for (auto downhill_pip : ctx->getPipsDownhill(dst)) { + bool found_uphill = false; + for (auto uphill_pip : ctx->getPipsUphill(ctx->getPipDstWire(downhill_pip))) { + if (uphill_pip == downhill_pip) { + ASSERT_FALSE(found_uphill); + found_uphill = true; + } + } + ASSERT_TRUE(found_uphill); + } + } +} diff --git a/ice40/main.cc b/ice40/main.cc new file mode 100644 index 0000000..60b9fda --- /dev/null +++ b/ice40/main.cc @@ -0,0 +1,27 @@ +/* + * nextpnr -- Next Generation Place and Route + * + * Copyright (C) 2018 Miodrag Milanovic <miodrag@symbioticeda.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include <vector> +#include "gtest/gtest.h" + +int main(int argc, char **argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/ice40/up5k.cc b/ice40/up5k.cc new file mode 100644 index 0000000..582876e --- /dev/null +++ b/ice40/up5k.cc @@ -0,0 +1,106 @@ +/* + * nextpnr -- Next Generation Place and Route + * + * Copyright (C) 2018 Clifford Wolf <clifford@symbioticeda.com> + * Copyright (C) 2018 Miodrag Milanovic <miodrag@symbioticeda.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include <vector> +#include "gtest/gtest.h" +#include "nextpnr.h" + +USING_NEXTPNR_NAMESPACE + +class UP5KTest : public ::testing::Test +{ + protected: + virtual void SetUp() + { + chipArgs.type = ArchArgs::UP5K; + chipArgs.package = "sg48"; + ctx = new Context(chipArgs); + } + + virtual void TearDown() { delete ctx; } + + ArchArgs chipArgs; + Context *ctx; +}; + +TEST_F(UP5KTest, bel_names) +{ + int bel_count = 0; + for (auto bel : ctx->getBels()) { + auto name = ctx->getBelName(bel); + ASSERT_EQ(bel, ctx->getBelByName(name)); + bel_count++; + } + ASSERT_EQ(bel_count, 5438); +} + +TEST_F(UP5KTest, wire_names) +{ + int wire_count = 0; + for (auto wire : ctx->getWires()) { + auto name = ctx->getWireName(wire); + assert(wire == ctx->getWireByName(name)); + wire_count++; + } + ASSERT_EQ(wire_count, 124503); +} + +TEST_F(UP5KTest, pip_names) +{ + int pip_count = 0; + for (auto pip : ctx->getPips()) { + auto name = ctx->getPipName(pip); + assert(pip == ctx->getPipByName(name)); + pip_count++; + } + ASSERT_EQ(pip_count, 1324704); +} + +TEST_F(UP5KTest, uphill_to_downhill) +{ + for (auto dst : ctx->getWires()) { + for (auto uphill_pip : ctx->getPipsUphill(dst)) { + bool found_downhill = false; + for (auto downhill_pip : ctx->getPipsDownhill(ctx->getPipSrcWire(uphill_pip))) { + if (uphill_pip == downhill_pip) { + ASSERT_FALSE(found_downhill); + found_downhill = true; + } + } + ASSERT_TRUE(found_downhill); + } + } +} + +TEST_F(UP5KTest, downhill_to_uphill) +{ + for (auto dst : ctx->getWires()) { + for (auto downhill_pip : ctx->getPipsDownhill(dst)) { + bool found_uphill = false; + for (auto uphill_pip : ctx->getPipsUphill(ctx->getPipDstWire(downhill_pip))) { + if (uphill_pip == downhill_pip) { + ASSERT_FALSE(found_uphill); + found_uphill = true; + } + } + ASSERT_TRUE(found_uphill); + } + } +} |