├── .gitmodules ├── TODO.md ├── core ├── common │ ├── .gitignore │ ├── subprocess_win.cpp │ ├── common.h │ ├── subprocess.h │ ├── matrix.cpp │ ├── subprocess_unix.cpp │ ├── fileutils.h │ └── logging.h ├── cppcheck │ └── CppCheckSuppressions.txt ├── export │ ├── export.h │ ├── ppm │ │ ├── ppmwriter.h │ │ └── ppmwriter.cpp │ ├── txt │ │ ├── txtwriter.h │ │ └── txtwriter.cpp │ ├── spef │ │ └── spefwriter.h │ ├── verilog │ │ └── verilogwriter.h │ ├── gds2 │ │ └── gds2writer.hpp │ ├── dot │ │ └── dotwriter.h │ └── def │ │ └── defwriter.h ├── database │ ├── row.cpp │ ├── properties.hpp │ ├── enums.toml │ ├── row.h │ ├── observer.h │ ├── module.h │ ├── cell.cpp │ ├── design.cpp │ ├── netlisttools.h │ ├── observer.cpp │ ├── netlist.h │ ├── net.cpp │ ├── design.h │ ├── floorplan.cpp │ ├── module.cpp │ ├── database.h │ ├── visitor.h │ └── pin.cpp ├── dummy.cpp ├── python │ ├── types │ │ ├── pycelllib.h │ │ ├── pytechlayers.h │ │ ├── pytechsites.h │ │ ├── pypin.h │ │ ├── pycell.h │ │ ├── pypininfo.h │ │ ├── pynets.h │ │ ├── pypininfolist.h │ │ ├── pysiteinfo.h │ │ ├── pyinstance.h │ │ ├── pylayerinfo.h │ │ ├── pynet.h │ │ └── pyinstances.h │ ├── consoleredirect.h │ ├── pylunapnr.h │ └── converters.h ├── utilities │ ├── CMakeLists.txt │ └── README.md ├── clangtidy │ └── clangtidy.yaml ├── cts │ └── cts_private.h ├── algebra │ ├── algebra.hpp │ └── solver.hpp ├── padring │ └── padringplacer.hpp ├── import │ ├── lef │ │ ├── lefreader.h │ │ └── lefreader.cpp │ ├── liberty │ │ ├── libreader.h │ │ └── libreader.cpp │ ├── ppm │ │ └── ppmreader.h │ ├── import.h │ └── def │ │ ├── defreader.h │ │ ├── defreader.cpp │ │ └── defreaderimpl.h ├── passes │ ├── passes.hpp │ ├── passes.cpp │ ├── clearpass.hpp │ ├── flattenpass.hpp │ └── ctspass.hpp ├── cellplacer │ ├── cellplacer.h │ ├── qplacertypes.cpp │ ├── cellplacer.cpp │ └── netlistsplitter.h ├── globalroute │ ├── wavefront.cpp │ ├── prim_private.cpp │ ├── wavefront.h │ ├── prim_private.h │ └── lshape.h ├── include │ └── lunacore.h └── cellplacer2 │ └── fillerhandler.h ├── test ├── files │ ├── results │ │ ├── placeholder.txt │ │ └── convert_dots.sh │ ├── ppm │ │ ├── route1.ppm │ │ ├── route2.ppm │ │ ├── route3.ppm │ │ ├── complexroute.ppm │ │ └── complexroute2.ppm │ ├── gen_padring.sh │ ├── clean_cells.sh │ ├── verilog │ │ ├── assign_test.v │ │ └── netcon_test.v │ ├── padring │ │ ├── padring.v │ │ └── padring.conf │ └── get_cells.bat ├── python │ ├── various │ │ ├── nullscript.py │ │ └── mandel.py │ ├── CMakeLists.txt │ └── main.cpp ├── CMakeLists.txt └── core │ ├── main.cpp │ ├── gds2test.cpp │ ├── ppmtests.cpp │ ├── svgwritertest.cpp │ ├── globalroutergridtest.cpp │ ├── spefwritertest.cpp │ ├── techlibtest.cpp │ ├── simplecellplacertest.cpp │ ├── fileutilstest.cpp │ └── dotwritertest.cpp ├── doc ├── .gitignore ├── screenshots │ ├── cellbrowser_2022.png │ ├── techbrowser_2022.png │ ├── mac32_floorplan_2022.png │ └── screenshot_8_10_2021.png └── codingconventions.md ├── gui ├── console │ ├── .gitignore │ ├── cmdcompleter.hpp │ ├── mtstringbuffer.h │ └── mtstringbuffer.cpp ├── resources │ ├── images │ │ ├── add.png │ │ ├── go.png │ │ ├── file.png │ │ ├── folded.png │ │ ├── folder.png │ │ ├── remove.png │ │ ├── pinicon.png │ │ ├── unfolded.png │ │ ├── floorplan.png │ │ ├── lunapnrlogo.png │ │ ├── properties.png │ │ ├── status_ok.png │ │ ├── status_empty.png │ │ ├── status_error.png │ │ └── status_running.png │ ├── icons │ │ ├── lunapnr.png │ │ ├── lunapnr128x128.png │ │ └── lunapnr256x256.png │ └── resources.qrc ├── common │ ├── imagemanip.h │ ├── msvcfix.h │ ├── database.cpp │ ├── hatchlibrary.h │ ├── imagemanip.cpp │ ├── pdkinfo.h │ ├── tasklist.h │ ├── database.h │ ├── customevents.h │ └── projectsetup.h ├── python │ ├── types │ │ └── pyproject.h │ └── pyluna_extra.h ├── widgets │ ├── layerwidget.cpp │ ├── layerwidget.h │ ├── clickablelabel.cpp │ ├── blockframe.h │ ├── clickablelabel.h │ ├── hatchbutton.h │ ├── hatchdisplay.h │ ├── colorbutton.h │ ├── blockframe.cpp │ ├── flatimage.h │ ├── hatchdialog.h │ ├── flatimagebutton.h │ ├── txtoverlay.h │ ├── flattogglebutton.h │ ├── flatactiontile.h │ ├── flatactiontile.cpp │ ├── rectdelegate.h │ ├── txtoverlay.cpp │ ├── flatimage.cpp │ ├── colorbutton.cpp │ ├── hatchdialog.cpp │ ├── flattilebase.h │ ├── flatimagebutton.cpp │ ├── hatchbutton.cpp │ ├── hatchdisplay.cpp │ └── blockcontainer.h ├── tasks │ ├── ctstask.h │ ├── place.h │ ├── globalroute.h │ ├── readallfiles.h │ ├── createfloorplan.h │ ├── preflightchecks.h │ ├── checktiming.h │ └── tasks.cpp ├── aboutdialog │ └── aboutdialog.h ├── src │ └── configurationdialog.h ├── ctsdialog │ └── ctsdialog.h ├── floorplandialog │ └── floorplandialog.h ├── propertyview │ └── propertyview.h ├── pdkdialog │ ├── pdkdialog.h │ ├── pdktile.h │ └── pdkdialog.cpp ├── models │ ├── cellinfomodel.h │ ├── moduleinfomodel.h │ └── layerappearancetablemodel.h ├── projectmanager │ ├── projectmanager.h │ └── filesetupmanager.h ├── designbrowser │ └── designbrowser.h └── pdkinstaller │ └── downloader.h ├── examples ├── adder8 │ ├── run.sh │ ├── adder8.v │ ├── adder8.sdc │ ├── adder8.ys │ ├── adder8_floorplan.py │ ├── adder8.lpr │ └── fa_map.v ├── femtorv32 │ ├── run.sh │ ├── femtov32_quark.sdc │ ├── femtorv32_quark.ys │ └── femtov32_quark.lpr ├── lfsr31 │ ├── run.sh │ ├── sim.sh │ ├── lfsr31.sdc │ ├── lfsr31_floorplan.py │ ├── lfsr31.ys │ ├── lfsr31.vhd │ ├── lfsr31.lpr │ └── lfsr31_tb.vhd ├── adder8_simplegates │ ├── run.sh │ ├── adder8.v │ ├── adder8.sdc │ ├── adder8_simplegates.ys │ ├── adder8_floorplan.py │ └── adder8_simplegates.lpr ├── mac32 │ ├── run.sh │ ├── mac32.sdc │ ├── mac32.tcl │ ├── mac32.v │ ├── mac32.lpr │ └── mac32_floorplan.py ├── osu180pdk.toml ├── sky130pdk.toml └── freepdk45.toml ├── resources ├── icons │ ├── lunapnr.png │ ├── lunapnr128x128.png │ └── lunapnr256x256.png └── lunapnr.desktop ├── bootstrap_release.bat ├── generate_deb.sh ├── .github └── FUNDING.yml ├── version ├── version.h ├── version.cpp.in └── compilerversion.cmake ├── .debian └── Copyright.txt ├── scripts ├── init_ihp130.py ├── init_osu180.py ├── loadall.py ├── place_adder8.py ├── place_multiplier.py ├── padring.pnr └── place_femtorv32.py ├── bootstrap_release.sh ├── bootstrap.sh ├── .gitignore └── mkappimage.sh /.gitmodules: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | # TODO 2 | 3 | -------------------------------------------------------------------------------- /core/common/.gitignore: -------------------------------------------------------------------------------- 1 | enums.h 2 | -------------------------------------------------------------------------------- /core/cppcheck/CppCheckSuppressions.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/files/results/placeholder.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /doc/.gitignore: -------------------------------------------------------------------------------- 1 | srcdoc 2 | index.html 3 | -------------------------------------------------------------------------------- /gui/console/.gitignore: -------------------------------------------------------------------------------- 1 | commandcompletion.inc -------------------------------------------------------------------------------- /examples/adder8/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | yosys -s adder8.ys 4 | -------------------------------------------------------------------------------- /test/python/various/nullscript.py: -------------------------------------------------------------------------------- 1 | # Script without any contents 2 | -------------------------------------------------------------------------------- /examples/femtorv32/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | yosys -s femtorv32_quark.ys 4 | -------------------------------------------------------------------------------- /examples/lfsr31/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | yosys -m ghdl -p 'script lfsr31.ys' 3 | -------------------------------------------------------------------------------- /examples/adder8_simplegates/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | yosys -s adder8_simplegates.ys 4 | -------------------------------------------------------------------------------- /test/files/ppm/route1.ppm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asicsforthemasses/LunaPnR/HEAD/test/files/ppm/route1.ppm -------------------------------------------------------------------------------- /test/files/ppm/route2.ppm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asicsforthemasses/LunaPnR/HEAD/test/files/ppm/route2.ppm -------------------------------------------------------------------------------- /test/files/ppm/route3.ppm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asicsforthemasses/LunaPnR/HEAD/test/files/ppm/route3.ppm -------------------------------------------------------------------------------- /gui/resources/images/add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asicsforthemasses/LunaPnR/HEAD/gui/resources/images/add.png -------------------------------------------------------------------------------- /gui/resources/images/go.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asicsforthemasses/LunaPnR/HEAD/gui/resources/images/go.png -------------------------------------------------------------------------------- /resources/icons/lunapnr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asicsforthemasses/LunaPnR/HEAD/resources/icons/lunapnr.png -------------------------------------------------------------------------------- /gui/resources/icons/lunapnr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asicsforthemasses/LunaPnR/HEAD/gui/resources/icons/lunapnr.png -------------------------------------------------------------------------------- /gui/resources/images/file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asicsforthemasses/LunaPnR/HEAD/gui/resources/images/file.png -------------------------------------------------------------------------------- /gui/resources/images/folded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asicsforthemasses/LunaPnR/HEAD/gui/resources/images/folded.png -------------------------------------------------------------------------------- /gui/resources/images/folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asicsforthemasses/LunaPnR/HEAD/gui/resources/images/folder.png -------------------------------------------------------------------------------- /gui/resources/images/remove.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asicsforthemasses/LunaPnR/HEAD/gui/resources/images/remove.png -------------------------------------------------------------------------------- /test/files/ppm/complexroute.ppm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asicsforthemasses/LunaPnR/HEAD/test/files/ppm/complexroute.ppm -------------------------------------------------------------------------------- /gui/resources/images/pinicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asicsforthemasses/LunaPnR/HEAD/gui/resources/images/pinicon.png -------------------------------------------------------------------------------- /gui/resources/images/unfolded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asicsforthemasses/LunaPnR/HEAD/gui/resources/images/unfolded.png -------------------------------------------------------------------------------- /test/files/ppm/complexroute2.ppm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asicsforthemasses/LunaPnR/HEAD/test/files/ppm/complexroute2.ppm -------------------------------------------------------------------------------- /doc/screenshots/cellbrowser_2022.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asicsforthemasses/LunaPnR/HEAD/doc/screenshots/cellbrowser_2022.png -------------------------------------------------------------------------------- /doc/screenshots/techbrowser_2022.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asicsforthemasses/LunaPnR/HEAD/doc/screenshots/techbrowser_2022.png -------------------------------------------------------------------------------- /examples/adder8/adder8.v: -------------------------------------------------------------------------------- 1 | module adder8(input [7:0] a, input [7:0] b, output [7:0] y); 2 | 3 | assign y = a+b; 4 | 5 | endmodule 6 | -------------------------------------------------------------------------------- /gui/resources/images/floorplan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asicsforthemasses/LunaPnR/HEAD/gui/resources/images/floorplan.png -------------------------------------------------------------------------------- /gui/resources/images/lunapnrlogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asicsforthemasses/LunaPnR/HEAD/gui/resources/images/lunapnrlogo.png -------------------------------------------------------------------------------- /gui/resources/images/properties.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asicsforthemasses/LunaPnR/HEAD/gui/resources/images/properties.png -------------------------------------------------------------------------------- /gui/resources/images/status_ok.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asicsforthemasses/LunaPnR/HEAD/gui/resources/images/status_ok.png -------------------------------------------------------------------------------- /resources/icons/lunapnr128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asicsforthemasses/LunaPnR/HEAD/resources/icons/lunapnr128x128.png -------------------------------------------------------------------------------- /resources/icons/lunapnr256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asicsforthemasses/LunaPnR/HEAD/resources/icons/lunapnr256x256.png -------------------------------------------------------------------------------- /bootstrap_release.bat: -------------------------------------------------------------------------------- 1 | 2 | set BOOST_ROOT=C:\Boost 3 | mkdir build 4 | cd build 5 | cmake -GNinja -DCMAKE_BUILD_TYPE=Release .. 6 | cd .. -------------------------------------------------------------------------------- /gui/resources/icons/lunapnr128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asicsforthemasses/LunaPnR/HEAD/gui/resources/icons/lunapnr128x128.png -------------------------------------------------------------------------------- /gui/resources/icons/lunapnr256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asicsforthemasses/LunaPnR/HEAD/gui/resources/icons/lunapnr256x256.png -------------------------------------------------------------------------------- /gui/resources/images/status_empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asicsforthemasses/LunaPnR/HEAD/gui/resources/images/status_empty.png -------------------------------------------------------------------------------- /gui/resources/images/status_error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asicsforthemasses/LunaPnR/HEAD/gui/resources/images/status_error.png -------------------------------------------------------------------------------- /doc/screenshots/mac32_floorplan_2022.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asicsforthemasses/LunaPnR/HEAD/doc/screenshots/mac32_floorplan_2022.png -------------------------------------------------------------------------------- /doc/screenshots/screenshot_8_10_2021.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asicsforthemasses/LunaPnR/HEAD/doc/screenshots/screenshot_8_10_2021.png -------------------------------------------------------------------------------- /gui/resources/images/status_running.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asicsforthemasses/LunaPnR/HEAD/gui/resources/images/status_running.png -------------------------------------------------------------------------------- /examples/adder8_simplegates/adder8.v: -------------------------------------------------------------------------------- 1 | module adder8(input [7:0] a, input [7:0] b, output [7:0] y); 2 | 3 | assign y = a+b; 4 | 5 | endmodule 6 | -------------------------------------------------------------------------------- /examples/lfsr31/sim.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ghdl -a lfsr31.vhd 4 | ghdl -a lfsr31_tb.vhd 5 | ghdl -e lfsr31_tb 6 | ghdl -r lfsr31_tb --wave=lfsr31.ghw -------------------------------------------------------------------------------- /core/export/export.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "verilog/verilogwriter.h" 4 | #include "def/defwriter.h" 5 | #include "txt/txtwriter.h" 6 | #include "gds2/gds2writer.hpp" 7 | -------------------------------------------------------------------------------- /core/database/row.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #include "row.h" -------------------------------------------------------------------------------- /test/files/gen_padring.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ../../../gdstools/build/gdsmerge -i iit_stdcells/lib/source/gds2/iit035_pads.gds2 -i results/padring.gds -o padring_merged.gds 4 | 5 | -------------------------------------------------------------------------------- /core/dummy.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | void dummy() 6 | { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /examples/femtorv32/femtov32_quark.sdc: -------------------------------------------------------------------------------- 1 | create_clock -name clk -period 12 {clk} 2 | set_input_delay -clock {clk} -max 1 [all_inputs] 3 | set_output_delay -clock {clk} -max 1 [all_outputs] 4 | -------------------------------------------------------------------------------- /examples/lfsr31/lfsr31.sdc: -------------------------------------------------------------------------------- 1 | 2 | create_clock -period 10 clk 3 | set_input_delay 1 -clock [get_clocks clk] [get_ports {rst_an}] 4 | set_output_delay -clock clk -max 1.5 [get_ports {dout}] 5 | -------------------------------------------------------------------------------- /test/files/results/convert_dots.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | dot -Tpng qlanetlist.dot -o qlanetlist.png 4 | dot -Tpng adder8.dot -o adder8.png 5 | dot -Tpng multiplier_after.dot -o multiplier_after.png -------------------------------------------------------------------------------- /generate_deb.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ## SPDX-FileCopyrightText: 2021-2025 Niels Moseley 3 | ## 4 | ## SPDX-License-Identifier: GPL-3.0-only 5 | 6 | cd build 7 | cpack -G DEB 8 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | ## SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | ## 3 | ## SPDX-License-Identifier: GPL-3.0-only 4 | 5 | ko_fi: namoseley 6 | github: asicsforthemasses 7 | -------------------------------------------------------------------------------- /examples/adder8/adder8.sdc: -------------------------------------------------------------------------------- 1 | 2 | create_clock -period 10 -name virtual_clk 3 | set_input_delay 1 -clock [get_clocks virtual_clk] [get_ports {a* b*}] 4 | set_output_delay -clock virtual_clk -max 1.5 [get_ports {y* carryout}] 5 | -------------------------------------------------------------------------------- /examples/adder8_simplegates/adder8.sdc: -------------------------------------------------------------------------------- 1 | 2 | create_clock -period 10 -name virtual_clk 3 | set_input_delay 1 -clock [get_clocks virtual_clk] [get_ports {a* b*}] 4 | set_output_delay -clock virtual_clk -max 1.5 [get_ports y*] 5 | -------------------------------------------------------------------------------- /version/version.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | extern const char *LUNAVERSIONSTRING; 8 | 9 | -------------------------------------------------------------------------------- /core/python/types/pycelllib.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | extern PyTypeObject PyCellLibType; 8 | -------------------------------------------------------------------------------- /gui/common/imagemanip.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | namespace GUI 7 | { 8 | 9 | std::optional makePDKIcon(const std::string &imageFilename); 10 | 11 | }; -------------------------------------------------------------------------------- /core/common/subprocess_win.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #include "subprocess.h" 6 | 7 | #error not implemented 8 | 9 | -------------------------------------------------------------------------------- /core/python/types/pytechlayers.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | extern PyTypeObject PyTechLibLayersType; 8 | -------------------------------------------------------------------------------- /core/python/types/pytechsites.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | extern PyTypeObject PyTechLibSitesType; 8 | -------------------------------------------------------------------------------- /resources/lunapnr.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Version=1.0 3 | Type=Application 4 | Name=LunaPnR 5 | Comment=Luna Place and Route 6 | TryExec=lunapnr 7 | Exec=lunapnr 8 | Icon=lunapnr 9 | MimeType=image/x-foo; 10 | Categories=Electronics; 11 | -------------------------------------------------------------------------------- /.debian/Copyright.txt: -------------------------------------------------------------------------------- 1 | Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ 2 | Source: https://www.github.com/asicsforthemasses/lunapnr 3 | 4 | Files: * 5 | Copyright: 2022, asicsforthemasses 6 | License: GPL-3 7 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ## SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | ## 3 | ## SPDX-License-Identifier: GPL-3.0-only 4 | 5 | cmake_minimum_required(VERSION 3.20) 6 | 7 | #add_subdirectory(python) 8 | add_subdirectory(core) 9 | -------------------------------------------------------------------------------- /examples/mac32/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # SPDX-FileCopyrightText: 2021-2025 Niels Moseley 4 | # 5 | # SPDX-License-Identifier: GPL-3.0-only 6 | 7 | #EXPORT PDK_PATH="/storage/programming/asic/luna_pnr/test.files/" 8 | yosys -s mac32.tcl 9 | -------------------------------------------------------------------------------- /test/core/main.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #define BOOST_TEST_MODULE "C++ Unit Tests for LunaCore" 6 | #include 7 | -------------------------------------------------------------------------------- /core/utilities/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | # 3 | # SPDX-License-Identifier: GPL-3.0-only 4 | 5 | add_executable(netlistgen 6 | netlistgen.cpp) 7 | 8 | target_link_libraries(netlistgen lunacore cxxopts) 9 | -------------------------------------------------------------------------------- /examples/mac32/mac32.sdc: -------------------------------------------------------------------------------- 1 | create_clock -name clk -period 10 [get_ports clk] 2 | set_input_delay -clock clk 0 [get_ports rst_an] 3 | set_input_delay -clock clk 0 [get_ports a_in*] 4 | set_input_delay -clock clk 0 [get_ports b_in*] 5 | set_output_delay 5 -clock clk [get_ports data_out*] 6 | -------------------------------------------------------------------------------- /scripts/init_ihp130.py: -------------------------------------------------------------------------------- 1 | clear() 2 | loadLib("test/files/ihp130/sg13g2_stdcell_typ_1p20V_25C.lib") 3 | loadLef("test/files/ihp130/sg13g2_tech.lef") 4 | loadLef("test/files/ihp130/sg13g2_stdcell.lef") 5 | loadLayers("scripts/ihp130.layers") 6 | print("IHP130 technology loaded") 7 | 8 | -------------------------------------------------------------------------------- /bootstrap_release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ## SPDX-FileCopyrightText: 2021-2025 Niels Moseley 3 | ## 4 | ## SPDX-License-Identifier: GPL-3.0-only 5 | 6 | rm -rf build 7 | mkdir build 8 | cd build 9 | cmake -GNinja -DCMAKE_BUILD_TYPE=Release -DUseCPPCHECK=ON .. 10 | -------------------------------------------------------------------------------- /core/clangtidy/clangtidy.yaml: -------------------------------------------------------------------------------- 1 | ## SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | ## 3 | ## SPDX-License-Identifier: GPL-3.0-only 4 | 5 | Checks: 'clang-diagnostic-*,clang-analyzer-*,cppcoreguidelines-*,modernize-*,-modernize-use-trailing-return-type' 6 | -------------------------------------------------------------------------------- /gui/common/msvcfix.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #ifdef NO_SSIZE_T 8 | #include 9 | typedef std::make_signed::type ssize_t; 10 | #endif -------------------------------------------------------------------------------- /bootstrap.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ## SPDX-FileCopyrightText: 2021-2025 Niels Moseley 3 | ## 4 | ## SPDX-License-Identifier: GPL-3.0-only 5 | 6 | rm -rf build 7 | mkdir build 8 | cd build 9 | cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DUseCPPCHECK=ON -DUseCLANGTIDY=OFF .. 10 | -------------------------------------------------------------------------------- /core/cts/cts_private.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "common/dbtypes.h" 3 | 4 | namespace LunaCore::CTS 5 | { 6 | 7 | /** node holding the instance key and the instance position */ 8 | struct Node 9 | { 10 | ChipDB::ObjectKey m_insKey; 11 | ChipDB::Coord64 m_pos; 12 | }; 13 | 14 | }; 15 | -------------------------------------------------------------------------------- /core/database/properties.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | namespace ChipDB 6 | { 7 | 8 | using PropertyValue = std::string; 9 | using PropertyName = std::string; 10 | using Properties = std::unordered_map; 11 | 12 | }; 13 | -------------------------------------------------------------------------------- /version/version.cpp.in: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | // 5 | // version.cpp is auto-generated - do not modify 6 | // 7 | 8 | #include "version.h" 9 | const char *LUNAVERSIONSTRING = "@LUNAVERSIONSTRING@"; 10 | -------------------------------------------------------------------------------- /test/files/clean_cells.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # SPDX-FileCopyrightText: 2021-2025 Niels Moseley 3 | # 4 | # SPDX-License-Identifier: GPL-3.0-only 5 | 6 | ../../../gdstools/build/gdsdelete -i iit_stdcells/lib/source/gds2/iit035_pads.gds2 -o iit_stdcells/lib/source/gds2/iit035_pads_clean.gds2 -s iit_stdcells_pads -------------------------------------------------------------------------------- /core/algebra/algebra.hpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include "vector.hpp" 8 | #include "sparsematrix.hpp" 9 | #include "matrix.hpp" 10 | #include "sdsolver.hpp" 11 | #include "cgsolver.hpp" 12 | -------------------------------------------------------------------------------- /gui/common/database.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #include "database.h" 6 | 7 | namespace GUI 8 | { 9 | 10 | void Database::clear() 11 | { 12 | m_coreDatabase.m_design.clear(); 13 | m_layerRenderInfoDB.clear(); 14 | } 15 | 16 | }; 17 | -------------------------------------------------------------------------------- /gui/python/types/pyproject.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | #include 7 | 8 | extern PyTypeObject PyProjectLefFilesType; 9 | extern PyTypeObject PyProjectLibFilesType; 10 | extern PyTypeObject PyProjectVerilogFilesType; 11 | -------------------------------------------------------------------------------- /test/files/verilog/assign_test.v: -------------------------------------------------------------------------------- 1 | // test to verify assign statements 2 | 3 | module testmodule(x1,x2,x3,x4,y1,y2,y3,y4); 4 | 5 | input x1; 6 | input x2; 7 | input x3; 8 | input x4; 9 | output y1; 10 | output y2; 11 | output y3; 12 | output y4; 13 | 14 | assign y1 = x1; 15 | assign y2 = x2; 16 | assign y3 = x3; 17 | assign y4 = x4; 18 | 19 | endmodule 20 | -------------------------------------------------------------------------------- /gui/common/hatchlibrary.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | 10 | namespace GUI 11 | { 12 | 13 | struct HatchLibrary 14 | { 15 | HatchLibrary(); 16 | std::vector m_hatches; 17 | }; 18 | 19 | }; 20 | -------------------------------------------------------------------------------- /scripts/init_osu180.py: -------------------------------------------------------------------------------- 1 | clear() 2 | loadLef("test/files/iit_stdcells/lib/tsmc018/lib/iit018_stdcells.lef") 3 | loadLef("test/files/iit_stdcells_extra/fake_ties018.lef") 4 | loadLib("test/files/iit_stdcells/lib/tsmc018/signalstorm/iit018_stdcells.lib") 5 | loadLib("test/files/iit_stdcells_extra/fake_ties018.lib") 6 | loadLayers("scripts/osu180_layers.json") 7 | print("OSU180 technology loaded") 8 | -------------------------------------------------------------------------------- /core/python/types/pypin.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | #include 7 | #include 8 | #include "database/database.h" 9 | 10 | extern PyTypeObject PyPinType; 11 | 12 | namespace Python 13 | { 14 | PyObject* toPython(const ChipDB::Instance::Pin &pin); 15 | }; 16 | -------------------------------------------------------------------------------- /scripts/loadall.py: -------------------------------------------------------------------------------- 1 | import Luna 2 | import LunaExtra 3 | 4 | Luna.clear() 5 | 6 | for lef in LunaExtra.ProjectLefFiles(): 7 | print("LEF: ", lef) 8 | Luna.loadLef(lef) 9 | 10 | for lib in LunaExtra.ProjectLibFiles(): 11 | print("LIB: ", lib) 12 | Luna.loadLib(lib) 13 | 14 | for verilog in LunaExtra.ProjectVerilogFiles(): 15 | print("Verilog: ", verilog) 16 | Luna.loadVerilog(verilog) 17 | -------------------------------------------------------------------------------- /core/python/types/pycell.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | #include 7 | #include 8 | #include "database/database.h" 9 | 10 | extern PyTypeObject PyCellType; 11 | 12 | namespace Python 13 | { 14 | PyObject* toPython(std::shared_ptr cellPtr); 15 | }; 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | ## 3 | ## SPDX-License-Identifier: GPL-3.0-only 4 | 5 | .vscode 6 | AppDir 7 | appimage-builder-cache 8 | build 9 | test/files/iitcells_lib* 10 | test/files/iit_stdcells 11 | test/files/nangate 12 | test/files/sky130 13 | test/files/ihp130 14 | test/files/results 15 | version/version.cpp 16 | noshare 17 | attic 18 | _packages 19 | -------------------------------------------------------------------------------- /core/python/types/pypininfo.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | #include 7 | #include 8 | #include "database/database.h" 9 | 10 | extern PyTypeObject PyPinInfoType; 11 | 12 | namespace Python 13 | { 14 | PyObject* toPython(std::shared_ptr ptr); 15 | }; 16 | -------------------------------------------------------------------------------- /core/utilities/README.md: -------------------------------------------------------------------------------- 1 | # LunaPnR Core Utilities 2 | 3 | ## Netlistgen 4 | 5 | A simple netlist generator meant for testing. 6 | 7 | ### Netlist format 8 | * number of instances, EOL. 9 | * number of nets, EOL. 10 | 11 | For each net: 12 | * number of connections. 13 | * instance ID. 14 | * EOL. 15 | 16 | Instance IDs are not necessarily contiguous, i.e. gaps may appear after netlist transformations by LunaPnR. 17 | -------------------------------------------------------------------------------- /core/python/types/pynets.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | #include 7 | #include 8 | #include "database/database.h" 9 | 10 | extern PyTypeObject PyNetsType; 11 | 12 | namespace Python 13 | { 14 | PyObject* toPythonAsNets(std::shared_ptr netlistPtr); 15 | }; 16 | -------------------------------------------------------------------------------- /core/python/types/pypininfolist.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | #include 7 | #include 8 | #include "database/database.h" 9 | 10 | extern PyTypeObject PyPinInfoListType; 11 | 12 | namespace Python 13 | { 14 | PyObject* toPython(ChipDB::PinInfoList *pinInfoListPtr); 15 | }; 16 | -------------------------------------------------------------------------------- /core/python/types/pysiteinfo.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | #include 7 | #include 8 | #include "database/database.h" 9 | 10 | extern PyTypeObject PySiteInfoType; 11 | 12 | namespace Python 13 | { 14 | PyObject* toPython(std::shared_ptr sitePtr); 15 | }; 16 | -------------------------------------------------------------------------------- /core/python/types/pyinstance.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | #include 7 | #include 8 | #include "database/database.h" 9 | 10 | extern PyTypeObject PyInstanceType; 11 | 12 | namespace Python 13 | { 14 | PyObject* toPython(std::shared_ptr instancePtr); 15 | }; 16 | -------------------------------------------------------------------------------- /core/python/types/pylayerinfo.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | #include 7 | #include 8 | #include "database/database.h" 9 | 10 | extern PyTypeObject PyLayerInfoType; 11 | 12 | namespace Python 13 | { 14 | PyObject* toPython(std::shared_ptr layerPtr); 15 | }; 16 | -------------------------------------------------------------------------------- /core/python/types/pynet.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | #include 7 | #include 8 | #include 9 | #include "database/database.h" 10 | 11 | extern PyTypeObject PyNetType; 12 | 13 | namespace Python 14 | { 15 | PyObject* toPython(std::shared_ptr netPtr); 16 | }; 17 | -------------------------------------------------------------------------------- /core/common/common.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include "fileutils.h" 8 | #include "strutils.hpp" 9 | #include "idiagnostics.hpp" 10 | #include "logging.h" 11 | #include "matrix.h" 12 | #include "subprocess.h" 13 | #include "tomlhelpers.h" 14 | #include "objectptr.hpp" 15 | #include "gds2defs.hpp" 16 | -------------------------------------------------------------------------------- /core/python/types/pyinstances.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | #include 7 | #include 8 | #include "database/database.h" 9 | 10 | extern PyTypeObject PyInstancesType; 11 | 12 | namespace Python 13 | { 14 | PyObject* toPythonAsInstances(std::shared_ptr netlistPtr); 15 | }; 16 | -------------------------------------------------------------------------------- /gui/widgets/layerwidget.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #include "layerwidget.h" 6 | 7 | namespace GUI 8 | { 9 | 10 | LayerWidget::LayerWidget(QWidget *parent) : QTableView(parent) 11 | { 12 | setSelectionBehavior(QTableView::SelectRows); 13 | setSelectionMode(QAbstractItemView::SingleSelection); 14 | } 15 | 16 | }; 17 | -------------------------------------------------------------------------------- /gui/common/imagemanip.cpp: -------------------------------------------------------------------------------- 1 | #include "imagemanip.h" 2 | 3 | namespace GUI 4 | { 5 | 6 | std::optional makePDKIcon(const std::string &imageFilename) 7 | { 8 | QImage img; 9 | if (!img.load(QString::fromStdString(imageFilename))) 10 | { 11 | return std::nullopt; 12 | } 13 | 14 | img = img.scaled(QSize(64,64), Qt::KeepAspectRatio, Qt::SmoothTransformation); 15 | return std::move(img); 16 | } 17 | 18 | }; 19 | -------------------------------------------------------------------------------- /core/export/ppm/ppmwriter.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | #include "ppm.h" 11 | 12 | namespace LunaCore::PPM 13 | { 14 | bool write(std::ostream &os, const Bitmap &bm); 15 | bool write(const std::string &filename, const Bitmap &bm); 16 | }; 17 | -------------------------------------------------------------------------------- /core/padring/padringplacer.hpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include "padring.hpp" 8 | #include "configreader.hpp" 9 | #include "database/database.h" 10 | 11 | namespace LunaCore::Padring 12 | { 13 | 14 | bool read(std::istream &is, Database &db, Padring &padring); 15 | bool place(Database &db, Padring &padring); 16 | 17 | }; -------------------------------------------------------------------------------- /test/files/verilog/netcon_test.v: -------------------------------------------------------------------------------- 1 | // test for removeNetconInstances 2 | 3 | module netcon(x1,x2,x3,x4,y1,y2,y3,y4); 4 | 5 | input x1; 6 | input x2; 7 | input x3; 8 | input x4; 9 | input x5; 10 | output y1; 11 | output y2; 12 | output y3; 13 | output y4; 14 | output y5; 15 | 16 | wire tmp; 17 | 18 | assign y1 = x1; 19 | assign y2 = x2; 20 | assign y3 = x3; 21 | assign y4 = x4; 22 | 23 | assign tmp = x5; 24 | assign y5 = tmp; 25 | 26 | endmodule 27 | -------------------------------------------------------------------------------- /examples/lfsr31/lfsr31_floorplan.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | # 3 | # SPDX-License-Identifier: GPL-3.0-only 4 | 5 | ## create floorplan 6 | createRegion("core", "core", 10000, 10000, 170000, 50000) 7 | 8 | setTopModule("LFSR31") 9 | 10 | ## place the pins 11 | placeInstance("clk", "LFSR31",500, 15000) 12 | placeInstance("rst_an", "LFSR31",500, 25000) 13 | placeInstance("dout", "LFSR31",200000, 20000) 14 | -------------------------------------------------------------------------------- /core/import/lef/lefreader.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include 8 | #include "database/database.h" 9 | 10 | /** Namespace for the LEF importers and exporters */ 11 | namespace ChipDB::LEF 12 | { 13 | 14 | class Reader 15 | { 16 | public: 17 | static bool load(Design &design, std::istream &source); 18 | }; 19 | 20 | }; 21 | -------------------------------------------------------------------------------- /core/passes/passes.hpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | #include 7 | #include 8 | #include "database/database.h" 9 | 10 | namespace LunaCore::Passes 11 | { 12 | bool run(Database &database, const std::string &cmdstring); 13 | void registerAllPasses(); 14 | 15 | std::vector getNamesOfPasses(); 16 | }; 17 | -------------------------------------------------------------------------------- /gui/tasks/ctstask.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include "tasks.h" 8 | 9 | namespace Tasks 10 | { 11 | 12 | class CTS : public Task 13 | { 14 | public: 15 | CTS() = default; 16 | virtual ~CTS() = default; 17 | 18 | protected: 19 | void execute(GUI::Database &database, ProgressCallback callback) override; 20 | }; 21 | 22 | }; 23 | -------------------------------------------------------------------------------- /core/common/subprocess.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | namespace ChipDB::Subprocess 15 | { 16 | bool run(const std::string &command, std::function lineCallback); 17 | }; 18 | -------------------------------------------------------------------------------- /core/import/liberty/libreader.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | 6 | #pragma once 7 | 8 | #include 9 | #include "database/database.h" 10 | 11 | /** Namespace for the Liberty timing file importers */ 12 | namespace ChipDB::Liberty 13 | { 14 | 15 | class Reader 16 | { 17 | public: 18 | static bool load(Design &design, std::istream &source); 19 | }; 20 | 21 | }; -------------------------------------------------------------------------------- /gui/tasks/place.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include "tasks.h" 8 | 9 | namespace Tasks 10 | { 11 | 12 | class Place : public Task 13 | { 14 | public: 15 | Place() = default; 16 | virtual ~Place() = default; 17 | 18 | protected: 19 | void execute(GUI::Database &database, ProgressCallback callback) override; 20 | }; 21 | 22 | }; 23 | -------------------------------------------------------------------------------- /core/cellplacer/cellplacer.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include "database/database.h" 8 | 9 | namespace LunaCore 10 | { 11 | 12 | /** stupidly simple placed - just places cells in order */ 13 | class SimpleCellPlacer 14 | { 15 | public: 16 | static void place(ChipDB::Netlist *nl, const ChipDB::Rect64 ®ionRect, const int64_t rowHeight); 17 | }; 18 | 19 | }; -------------------------------------------------------------------------------- /core/import/ppm/ppmreader.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "export/ppm/ppm.h" 12 | 13 | namespace LunaCore::PPM 14 | { 15 | std::optional read(std::istream &is); 16 | std::optional read(const std::string &filename); 17 | 18 | }; //namespace 19 | -------------------------------------------------------------------------------- /doc/codingconventions.md: -------------------------------------------------------------------------------- 1 | # Coding conventions 2 | 3 | ## C++ coding style 4 | * Format code using the Allman style from AStyle. 5 | * C++ header file extensions should be .hpp 6 | * Use 4 spaces for indentation. 7 | 8 | ## Dependencies 9 | * Source dependencies: 10 | * Python3 11 | * tinysvgpp 12 | * Eigen3 13 | * Qt6 14 | * libreadline 15 | 16 | * Build dependencies: 17 | * Python >=3.8 18 | * GCC >=11.x 19 | * CMake >=2.16 20 | * Ninja-build 21 | * wget 22 | -------------------------------------------------------------------------------- /gui/console/cmdcompleter.hpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | #include 7 | #include 8 | #include 9 | #include "replwidget.hpp" 10 | 11 | namespace GUI 12 | { 13 | 14 | struct LunaCommandCompleter : public ReplWidget::ICompleter 15 | { 16 | QString tryComplete(const QString &str); 17 | 18 | std::vector m_words; 19 | }; 20 | 21 | }; -------------------------------------------------------------------------------- /gui/tasks/globalroute.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include "tasks.h" 8 | 9 | namespace Tasks 10 | { 11 | 12 | class GlobalRoute : public Task 13 | { 14 | public: 15 | GlobalRoute() = default; 16 | virtual ~GlobalRoute() = default; 17 | 18 | protected: 19 | void execute(GUI::Database &database, ProgressCallback callback) override; 20 | }; 21 | 22 | }; 23 | -------------------------------------------------------------------------------- /gui/aboutdialog/aboutdialog.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | namespace GUI 12 | { 13 | 14 | class AboutDialog : public QDialog 15 | { 16 | Q_OBJECT 17 | public: 18 | AboutDialog(QWidget *parent = nullptr); 19 | 20 | protected: 21 | QDialogButtonBox *m_buttonBox; 22 | }; 23 | 24 | }; -------------------------------------------------------------------------------- /gui/tasks/readallfiles.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include "tasks.h" 8 | 9 | namespace Tasks 10 | { 11 | 12 | class ReadAllFiles : public Task 13 | { 14 | public: 15 | ReadAllFiles() = default; 16 | virtual ~ReadAllFiles() = default; 17 | 18 | protected: 19 | void execute(GUI::Database &database, ProgressCallback callback) override; 20 | }; 21 | 22 | }; 23 | -------------------------------------------------------------------------------- /gui/widgets/layerwidget.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | #include "lunacore.h" 7 | 8 | #include 9 | 10 | /** List of layers with a specific ordering. 11 | layers can be enabled/disabled by the user 12 | */ 13 | namespace GUI 14 | { 15 | 16 | class LayerWidget : public QTableView 17 | { 18 | public: 19 | LayerWidget(QWidget *parent = nullptr); 20 | 21 | }; 22 | 23 | }; -------------------------------------------------------------------------------- /gui/tasks/createfloorplan.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include "tasks.h" 8 | 9 | namespace Tasks 10 | { 11 | 12 | class CreateFloorplan : public Task 13 | { 14 | public: 15 | CreateFloorplan() = default; 16 | virtual ~CreateFloorplan() = default; 17 | 18 | protected: 19 | void execute(GUI::Database &database, ProgressCallback callback) override; 20 | }; 21 | 22 | }; 23 | -------------------------------------------------------------------------------- /gui/tasks/preflightchecks.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include "tasks.h" 8 | 9 | namespace Tasks 10 | { 11 | 12 | class PreflightChecks : public Task 13 | { 14 | public: 15 | PreflightChecks() = default; 16 | virtual ~PreflightChecks() = default; 17 | 18 | protected: 19 | void execute(GUI::Database &database, ProgressCallback callback) override; 20 | }; 21 | 22 | }; 23 | -------------------------------------------------------------------------------- /core/import/import.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "liberty/libparser.h" 4 | #include "liberty/libreaderimpl.h" 5 | #include "liberty/libreader.h" 6 | #include "lef/lefparser.h" 7 | #include "lef/lefreaderimpl.h" 8 | #include "lef/lefreader.h" 9 | #include "def/defparser.h" 10 | #include "def/defreaderimpl.h" 11 | #include "def/defreader.h" 12 | #include "verilog/verilogparser.h" 13 | #include "verilog/veriloglexer.h" 14 | #include "verilog/verilogreader.h" 15 | #include "ppm/ppmreader.h" 16 | #include "gds2/gds2reader.hpp" 17 | -------------------------------------------------------------------------------- /examples/lfsr31/lfsr31.ys: -------------------------------------------------------------------------------- 1 | 2 | ghdl lfsr31.vhd -e LFSR31 3 | 4 | proc 5 | flatten 6 | synth -run coarse 7 | techmap 8 | 9 | dfflibmap -liberty ../../test/files/iit_stdcells/lib/tsmc018/signalstorm/iit018_stdcells.lib 10 | abc -liberty ../../test/files/iit_stdcells/lib/tsmc018/signalstorm/iit018_stdcells.lib -liberty ../../test/files/iit_stdcells_extra/fake_ties018.lib 11 | 12 | splitnets -ports 13 | 14 | hilomap -hicell TIEHI Y -locell TIELO Y 15 | 16 | clean -purge 17 | write_verilog -renameprefix ins -noexpr lfsr31_netlist.v 18 | -------------------------------------------------------------------------------- /gui/widgets/clickablelabel.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #include "clickablelabel.h" 6 | 7 | using namespace GUI; 8 | 9 | ClickableLabel::ClickableLabel(QWidget* parent) : QLabel(parent) 10 | { 11 | } 12 | 13 | ClickableLabel::ClickableLabel(const QString &text, QWidget* parent) : QLabel(text, parent) 14 | { 15 | } 16 | 17 | void ClickableLabel::mousePressEvent(QMouseEvent* event) 18 | { 19 | emit clicked(); 20 | } 21 | -------------------------------------------------------------------------------- /examples/adder8_simplegates/adder8_simplegates.ys: -------------------------------------------------------------------------------- 1 | 2 | read_verilog adder8.v 3 | 4 | proc 5 | flatten 6 | synth -run coarse 7 | techmap 8 | 9 | dfflibmap -liberty ../../test/files/iit_stdcells/lib/tsmc018/signalstorm/iit018_stdcells.lib 10 | abc -liberty ../../test/files/iit_stdcells/lib/tsmc018/signalstorm/iit018_stdcells.lib -liberty ../../test/files/iit_stdcells_extra/fake_ties018.lib 11 | 12 | splitnets -ports 13 | 14 | hilomap -hicell TIEHI Y -locell TIELO Y 15 | 16 | clean -purge 17 | write_verilog -noexpr adder8_simplegates_netlist.v 18 | -------------------------------------------------------------------------------- /gui/widgets/blockframe.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | #include 7 | #include 8 | 9 | namespace GUI 10 | { 11 | 12 | class BlockFrame : public QFrame 13 | { 14 | public: 15 | BlockFrame(QWidget *parent = nullptr); 16 | 17 | void addWidget(QWidget *widget, int stetch = 0, Qt::Alignment alignment = Qt::Alignment()); 18 | 19 | protected: 20 | QVBoxLayout *m_layout; 21 | }; 22 | 23 | }; 24 | -------------------------------------------------------------------------------- /core/database/enums.toml: -------------------------------------------------------------------------------- 1 | namespace = "ChipDB" 2 | 3 | [enums] 4 | CellClass = ["NONE", "CORE", "COVER", "RING", "PAD", "ENDCAP", "BLOCK"] 5 | 6 | CellSubclass = ["NONE", "BUMP", "BLACKBOX", "SOFT", "INPUT", "OUTPUT", "INOUT", "POWER", 7 | "SPACER", "DECAP", "AREAIO", "FEEDTHRU", "TIEHIGH", "TIELOW", "ANTENNACELL", "WELLTAP", 8 | "PRE", "POST", "TOPLEFT", "TOPRIGHT", "BOTTOMLEFT", "BOTTOMRIGHT"] 9 | 10 | Orientation = ["R0","R90","R180","R270","MX","MX90","MY","MY90"] 11 | 12 | PlacementInfo = ["IGNORE", "UNPLACED", "PLACED", "PLACEDANDFIXED"] 13 | -------------------------------------------------------------------------------- /examples/adder8/adder8.ys: -------------------------------------------------------------------------------- 1 | 2 | read_verilog adder8.v 3 | 4 | proc 5 | flatten 6 | synth -run coarse 7 | techmap -map fa_map.v 8 | techmap 9 | 10 | dfflibmap -liberty ../../test/files/iit_stdcells/lib/tsmc018/signalstorm/iit018_stdcells.lib 11 | abc -liberty ../../test/files/iit_stdcells/lib/tsmc018/signalstorm/iit018_stdcells.lib -liberty ../../test/files/iit_stdcells_extra/fake_ties018.lib 12 | 13 | splitnets -ports 14 | 15 | hilomap -hicell TIEHI Y -locell TIELO Y 16 | 17 | clean -purge 18 | write_verilog -renameprefix ins -noexpr adder8_netlist.v 19 | -------------------------------------------------------------------------------- /examples/femtorv32/femtorv32_quark.ys: -------------------------------------------------------------------------------- 1 | 2 | read_verilog femtorv32_quark.v 3 | 4 | synth -top FemtoRV32 5 | 6 | dfflibmap -liberty ../../test/files/iit_stdcells/lib/tsmc018/signalstorm/iit018_stdcells.lib 7 | abc -liberty ../../test/files/iit_stdcells/lib/tsmc018/signalstorm/iit018_stdcells.lib -liberty ../../test/files/iit_stdcells_extra/fake_ties018.lib 8 | 9 | splitnets -ports 10 | 11 | # for now, we'll use fake tie cells 12 | hilomap -hicell TIEHI Y -locell TIELO Y 13 | 14 | opt_clean -purge 15 | clean 16 | write_verilog -noexpr femtorv32_quark_netlist.v 17 | -------------------------------------------------------------------------------- /core/globalroute/wavefront.cpp: -------------------------------------------------------------------------------- 1 | 2 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 3 | // 4 | // SPDX-License-Identifier: GPL-3.0-only 5 | 6 | #include "wavefront.h" 7 | #include 8 | 9 | using namespace LunaCore; 10 | 11 | const GlobalRouter::WavefrontItem& GlobalRouter::Wavefront::getLowestCostItem() const 12 | { 13 | return m_items.top(); 14 | } 15 | 16 | void GlobalRouter::Wavefront::push(const WavefrontItem &item) 17 | { 18 | m_items.push(item); 19 | } 20 | 21 | void GlobalRouter::Wavefront::clear() 22 | { 23 | m_items = PQueueType{}; 24 | } 25 | -------------------------------------------------------------------------------- /gui/widgets/clickablelabel.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | 10 | namespace GUI 11 | { 12 | 13 | class ClickableLabel : public QLabel 14 | { 15 | Q_OBJECT 16 | public: 17 | explicit ClickableLabel(QWidget* parent = nullptr); 18 | ClickableLabel(const QString &text, QWidget* parent = nullptr); 19 | 20 | signals: 21 | void clicked(); 22 | 23 | protected: 24 | void mousePressEvent(QMouseEvent* event); 25 | }; 26 | 27 | }; 28 | -------------------------------------------------------------------------------- /gui/widgets/hatchbutton.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | 10 | namespace GUI 11 | { 12 | 13 | class SelectHatchButton : public QPushButton 14 | { 15 | Q_OBJECT 16 | public: 17 | SelectHatchButton(QWidget *parent = nullptr); 18 | 19 | void setHatch(const QPixmap &hatch); 20 | QPixmap getHatch() const; 21 | 22 | protected: 23 | void paintEvent(QPaintEvent *event); 24 | 25 | private: 26 | QPixmap m_pixmap; 27 | }; 28 | 29 | }; -------------------------------------------------------------------------------- /core/export/txt/txtwriter.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | #include "database/database.h" 11 | 12 | /** Export net terminal positions in a simple text file format 13 | * meant for testing the global router. 14 | * 15 | */ 16 | namespace LunaCore::TXT 17 | { 18 | bool write(std::ostream &os, const std::shared_ptr module); 19 | bool write(std::ostream &os, const std::shared_ptr netlist); 20 | }; 21 | -------------------------------------------------------------------------------- /gui/widgets/hatchdisplay.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include 8 | #include "../common/hatchlibrary.h" 9 | 10 | namespace GUI 11 | { 12 | 13 | class HatchDisplay : public QScrollArea 14 | { 15 | Q_OBJECT 16 | 17 | public: 18 | HatchDisplay(HatchLibrary &hatchLibrary, QWidget *parent = nullptr); 19 | 20 | signals: 21 | void clicked(int hatchindex); 22 | 23 | protected slots: 24 | void onHatchClick(); 25 | 26 | protected: 27 | HatchLibrary &m_hatchLibrary; 28 | }; 29 | 30 | }; -------------------------------------------------------------------------------- /test/python/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ## LunaPnR Source Code 2 | ## 3 | ## SPDX-License-Identifier: GPL-3.0-only 4 | ## SPDX-FileCopyrightText: 2022,2023 Niels Moseley 5 | ## 6 | 7 | cmake_minimum_required(VERSION 3.20) 8 | 9 | ## Make Debian/Ubuntu happy: this way the executable is not detected as a shared lib :-/ 10 | set(CMAKE_POSITION_INDEPENDENT_CODE OFF) 11 | 12 | if (USE_PYTHON) 13 | 14 | project(core_python) 15 | 16 | add_executable(core_python main.cpp) 17 | target_include_directories(core_python PRIVATE ../../core/include) 18 | target_link_libraries(core_python lunacore) 19 | 20 | endif(USE_PYTHON) 21 | -------------------------------------------------------------------------------- /core/export/spef/spefwriter.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | #include "database/database.h" 11 | 12 | /** Parasitic file output for OpenSTA 13 | * For now, it only does manhattan segment lengths from source to sink, 14 | * all tied at the source. 15 | * 16 | */ 17 | namespace LunaCore::SPEF 18 | { 19 | bool write(std::ostream &os, const std::shared_ptr mod); 20 | bool write(const std::string &filename, const std::shared_ptr mod); 21 | }; 22 | -------------------------------------------------------------------------------- /examples/mac32/mac32.tcl: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | # 3 | # SPDX-License-Identifier: GPL-3.0-only 4 | 5 | read_verilog mac32.v 6 | 7 | synth -top mac32 8 | 9 | dfflibmap -liberty ../../test/files/iit_stdcells/lib/tsmc018/signalstorm/iit018_stdcells.lib 10 | abc -liberty ../../test/files/iit_stdcells/lib/tsmc018/signalstorm/iit018_stdcells.lib -liberty ../../test/files/iit_stdcells_extra/fake_ties018.lib 11 | 12 | flatten 13 | 14 | # for now, we'll use fake tie cells 15 | hilomap -hicell TIEHI Y -locell TIELO Y 16 | 17 | splitnets -ports 18 | 19 | clean -purge 20 | write_verilog -renameprefix ins -noexpr mac32_netlist.v 21 | -------------------------------------------------------------------------------- /core/import/def/defreader.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include 8 | #include "database/database.h" 9 | 10 | /** Namespace for the DEF importers and exporters */ 11 | namespace ChipDB::DEF 12 | { 13 | 14 | class Reader 15 | { 16 | public: 17 | /** loads placement information from the DEF file into the database. 18 | * The database needs to contain a valid netlist and all 19 | * cells/instances referenced in the DEF file must 20 | * exist. 21 | */ 22 | static bool load(Design &design, std::istream &source); 23 | }; 24 | 25 | }; 26 | -------------------------------------------------------------------------------- /gui/python/pyluna_extra.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #ifdef USE_PYTHON 8 | 9 | #include "lunacore.h" 10 | #include "common/database.h" 11 | #include "console/mmconsole.h" 12 | 13 | namespace GUI 14 | { 15 | 16 | class Python : public Scripting::Python 17 | { 18 | public: 19 | Python(GUI::Database *db, GUI::MMConsole *console); 20 | virtual ~Python(); 21 | 22 | bool preInitHook() override; 23 | bool postInitHook() override; 24 | 25 | protected: 26 | GUI::Database *m_db; 27 | GUI::MMConsole *m_console; 28 | }; 29 | 30 | }; 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /gui/widgets/colorbutton.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | 10 | namespace GUI 11 | { 12 | 13 | class SelectColorButton : public QPushButton 14 | { 15 | Q_OBJECT 16 | public: 17 | SelectColorButton(QWidget *parent = nullptr); 18 | 19 | void setColor(const QColor &color); 20 | QColor getColor() const; 21 | 22 | public slots: 23 | void changeColor(); 24 | 25 | signals: 26 | void onColorChanged(); 27 | 28 | protected: 29 | void paintEvent(QPaintEvent *event); 30 | 31 | private: 32 | QColor m_color; 33 | }; 34 | 35 | }; -------------------------------------------------------------------------------- /gui/src/configurationdialog.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include "common/database.h" 10 | 11 | namespace GUI 12 | { 13 | 14 | class ConfigurationDialog : public QDialog 15 | { 16 | Q_OBJECT 17 | public: 18 | ConfigurationDialog(Database &db, QWidget *parent = nullptr); 19 | 20 | QString getOpenSTALocation() const noexcept; 21 | 22 | protected slots: 23 | void accept() override; 24 | 25 | protected: 26 | void onOpenSTALocationOpen(); 27 | QLineEdit *m_openSTALocationEdit; 28 | Database &m_db; 29 | }; 30 | 31 | }; 32 | -------------------------------------------------------------------------------- /gui/widgets/blockframe.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #include "blockframe.h" 6 | 7 | using namespace GUI; 8 | 9 | BlockFrame::BlockFrame(QWidget *parent) : QFrame(parent) 10 | { 11 | m_layout = new QVBoxLayout(); 12 | setFrameStyle(QFrame::Box); 13 | 14 | QPalette pal = QPalette(); 15 | pal.setColor(QPalette::Window, Qt::white); 16 | 17 | setAutoFillBackground(true); 18 | setPalette(pal); 19 | 20 | setLayout(m_layout); 21 | } 22 | 23 | void BlockFrame::addWidget(QWidget *widget, int stetch, Qt::Alignment alignment) 24 | { 25 | m_layout->addWidget(widget, stetch, alignment); 26 | } 27 | -------------------------------------------------------------------------------- /core/export/verilog/verilogwriter.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | /* 6 | 7 | Experimental verilog writer 8 | 9 | */ 10 | 11 | #pragma once 12 | #include 13 | #include "database/database.h" 14 | 15 | namespace LunaCore::Verilog 16 | { 17 | 18 | class Writer 19 | { 20 | public: 21 | 22 | static bool write(std::ostream &os, const std::shared_ptr mod); 23 | 24 | protected: 25 | static bool writeModuleDefinition(std::ostream &os, const std::shared_ptr mod); 26 | static bool writeModuleInstances(std::ostream &os, const std::shared_ptr mod); 27 | }; 28 | 29 | }; -------------------------------------------------------------------------------- /gui/common/pdkinfo.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace GUI 10 | { 11 | 12 | struct PDKInfo 13 | { 14 | std::string m_title; 15 | std::string m_name; 16 | std::string m_version; 17 | std::string m_date; 18 | std::string m_copyright; 19 | std::string m_description; 20 | std::string m_layerfile; 21 | std::vector m_lefs; 22 | std::vector m_libs; 23 | std::filesystem::path m_path; // should not be serialised! 24 | }; 25 | 26 | toml::table toToml(const PDKInfo &pdkinfo); 27 | bool fromToml(std::istream &is, PDKInfo &pdkinfo); 28 | 29 | }; 30 | -------------------------------------------------------------------------------- /gui/widgets/flatimage.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace GUI 13 | { 14 | 15 | class FlatImage : public QWidget 16 | { 17 | Q_OBJECT 18 | public: 19 | FlatImage(QWidget *parent = nullptr); 20 | FlatImage(const QString &pixmapUrl, QWidget *parent = nullptr); 21 | 22 | void setPixmap(const QString &pixmapUrl); 23 | 24 | QSize sizeHint() const; 25 | 26 | protected: 27 | void paintEvent(QPaintEvent* e) override; 28 | 29 | std::unique_ptr m_pixmap; 30 | }; 31 | 32 | }; 33 | -------------------------------------------------------------------------------- /gui/widgets/hatchdialog.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include 8 | #include "../common/hatchlibrary.h" 9 | #include "../common/msvcfix.h" 10 | 11 | namespace GUI 12 | { 13 | 14 | class HatchDialog : public QDialog 15 | { 16 | Q_OBJECT 17 | 18 | public: 19 | HatchDialog(HatchLibrary &hatchLibrary, QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags()); 20 | 21 | ssize_t getHatchIndex() const noexcept 22 | { 23 | return m_hatchIndex; 24 | } 25 | 26 | protected slots: 27 | void onHatchClicked(int index); 28 | 29 | protected: 30 | ssize_t m_hatchIndex; 31 | }; 32 | 33 | }; -------------------------------------------------------------------------------- /gui/widgets/flatimagebutton.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | namespace GUI 12 | { 13 | 14 | class FlatImageButton : public QAbstractButton 15 | { 16 | Q_OBJECT 17 | public: 18 | FlatImageButton(QWidget *parent = nullptr); 19 | FlatImageButton(const QString &pixmapUrl, QWidget *parent = nullptr); 20 | 21 | void setPixmap(const QString &pixmapUrl); 22 | 23 | QSize sizeHint() const; 24 | 25 | protected: 26 | void paintEvent(QPaintEvent* e) override; 27 | 28 | std::unique_ptr m_pixmap; 29 | }; 30 | 31 | }; 32 | -------------------------------------------------------------------------------- /core/globalroute/prim_private.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #include "prim_private.h" 6 | 7 | bool LunaCore::Prim::Private::operator<( 8 | const LunaCore::Prim::Private::CostTuple &lhs, 9 | const LunaCore::Prim::Private::CostTuple &rhs) noexcept 10 | { 11 | if (lhs.m_dist < rhs.m_dist) return true; 12 | if (lhs.m_dist > rhs.m_dist) return false; 13 | 14 | // lhs.m_dist == rhs.m_dist here. 15 | if (lhs.m_minAbsY < rhs.m_minAbsY) return true; 16 | if (lhs.m_minAbsY > rhs.m_minAbsY) return false; 17 | 18 | // lhs.m_dist == rhs.m_dist here. 19 | // and lhs.m_minAbsY == rhs.m_minAbsY here. 20 | return (lhs.m_minMaxX < rhs.m_minMaxX); 21 | } 22 | -------------------------------------------------------------------------------- /gui/ctsdialog/ctsdialog.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | #include "common/database.h" 11 | #include "lunacore.h" 12 | 13 | namespace GUI 14 | { 15 | 16 | class CTSDialog : public QDialog 17 | { 18 | Q_OBJECT 19 | public: 20 | CTSDialog(Database &db, QWidget *parent = nullptr); 21 | virtual ~CTSDialog() = default; 22 | 23 | protected slots: 24 | void accept() override; 25 | 26 | protected: 27 | void populateBufferList(); 28 | 29 | Database &m_db; 30 | QComboBox *m_ctsBufferCombo{nullptr}; 31 | QLineEdit *m_ctsMaxCap{nullptr}; 32 | }; 33 | 34 | }; 35 | -------------------------------------------------------------------------------- /core/common/matrix.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #include "matrix.h" 6 | 7 | #if 0 8 | void LunaCore::toEigen(const Matrix &matrix, Eigen::SparseMatrix &eigenMatrix) noexcept 9 | { 10 | auto nnz = matrix.nonZeroItemCount(); 11 | 12 | std::vector > triples; 13 | triples.reserve(nnz); 14 | 15 | eigenMatrix.reserve(nnz); 16 | for(auto const& row : matrix) 17 | { 18 | for(auto item : row.second) 19 | { 20 | triples.emplace_back(Eigen::Triplet{row.first, item.first, item.second}); 21 | } 22 | } 23 | 24 | eigenMatrix.setFromTriplets(triples.begin(), triples.end()); 25 | } 26 | #endif 27 | -------------------------------------------------------------------------------- /core/python/consoleredirect.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | #include 7 | 8 | #define PY_SSIZE_T_CLEAN 9 | #include 10 | 11 | PyMODINIT_FUNC PyInit_ConsoleRedirect(void); 12 | 13 | #ifdef NO_SSIZE_T 14 | #include 15 | typedef std::make_signed::type ssize_t; 16 | #endif 17 | 18 | namespace Scripting::PyConsoleRedirect 19 | { 20 | 21 | struct PyStdout 22 | { 23 | PyObject_HEAD 24 | std::function writeFunc; 25 | 26 | static PyObject* pyWrite(PyObject *self, PyObject *args); 27 | static PyObject* pyFlush(PyObject *self, PyObject *args); 28 | }; 29 | 30 | }; //namespace 31 | -------------------------------------------------------------------------------- /test/files/padring/padring.v: -------------------------------------------------------------------------------- 1 | module top(); 2 | 3 | PADFC c_ul (); 4 | PADFC c_ur (); 5 | PADFC c_ll (); 6 | PADFC c_lr (); 7 | 8 | PADINOUT \GPIO[0] (); 9 | PADINOUT \GPIO[1] (); 10 | PADINOUT \GPIO[2] (); 11 | PADINOUT \GPIO[3] (); 12 | PADINOUT \GPIO[4] (); 13 | PADINOUT \GPIO[5] (); 14 | PADINOUT \GPIO[6] (); 15 | PADINOUT \GPIO[7] (); 16 | 17 | PADINC CLK (); 18 | PADINC RESET (); 19 | PADINC MISO (); 20 | PADOUT MOSI (); 21 | PADINC SCK (); 22 | PADINC SPI_CS_N (); 23 | PADOUT UART_TX (); 24 | PADINC UART_RX (); 25 | 26 | PADOUT PWM_1 (); 27 | PADOUT PWM_2 (); 28 | PADVDD VDD_1 (); 29 | PADGND GND_1 (); 30 | PADOUT PWM_3 (); 31 | PADOUT PWM_4 (); 32 | 33 | PADOUT DAC_0 (); 34 | PADOUT DAC_1 (); 35 | PADVDD VDD_2 (); 36 | PADGND GND_2 (); 37 | PADOUT DAC_2 (); 38 | PADOUT DAC_3 (); 39 | 40 | endmodule 41 | -------------------------------------------------------------------------------- /core/algebra/solver.hpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | #include 7 | #include 8 | 9 | namespace LunaCore::Algebra 10 | { 11 | 12 | /** result type for 'solve' that provides solution accuracy information and number of iterations. */ 13 | struct ComputeInfo 14 | { 15 | std::size_t m_iterations{0}; ///< number of iterations used to deliver the solution 16 | float m_error{0.0f}; ///< error sqrt(|residual|^2 / |b|^2) 17 | }; 18 | 19 | }; 20 | 21 | inline std::ostream& operator<<(std::ostream& os, const LunaCore::Algebra::ComputeInfo &info) 22 | { 23 | os << "Iterations: " << info.m_iterations << " MSE: " << info.m_error; 24 | return os; 25 | } 26 | -------------------------------------------------------------------------------- /core/export/gds2/gds2writer.hpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | #include 7 | #include "database/database.h" 8 | 9 | namespace LunaCore::GDS2 10 | { 11 | 12 | bool write(std::ostream &os, const Database &database, const std::string &moduleName); 13 | 14 | }; 15 | 16 | namespace LunaCore::GDS2::WriterImpl 17 | { 18 | void write32(std::ostream &os, uint32_t value); 19 | void write16(std::ostream &os, uint16_t value); 20 | void write8(std::ostream &os, uint8_t value); 21 | 22 | // returns actual number of bytes written 23 | std::size_t write(std::ostream &os, std::string_view view); 24 | 25 | void write(std::ostream &os, const ChipDB::Instance &instance); 26 | }; 27 | -------------------------------------------------------------------------------- /test/core/gds2test.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #include "lunacore.h" 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | BOOST_AUTO_TEST_SUITE(GDS2Test) 17 | 18 | BOOST_AUTO_TEST_CASE(test_float_versions) 19 | { 20 | std::cout << "--== GDS2 FLOAT CONVERSION ==--\n"; 21 | 22 | auto flt1 = LunaCore::GDS2::IEEE2GDSFloat(3.1415927); 23 | 24 | auto flt1_ = LunaCore::GDS2::GDS2Float2IEEE(flt1); 25 | 26 | std::cout << flt1_ << "\n"; 27 | 28 | BOOST_CHECK(flt1_ == 3.1415927); 29 | 30 | } 31 | 32 | BOOST_AUTO_TEST_SUITE_END() -------------------------------------------------------------------------------- /scripts/place_adder8.py: -------------------------------------------------------------------------------- 1 | 2 | createRegion("core", 10000, 10000, 60000, 40000) 3 | createRows("core", 0, 10000, 8) 4 | print("Floorplan and rows created") 5 | 6 | loadVerilog("test/files/verilog/adder8.v") 7 | 8 | setTopModule("adder8") 9 | 10 | ## place the pins 11 | xpos = 0 12 | xinc = 4000 13 | x = 10000 14 | for idx in range(0,8): 15 | pinName = "a[" + str(idx) + "]" 16 | placeInstance(pinName, "adder8", x, 50000) 17 | x = x + xinc 18 | pinName = "b[" + str(idx) + "]" 19 | placeInstance(pinName, "adder8", x, 50000) 20 | x = x + xinc 21 | 22 | xinc = 8000 23 | x = 10000 24 | for idx in range(0,8): 25 | pinName = "y[" + str(idx) + "]" 26 | placeInstance(pinName, "adder8", x, 10000) 27 | x = x + xinc 28 | 29 | ## place the instances in the top level module 30 | placeModule("adder8", "core") 31 | -------------------------------------------------------------------------------- /examples/mac32/mac32.v: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | // 5 | // clocked 32x32 multiplier with 64 bit accumulator 6 | 7 | module mac32 8 | ( 9 | input clk, 10 | input rst_an, 11 | input signed [31:0] a_in, 12 | input signed [31:0] b_in, 13 | output signed [63:0] data_out 14 | ); 15 | 16 | wire signed [63:0] multresult; 17 | reg signed [63:0] accu; 18 | 19 | assign multresult = a_in * b_in; 20 | 21 | always @(posedge clk or negedge rst_an) 22 | begin 23 | if (rst_an == 0) 24 | begin 25 | accu <= 0; 26 | end 27 | else 28 | begin 29 | accu <= accu + multresult; 30 | end 31 | end 32 | 33 | assign data_out = accu; 34 | 35 | endmodule -------------------------------------------------------------------------------- /examples/adder8/adder8_floorplan.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | # 3 | # SPDX-License-Identifier: GPL-3.0-only 4 | 5 | ## create floorplan 6 | createRegion("core", "core", 10000, 10000, 170000, 30000) 7 | 8 | setTopModule("adder8") 9 | 10 | ## place the pins 11 | xpos = 0 12 | xinc = 10000 13 | x = 20000 14 | 15 | for idx in range(0,8): 16 | pinName = "a[" + str(idx) + "]" 17 | placeInstance(pinName, "adder8", x, 50000) 18 | x = x + xinc 19 | pinName = "b[" + str(idx) + "]" 20 | placeInstance(pinName, "adder8", x, 50000) 21 | x = x + xinc 22 | 23 | xinc = 20000 24 | x = 10000 25 | 26 | for idx in range(0,8): 27 | pinName = "y[" + str(idx) + "]" 28 | placeInstance(pinName, "adder8", x, 10000) 29 | x = x + xinc 30 | 31 | placeInstance("carryout", "adder8", x, 10000) 32 | -------------------------------------------------------------------------------- /gui/widgets/txtoverlay.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | 10 | namespace GUI 11 | { 12 | 13 | class TxtOverlay : public QWidget 14 | { 15 | Q_OBJECT 16 | 17 | public: 18 | explicit TxtOverlay(QWidget *parent = nullptr) : QWidget(parent) 19 | { 20 | m_margins = QMargins(12,8,12,8); 21 | setAttribute(Qt::WA_NoSystemBackground); 22 | setAttribute(Qt::WA_TransparentForMouseEvents); 23 | setText(""); 24 | } 25 | 26 | void setText(const QString &txt); 27 | 28 | protected: 29 | 30 | void paintEvent(QPaintEvent *) override; 31 | 32 | QString m_txt; 33 | QRect m_txtRect; 34 | QMargins m_margins; 35 | }; 36 | 37 | }; -------------------------------------------------------------------------------- /core/database/row.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include "dbtypes.h" 10 | 11 | namespace ChipDB 12 | { 13 | 14 | // predeclarations 15 | struct Region; 16 | //class Instance; 17 | 18 | enum class RowType 19 | { 20 | NORMAL, ///< regular row: cells are placed as-is 21 | FLIPY ///< cells are placed vertically flipped 22 | }; 23 | 24 | struct Row 25 | { 26 | Row() : m_rowType(RowType::NORMAL), m_region(nullptr) {} 27 | 28 | RowType m_rowType; ///< orientation of the row 29 | Rect64 m_rect; ///< location and size of the row relative to the region. 30 | 31 | std::shared_ptr m_region; ///< the region this row belongs to. 32 | }; 33 | 34 | }; -------------------------------------------------------------------------------- /examples/adder8_simplegates/adder8_floorplan.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | # 3 | # SPDX-License-Identifier: GPL-3.0-only 4 | 5 | ## create floorplan 6 | createRegion("core", "core", 10000, 10000, 170000, 30000) 7 | 8 | setTopModule("adder8") 9 | 10 | ## place the pins 11 | xpos = 0 12 | xinc = 10000 13 | x = 20000 14 | 15 | for idx in range(0,8): 16 | pinName = "a[" + str(idx) + "]" 17 | placeInstance(pinName, "adder8", x, 50000) 18 | x = x + xinc 19 | pinName = "b[" + str(idx) + "]" 20 | placeInstance(pinName, "adder8", x, 50000) 21 | x = x + xinc 22 | 23 | xinc = 20000 24 | x = 10000 25 | 26 | for idx in range(0,8): 27 | pinName = "y[" + str(idx) + "]" 28 | placeInstance(pinName, "adder8", x, 10000) 29 | x = x + xinc 30 | 31 | placeInstance("carryout", "adder8", x, 10000) 32 | -------------------------------------------------------------------------------- /core/import/def/defreader.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #include "common/logging.h" 6 | #include "defreader.h" 7 | #include "defreaderimpl.h" 8 | 9 | using namespace ChipDB::DEF; 10 | 11 | bool Reader::load(Design &design, std::istream &source) 12 | { 13 | try 14 | { 15 | std::stringstream src; 16 | src << source.rdbuf(); 17 | 18 | ReaderImpl readerimpl(design); 19 | if (!readerimpl.parse(src.str())) 20 | { 21 | Logging::logError("DEF::Reader failed to load file.\n"); 22 | return false; 23 | } 24 | 25 | return true; 26 | } 27 | catch(std::runtime_error &e) 28 | { 29 | Logging::logError("%s\n", e.what()); 30 | } 31 | 32 | return false; 33 | } 34 | -------------------------------------------------------------------------------- /core/import/lef/lefreader.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #include "common/logging.h" 6 | #include "lefreader.h" 7 | #include "lefreaderimpl.h" 8 | 9 | using namespace ChipDB::LEF; 10 | 11 | bool Reader::load(Design &design, std::istream &source) 12 | { 13 | try 14 | { 15 | std::stringstream src; 16 | src << source.rdbuf(); 17 | 18 | ReaderImpl readerimpl(design); 19 | if (!readerimpl.parse(src.str())) 20 | { 21 | Logging::logError("LEF::Reader failed to load file.\n"); 22 | return false; 23 | } 24 | 25 | return true; 26 | } 27 | catch(std::runtime_error &e) 28 | { 29 | Logging::logError("%s\n", e.what()); 30 | } 31 | 32 | return false; 33 | } 34 | -------------------------------------------------------------------------------- /scripts/place_multiplier.py: -------------------------------------------------------------------------------- 1 | createRegion("core", 10000, 10000, 80000, 80000) 2 | createRows("core", 0, 10000, 8) 3 | print("Floorplan and rows created") 4 | 5 | loadVerilog("test/files/verilog/multiplier.v") 6 | 7 | setTopModule("multiplier") 8 | 9 | ## place the pins 10 | xpos = 0 11 | xinc = 10000 12 | x = 10000 13 | for idx in range(0,4): 14 | pinName = "a_in[" + str(idx) + "]" 15 | placeInstance(pinName, "multiplier", x, 90000) 16 | x = x + xinc 17 | pinName = "b_in[" + str(idx) + "]" 18 | placeInstance(pinName, "multiplier", x, 90000) 19 | x = x + xinc 20 | 21 | xinc = 10000 22 | x = 10000 23 | for idx in range(0,8): 24 | pinName = "data_out[" + str(idx) + "]" 25 | placeInstance(pinName, "multiplier", x, 10000) 26 | x = x + xinc 27 | 28 | ## place the instances in the top level module 29 | placeModule("multiplier", "core") 30 | -------------------------------------------------------------------------------- /gui/widgets/flattogglebutton.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | namespace GUI 14 | { 15 | 16 | class FlatToggleButton : public QAbstractButton 17 | { 18 | Q_OBJECT 19 | public: 20 | FlatToggleButton(QWidget *parent = nullptr); 21 | 22 | QSize sizeHint() const; 23 | 24 | protected: 25 | bool eventFilter(QObject * watched, QEvent * event) override; 26 | void resizeEvent(QResizeEvent *e) override; 27 | void paintEvent(QPaintEvent* e) override; 28 | 29 | std::unique_ptr m_onPixmap; 30 | std::unique_ptr m_offPixmap; 31 | bool m_hover = false; 32 | }; 33 | 34 | }; 35 | -------------------------------------------------------------------------------- /core/database/observer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | namespace ChipDB 8 | { 9 | 10 | struct IObserver 11 | { 12 | virtual void update(int id) = 0; 13 | }; 14 | 15 | /** Subject interface of observer */ 16 | class Subject 17 | { 18 | public: 19 | using updateCallback = std::function; 20 | 21 | void notify(); 22 | 23 | void addObserver(IObserver *observer); 24 | void addObserver(const std::string &name, updateCallback cb); 25 | 26 | void removeObserver(IObserver *observer); 27 | void removeObserver(const std::string &name); 28 | 29 | void setSubjectID(int id); 30 | 31 | protected: 32 | int m_subjectId{-1}; 33 | 34 | std::list m_observers; 35 | std::unordered_map m_callbacks; 36 | }; 37 | 38 | }; -------------------------------------------------------------------------------- /core/import/liberty/libreader.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #include "common/logging.h" 6 | #include "libreader.h" 7 | #include "libreaderimpl.h" 8 | 9 | using namespace ChipDB::Liberty; 10 | 11 | bool Reader::load(Design &design, std::istream &source) 12 | { 13 | try 14 | { 15 | std::stringstream src; 16 | src << source.rdbuf(); 17 | 18 | ReaderImpl readerimpl(design); 19 | if (!readerimpl.parse(src.str())) 20 | { 21 | Logging::logError("Liberty::Reader failed to load file.\n"); 22 | return false; 23 | } 24 | 25 | return true; 26 | } 27 | catch(std::runtime_error &e) 28 | { 29 | Logging::logError("%s\n", e.what()); 30 | } 31 | 32 | return false; 33 | } 34 | -------------------------------------------------------------------------------- /gui/tasks/checktiming.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include "tasks.h" 8 | 9 | namespace Tasks 10 | { 11 | 12 | class CheckTiming : public Task 13 | { 14 | public: 15 | 16 | enum class Mode 17 | { 18 | BARE, 19 | CTS, 20 | WITHSPEF 21 | }; 22 | 23 | CheckTiming(Mode mode) : m_mode(mode) {} 24 | 25 | virtual ~CheckTiming() = default; 26 | 27 | protected: 28 | std::string createTCL(const GUI::Database &database, 29 | const std::string &topModuleName, 30 | const std::string &spefFilename, 31 | const std::string &verilogFilename) const; 32 | 33 | void execute(GUI::Database &database, ProgressCallback callback) override; 34 | 35 | Mode m_mode{Mode::BARE}; 36 | }; 37 | 38 | }; 39 | -------------------------------------------------------------------------------- /examples/lfsr31/lfsr31.vhd: -------------------------------------------------------------------------------- 1 | LIBRARY ieee; 2 | USE ieee.std_logic_1164.ALL; 3 | 4 | ENTITY LFSR31 IS 5 | PORT( 6 | clk : IN std_logic; 7 | rst_an : IN std_logic; 8 | dout : OUT std_logic 9 | ); 10 | END LFSR31; 11 | 12 | ARCHITECTURE rtl OF LFSR31 IS 13 | SIGNAL curState, nextState: std_logic_vector (30 DOWNTO 0); 14 | SIGNAL feedback: std_logic; 15 | BEGIN 16 | 17 | proc_clk: PROCESS(clk, rst_an) 18 | BEGIN 19 | IF (rst_an = '0') THEN 20 | curState <= (OTHERS =>'0'); 21 | curState(0) <= '1'; 22 | ELSIF rising_edge(clk) THEN 23 | curState <= nextState; 24 | END IF; 25 | END PROCESS proc_clk; 26 | 27 | -- Polynomial 31, 28 28 | feedback <= curState(30) XNOR curState(27); 29 | nextState <= curstate(29 DOWNTO 0) & feedback; 30 | dout <= curState(0); 31 | 32 | END rtl; 33 | -------------------------------------------------------------------------------- /test/python/various/mandel.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # Draw an ASCII mandelbrot set 3 | 4 | import cmath 5 | import numpy as np 6 | 7 | def mandelIterations(c : complex) -> int: 8 | maxIter = 64 9 | z = c 10 | for iter in range(0,maxIter): 11 | magnitudeSquared = z*z.conjugate() 12 | if (magnitudeSquared.real >= 4.0): 13 | return iter 14 | z = z*z + c 15 | return maxIter 16 | 17 | def mandel(): 18 | for y in np.linspace(-1,1,40): 19 | for x in np.linspace(-2,1,80): 20 | c = complex(x,y) 21 | iters = mandelIterations(c) 22 | if (iters > 10): 23 | print("*", end = '') 24 | else: 25 | print(" ", end = '') 26 | print() 27 | 28 | 29 | if __name__ == '__main__': 30 | # Script2.py executed as script 31 | # do something 32 | mandel() 33 | 34 | -------------------------------------------------------------------------------- /gui/floorplandialog/floorplandialog.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | #include "common/database.h" 11 | #include "lunacore.h" 12 | 13 | namespace GUI 14 | { 15 | 16 | class FloorplanDialog : public QDialog 17 | { 18 | Q_OBJECT 19 | public: 20 | FloorplanDialog(Database &db, QWidget *parent = nullptr); 21 | virtual ~FloorplanDialog() = default; 22 | 23 | protected slots: 24 | void onAddRegionRow(); 25 | void accept() override; 26 | 27 | protected: 28 | void onOpenScriptLocationOpen(); 29 | void createTableRow(size_t row, const RegionSetup ®ion); 30 | 31 | Database &m_db; 32 | QTableWidget *m_regionTable; 33 | QLineEdit *m_floorplanScriptEdit; 34 | }; 35 | 36 | }; -------------------------------------------------------------------------------- /gui/propertyview/propertyview.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | namespace GUI 12 | { 13 | 14 | class PropertyModelInterface 15 | { 16 | 17 | }; 18 | 19 | class PropertyView : public QWidget 20 | { 21 | Q_OBJECT 22 | 23 | public: 24 | explicit PropertyView(QWidget *parent = nullptr); 25 | virtual ~PropertyView(); 26 | 27 | void setPropertyModel(PropertyModelInterface *model) 28 | { 29 | m_model = model; 30 | } 31 | 32 | protected: 33 | QLabel* createTextLabel(const std::string &txt); 34 | void addPropertyWidget(QWidget *widget, int32_t row, int32_t col); 35 | 36 | PropertyModelInterface* m_model; 37 | QGridLayout* m_gridLayout; 38 | }; 39 | 40 | }; -------------------------------------------------------------------------------- /version/compilerversion.cmake: -------------------------------------------------------------------------------- 1 | file(REAL_PATH /usr/bin/c++ REAL_COMPILER_PATH) 2 | 3 | execute_process(COMMAND ${REAL_COMPILER_PATH} --version 4 | COMMAND head -n 1 5 | OUTPUT_VARIABLE COMPILER_VERSION_STRING 6 | ERROR_QUIET) 7 | 8 | if ("${COMPILER_VERSION_STRING}" STREQUAL "") 9 | set(COMPILER_VERSION_STRING "Compiler string N/A") 10 | endif() 11 | 12 | string(STRIP "${COMPILER_VERSION_STRING}" COMPILER_VERSION_STRING) 13 | 14 | set(VERSION "const char* COMPILER_VERSION=\"'${COMPILER_VERSION_STRING}'\";") 15 | 16 | if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/version/compilerversion.cpp) 17 | file(READ ${CMAKE_CURRENT_SOURCE_DIR}/version/compilerversion.cpp VERSION_) 18 | else() 19 | set(VERSION_ "") 20 | endif() 21 | 22 | if (NOT "${VERSION}" STREQUAL "${VERSION_}") 23 | file(WRITE ${CMAKE_CURRENT_SOURCE_DIR}/version/compilerversion.cpp "${VERSION}") 24 | endif() 25 | -------------------------------------------------------------------------------- /mkappimage.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ## SPDX-FileCopyrightText: 2021-2025 Niels Moseley 3 | ## 4 | ## SPDX-License-Identifier: GPL-3.0-only 5 | 6 | sudo apt install -y python3-pip python3-setuptools patchelf desktop-file-utils libgtk-pixbuf2.0-dev fakeroot strace 7 | sudo wget https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage -O /usr/local/bin/appimagetool 8 | sudo chmod +x /usr/local/bin/appimagetool 9 | sudo pip3 install appimage-builder 10 | 11 | mkdir -p AppDir/usr/bin 12 | mkdir -p AppDir/usr/share/icons/hicolor/128x128/apps/ 13 | mkdir -p AppDir/usr/share/applications 14 | 15 | cp build/gui/lunapnr AppDir/usr/bin 16 | cp resources/icons/lunapnr.png AppDir/usr/share/icons/hicolor/128x128/apps/ 17 | cp resources/lunapnr.desktop AppDir/usr/share/applications/ 18 | 19 | appimage-builder --recipe AppImageBuilder.yml 20 | 21 | rm -rf AppDir 22 | rm -rf appimage-builder-cache 23 | -------------------------------------------------------------------------------- /gui/pdkdialog/pdkdialog.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | #include 7 | #include "common/pdkinfo.h" 8 | #include "pdktile.h" 9 | #include 10 | #include 11 | #include 12 | 13 | namespace GUI 14 | { 15 | 16 | class PDKDialog : public QDialog 17 | { 18 | Q_OBJECT 19 | public: 20 | PDKDialog(std::vector &pdks); 21 | 22 | constexpr int selected() const noexcept 23 | { 24 | return m_tileList->selected(); 25 | } 26 | 27 | private slots: 28 | void onSelectionChanged(int id); 29 | 30 | protected: 31 | int m_selected{-1}; 32 | std::vector &m_pdks; 33 | 34 | PDKTileList *m_tileList{nullptr}; 35 | QScrollArea *m_tileListScroll{nullptr}; 36 | 37 | QDialogButtonBox *m_buttonBox{nullptr}; 38 | 39 | }; 40 | 41 | }; 42 | -------------------------------------------------------------------------------- /core/database/module.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include 8 | #include "cell.h" 9 | #include "netlist.h" 10 | 11 | namespace ChipDB 12 | { 13 | 14 | class Module : public Cell 15 | { 16 | public: 17 | Module(const std::string &name); 18 | 19 | virtual bool isModule() const override 20 | { 21 | return true; 22 | } 23 | 24 | KeyObjPair addInstance(std::shared_ptr insPtr); 25 | KeyObjPair createNet(const std::string &netName); 26 | 27 | bool connect(const std::string &insName, const std::string &pinName, const std::string &netName); 28 | bool connect(InstanceObjectKey insKey, PinObjectKey pinKey, NetObjectKey netKey); 29 | 30 | /** pointer to netlist, or null if the module is a black box */ 31 | std::shared_ptr m_netlist; 32 | }; 33 | 34 | }; -------------------------------------------------------------------------------- /examples/mac32/mac32.lpr: -------------------------------------------------------------------------------- 1 | { 2 | "FloorplanScriptLocation": "/storage/programming/asic/luna_pnr/examples/mac32/mac32_floorplan.py", 3 | "LEF": [ 4 | "/storage/programming/asic/luna_pnr/test/files/iit_stdcells/lib/tsmc018/lib/iit018_stdcells.lef", 5 | "/storage/programming/asic/luna_pnr/test/files/iit_stdcells_extra/fake_ties018.lef" 6 | ], 7 | "LIB": [ 8 | "/storage/programming/asic/luna_pnr/test/files/iit_stdcells/lib/tsmc018/signalstorm/iit018_stdcells.lib", 9 | "/storage/programming/asic/luna_pnr/test/files/iit_stdcells_extra/fake_ties018.lib" 10 | ], 11 | "Layers": [ 12 | "/storage/programming/asic/luna_pnr/scripts/osu180.layers" 13 | ], 14 | "Regions": [ 15 | ], 16 | "Timing": [ 17 | "/storage/programming/asic/luna_pnr/examples/mac32/mac32.sdc" 18 | ], 19 | "Verilog": [ 20 | "/storage/programming/asic/luna_pnr/examples/mac32/mac32_netlist.v" 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /core/database/cell.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #include "cell.h" 6 | 7 | using namespace ChipDB; 8 | 9 | // ********************************************************************** 10 | // Cell 11 | // ********************************************************************** 12 | 13 | KeyObjPair Cell::createPin(const std::string &name) 14 | { 15 | return m_pins.createPin(name); 16 | } 17 | 18 | KeyObjPair Cell::lookupPin(const std::string &name) 19 | { 20 | return m_pins[name]; 21 | } 22 | 23 | KeyObjPair Cell::lookupPin(const std::string &name) const 24 | { 25 | return m_pins[name]; 26 | } 27 | 28 | std::shared_ptr Cell::lookupPin(ObjectKey key) 29 | { 30 | return m_pins[key]; 31 | } 32 | 33 | std::shared_ptr Cell::lookupPin(ObjectKey key) const 34 | { 35 | return m_pins[key]; 36 | } 37 | -------------------------------------------------------------------------------- /gui/models/cellinfomodel.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | #include "lunacore.h" 14 | #include "../common/guihelpers.h" 15 | #include "modelnodebase.h" 16 | 17 | namespace GUI 18 | { 19 | 20 | class CellInfoNode : public NodeBase 21 | { 22 | public: 23 | CellInfoNode(const QString &valueName, QVariant value, QColor bkColor = Qt::white); 24 | virtual ~CellInfoNode(); 25 | }; 26 | 27 | class CellInfoModel : public ModelBase 28 | { 29 | public: 30 | CellInfoModel(); 31 | virtual ~CellInfoModel(); 32 | 33 | void setCell(const std::shared_ptr cell); 34 | 35 | protected: 36 | QColor m_pinColor; 37 | QColor m_separatorColor; 38 | AlternatingColors m_altColors; 39 | }; 40 | 41 | }; 42 | -------------------------------------------------------------------------------- /core/python/pylunapnr.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | #include 7 | #include 8 | #include 9 | #include "database/database.h" 10 | 11 | namespace Scripting 12 | { 13 | 14 | class Python 15 | { 16 | public: 17 | Python(ChipDB::Design *design); 18 | virtual ~Python(); 19 | 20 | void init(); 21 | 22 | virtual bool preInitHook() { return true; }; 23 | virtual bool postInitHook() { return true; }; 24 | 25 | bool executeScript(const std::string &code); 26 | bool executeScriptFile(const std::string &fileName); 27 | 28 | void setConsoleRedirect(std::function stdoutFunc, 29 | std::function stderrFunc); 30 | 31 | protected: 32 | bool m_initCalled = false; 33 | ChipDB::Design *m_design; 34 | }; 35 | 36 | }; -------------------------------------------------------------------------------- /examples/adder8/adder8.lpr: -------------------------------------------------------------------------------- 1 | { 2 | "FloorplanScriptLocation": "/storage/programming/asic/luna_pnr/examples/adder8/adder8_floorplan.py", 3 | "LEF": [ 4 | "/storage/programming/asic/luna_pnr/test/files/iit_stdcells/lib/tsmc018/lib/iit018_stdcells.lef", 5 | "/storage/programming/asic/luna_pnr/test/files/iit_stdcells_extra/fake_ties018.lef" 6 | ], 7 | "LIB": [ 8 | "/storage/programming/asic/luna_pnr/test/files/iit_stdcells/lib/tsmc018/signalstorm/iit018_stdcells.lib", 9 | "/storage/programming/asic/luna_pnr/test/files/iit_stdcells_extra/fake_ties018.lib" 10 | ], 11 | "Layers": [ 12 | "/storage/programming/asic/luna_pnr/scripts/osu180.layers" 13 | ], 14 | "Regions": [ 15 | ], 16 | "Timing": [ 17 | "/storage/programming/asic/luna_pnr/examples/adder8/adder8.sdc" 18 | ], 19 | "Verilog": [ 20 | "/storage/programming/asic/luna_pnr/examples/adder8/adder8_netlist.v" 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /examples/lfsr31/lfsr31.lpr: -------------------------------------------------------------------------------- 1 | { 2 | "FloorplanScriptLocation": "/storage/programming/asic/luna_pnr/examples/lfsr31/lfsr31_floorplan.py", 3 | "LEF": [ 4 | "/storage/programming/asic/luna_pnr/test/files/iit_stdcells/lib/tsmc018/lib/iit018_stdcells.lef", 5 | "/storage/programming/asic/luna_pnr/test/files/iit_stdcells_extra/fake_ties018.lef" 6 | ], 7 | "LIB": [ 8 | "/storage/programming/asic/luna_pnr/test/files/iit_stdcells/lib/tsmc018/signalstorm/iit018_stdcells.lib", 9 | "/storage/programming/asic/luna_pnr/test/files/iit_stdcells_extra/fake_ties018.lib" 10 | ], 11 | "Layers": [ 12 | "/storage/programming/asic/luna_pnr/scripts/osu180.layers" 13 | ], 14 | "Regions": [ 15 | ], 16 | "Timing": [ 17 | "/storage/programming/asic/luna_pnr/examples/lfsr31/lfsr31.sdc" 18 | ], 19 | "Verilog": [ 20 | "/storage/programming/asic/luna_pnr/examples/lfsr31/lfsr31_netlist.v" 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /gui/models/moduleinfomodel.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | #include "lunacore.h" 14 | #include "../common/guihelpers.h" 15 | #include "modelnodebase.h" 16 | 17 | namespace GUI 18 | { 19 | 20 | class ModuleInfoNode : public NodeBase 21 | { 22 | public: 23 | ModuleInfoNode(const QString &valueName, QVariant value, QColor bkColor = Qt::white); 24 | virtual ~ModuleInfoNode(); 25 | }; 26 | 27 | class ModuleInfoModel : public ModelBase 28 | { 29 | public: 30 | ModuleInfoModel(); 31 | virtual ~ModuleInfoModel(); 32 | 33 | void setModule(std::shared_ptr module); 34 | 35 | protected: 36 | QColor m_pinColor; 37 | QColor m_separatorColor; 38 | AlternatingColors m_altColors; 39 | }; 40 | 41 | }; 42 | -------------------------------------------------------------------------------- /core/cellplacer/qplacertypes.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #include 6 | #include "qplacertypes.h" 7 | 8 | using namespace LunaCore::QPlacer; 9 | 10 | PlacerNetId PlacerNetlist::createNet() 11 | { 12 | m_nets.emplace_back(); 13 | return m_nets.size()-1; 14 | } 15 | 16 | PlacerNodeId PlacerNetlist::createNode() 17 | { 18 | m_nodes.emplace_back(); 19 | return m_nodes.size()-1; 20 | } 21 | 22 | void PlacerNetlist::dump(std::ostream &os) const 23 | { 24 | os << "PlacerNetlist:\n"; 25 | size_t idx = 0; 26 | for(auto const& node: m_nodes) 27 | { 28 | std::cout << "Node: " << idx << " "; 29 | node.dump(os); 30 | idx++; 31 | } 32 | 33 | idx = 0; 34 | for(auto const& net: m_nets) 35 | { 36 | std::cout << "Net: " << idx << " "; 37 | net.dump(os); 38 | idx++; 39 | } 40 | os << "done.\n"; 41 | } 42 | -------------------------------------------------------------------------------- /gui/widgets/flatactiontile.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | #include "flattilebase.h" 11 | #include "flatimagebutton.h" 12 | 13 | namespace GUI 14 | { 15 | 16 | class FlatActionTile : public FlatTileBase 17 | { 18 | Q_OBJECT 19 | public: 20 | FlatActionTile(const QString &actionTitle, 21 | const QString &iconUrl, 22 | const QString &actionIconUrl, 23 | const QString &actionName, 24 | QWidget *parent = nullptr); 25 | 26 | virtual ~FlatActionTile() = default; 27 | 28 | void setActionIcon(const QString &iconUrl); 29 | 30 | signals: 31 | void onAction(QString actionName); 32 | 33 | private slots: 34 | void onActionPrivate(); 35 | 36 | protected: 37 | QString m_actionName; 38 | FlatImageButton *m_actionButton = nullptr; 39 | }; 40 | 41 | }; 42 | -------------------------------------------------------------------------------- /examples/lfsr31/lfsr31_tb.vhd: -------------------------------------------------------------------------------- 1 | 2 | LIBRARY ieee; 3 | USE ieee.std_logic_1164.ALL; 4 | 5 | ENTITY LFSR31_TB IS 6 | END LFSR31_TB; 7 | 8 | ARCHITECTURE tb OF LFSR31_TB IS 9 | 10 | SIGNAL clk, rst_an : std_logic; 11 | SIGNAL data : std_logic; 12 | SIGNAL quit : std_logic := '0'; 13 | BEGIN 14 | 15 | u_DUT: ENTITY work.LFSR31(rtl) 16 | PORT MAP 17 | ( 18 | clk => clk, 19 | rst_an => rst_an, 20 | dout => data 21 | ); 22 | 23 | proc_clk: PROCESS 24 | BEGIN 25 | clk <= '1'; 26 | WAIT FOR 10 ns; 27 | clk <= '0'; 28 | WAIT FOR 10 ns; 29 | IF (quit = '1') THEN 30 | WAIT; 31 | END IF; 32 | END PROCESS proc_clk; 33 | 34 | proc_sim: PROCESS 35 | BEGIN 36 | rst_an <= '0'; 37 | WAIT FOR 20 ns; 38 | rst_an <= '1'; 39 | WAIT FOR 10000 ns; 40 | quit <= '1'; 41 | WAIT; 42 | END PROCESS proc_sim; 43 | 44 | 45 | END tb; 46 | -------------------------------------------------------------------------------- /gui/widgets/flatactiontile.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #include 6 | #include "flatactiontile.h" 7 | 8 | using namespace GUI; 9 | 10 | FlatActionTile::FlatActionTile(const QString &actionTitle, 11 | const QString &iconUrl, 12 | const QString &actionIconUrl, 13 | const QString &actionName, 14 | QWidget *parent) : FlatTileBase(actionTitle, iconUrl, actionName, parent), m_actionName(actionName) 15 | { 16 | m_actionButton = new FlatImageButton(actionIconUrl); 17 | 18 | m_hlayout->addWidget(m_actionButton); 19 | 20 | connect(m_actionButton, &FlatImageButton::pressed, this, &FlatActionTile::onActionPrivate); 21 | 22 | setLayout(m_hlayout); 23 | } 24 | 25 | void FlatActionTile::onActionPrivate() 26 | { 27 | emit onAction(m_actionName); 28 | } 29 | 30 | void FlatActionTile::setActionIcon(const QString &iconUrl) 31 | { 32 | m_actionButton->setPixmap(iconUrl); 33 | } 34 | -------------------------------------------------------------------------------- /scripts/padring.pnr: -------------------------------------------------------------------------------- 1 | # padring script 2 | 3 | # load the design 4 | read -lib ./test/files/iit_stdcells/lib/ami035/signalstorm/iit035_stdcells.lib 5 | read -lef ./test/files/iit_stdcells/lib/ami035/lib/iit035_stdcells.lef 6 | read -lef ./test/files/iit_stdcells_extra/fake_pad_fillers35.lef 7 | read -verilog ./test/files/padring/padring.v 8 | 9 | # create floorplan 10 | floorplan -width 1000000 -height 1000000 -coremargins 10000 10000 10000 10000 -cornersize 300000 11 | 12 | # create padring 13 | set -cell PADNC -subclass SPACER 14 | set -cell PADNC5 -subclass SPACER 15 | set -cell PADNC10 -subclass SPACER 16 | set -cell PADNC50 -subclass SPACER 17 | padring -place ./test/files/padring/padring.conf -module top 18 | 19 | write -def top ./test/files/results/padring.def 20 | set -loglevel VERBOSE 21 | write -gds2 top ./test/files/results/padring.gds 22 | set -loglevel NORMAL 23 | 24 | gdsmerge -output ./test/files/results/padring_merged.gds ./test/files/iit_stdcells/lib/source/gds2/iit035_pads.gds2 ./test/files/results/padring.gds 25 | -------------------------------------------------------------------------------- /core/database/design.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #include "design.h" 6 | 7 | using namespace ChipDB; 8 | 9 | Design::Design() 10 | { 11 | m_techLib = std::make_shared(); 12 | m_cellLib = std::make_shared(); 13 | m_moduleLib = std::make_shared(); 14 | m_floorplan = std::make_shared(); 15 | } 16 | 17 | void Design::clear() 18 | { 19 | //m_netlist->clear(); 20 | m_techLib->clear(); 21 | m_cellLib->clear(); 22 | m_moduleLib->clear(); 23 | m_floorplan->clear(); 24 | 25 | m_topModule = nullptr; 26 | m_uniqueIDCounter = 0; 27 | } 28 | 29 | bool Design::setTopModule(const std::string &moduleName) 30 | { 31 | auto moduleKeyObjPair = m_moduleLib->lookupModule(moduleName); 32 | if (moduleKeyObjPair.isValid()) 33 | { 34 | m_topModule = moduleKeyObjPair.ptr(); 35 | return true; 36 | } 37 | return false; 38 | } 39 | -------------------------------------------------------------------------------- /examples/adder8_simplegates/adder8_simplegates.lpr: -------------------------------------------------------------------------------- 1 | { 2 | "FloorplanScriptLocation": "/storage/programming/asic/luna_pnr/examples/adder8_simplegates/adder8_floorplan.py", 3 | "LEF": [ 4 | "/storage/programming/asic/luna_pnr/test/files/iit_stdcells/lib/tsmc018/lib/iit018_stdcells.lef", 5 | "/storage/programming/asic/luna_pnr/test/files/iit_stdcells_extra/fake_ties018.lef" 6 | ], 7 | "LIB": [ 8 | "/storage/programming/asic/luna_pnr/test/files/iit_stdcells/lib/tsmc018/signalstorm/iit018_stdcells.lib", 9 | "/storage/programming/asic/luna_pnr/test/files/iit_stdcells_extra/fake_ties018.lib" 10 | ], 11 | "Layers": [ 12 | "/storage/programming/asic/luna_pnr/scripts/osu180.layers" 13 | ], 14 | "Regions": [ 15 | ], 16 | "Timing": [ 17 | "/storage/programming/asic/luna_pnr/examples/adder8_simplegates/adder8.sdc" 18 | ], 19 | "Verilog": [ 20 | "/storage/programming/asic/luna_pnr/examples/adder8_simplegates/adder8_simplegates_netlist.v" 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /gui/widgets/rectdelegate.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | // https://doc.qt.io/qt-6/qtwidgets-itemviews-stardelegate-example.html 8 | 9 | #include 10 | 11 | namespace GUI 12 | { 13 | 14 | class RectDelegate : public QStyledItemDelegate 15 | { 16 | Q_OBJECT 17 | public: 18 | 19 | void paint(QPainter *painter, const QStyleOptionViewItem &option, 20 | const QModelIndex &index) const override; 21 | 22 | QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, 23 | const QModelIndex &index) const override; 24 | 25 | QSize sizeHint(const QStyleOptionViewItem &option, 26 | const QModelIndex &index) const override; 27 | 28 | void setEditorData(QWidget *editor, const QModelIndex &index) const override; 29 | 30 | private slots: 31 | void commitAndCloseEditor(); 32 | }; 33 | 34 | }; 35 | -------------------------------------------------------------------------------- /gui/widgets/txtoverlay.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #include 6 | #include "txtoverlay.h" 7 | 8 | using namespace GUI; 9 | 10 | void TxtOverlay::paintEvent(QPaintEvent *event) 11 | { 12 | QPainter painter(this); 13 | 14 | // detect a text size change 15 | QFontMetrics fm(painter.font()); 16 | auto txtRect = fm.boundingRect(m_txt); 17 | txtRect = txtRect.marginsAdded(m_margins); 18 | if (txtRect != m_txtRect) 19 | { 20 | m_txtRect = txtRect; 21 | resize(m_txtRect.size()); 22 | } 23 | 24 | QColor bkcolor("#C0333333"); 25 | QColor txtcolor("#FFFFFFFF"); 26 | 27 | painter.setBrush(bkcolor); 28 | painter.setPen(bkcolor); 29 | painter.drawRoundedRect(rect(),4,4); 30 | painter.setPen(txtcolor); 31 | 32 | painter.drawText(rect(), Qt::AlignVCenter | Qt::AlignHCenter, m_txt); 33 | } 34 | 35 | void TxtOverlay::setText(const QString &txt) 36 | { 37 | m_txt = txt; 38 | } 39 | -------------------------------------------------------------------------------- /core/import/def/defreaderimpl.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include 8 | #include "defparser.h" 9 | 10 | namespace ChipDB::DEF 11 | { 12 | 13 | class ReaderImpl : public Parser 14 | { 15 | public: 16 | ReaderImpl(Design &design); 17 | 18 | void onDesign(const std::string &designName) override; 19 | void onEndDesign(const std::string &designName) override; 20 | void onComponent(const std::string &insName, const std::string &archetype) override; 21 | void onComponentPlacement(const ChipDB::Coord64 &pos, 22 | const ChipDB::PlacementInfo placement, 23 | const ChipDB::Orientation orient) override; 24 | 25 | void onEndParse() override; 26 | 27 | protected: 28 | std::shared_ptr m_module; ///< current module being processed 29 | std::shared_ptr m_instance; ///< current instance being processed 30 | Design &m_design; 31 | }; 32 | 33 | }; //namespace 34 | -------------------------------------------------------------------------------- /examples/femtorv32/femtov32_quark.lpr: -------------------------------------------------------------------------------- 1 | { 2 | "CTSBuffer": "CLKBUF2", 3 | "CTSMaxCap": 2.9999998795923744e-13, 4 | "FloorplanScriptLocation": "/storage/programming/asic/luna_pnr/examples/femtorv32/femtov32_quark_floorplan.py", 5 | "LEF": [ 6 | "/storage/programming/asic/luna_pnr/test/files/iit_stdcells/lib/tsmc018/lib/iit018_stdcells.lef", 7 | "/storage/programming/asic/luna_pnr/test/files/iit_stdcells_extra/fake_ties018.lef" 8 | ], 9 | "LIB": [ 10 | "/storage/programming/asic/luna_pnr/test/files/iit_stdcells/lib/tsmc018/signalstorm/iit018_stdcells.lib", 11 | "/storage/programming/asic/luna_pnr/test/files/iit_stdcells_extra/fake_ties018.lib" 12 | ], 13 | "Layers": [ 14 | "/storage/programming/asic/luna_pnr/scripts/osu180.layers" 15 | ], 16 | "Regions": [ 17 | ], 18 | "Timing": [ 19 | "/storage/programming/asic/luna_pnr/examples/femtorv32/femtov32_quark.sdc" 20 | ], 21 | "Verilog": [ 22 | "/storage/programming/asic/luna_pnr/examples/femtorv32/femtorv32_quark_netlist.v" 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /core/common/subprocess_unix.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #include "subprocess.h" 6 | 7 | #include 8 | #include 9 | 10 | bool ChipDB::Subprocess::run(const std::string &command, std::function lineCallback) 11 | { 12 | FILE *pipe = popen(command.c_str(), "r"); 13 | if (pipe == nullptr) 14 | { 15 | return false; 16 | } 17 | 18 | std::string strBuffer; 19 | std::array buffer; 20 | 21 | while(fgets(&buffer.at(0), buffer.size(), pipe) != nullptr) 22 | { 23 | strBuffer += &buffer.at(0); 24 | if (!strBuffer.empty() && strBuffer.back() == '\n') 25 | { 26 | lineCallback(strBuffer); 27 | strBuffer.clear(); 28 | } 29 | if (!strBuffer.empty()) 30 | { 31 | lineCallback(strBuffer); 32 | } 33 | } 34 | 35 | if (pclose(pipe) < 0) 36 | { 37 | return false; 38 | } 39 | 40 | return true; 41 | }; 42 | -------------------------------------------------------------------------------- /core/database/netlisttools.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include 8 | #include "netlist.h" 9 | 10 | namespace LunaCore::NetlistTools 11 | { 12 | 13 | /** write a placement file (for debugging) 14 | * for each instance: x y xsize ysize 15 | */ 16 | bool writePlacementFile(std::ostream &os, const ChipDB::Netlist *netlist); 17 | 18 | using NetlistHistogram = std::map; 19 | 20 | /** returns a histogram of the net connections */ 21 | NetlistHistogram calcNetlistHistogram(const ChipDB::Netlist *netlist); 22 | 23 | /** remote NETCON instances from a netlist. FIXME: does not work!!! */ 24 | bool removeNetconInstances(ChipDB::Netlist &netlist); 25 | 26 | /** calculate half-perimiter wire length, ignoring the exact pin locations */ 27 | double calcHPWL(const ChipDB::Netlist &netlist); 28 | 29 | /** calculate the total cell area of cells in the netlist */ 30 | double calcTotalCellArea(const ChipDB::Netlist &netlist); 31 | }; 32 | -------------------------------------------------------------------------------- /gui/projectmanager/projectmanager.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "../common/database.h" 12 | #include "../widgets/flatactiontile.h" 13 | #include "filesetupmanager.h" 14 | 15 | namespace GUI 16 | { 17 | 18 | class ProjectManager : public QWidget 19 | { 20 | Q_OBJECT 21 | public: 22 | ProjectManager(Database &db, QWidget *parent = nullptr); 23 | 24 | void repopulate(); 25 | 26 | signals: 27 | void onAction(QString actionName); 28 | 29 | protected slots: 30 | void onFloorplanSetup(QString actionName); 31 | void onWriteToDef(QString actionName); 32 | void onCTSSetup(QString actionName); 33 | 34 | protected: 35 | bool event(QEvent * event) override; 36 | void create(); 37 | 38 | Database &m_db; 39 | ProjectSetup &m_projectSetup; 40 | 41 | QVBoxLayout *m_managerLayout = nullptr; 42 | 43 | GUI::FileSetupManager *m_fileSetupManager = nullptr; 44 | std::vector m_tiles; 45 | }; 46 | 47 | } -------------------------------------------------------------------------------- /test/core/ppmtests.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #include "lunacore.h" 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | BOOST_AUTO_TEST_SUITE(PPMTests) 15 | 16 | BOOST_AUTO_TEST_CASE(check_PPM_IO) 17 | { 18 | std::cout << "--== CHECK PPM I/O ==--\n"; 19 | 20 | LunaCore::PPM::Bitmap bm; 21 | bm.m_height = 256; 22 | bm.m_width = 256; 23 | bm.m_data.resize(256*256, {0,0,0,0}); 24 | 25 | for(int x=0; xm_width==256); 36 | BOOST_CHECK(checkbm->m_height==256); 37 | 38 | BOOST_CHECK(checkbm->m_data == bm.m_data); 39 | } 40 | 41 | BOOST_AUTO_TEST_SUITE_END() -------------------------------------------------------------------------------- /test/core/svgwritertest.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #include "lunacore.h" 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | BOOST_AUTO_TEST_SUITE(SVGWriterTest) 15 | 16 | BOOST_AUTO_TEST_CASE(can_write_svg) 17 | { 18 | std::cout << "--== SVG WRITER ==--\n"; 19 | 20 | std::ofstream ofile("test/files/results/svgwriter.svg"); 21 | 22 | LunaCore::SVG::Writer svg(ofile, 2000, 2000); 23 | svg.setFillColour(0x000000A0); 24 | svg.setStrokeWidth(10); 25 | svg.drawCircle({1000,1000}, 500); 26 | 27 | svg.setFillColour(0xFF0000A0); 28 | svg.drawRectangle({0, 0}, {500, 500}); 29 | 30 | svg.setStrokeWidth(40); 31 | svg.setStrokeColour(0xF0F000FF); 32 | svg.drawLine({400,400},{900,900}); 33 | 34 | svg.setFontFamily("Arial, Helvetica, sans-serif"); 35 | svg.setFontSize(300); 36 | svg.setStrokeColour(0xF000F0FF); 37 | svg.drawCenteredText({1000,1000}, "Garfield"); 38 | } 39 | 40 | BOOST_AUTO_TEST_SUITE_END() 41 | -------------------------------------------------------------------------------- /core/export/ppm/ppmwriter.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #include 6 | #include "common/logging.h" 7 | #include "ppmwriter.h" 8 | 9 | bool LunaCore::PPM::write(const std::string &filename, const Bitmap &bm) 10 | { 11 | std::ofstream ofile(filename); 12 | if (!ofile.good()) 13 | { 14 | return false; 15 | } 16 | if (!ofile.is_open()) 17 | { 18 | return false; 19 | } 20 | 21 | return write(ofile, bm); 22 | } 23 | 24 | bool LunaCore::PPM::write(std::ostream &os, const Bitmap &bm) 25 | { 26 | if (!os.good()) return false; 27 | if (bm.m_width == 0) return false; 28 | 29 | const int maxColorValue = 255; 30 | 31 | os << "P6 " << bm.m_width << " " << bm.m_height << " " << maxColorValue << "\n"; 32 | 33 | for(int y=0; y(&bm.m_data.at(h_offset + x)), 3); 39 | } 40 | } 41 | 42 | return true; 43 | } 44 | -------------------------------------------------------------------------------- /examples/mac32/mac32_floorplan.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | # 3 | # SPDX-License-Identifier: GPL-3.0-only 4 | 5 | setLogLevel("VERBOSE") 6 | 7 | cell_height = 10000 8 | cell_width = 800 9 | 10 | rows = 100 11 | ys = cell_height * rows 12 | xs = ys 13 | 14 | xofs = 50000 15 | yofs = 50000 16 | pin_distance = 40000 17 | 18 | ## create floorplan 19 | createRegion("core", "core", xofs, yofs, xs, ys) 20 | 21 | setTopModule("mac32") 22 | 23 | ## place the pins 24 | xpos = 0 25 | xinc = 16000 26 | x = xofs+10000 27 | 28 | for idx in range(0,32): 29 | pinName = "a_in[" + str(idx) + "]" 30 | placeInstance(pinName, "mac32", x, yofs+ys+pin_distance) 31 | x = x + xinc 32 | pinName = "b_in[" + str(idx) + "]" 33 | placeInstance(pinName, "mac32", x, yofs+ys+pin_distance) 34 | x = x + xinc 35 | 36 | xinc = 16000 37 | x = xofs+10000 38 | 39 | placeInstance("clk", "mac32", x, yofs-pin_distance) 40 | x = x + xinc 41 | placeInstance("rst_an", "mac32", x, yofs-pin_distance) 42 | x = x + xinc 43 | 44 | for idx in range(0,64): 45 | pinName = "data_out[" + str(idx) + "]" 46 | placeInstance(pinName, "mac32", x, yofs-pin_distance) 47 | x = x + xinc 48 | -------------------------------------------------------------------------------- /core/database/observer.cpp: -------------------------------------------------------------------------------- 1 | #include "observer.h" 2 | 3 | namespace ChipDB 4 | { 5 | 6 | void Subject::setSubjectID(int id) 7 | { 8 | m_subjectId = id; 9 | } 10 | 11 | void Subject::notify() 12 | { 13 | for(auto &observer : m_observers) 14 | { 15 | observer->update(m_subjectId); 16 | } 17 | 18 | for(auto &cb : m_callbacks) 19 | { 20 | if (cb.second) 21 | { 22 | cb.second(m_subjectId); 23 | } 24 | } 25 | } 26 | 27 | void Subject::addObserver(IObserver *observer) 28 | { 29 | auto iter = std::find(m_observers.begin(), m_observers.end(), observer); 30 | if (iter == m_observers.end()) 31 | { 32 | m_observers.push_back(observer); 33 | } 34 | } 35 | 36 | void Subject::addObserver(const std::string &name, updateCallback cb) 37 | { 38 | m_callbacks[name] = cb; 39 | } 40 | 41 | void Subject::removeObserver(IObserver *observer) 42 | { 43 | auto iter = std::find(m_observers.begin(), m_observers.end(), observer); 44 | if (iter != m_observers.end()) 45 | { 46 | m_observers.erase(iter); 47 | } 48 | } 49 | 50 | void Subject::removeObserver(const std::string &name) 51 | { 52 | m_callbacks.erase(name); 53 | } 54 | 55 | }; 56 | -------------------------------------------------------------------------------- /test/core/globalroutergridtest.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #include "lunacore.h" 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | BOOST_AUTO_TEST_SUITE(GlobalRouterGridTest) 15 | 16 | BOOST_AUTO_TEST_CASE(check_grid) 17 | { 18 | std::cout << "--== CHECK GLOBAL ROUTER GRID ==--\n"; 19 | 20 | LunaCore::GlobalRouter::Grid grid(20,10,{1,1}); 21 | 22 | BOOST_CHECK(grid.height() == 10); 23 | BOOST_CHECK(grid.width() == 20); 24 | 25 | // check that all cells have reset flags 26 | for(auto const& cell : grid.gcells()) 27 | { 28 | BOOST_CHECK(!cell.isBlocked()); 29 | BOOST_CHECK(!cell.isMarked()); 30 | BOOST_CHECK(!cell.isTarget()); 31 | BOOST_CHECK(!cell.isReached()); 32 | BOOST_CHECK(!cell.isSource()); 33 | BOOST_CHECK(cell.isValid()); 34 | } 35 | 36 | // check that an out-of-bounds cell access 37 | // returns an invalid cell 38 | BOOST_CHECK(!grid.at(-1,-1).isValid()); 39 | } 40 | 41 | 42 | BOOST_AUTO_TEST_SUITE_END() -------------------------------------------------------------------------------- /gui/resources/resources.qrc: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 10 | ./images/add.png 11 | ./images/pinicon.png 12 | ./images/folder.png 13 | ./images/file.png 14 | ./images/folded.png 15 | ./images/remove.png 16 | ./images/unfolded.png 17 | ./images/properties.png 18 | ./images/floorplan.png 19 | ./images/go.png 20 | ./images/status_ok.png 21 | ./images/status_error.png 22 | ./images/status_empty.png 23 | ./images/status_running.png 24 | ./images/lunapnrlogo.png 25 | ./icons/lunapnr128x128.png 26 | ./icons/lunapnr256x256.png 27 | 28 | 29 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /gui/console/mtstringbuffer.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "common/logging.h" 14 | 15 | namespace GUI 16 | { 17 | 18 | /** multi-threaded string buffer 19 | * used by MMConsole to store log messages coming in from other threads. 20 | */ 21 | class MTStringBuffer 22 | { 23 | public: 24 | struct LogString 25 | { 26 | Logging::LogType m_logType{Logging::LogType::INFO}; 27 | std::string m_txt; 28 | }; 29 | 30 | MTStringBuffer(QObject *eventReceiver); 31 | 32 | void print(const std::string &txt); 33 | void print(const std::string_view &txt); 34 | 35 | void print(const Logging::LogType &logType, const std::string &txt); 36 | void print(const Logging::LogType &logType, const std::string_view &txt); 37 | 38 | LogString pop(); 39 | bool containsString(); 40 | 41 | protected: 42 | QObject *m_eventReceiver = nullptr; 43 | std::mutex m_mutex; 44 | 45 | std::list m_buffer; 46 | }; 47 | 48 | }; //namespace -------------------------------------------------------------------------------- /core/globalroute/wavefront.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include "datatypes.h" 10 | 11 | namespace LunaCore::GlobalRouter 12 | { 13 | 14 | struct WavefrontItem 15 | { 16 | Predecessor m_pred{Predecessor::Undefined}; 17 | GCellCoord m_gridpos; 18 | PathCostType m_pathCost{0}; 19 | }; 20 | 21 | class Wavefront 22 | { 23 | public: 24 | using iterator_type = std::vector::iterator; 25 | 26 | const WavefrontItem& getLowestCostItem() const; 27 | 28 | bool empty() const {return m_items.empty(); } 29 | void push(const WavefrontItem &item); 30 | void pop() {m_items.pop(); } 31 | void clear(); 32 | 33 | protected: 34 | 35 | struct WavefrontItemCompare 36 | { 37 | constexpr bool operator()(const WavefrontItem &left, const WavefrontItem &right) const 38 | { 39 | return left.m_pathCost > right.m_pathCost; 40 | } 41 | }; 42 | 43 | using PQueueType = std::priority_queue, WavefrontItemCompare>; 44 | 45 | PQueueType m_items; 46 | }; 47 | 48 | }; -------------------------------------------------------------------------------- /core/database/netlist.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include "visitor.h" 12 | #include "namedstorage.h" 13 | #include "net.h" 14 | #include "instance.h" 15 | 16 | namespace ChipDB 17 | { 18 | 19 | class Netlist 20 | { 21 | public: 22 | Netlist() = default; 23 | 24 | void clear(); 25 | 26 | IMPLEMENT_ACCEPT; 27 | 28 | NamedStorage m_instances; 29 | NamedStorage m_nets; 30 | 31 | std::shared_ptr lookupInstance(InstanceObjectKey key); 32 | KeyObjPair lookupInstance(const std::string &name); 33 | 34 | std::shared_ptr lookupNet(InstanceObjectKey key); 35 | KeyObjPair lookupNet(const std::string &name); 36 | 37 | KeyObjPair createNet(const std::string &netName); 38 | 39 | bool connect(const std::string &insName, const std::string &pinName, const std::string &netName); 40 | bool connect(InstanceObjectKey insKey, PinObjectKey pinKey, NetObjectKey netKey); 41 | 42 | std::size_t createUniqueID(); 43 | 44 | protected: 45 | std::size_t m_uniqueCounter{0}; 46 | }; 47 | 48 | }; // namespace -------------------------------------------------------------------------------- /gui/widgets/flatimage.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #include 6 | #include 7 | #include "flatimage.h" 8 | 9 | using namespace GUI; 10 | 11 | FlatImage::FlatImage(const QString &pixmapUrl, QWidget *parent) : QWidget(parent) 12 | { 13 | setPixmap(pixmapUrl); 14 | } 15 | 16 | FlatImage::FlatImage(QWidget *parent) 17 | : QWidget(parent) 18 | { 19 | setMinimumSize(QSize(24,24)); 20 | } 21 | 22 | void FlatImage::setPixmap(const QString &pixmapUrl) 23 | { 24 | m_pixmap = std::make_unique(pixmapUrl); 25 | if (m_pixmap && (!m_pixmap->isNull())) 26 | { 27 | setMinimumSize(m_pixmap->size()); 28 | } 29 | else 30 | { 31 | setMinimumSize(QSize(24,24)); 32 | } 33 | } 34 | 35 | void FlatImage::paintEvent(QPaintEvent *event) 36 | { 37 | QPainter painter(this); 38 | 39 | if ((m_pixmap) && (!m_pixmap->isNull())) 40 | painter.drawPixmap(0,0, *m_pixmap); 41 | } 42 | 43 | QSize FlatImage::sizeHint() const 44 | { 45 | if (!m_pixmap) return minimumSize(); 46 | 47 | if (!m_pixmap->isNull()) 48 | { 49 | return m_pixmap->size(); 50 | } 51 | 52 | return minimumSize(); 53 | } 54 | -------------------------------------------------------------------------------- /test/files/get_cells.bat: -------------------------------------------------------------------------------- 1 | REM SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | REM 3 | REM SPDX-License-Identifier: GPL-3.0-only 4 | 5 | wget -nc https://vlsiarch.ecen.okstate.edu/flows/MOSIS_SCMOS/iit_stdcells_v2.3beta/iitcells_lib_2.3.tar.gz 6 | tar -xzf iitcells_lib_2.3.tar.gz 7 | rem ./clean_cells.sh 8 | 9 | mkdir -p nangate 10 | wget -nc https://raw.githubusercontent.com/JulianKemmerer/Drexel-ECEC575/master/Encounter/NangateOpenCellLibrary/Low_Power/Front_End/Liberty/LowPowerOpenCellLibrary_functional.lib -O nangate/lpocl_functional.lib 11 | wget -nc https://raw.githubusercontent.com/JulianKemmerer/Drexel-ECEC575/master/Encounter/NangateOpenCellLibrary/Front_End/Liberty/NangateOpenCellLibrary_functional.lib -O nangate/ocl_functional.lib 12 | wget -nc https://raw.githubusercontent.com/JulianKemmerer/Drexel-ECEC575/master/Encounter/NangateOpenCellLibrary/Back_End/lef/NangateOpenCellLibrary.lef -O nangate/ocl.lef 13 | wget -nc https://github.com/JulianKemmerer/Drexel-ECEC575/raw/master/Encounter/NangateOpenCellLibrary/Back_End/gds/NangateOpenCellLibrary.gds -O nangate/ocl.gds 14 | wget -nc https://raw.githubusercontent.com/JulianKemmerer/Drexel-ECEC575/master/Encounter/NangateOpenCellLibrary/Back_End/lef/NangateOpenCellLibrary.tech.lef -O nangate/ocl.tech.lef 15 | 16 | Exit 0 -------------------------------------------------------------------------------- /gui/common/tasklist.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | 15 | #include "database.h" 16 | #include "tasks/tasks.h" 17 | 18 | namespace GUI 19 | { 20 | 21 | class TaskList 22 | { 23 | public: 24 | TaskList(QObject *projectManager); 25 | virtual ~TaskList(); 26 | 27 | size_t numberOfTasks() const noexcept 28 | { 29 | return m_tasks.size(); 30 | } 31 | 32 | const Tasks::Task* at(size_t index) const 33 | { 34 | return m_tasks.at(index).get(); 35 | } 36 | 37 | bool executeToTask(Database &db, const std::string &taskName); 38 | 39 | protected: 40 | void createTask(const std::string &taskName, Tasks::Task *task); 41 | 42 | QObject *m_projectManager = nullptr; 43 | 44 | std::vector > m_tasks; 45 | 46 | using TaskName = std::string; 47 | std::map m_nameToIndex; 48 | 49 | void taskThread(Database &db, size_t firstTask, size_t lastTask, QObject *projectManager); 50 | std::unique_ptr m_thread; 51 | }; 52 | 53 | }; 54 | -------------------------------------------------------------------------------- /test/core/spefwritertest.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #include "lunacore.h" 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | BOOST_AUTO_TEST_SUITE(SPEFWriterTest) 15 | 16 | 17 | BOOST_AUTO_TEST_CASE(can_write_spef) 18 | { 19 | std::cout << "--== SPEF WRITER ==--\n"; 20 | 21 | std::ifstream leffile("test/files/iit_stdcells/lib/tsmc018/lib/iit018_stdcells.lef"); 22 | BOOST_REQUIRE(leffile.good()); 23 | 24 | ChipDB::Design design; 25 | BOOST_REQUIRE(ChipDB::LEF::Reader::load(design, leffile)); 26 | 27 | std::ifstream verilogfile("test/files/verilog/adder2.v"); 28 | BOOST_REQUIRE(verilogfile.good()); 29 | 30 | BOOST_REQUIRE(ChipDB::Verilog::Reader::load(design, verilogfile)); 31 | 32 | // check the design 33 | BOOST_REQUIRE(design.m_moduleLib->size() == 1); 34 | BOOST_REQUIRE(design.m_moduleLib->lookupModule("adder2").isValid()); 35 | 36 | auto mod = design.m_moduleLib->lookupModule("adder2"); 37 | 38 | BOOST_CHECK(LunaCore::SPEF::write("test/files/results/adders2.spef", mod.ptr())); 39 | } 40 | 41 | BOOST_AUTO_TEST_SUITE_END() 42 | -------------------------------------------------------------------------------- /core/include/lunacore.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include "../common/common.h" 8 | #include "../import/import.h" 9 | #include "../database/database.h" 10 | 11 | #include "../cellplacer/cellplacer.h" 12 | //#include "../cellplacer/qplacer.h" 13 | #include "../cellplacer/qlaplacer.h" 14 | //#include "../cellplacer/densitybitmap.h" 15 | #include "../cellplacer/netlistsplitter.h" 16 | #include "../cellplacer/rowlegalizer.h" 17 | #include "../cellplacer2/cellplacer2.h" 18 | #include "../cellplacer2/fillerhandler.h" 19 | #include "../partitioner/fmpart.h" 20 | 21 | #include "../export/svg/svgwriter.h" 22 | #include "../export/dot/dotwriter.h" 23 | #include "../export/verilog/verilogwriter.h" 24 | #include "../export/def/defwriter.h" 25 | #include "../export/txt/txtwriter.h" 26 | #include "../export/ppm/ppmwriter.h" 27 | #include "../export/spef/spefwriter.h" 28 | #include "../cts/cts.h" 29 | #include "../globalroute/globalrouter.h" 30 | #include "../globalroute/prim.h" 31 | #include "../globalroute/lshape.h" 32 | 33 | #include "../passes/passes.hpp" 34 | #include "../padring/padring.hpp" 35 | #include "../padring/padringplacer.hpp" 36 | 37 | #ifdef USE_PYTHON 38 | #include "../python/pylunapnr.h" 39 | #endif 40 | -------------------------------------------------------------------------------- /gui/widgets/colorbutton.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #include "colorbutton.h" 6 | #include 7 | #include 8 | 9 | using namespace GUI; 10 | 11 | SelectColorButton::SelectColorButton(QWidget *parent) : m_color(Qt::white) 12 | { 13 | setFixedSize(QSize{80,80}); 14 | connect(this, SIGNAL(clicked()), this, SLOT(changeColor())); 15 | } 16 | 17 | void SelectColorButton::changeColor() 18 | { 19 | QColor newColor = QColorDialog::getColor(m_color, parentWidget(), 20 | tr("Select color"), QColorDialog::ShowAlphaChannel | QColorDialog::DontUseNativeDialog); 21 | if (newColor.isValid() && (newColor != m_color)) 22 | { 23 | setColor(newColor); 24 | emit onColorChanged(); 25 | } 26 | } 27 | 28 | void SelectColorButton::setColor(const QColor &color) 29 | { 30 | m_color = color; 31 | update(); 32 | } 33 | 34 | QColor SelectColorButton::getColor() const 35 | { 36 | return m_color; 37 | } 38 | 39 | void SelectColorButton::paintEvent(QPaintEvent *event) 40 | { 41 | QPainter painter(this); 42 | 43 | auto r = rect().adjusted(2,2,-2,-2); 44 | 45 | painter.setPen(Qt::black); 46 | painter.setBrush(m_color); 47 | painter.drawRect(r); 48 | } 49 | -------------------------------------------------------------------------------- /core/database/net.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #include 6 | #include "net.h" 7 | 8 | using namespace ChipDB; 9 | 10 | bool Net::hasConnection(InstanceObjectKey insKey, PinObjectKey pinKey) const 11 | { 12 | const NetConnect connection(insKey, pinKey); 13 | 14 | auto iter = std::find_if(m_connections.begin(), m_connections.end(), 15 | [connection](auto const& listConn) 16 | { 17 | return listConn == connection; 18 | } 19 | ); 20 | 21 | return (iter != m_connections.end()); 22 | } 23 | 24 | void Net::addConnection(InstanceObjectKey insKey, PinObjectKey pinKey) 25 | { 26 | m_connections.emplace_back(NetConnect(insKey, pinKey)); 27 | } 28 | 29 | bool Net::removeConnection(InstanceObjectKey insKey, PinObjectKey pinKey) 30 | { 31 | const NetConnect connection(insKey, pinKey); 32 | 33 | auto iter = std::find_if(m_connections.begin(), m_connections.end(), 34 | [connection](auto const& listConn) 35 | { 36 | return listConn == connection; 37 | } 38 | ); 39 | 40 | if (iter != m_connections.end()) 41 | { 42 | m_connections.erase(iter); 43 | return true; 44 | } 45 | 46 | return false; 47 | } 48 | 49 | -------------------------------------------------------------------------------- /gui/tasks/tasks.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #include 6 | #include "tasks.h" 7 | #include "common/logging.h" 8 | 9 | using namespace Tasks; 10 | 11 | Task::Task() 12 | { 13 | } 14 | 15 | void Task::setName(const std::string &taskName) 16 | { 17 | m_name = taskName; 18 | } 19 | 20 | bool Task::run(GUI::Database &db, ProgressCallback callback) 21 | { 22 | execute(db, callback); 23 | return m_status.load() == Status::DONE_OK; 24 | } 25 | 26 | void Task::error(const std::string_view fmt, ...) 27 | { 28 | std::va_list args; 29 | va_start(args, fmt); 30 | Logging::logError(fmt, args); 31 | va_end(args); 32 | 33 | m_status.store(Status::DONE_ERROR); 34 | } 35 | 36 | void Task::warning(const std::string_view fmt, ...) 37 | { 38 | std::va_list args; 39 | va_start(args, fmt); 40 | Logging::logWarning(fmt, args); 41 | va_end(args); 42 | } 43 | 44 | void Task::info(const std::string_view fmt, ...) 45 | { 46 | std::va_list args; 47 | va_start(args, fmt); 48 | Logging::logInfo(fmt, args); 49 | va_end(args); 50 | } 51 | 52 | void Task::done() 53 | { 54 | m_status.store(Status::DONE_OK); 55 | } 56 | 57 | void Task::reset() 58 | { 59 | m_status.store(Status::RESET); 60 | } 61 | -------------------------------------------------------------------------------- /core/export/dot/dotwriter.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | 6 | #pragma once 7 | 8 | #include 9 | #include 10 | #include "database/database.h" 11 | 12 | namespace LunaCore::Dot 13 | { 14 | 15 | class AbstractNodeDecorator 16 | { 17 | public: 18 | virtual void decorate(const std::shared_ptr ins, std::ostream &os) = 0; 19 | }; 20 | 21 | /** Writer writes module netlist in Graphviz DOT format */ 22 | class Writer 23 | { 24 | public: 25 | static bool write(std::ostream &os, const std::shared_ptr module, 26 | AbstractNodeDecorator *decorator = nullptr); 27 | 28 | static bool write(std::ostream &os, const std::shared_ptr modInstance, 29 | AbstractNodeDecorator *decorator = nullptr); 30 | 31 | protected: 32 | Writer(const std::shared_ptr module); 33 | 34 | bool execute(std::ostream &os, AbstractNodeDecorator *decorator); 35 | 36 | void writeInputs(std::ostream &os, const std::shared_ptr ins); 37 | void writeOutputs(std::ostream &os, const std::shared_ptr ins); 38 | std::string escapeString(const std::string &txt); 39 | 40 | const std::shared_ptr m_module; 41 | }; 42 | 43 | }; // namespace -------------------------------------------------------------------------------- /gui/designbrowser/designbrowser.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "../common/database.h" 18 | #include "../models/modulemodel.h" 19 | #include "../models/moduleinfomodel.h" 20 | 21 | namespace GUI 22 | { 23 | 24 | class DesignBrowser : public QWidget 25 | { 26 | Q_OBJECT 27 | 28 | public: 29 | explicit DesignBrowser(QWidget *parent = nullptr); 30 | virtual ~DesignBrowser(); 31 | 32 | void setDatabase(std::shared_ptr db); 33 | void refreshDatabase(); 34 | 35 | QSize sizeHint() const; 36 | 37 | public slots: 38 | void onModuleSelectionChanged(const QItemSelection &cur, const QItemSelection &prev); 39 | 40 | protected: 41 | std::unique_ptr m_moduleModel; 42 | std::unique_ptr m_moduleInfoModel; 43 | 44 | QHBoxLayout *m_layout; 45 | QVBoxLayout *m_layout2; 46 | QTableView *m_moduleTableView; 47 | QTreeView *m_moduleTreeView; 48 | 49 | std::shared_ptr m_db; 50 | }; 51 | 52 | }; // namespace -------------------------------------------------------------------------------- /examples/osu180pdk.toml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | # SPDX-License-Identifier: GPL-3.0-only 3 | # 4 | # OSU180 PDK for LunaPnR 5 | 6 | title = "OSU 180nm" # title/name the user sees. 7 | name = "OSU180_v2.4" # name used to reference the PDK internally. 8 | version = "v2.4" # version the user sees. 9 | installdir = "osu180_v2_4" # installation dir, must be a relative path. 10 | date = "05-09-2023" 11 | copyright = "OSU" 12 | description = "Generic 180nm CMOS cell library" 13 | icon = "https://brand.okstate.edu/site-files/images/brand-guide/primary-brand.png" 14 | 15 | # source locations for the LEF/DEF/Layer etc files. 16 | url = [ 17 | ["https://vlsiarch.ecen.okstate.edu/flows/MOSIS_SCMOS/osu_stdcells_v2.4/osu_stdcells_lib.v2.4.tar.gz", "osu_stdcells_lib.v2.4.tar.gz"], 18 | ] 19 | 20 | # archive extraction instructions, if any. 21 | # the second argument is the archive type 22 | # "tgz", "zip", "bz2", "xz" 23 | extract = [ 24 | ["osu_stdcells_lib.v2.4.tar.gz", "tgz"] 25 | ] 26 | 27 | # lef files, technology LEF *must* go first 28 | lef = [ 29 | "osu_stdcells/lib/tsmc018/lib/osu018_stdcells.lib" 30 | ] 31 | 32 | # liberty files 33 | lib = [ 34 | "osu_stdcells/lib/tsmc018/signalstorm/osu018_stdcells.lib" 35 | ] 36 | 37 | # layer file for the colours and hatch patterns 38 | layerfile = "osu180.layers" 39 | -------------------------------------------------------------------------------- /core/cellplacer2/fillerhandler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include "database/database.h" 6 | 7 | namespace LunaCore 8 | { 9 | 10 | class FillerHandler 11 | { 12 | public: 13 | FillerHandler(const ChipDB::CellLib &cellLib); 14 | 15 | std::size_t numberOfFillers() const 16 | { 17 | return m_fillers.size(); 18 | } 19 | 20 | bool addFillerByName(const ChipDB::CellLib &cellLib, const std::string &fillerName); 21 | 22 | bool placeFillers(ChipDB::Design &design, const ChipDB::Region ®ion, ChipDB::Netlist &netlist); 23 | 24 | protected: 25 | 26 | void identifyFillers(const ChipDB::CellLib &cellLib); 27 | 28 | void sortFillers(); 29 | 30 | [[nodiscard]] bool isFillerAlreadyInList(const std::string &name) const; 31 | 32 | [[nodiscard]] bool fillSpaceWithFillers(const ChipDB::Design &design, 33 | ChipDB::Netlist &netlist, 34 | const ChipDB::Coord64 &lowerLeftPos, 35 | const ChipDB::CoordType width); 36 | 37 | struct FillerInfo 38 | { 39 | std::string m_name; ///< name of filler cell 40 | ChipDB::ObjectKey m_cellKey; ///< filler cell key in celllib 41 | ChipDB::Coord64 m_size; ///< size of filler cell 42 | }; 43 | 44 | std::vector m_fillers; ///< fillers sorted by width 45 | std::size_t m_fillerID{0}; 46 | }; 47 | 48 | }; -------------------------------------------------------------------------------- /gui/projectmanager/filesetupmanager.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "../models/filesetupmodel.h" 13 | 14 | namespace GUI 15 | { 16 | class FileSetupManager : public QTreeView 17 | { 18 | Q_OBJECT 19 | public: 20 | FileSetupManager(QWidget *parent = nullptr); 21 | 22 | /** add a file category with a single file extension */ 23 | void addCategory(const QString &name, const QString &fileExt, 24 | std::vector *data); 25 | 26 | /** add a file category with multiple file extensions */ 27 | void addCategory(const QString &name, const QStringList &fileExt, 28 | std::vector *data); 29 | 30 | void addCategoryItem(size_t categoryIndex, const QString &name); 31 | 32 | void repopulate(); 33 | 34 | protected: 35 | FileSetupModel m_model; 36 | void onContextMenuRequested(const QPoint &point); 37 | void onAddResource(); 38 | void onRemoveResource(); 39 | 40 | QModelIndex m_itemModelIndex; 41 | 42 | QAction *m_addResourceAction; 43 | QAction *m_removeResourceAction; 44 | 45 | QMenu *m_categoryContextMenu; 46 | QMenu *m_itemContextMenu; 47 | }; 48 | 49 | }; 50 | -------------------------------------------------------------------------------- /core/common/fileutils.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | namespace LunaCore 12 | { 13 | /** replace {envvar} with its expansion */ 14 | std::string expandEnvironmentVars(const std::string &path); 15 | 16 | bool setEnvironmentVar(const std::string &key, const std::string &value); 17 | bool unsetEnvironmentVar(const std::string &key); 18 | std::string getEnvironmentVar(const std::string &key); 19 | 20 | struct TempFileDescriptor 21 | { 22 | virtual ~TempFileDescriptor(); 23 | std::string m_name; 24 | std::ofstream m_stream; 25 | 26 | bool good() const 27 | { 28 | return m_stream.good(); 29 | } 30 | 31 | void close() 32 | { 33 | if (m_stream.is_open()) m_stream.close(); 34 | } 35 | }; 36 | 37 | bool deleteFile(const std::string &filename) noexcept; 38 | bool renameFile(const std::string &oldName, const std::string &newName) noexcept; 39 | bool copyFile(const std::string &srcName, const std::string ©Name) noexcept; 40 | bool fileExists(const std::string &filename) noexcept; 41 | std::unique_ptr createTempFile(const std::string &extension); 42 | 43 | }; 44 | -------------------------------------------------------------------------------- /core/common/logging.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #ifdef __GNUC__ 12 | #include 13 | #define BREAK_HERE raise(SIGINT) 14 | #endif 15 | 16 | namespace Logging 17 | { 18 | 19 | enum class LogType : uint8_t 20 | { 21 | VERBOSE = 1, 22 | DEBUG = 2, 23 | INFO = 3, 24 | WARNING = 4, 25 | ERROR = 8, 26 | PRINT = 100 27 | }; 28 | 29 | /** subclass LogOutputHandler to provide your own output processing 30 | * you must provide multi-threading support yourself. 31 | */ 32 | struct LogOutputHandler 33 | { 34 | virtual void print(LogType level, const std::string &txt) = 0; 35 | virtual void print(LogType level, const std::string_view &txt) = 0; 36 | }; 37 | 38 | /** set the log level ... */ 39 | void setLogLevel(LogType level); 40 | 41 | /** get the log level ... */ 42 | LogType getLogLevel(); 43 | 44 | /** set new log output handler */ 45 | void setOutputHandler(LogOutputHandler *handler); 46 | 47 | void logError(std::string_view fmt, ...); 48 | void logWarning(std::string_view fmt, ...); 49 | void logVerbose(std::string_view fmt, ...); 50 | void logDebug(std::string_view fmt, ...); 51 | void logPrint(std::string_view fmt, ...); 52 | void logInfo(std::string_view fmt, ...); 53 | 54 | }; 55 | -------------------------------------------------------------------------------- /gui/common/database.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include "lunacore.h" 8 | #include "layerrenderinfo.h" 9 | #include "hatchlibrary.h" 10 | #include "projectsetup.h" 11 | 12 | namespace GUI 13 | { 14 | 15 | class Database 16 | { 17 | public: 18 | Database() {} 19 | 20 | /** clear the entire database */ 21 | void clear(); 22 | 23 | const ChipDB::Design& design() const 24 | { 25 | return m_coreDatabase.m_design; 26 | } 27 | 28 | ChipDB::Design& design() 29 | { 30 | return m_coreDatabase.m_design; 31 | } 32 | 33 | std::shared_ptr cellLib() const 34 | { 35 | return m_coreDatabase.m_design.m_cellLib; 36 | } 37 | 38 | std::shared_ptr techLib() const 39 | { 40 | return m_coreDatabase.m_design.m_techLib; 41 | } 42 | 43 | std::shared_ptr moduleLib() const 44 | { 45 | return m_coreDatabase.m_design.m_moduleLib; 46 | } 47 | 48 | std::shared_ptr floorplan() const 49 | { 50 | return m_coreDatabase.m_design.m_floorplan; 51 | } 52 | 53 | LunaCore::Database m_coreDatabase; 54 | LayerRenderInfoDB m_layerRenderInfoDB; 55 | HatchLibrary m_hatchLib; 56 | ProjectSetup m_projectSetup; 57 | }; 58 | 59 | }; -------------------------------------------------------------------------------- /scripts/place_femtorv32.py: -------------------------------------------------------------------------------- 1 | 2 | createRegion("core", 10000, 10000, 800000, 500000) 3 | createRows("core", 0, 10000, 60) 4 | print("Floorplan and rows created") 5 | 6 | loadVerilog("test/files/verilog/femtorv32_quark.v") 7 | 8 | setTopModule("FemtoRV32") 9 | 10 | xTopPos = 10000 11 | xTopInc = 10000 12 | 13 | xBottomPos = 10000 14 | xBottomInc = 15000 15 | 16 | yTop = 510000 17 | yBottom = 10000 18 | 19 | def placePinAtTop(pinName): 20 | global xTopPos 21 | placeInstance(pinName, "FemtoRV32", xTopPos, yTop) 22 | xTopPos = xTopPos + xTopInc 23 | 24 | def placePinAtBottom(pinName): 25 | global xBottomPos 26 | placeInstance(pinName, "FemtoRV32", xBottomPos, yBottom) 27 | xBottomPos = xBottomPos + xBottomInc 28 | 29 | placePinAtTop("clk") 30 | placePinAtTop("reset") 31 | for num in range(0,32): 32 | placePinAtTop("mem_addr[" + str(num) + "]") 33 | 34 | for num in range(0,32): 35 | placePinAtTop("mem_wdata[" + str(num) + "]") 36 | 37 | placePinAtBottom("mem_wmask[0]") 38 | placePinAtBottom("mem_wmask[1]") 39 | placePinAtBottom("mem_wmask[2]") 40 | placePinAtBottom("mem_wmask[3]") 41 | placePinAtBottom("mem_wbusy") 42 | 43 | for num in range(0,32): 44 | placePinAtBottom("mem_rdata[" + str(num) + "]") 45 | 46 | placePinAtBottom("mem_rstrb") 47 | placePinAtBottom("mem_rbusy") 48 | 49 | # place the instances in the top level module 50 | placeModule("FemtoRV32", "core") 51 | 52 | #write_density_bitmap("FemtoRV32", "core", "bitmap.pgm") 53 | -------------------------------------------------------------------------------- /gui/widgets/hatchdialog.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #include 6 | #include 7 | #include "hatchdialog.h" 8 | #include "hatchdisplay.h" 9 | #include "../common/logging.h" 10 | 11 | using namespace GUI; 12 | 13 | HatchDialog::HatchDialog(HatchLibrary &hatchLibrary, QWidget *parent, Qt::WindowFlags f) 14 | : QDialog(parent, f), m_hatchIndex(-1) 15 | { 16 | auto topLayout = new QVBoxLayout(); 17 | 18 | auto display = new HatchDisplay(hatchLibrary, this); 19 | topLayout->addWidget(display, 1); 20 | 21 | auto buttonLayout = new QHBoxLayout(); 22 | 23 | auto okButton = new QPushButton(tr("Ok")); 24 | auto cancelButton = new QPushButton(tr("Cancel")); 25 | 26 | buttonLayout->addWidget(cancelButton, 0); 27 | buttonLayout->addWidget(okButton, 0); 28 | 29 | topLayout->addLayout(buttonLayout); 30 | 31 | connect(okButton, SIGNAL(clicked()), this, SLOT(accept()) ); 32 | connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject()) ); 33 | connect(display, SIGNAL(clicked(int)), this, SLOT(onHatchClicked(int))); 34 | 35 | setLayout(topLayout); 36 | setWindowTitle(tr("Choose new layer hatch pattern")); 37 | } 38 | 39 | 40 | void HatchDialog::onHatchClicked(int index) 41 | { 42 | m_hatchIndex = index; 43 | Logging::logVerbose("onHatchClicked index = %d\n", index); 44 | accept(); 45 | } 46 | -------------------------------------------------------------------------------- /core/database/design.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include 8 | #include "properties.hpp" 9 | #include "floorplan.h" 10 | #include "netlist.h" 11 | #include "techlib.h" 12 | #include "celllib.h" 13 | 14 | namespace ChipDB 15 | { 16 | 17 | class Design 18 | { 19 | public: 20 | Design(); 21 | 22 | /** clear netlist, celllib, modules and technology information */ 23 | void clear(); 24 | 25 | std::shared_ptr m_cellLib; 26 | std::shared_ptr m_moduleLib; 27 | std::shared_ptr m_techLib; 28 | std::shared_ptr m_floorplan; 29 | 30 | auto createUniqueID() 31 | { 32 | return m_uniqueIDCounter++; 33 | } 34 | 35 | bool setTopModule(const std::string &moduleName); 36 | 37 | std::shared_ptr getTopModule() 38 | { 39 | return m_topModule; 40 | } 41 | 42 | std::shared_ptr getTopModule() const 43 | { 44 | return m_topModule; 45 | } 46 | 47 | auto& properties() noexcept 48 | { 49 | return m_properties; 50 | } 51 | 52 | auto const& properties() const noexcept 53 | { 54 | return m_properties; 55 | } 56 | 57 | protected: 58 | std::shared_ptr m_topModule; 59 | uint32_t m_uniqueIDCounter{0}; 60 | 61 | Properties m_properties; 62 | }; 63 | 64 | }; 65 | -------------------------------------------------------------------------------- /gui/widgets/flattilebase.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "flatimage.h" 13 | 14 | namespace GUI 15 | { 16 | 17 | class FlatTileBase : public QFrame 18 | { 19 | Q_OBJECT 20 | public: 21 | FlatTileBase(const QString &text, const QString &iconUrl, 22 | const QString &actionName, QWidget *parent = nullptr); 23 | 24 | virtual ~FlatTileBase() = default; 25 | 26 | [[nodiscard]] QString text() const noexcept; 27 | void setText(const QString &text) noexcept; 28 | 29 | void setIcon(const QString &iconUrl) noexcept; 30 | 31 | enum class Status 32 | { 33 | NONE, 34 | RUNNING, 35 | OK, 36 | ERROR 37 | }; 38 | 39 | void setStatus(Status s) noexcept; 40 | 41 | /** get action name -- used for action events */ 42 | QString actionName() const; 43 | 44 | /** set action name -- used for action events */ 45 | void setActionName(const QString &actionName); 46 | 47 | protected: 48 | QLabel *m_textLabel = nullptr; 49 | QString m_actionName; 50 | FlatImage *m_statusIndicator = nullptr; 51 | FlatImage *m_icon = nullptr; 52 | QHBoxLayout *m_hlayout = nullptr; 53 | Status m_status{Status::NONE}; 54 | }; 55 | 56 | using FlatStatusTile = FlatTileBase; 57 | 58 | }; 59 | -------------------------------------------------------------------------------- /core/database/floorplan.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #include "floorplan.h" 6 | 7 | using namespace ChipDB; 8 | 9 | void Floorplan::clear() 10 | { 11 | m_coreSize = Size64(); 12 | m_io2coreMargins = Margins64(); 13 | m_ioMargins = Margins64(); 14 | } 15 | 16 | Rect64 Floorplan::coreRect() const noexcept 17 | { 18 | Rect64 core; 19 | core.setLL( 20 | Coord64( 21 | m_io2coreMargins.left() + 22 | m_ioMargins.left(), 23 | m_io2coreMargins.bottom() + 24 | m_ioMargins.bottom() 25 | ) 26 | ); 27 | 28 | core.setSize(m_coreSize); 29 | return core; 30 | } 31 | 32 | Size64 Floorplan::dieSize() const noexcept 33 | { 34 | // calculate the die size 35 | auto width = m_coreSize.m_x + 36 | m_io2coreMargins.left() + 37 | m_io2coreMargins.right() + 38 | m_ioMargins.left() + 39 | m_ioMargins.right(); 40 | 41 | auto height = m_coreSize.m_y + 42 | m_io2coreMargins.top() + 43 | m_io2coreMargins.bottom() + 44 | m_ioMargins.top() + 45 | m_ioMargins.bottom(); 46 | 47 | return Size64(width, height); 48 | } 49 | 50 | void Floorplan::addListener(INamedStorageListener *listener) 51 | { 52 | 53 | } 54 | 55 | void Floorplan::removeListener(INamedStorageListener *listener) 56 | { 57 | 58 | } 59 | 60 | void Floorplan::contentsChanged() const 61 | { 62 | 63 | } 64 | -------------------------------------------------------------------------------- /test/core/techlibtest.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #include "lunacore.h" 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | BOOST_AUTO_TEST_SUITE(TechlibTest) 15 | 16 | BOOST_AUTO_TEST_CASE(various_tech_tests) 17 | { 18 | std::cout << "--== TECHLIB TEST ==--\n"; 19 | 20 | std::ifstream leffile("test/files/iit_stdcells/lib/tsmc018/lib/iit018_stdcells.lef"); 21 | BOOST_CHECK(leffile.good()); 22 | 23 | ChipDB::Design design; 24 | BOOST_CHECK(ChipDB::LEF::Reader::load(design, leffile)); 25 | 26 | auto techlib = design.m_techLib; 27 | 28 | BOOST_CHECK(techlib->getNumberOfLayers() > 0); 29 | 30 | // iterate over layers 31 | std::cout << "Iterating over layers:\n"; 32 | 33 | auto iter = techlib->layers().begin(); 34 | while(iter != techlib->layers().end()) 35 | { 36 | std::cout << " Layer: " << iter->name() << "\n"; 37 | iter++; 38 | } 39 | 40 | BOOST_CHECK(techlib->getNumberOfSites() > 0); 41 | 42 | // iterate over sites 43 | std::cout << "Iterating over sites:\n"; 44 | auto iter2 = techlib->sites().begin(); 45 | while(iter2 != techlib->sites().end()) 46 | { 47 | std::cout << " Site: " << iter2->name() << "\n"; 48 | iter2++; 49 | } 50 | } 51 | 52 | BOOST_AUTO_TEST_SUITE_END() 53 | -------------------------------------------------------------------------------- /test/files/padring/padring.conf: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | # 3 | # SPDX-License-Identifier: GPL-3.0-only 4 | # 5 | # LunaPnR padring configuration file 6 | 7 | # set the default PAD orientation to N for this technology 8 | 9 | DEFAULTORIENTATION N ; 10 | 11 | # Place the corners 12 | # CORNER ; 13 | 14 | CORNER c_ul NE ; 15 | CORNER c_ur NW ; 16 | CORNER c_ll SE ; 17 | CORNER c_lr SW ; 18 | 19 | # Define the north edge of the pad ring 20 | # PAD [FLIP] ; 21 | # 22 | # SPACE : use fixed space between preceding and succeeding cell. 23 | # 24 | 25 | # north side is occupied by an 8-bit bus control interface 26 | PAD GPIO[0] N ; 27 | PAD GPIO[1] N ; 28 | PAD GPIO[2] N ; 29 | PAD GPIO[3] N ; 30 | PAD GPIO[4] N ; 31 | PAD GPIO[5] N ; 32 | PAD GPIO[6] N ; 33 | PAD GPIO[7] N ; 34 | 35 | # Define the south edge of the pad ring 36 | # which has the clock, reset, SPI and UART 37 | 38 | PAD CLK S ; 39 | PAD RESET S ; 40 | PAD MISO S ; 41 | PAD MOSI S ; 42 | PAD SCK S ; 43 | PAD SPI_CS_N S ; 44 | PAD UART_TX S ; 45 | PAD UART_RX S ; 46 | 47 | # Define the east edge of the pad ring 48 | # Power and some PWM pins 49 | 50 | PAD PWM_1 E ; 51 | PAD PWM_2 E ; 52 | PAD VDD_1 E ; 53 | PAD GND_1 E ; 54 | PAD PWM_3 E ; 55 | PAD PWM_4 E ; 56 | 57 | # Define the west edge of the pad ring 58 | # DAC outputs and power. 59 | PAD DAC_0 W ; 60 | PAD DAC_1 W ; 61 | PAD VDD_2 W ; 62 | PAD GND_2 W ; 63 | PAD DAC_2 W ; 64 | PAD DAC_3 W ; 65 | -------------------------------------------------------------------------------- /gui/widgets/flatimagebutton.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #include 6 | #include 7 | #include "flatimagebutton.h" 8 | 9 | using namespace GUI; 10 | 11 | FlatImageButton::FlatImageButton(const QString &pixmapUrl, QWidget *parent) 12 | { 13 | setPixmap(pixmapUrl); 14 | } 15 | 16 | FlatImageButton::FlatImageButton(QWidget *parent) 17 | : QAbstractButton(parent) 18 | { 19 | setMinimumSize(QSize(24,24)); 20 | } 21 | 22 | void FlatImageButton::setPixmap(const QString &pixmapUrl) 23 | { 24 | m_pixmap = std::make_unique(pixmapUrl); 25 | if (m_pixmap && (!m_pixmap->isNull())) 26 | { 27 | setMinimumSize(m_pixmap->size()); 28 | } 29 | else 30 | { 31 | setMinimumSize(QSize(24,24)); 32 | } 33 | } 34 | 35 | void FlatImageButton::paintEvent(QPaintEvent *event) 36 | { 37 | // make sure we have at least a little stylesheet support.. 38 | QStyleOption opt; 39 | opt.initFrom(this); 40 | 41 | QPainter painter(this); 42 | style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this); 43 | 44 | if ((m_pixmap) && (!m_pixmap->isNull())) 45 | painter.drawPixmap(0,0, *m_pixmap); 46 | } 47 | 48 | QSize FlatImageButton::sizeHint() const 49 | { 50 | if (!m_pixmap) return minimumSize(); 51 | 52 | if (!m_pixmap->isNull()) 53 | { 54 | return m_pixmap->size(); 55 | } 56 | 57 | return minimumSize(); 58 | } 59 | -------------------------------------------------------------------------------- /test/core/simplecellplacertest.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #include "lunacore.h" 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | BOOST_AUTO_TEST_SUITE(SimpleCellPlacerTest) 15 | 16 | BOOST_AUTO_TEST_CASE(check_simplecellplacer) 17 | { 18 | std::cout << "--== CHECK SIMPLECELLPLACER ==--\n"; 19 | 20 | std::ifstream leffile("test/files/iit_stdcells/lib/tsmc018/lib/iit018_stdcells.lef"); 21 | BOOST_CHECK(leffile.good()); 22 | 23 | ChipDB::Design design; 24 | BOOST_CHECK(ChipDB::LEF::Reader::load(design, leffile)); 25 | 26 | std::ifstream verilogfile("test/files/verilog/nerv_tsmc018.v"); 27 | BOOST_CHECK(verilogfile.good()); 28 | 29 | ChipDB::Verilog::Reader::load(design, verilogfile); 30 | 31 | auto mod = design.m_moduleLib->lookupModule("nerv"); 32 | BOOST_CHECK(mod.isValid()); 33 | 34 | LunaCore::SimpleCellPlacer::place(mod->m_netlist.get(), ChipDB::Rect64{{0,0},{650000,650000}}, 10000); 35 | 36 | auto hpwl = LunaCore::NetlistTools::calcHPWL(*mod->m_netlist.get()); 37 | BOOST_CHECK(hpwl > 0); 38 | std::cout << " HPWL = " << hpwl << " nm\n"; 39 | 40 | auto area = LunaCore::NetlistTools::calcTotalCellArea(*mod->m_netlist.get()); 41 | BOOST_CHECK(area > 0.0); 42 | std::cout << " Area = " << area << " um²\n"; 43 | }; 44 | 45 | 46 | BOOST_AUTO_TEST_SUITE_END() -------------------------------------------------------------------------------- /core/export/def/defwriter.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | #include "database/database.h" 11 | 12 | namespace LunaCore::DEF 13 | { 14 | struct WriterOptions 15 | { 16 | bool exportFillers{true}; ///< if true, it exports filler cells 17 | bool exportDecap{true}; ///< if true, it exports decap cells 18 | }; 19 | 20 | /** write a module as a DEF file - exports depend on the options. */ 21 | bool write(std::ostream &os, const std::shared_ptr module, 22 | const WriterOptions &options); 23 | 24 | /** write a module as a DEF file - exports everything. */ 25 | bool write(std::ostream &os, const std::shared_ptr module); 26 | }; 27 | 28 | namespace LunaCore::DEF::Private 29 | { 30 | class WriterImpl 31 | { 32 | public: 33 | WriterImpl(std::ostream &os); 34 | virtual ~WriterImpl(); 35 | 36 | ChipDB::Coord64 toDEFCoordinates(const ChipDB::Coord64 &pos) const noexcept; 37 | 38 | bool write(const std::shared_ptr instance); 39 | 40 | size_t m_cellCount = 0; 41 | int64_t m_databaseUnits = 100; /** NOTE: default, actual should come from from LEF file */ 42 | 43 | std::stringstream m_ss; 44 | std::ostream &m_os; 45 | std::string m_designName; 46 | }; 47 | 48 | 49 | 50 | }; 51 | -------------------------------------------------------------------------------- /gui/widgets/hatchbutton.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #include "hatchbutton.h" 6 | #include "../core/common/logging.h" 7 | #include "hatchdialog.h" 8 | #include 9 | #include 10 | 11 | using namespace GUI; 12 | 13 | SelectHatchButton::SelectHatchButton(QWidget *parent) 14 | { 15 | setFixedSize(QSize{80,80}); 16 | } 17 | 18 | #if 0 19 | void SelectHatchButton::changeHatch() 20 | { 21 | HatchLibrary hatchLib; 22 | HatchDialog dialog(hatchLib, this); 23 | 24 | auto retval = dialog.exec(); 25 | if (retval == QDialog::Accepted) 26 | { 27 | auto index = dialog.getHatchIndex(); 28 | if (index >= 0) 29 | { 30 | setHatch(hatchLib.m_hatches.at(index)); 31 | emit onHatchChanged(); 32 | } 33 | } 34 | } 35 | #endif 36 | 37 | void SelectHatchButton::setHatch(const QPixmap &pixmap) 38 | { 39 | m_pixmap = pixmap; 40 | update(); 41 | } 42 | 43 | QPixmap SelectHatchButton::getHatch() const 44 | { 45 | return m_pixmap; 46 | } 47 | 48 | void SelectHatchButton::paintEvent(QPaintEvent *event) 49 | { 50 | QPainter painter(this); 51 | 52 | auto r = rect().adjusted(2,2,-2,-2); 53 | 54 | painter.setPen(Qt::black); 55 | painter.setBrush(Qt::white); 56 | if (!m_pixmap.isNull()) 57 | { 58 | painter.setBrush(m_pixmap); 59 | } 60 | else 61 | { 62 | painter.setBrush(Qt::black); 63 | } 64 | painter.drawRect(r); 65 | } 66 | -------------------------------------------------------------------------------- /gui/common/customevents.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include "../tasks/tasks.h" 10 | 11 | namespace GUI 12 | { 13 | 14 | class TaskListEvent : public QEvent 15 | { 16 | public: 17 | static constexpr auto EventType = (QEvent::Type)(QEvent::User+1); 18 | 19 | virtual ~TaskListEvent() = default; 20 | 21 | TaskListEvent(QString taskName, Tasks::Task::Status status, size_t taskIndex, int progress = 0) 22 | : QEvent(EventType), m_taskName(taskName), m_taskStatus(status), m_progress(progress) 23 | { 24 | } 25 | 26 | /** return the task status */ 27 | [[nodiscard]] constexpr auto status() const noexcept 28 | { 29 | return m_taskStatus; 30 | } 31 | 32 | /** return the task index */ 33 | [[nodiscard]] constexpr auto index() const noexcept 34 | { 35 | return m_taskIndex; 36 | } 37 | 38 | /** return the progress 0 .. 100 */ 39 | [[nodiscard]] constexpr auto progress() const noexcept 40 | { 41 | return m_progress; 42 | } 43 | 44 | /** return the task name */ 45 | [[nodiscard]] auto const name() const noexcept 46 | { 47 | return m_taskName; 48 | } 49 | 50 | protected: 51 | QString m_taskName; 52 | Tasks::Task::Status m_taskStatus = Tasks::Task::Status::INVALID; 53 | size_t m_taskIndex = 0; ///< index into TaskList array 54 | int m_progress = 0; 55 | }; 56 | 57 | }; 58 | -------------------------------------------------------------------------------- /test/python/main.cpp: -------------------------------------------------------------------------------- 1 | /* LunaPnR Source Code 2 | 3 | SPDX-License-Identifier: GPL-3.0-only 4 | SPDX-FileCopyrightText: 2022,2023 Niels Moseley 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include "lunacore.h" 11 | 12 | int main(int argc, char *argv[]) 13 | { 14 | ChipDB::Design design; 15 | Scripting::Python p(&design); 16 | 17 | p.init(); 18 | 19 | // in case of no arguments, give the user some idea what this is for. 20 | if (argc == 1) 21 | { 22 | std::cout << "--============================================================--\n"; 23 | std::cout << " LunaPnR Python subsystem test program\n"; 24 | std::cout << " Usage: core_python script1.py script2.py ..\n"; 25 | std::cout << "--============================================================--\n\n"; 26 | return EXIT_FAILURE; 27 | } 28 | 29 | // run each script in succession 30 | for(int arg=1; arg 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | #include 7 | #include "database/database.h" 8 | #include "prim.h" 9 | 10 | namespace LunaCore::Prim::Private 11 | { 12 | 13 | /** Calculate cost based on 3-tuple from "New Algorithms for the Rectilinear Steiner Tree 14 | Problem", IEEE TRANSACTIONS ON COMPUTER-AIDED DESIGN, VOL 9 NO 2, FEBRUARY 1990 */ 15 | struct CostTuple 16 | { 17 | ChipDB::CoordType m_dist; 18 | ChipDB::CoordType m_minAbsY; 19 | ChipDB::CoordType m_minMaxX; 20 | }; 21 | 22 | [[nodiscard]] bool operator<(const CostTuple &lhs, const CostTuple &rhs) noexcept; 23 | 24 | struct TreeEdge 25 | { 26 | static constexpr NodeId c_Undefined = -1; 27 | NodeId from{c_Undefined}; 28 | NodeId to{c_Undefined}; 29 | CostTuple m_edgeCost; 30 | }; 31 | 32 | struct TreeEdgeCompare 33 | { 34 | [[nodiscard]] bool operator()(const TreeEdge* lhs, const TreeEdge* rhs) const noexcept 35 | { 36 | return !(lhs->m_edgeCost < rhs->m_edgeCost); 37 | } 38 | }; 39 | 40 | using PriorityQueue = std::priority_queue, TreeEdgeCompare>; 41 | 42 | inline CostTuple calcCost(const ChipDB::Coord64 &node1, const ChipDB::Coord64 &node2) noexcept 43 | { 44 | CostTuple t; 45 | t.m_dist = std::abs(node1.m_x - node2.m_x) + std::abs(node1.m_y - node2.m_y); 46 | t.m_minAbsY = -std::abs(node1.m_y - node2.m_y); 47 | t.m_minMaxX = -std::max(node1.m_x, node2.m_x); 48 | return t; 49 | }; 50 | 51 | }; -------------------------------------------------------------------------------- /gui/widgets/hatchdisplay.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #include "hatchdisplay.h" 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace GUI; 11 | 12 | HatchDisplay::HatchDisplay(HatchLibrary &hatchLibrary, QWidget *parent) 13 | : QScrollArea(parent), m_hatchLibrary(hatchLibrary) 14 | { 15 | setWidgetResizable(true); 16 | 17 | QWidget *widget = new QWidget(); 18 | 19 | auto mainLayout = new QVBoxLayout(); 20 | widget->setLayout(mainLayout); 21 | 22 | setWidget(widget); 23 | 24 | int hatchIndex = 0; 25 | for(auto const& hatchPixmap : m_hatchLibrary.m_hatches) 26 | { 27 | auto hatchButton = new QPushButton(); 28 | hatchButton->setFlat(true); 29 | hatchButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); 30 | hatchButton->setIcon(QIcon(hatchPixmap)); 31 | hatchButton->setIconSize(hatchPixmap.rect().size()); 32 | hatchButton->setProperty("hatchindex", QVariant(hatchIndex)); 33 | 34 | hatchIndex++; 35 | 36 | mainLayout->addWidget(hatchButton); 37 | 38 | connect(hatchButton, SIGNAL(clicked()), this, SLOT(onHatchClick())); 39 | } 40 | } 41 | 42 | void HatchDisplay::onHatchClick() 43 | { 44 | QPushButton* buttonSender = qobject_cast(sender()); 45 | if (buttonSender != nullptr) 46 | { 47 | auto index = buttonSender->property("hatchindex").toInt(); 48 | emit clicked(index); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /core/database/module.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #include "module.h" 6 | 7 | using namespace ChipDB; 8 | 9 | // ********************************************************************** 10 | // Module 11 | // ********************************************************************** 12 | 13 | Module::Module(const std::string &name) : Cell(name) 14 | { 15 | m_netlist = std::make_shared(); 16 | } 17 | 18 | KeyObjPair Module::addInstance(std::shared_ptr insPtr) 19 | { 20 | if (!insPtr) 21 | { 22 | return KeyObjPair{}; 23 | } 24 | 25 | if (insPtr->name().empty()) 26 | { 27 | return KeyObjPair{}; 28 | } 29 | 30 | if (m_netlist) 31 | { 32 | auto result = m_netlist->m_instances.add(insPtr); 33 | return result.value(); 34 | } 35 | 36 | return KeyObjPair{}; // cannot add instances to a black box 37 | } 38 | 39 | KeyObjPair Module::createNet(const std::string &netName) 40 | { 41 | if (!m_netlist) 42 | { 43 | return KeyObjPair{}; 44 | } 45 | 46 | return m_netlist->createNet(netName); 47 | } 48 | 49 | bool Module::connect(const std::string &insName, const std::string &pinName, const std::string &netName) 50 | { 51 | return m_netlist->connect(insName, pinName, netName); 52 | } 53 | 54 | bool Module::connect(InstanceObjectKey insKey, PinObjectKey pinKey, NetObjectKey netKey) 55 | { 56 | return m_netlist->connect(insKey, pinKey, netKey); 57 | } 58 | -------------------------------------------------------------------------------- /examples/adder8/fa_map.v: -------------------------------------------------------------------------------- 1 | (* techmap_celltype = "$alu" *) 2 | module tsmc018_alu (A, B, CI, BI, X, Y, CO); 3 | parameter A_SIGNED = 0; 4 | parameter B_SIGNED = 0; 5 | parameter A_WIDTH = 1; 6 | parameter B_WIDTH = 1; 7 | parameter Y_WIDTH = 1; 8 | 9 | input [A_WIDTH-1:0] A; // Input operand 10 | input [B_WIDTH-1:0] B; // Input operand 11 | output [Y_WIDTH-1:0] X; // A xor B (sign-extended, optional B inversion, 12 | // used in combination with 13 | // reduction-AND for $eq/$ne ops) 14 | output [Y_WIDTH-1:0] Y; // Sum 15 | 16 | input CI; // Carry-in (set for $sub) 17 | input BI; // Invert-B (set for $sub) 18 | output [Y_WIDTH-1:0] CO; // Carry-out 19 | 20 | wire [Y_WIDTH-1:0] AA, BB; 21 | 22 | generate 23 | if (A_SIGNED && B_SIGNED) begin:BLOCK1 24 | assign AA = $signed(A), BB = BI ? ~$signed(B) : $signed(B); 25 | end else begin:BLOCK2 26 | assign AA = $unsigned(A), BB = BI ? ~$unsigned(B) : $unsigned(B); 27 | end 28 | endgenerate 29 | 30 | genvar i; 31 | generate 32 | FAX1 adder ( 33 | .A(AA[0]), 34 | .B(BB[0]), 35 | .C(CI), 36 | .YC(CO[0]), 37 | .YS(Y[0])); 38 | 39 | for (i = 1; i < Y_WIDTH; i = i+1) begin:BLOCK2 40 | FAX1 adder( 41 | .A(AA[i]), 42 | .B(BB[i]), 43 | .C(CO[i-1]), 44 | .YC(CO[i]), 45 | .YS(Y[i])); 46 | end 47 | endgenerate 48 | 49 | endmodule -------------------------------------------------------------------------------- /core/export/txt/txtwriter.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #include "version.h" 6 | #include "common/logging.h" 7 | #include "txtwriter.h" 8 | 9 | bool LunaCore::TXT::write(std::ostream &os, const std::shared_ptr netlist) 10 | { 11 | if (!netlist) 12 | { 13 | Logging::logError("TXT writer: netlist is nullptr\n"); 14 | return false; 15 | } 16 | 17 | os << "# Routing positions to center of the cells. Generated by LunaPnR " << LUNAVERSIONSTRING << "\n"; 18 | os << "# Format: ... \n"; 19 | 20 | for(auto const netKeyPair : netlist->m_nets) 21 | { 22 | // write number of points in the net 23 | os << netKeyPair->numberOfConnections() << " "; 24 | 25 | // write locations of all the terminals 26 | for(auto netConnect : *netKeyPair) 27 | { 28 | auto ins = netlist->lookupInstance(netConnect.m_instanceKey); 29 | if (!ins->isPlaced()) 30 | { 31 | Logging::logWarning("TXT writer: instance %s has no location / is not placed.!\n", ins->name().c_str()); 32 | return false; 33 | } 34 | 35 | os << ins->m_pos.m_x << " " << ins->m_pos.m_y << " "; 36 | } 37 | os << "\n"; 38 | } 39 | 40 | return true; 41 | } 42 | 43 | bool LunaCore::TXT::write(std::ostream &os, const std::shared_ptr mod) 44 | { 45 | return LunaCore::TXT::write(os, mod->m_netlist); 46 | } 47 | -------------------------------------------------------------------------------- /examples/sky130pdk.toml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | # SPDX-License-Identifier: GPL-3.0-only 3 | # 4 | # IHP130 PDK for LunaPnR 5 | 6 | title = "Skywater 130nm" # title/name the user sees. 7 | name = "sky130" # name used to reference the PDK internally. 8 | version = "v0.1" # version the user sees. 9 | installdir = "sky130" # installation dir, must be a relative path. 10 | date = "06-09-2023" 11 | copyright = "Skywater/Google" 12 | description = "Skywater 130nm cell library" 13 | icon = "https://lh3.googleusercontent.com/COxitqgJr1sJnIDe8-jiKhxDx1FrYbtRHKJ9z_hELisAlapwE9LUPh6fcXIfb5vwpbMl4xl9H9TRFPc5NOO8Sb3VSgIBrfRYvW6cUA" 14 | 15 | # source locations for the LEF/DEF/Layer etc files. 16 | url = [ 17 | ["https://github.com/asicsforthemasses/sky130_testing/raw/main/sky130_fd_sc_hd_liberty.tar.xz", "sky130_fd_sc_hd.tar.xz"], 18 | ["https://github.com/asicsforthemasses/sky130_testing/raw/main/sky130_fd_sc_hd.tlef", "sky130_fd_sc_hd.tlef"], 19 | ["https://github.com/asicsforthemasses/sky130_testing/raw/main/sky130_fd_sc_hd.lef", "sky130_fd_sc_hd.lef"], 20 | ] 21 | 22 | # archive extraction instructions, if any. 23 | # the second argument is the archive type 24 | # "tgz", "zip", "bz2", "xz" 25 | extract = [ 26 | ["sky130_fd_sc_hd.tar.xz", "xz"] 27 | ] 28 | 29 | # lef files, technology LEF *must* go first 30 | lef = [ 31 | "sky130_fd_sc_hd.tlef", "sky130_fd_sc_hd.lef" 32 | ] 33 | 34 | # liberty files 35 | lib = [ 36 | "sky130_fd_sc_hd__tt_025C_1v80" 37 | ] 38 | 39 | # layer file for the colours and hatch patterns 40 | layerfile = "freepdk45.layers" 41 | -------------------------------------------------------------------------------- /core/cellplacer/cellplacer.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #include 6 | #include "cellplacer.h" 7 | #include "database/database.h" 8 | #include "common/logging.h" 9 | 10 | using namespace LunaCore; 11 | 12 | void SimpleCellPlacer::place(ChipDB::Netlist *nl, const ChipDB::Rect64 ®ionRect, const int64_t rowHeight) 13 | { 14 | bool flip = false; 15 | ChipDB::Coord64 curPos = regionRect.m_ll; 16 | for(auto ins : nl->m_instances) 17 | { 18 | // do not place pins 19 | if (ins->isPin()) 20 | continue; 21 | 22 | auto cellSize = ins->instanceSize(); 23 | 24 | // is there space for the next cell in the current row? 25 | if ((cellSize.m_x + curPos.m_x) > regionRect.m_ur.m_x) 26 | { 27 | // no, got to next row 28 | curPos.m_x = regionRect.m_ll.m_x; 29 | curPos.m_y += rowHeight; 30 | 31 | flip = !flip; 32 | } 33 | 34 | ins->m_pos = curPos; 35 | curPos.m_x += cellSize.m_x; 36 | 37 | if (flip) 38 | ins->m_orientation = ChipDB::Orientation::MX; 39 | else 40 | ins->m_orientation = ChipDB::Orientation::R0; 41 | } 42 | 43 | if (curPos.m_y >= regionRect.m_ur.m_y) 44 | { 45 | std::stringstream ss; 46 | ss << "SimpleCellPlacer: not enough room in region for all instances\n"; 47 | ss << " need at least " << (curPos.m_y - regionRect.m_ur.m_y) << " nm more height\n"; 48 | Logging::logError(ss.str()); 49 | } 50 | } 51 | 52 | -------------------------------------------------------------------------------- /gui/pdkinstaller/downloader.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | namespace GUI 16 | { 17 | 18 | class Downloader : public QObject 19 | { 20 | Q_OBJECT 21 | public: 22 | Downloader(QObject *parent = nullptr); 23 | virtual ~Downloader() = default; 24 | 25 | /** add a download to the queue */ 26 | void download(QUrl url, QString filename); 27 | 28 | /** returns true if the download queue is empty */ 29 | [[nodiscard]] bool empty() const noexcept 30 | { 31 | return m_queue.empty(); 32 | } 33 | 34 | signals: 35 | void downloaded(QString filename); 36 | void downloadProgress(int percent); 37 | void error(QString error); 38 | 39 | private slots: 40 | void onReadReady(); 41 | void onFileDownloaded(QNetworkReply *reply); 42 | void onDownloadProgress(int64_t bytes, int64_t total); 43 | 44 | protected: 45 | constexpr bool busy() const noexcept 46 | { 47 | return m_reply != nullptr; 48 | } 49 | 50 | struct DownloadItem 51 | { 52 | QUrl m_url; 53 | QString m_filename; 54 | }; 55 | 56 | void startDownload(const DownloadItem &item); 57 | 58 | std::deque m_queue; 59 | 60 | QNetworkReply *m_reply{nullptr}; 61 | QNetworkAccessManager m_webCtrl; 62 | 63 | QFile m_currentFile; 64 | }; 65 | 66 | }; -------------------------------------------------------------------------------- /core/passes/passes.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #include 6 | 7 | #include "common/strutils.hpp" 8 | #include "passes.hpp" 9 | #include "floorplanpass.hpp" 10 | #include "readpass.hpp" 11 | #include "writepass.hpp" 12 | #include "infopass.hpp" 13 | #include "scriptpass.hpp" 14 | #include "filesystempass.hpp" 15 | #include "checkpass.hpp" 16 | #include "placepass.hpp" 17 | #include "flattenpass.hpp" 18 | #include "ctspass.hpp" 19 | #include "padringpass.hpp" 20 | #include "setpass.hpp" 21 | #include "clearpass.hpp" 22 | #include "gdsmerge.hpp" 23 | 24 | namespace LunaCore::Passes 25 | { 26 | 27 | bool run(Database &database, const std::string &cmdstring) 28 | { 29 | auto chunks = LunaCore::split(cmdstring, ' '); 30 | if (!chunks.empty()) 31 | { 32 | return runPass(database,chunks.front(), std::span(chunks.begin()+1, chunks.end())); 33 | } 34 | 35 | return false; 36 | } 37 | 38 | void registerAllPasses() 39 | { 40 | registerPass(new Floorplan()); 41 | registerPass(new ReadPass()); 42 | registerPass(new WritePass()); 43 | registerPass(new InfoPass()); 44 | registerPass(new ScriptPass()); 45 | registerPass(new LSPass()); 46 | registerPass(new CDPass()); 47 | registerPass(new CWDPass()); 48 | registerPass(new CheckPass()); 49 | registerPass(new PlacePass()); 50 | registerPass(new FlattenPass()); 51 | registerPass(new CTSPass()); 52 | registerPass(new PadringPass()); 53 | registerPass(new SetPass()); 54 | registerPass(new ClearPass()); 55 | registerPass(new GDSMergePass()); 56 | } 57 | 58 | }; 59 | -------------------------------------------------------------------------------- /test/core/fileutilstest.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #include "lunacore.h" 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | BOOST_AUTO_TEST_SUITE(FileUtils) 15 | 16 | BOOST_AUTO_TEST_CASE(file_utils_test) 17 | { 18 | std::cout << "--== CHECK FILE UTILS: envvars ==--\n"; 19 | const std::string envName{"CheckFileUtilsEnvVarTest"}; 20 | 21 | BOOST_CHECK(LunaCore::setEnvironmentVar(envName, "1234")); 22 | BOOST_CHECK(LunaCore::getEnvironmentVar(envName) == "1234"); 23 | 24 | std::string fileName{"/usr/local/{CheckFileUtilsEnvVarTest}"}; 25 | auto expandedName = LunaCore::expandEnvironmentVars(fileName); 26 | BOOST_CHECK(expandedName == "/usr/local/1234"); 27 | 28 | BOOST_CHECK(LunaCore::unsetEnvironmentVar(envName)); 29 | }; 30 | 31 | BOOST_AUTO_TEST_CASE(file_utils_test2) 32 | { 33 | std::cout << "--== CHECK FILE UTILS: find and replace ==--\n"; 34 | 35 | auto result1 = LunaCore::findAndReplace("Hello 1234!", "1234", "4321"); 36 | BOOST_CHECK(result1 == "Hello 4321!"); 37 | 38 | auto result2 = LunaCore::findAndReplace("Hello 12341234!", "1234", "4321"); 39 | BOOST_CHECK(result2 == "Hello 43214321!"); 40 | 41 | auto result3 = LunaCore::findAndReplace("1234Hello!", "1234", "4321"); 42 | BOOST_CHECK(result3 == "4321Hello!"); 43 | 44 | auto result4 = LunaCore::findAndReplace("1234Hello1234", "1234", "4321"); 45 | BOOST_CHECK(result4 == "4321Hello4321"); 46 | }; 47 | 48 | BOOST_AUTO_TEST_SUITE_END() -------------------------------------------------------------------------------- /gui/common/projectsetup.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | #include "lunacore.h" 11 | 12 | namespace GUI 13 | { 14 | 15 | struct RegionSetup 16 | { 17 | std::string m_regionName; ///< region name 18 | ChipDB::Rect64 m_regionSize; ///< region size including halo 19 | ChipDB::Margins64 m_regionHalo; ///< region halo margins 20 | std::string m_site; ///< site name, corresponding to LEF file. 21 | }; 22 | 23 | /** LunaPnR project information, used by the project browser/manager. */ 24 | struct ProjectSetup 25 | { 26 | std::vector m_lefFiles; 27 | std::vector m_libFiles; 28 | std::vector m_verilogFiles; 29 | std::vector m_timingConstraintFiles; 30 | std::vector m_layerFiles; 31 | 32 | std::string m_ctsBuffer; ///< architype name of clock buffer. 33 | float m_ctsMaxCap{0.2e-12}; ///< maximum capacity of CTS subtree. 34 | 35 | std::vector m_regions; 36 | 37 | std::string m_openSTALocation{"/usr/local/bin/sta"}; ///< this comes from the Luna config file, not the project file. 38 | std::string m_floorplanScriptLocation; ///< if this is not empty, this script is used to generate the floorplan 39 | 40 | bool readFromJSON(std::istream &is); 41 | bool writeToJSON(std::ostream &os) const; 42 | 43 | bool readFromTOML(std::istream &is); 44 | bool writeToTOML(std::ostream &os) const; 45 | }; 46 | 47 | }; 48 | -------------------------------------------------------------------------------- /core/globalroute/lshape.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | #include 7 | #include "database/database.h" 8 | 9 | namespace LunaCore 10 | { 11 | 12 | /** Specification for the 3-point L shape configuration */ 13 | enum class LShape 14 | { 15 | UNKNOWN = 0, 16 | UPPER, 17 | LOWER, 18 | NONE 19 | }; 20 | 21 | /** generate the optional 3rd "Steiner" point for an L shape, given two corners of the bounding box. */ 22 | constexpr std::optional LSteinerPoint(const ChipDB::Coord64 &p1, const ChipDB::Coord64 &p2, LShape shape) noexcept 23 | { 24 | // there is no L-shape / Steiner point when the points 25 | // lie on the same horizontal or vertical line. 26 | if ((p1.m_x == p2.m_x) || (p1.m_y == p2.m_y)) 27 | { 28 | return std::nullopt; 29 | } 30 | 31 | switch(shape) 32 | { 33 | case LShape::UPPER: 34 | { 35 | if (p1.m_y > p2.m_y) 36 | { 37 | return ChipDB::Coord64{p2.m_x, p1.m_y}; 38 | } 39 | else 40 | { 41 | return ChipDB::Coord64{p1.m_x, p2.m_y}; 42 | } 43 | } 44 | case LShape::LOWER: 45 | { 46 | if (p1.m_y > p2.m_y) 47 | { 48 | return ChipDB::Coord64{p1.m_x, p2.m_y}; 49 | } 50 | else 51 | { 52 | return ChipDB::Coord64{p2.m_x, p1.m_y}; 53 | } 54 | } 55 | case LShape::NONE: 56 | case LShape::UNKNOWN: 57 | break; 58 | } 59 | 60 | return std::nullopt; 61 | }; 62 | 63 | }; -------------------------------------------------------------------------------- /core/python/converters.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #define PY_SSIZE_T_CLEAN 8 | #include 9 | 10 | #include 11 | #include 12 | #include "database/database.h" 13 | 14 | namespace Python 15 | { 16 | 17 | // ******************************************************************************** 18 | // 19 | // toPython 20 | // 21 | // The toPython template function converts a C++ type and exposes it to Python. 22 | // 23 | // ******************************************************************************** 24 | 25 | PyObject* toPython(const int &t); 26 | 27 | PyObject* toPython(const unsigned int &t); 28 | 29 | PyObject* toPython(const float &t); 30 | 31 | PyObject* toPython(const double &t); 32 | 33 | PyObject* toPython(const size_t &t); 34 | 35 | PyObject* toPython(const ssize_t &t); 36 | 37 | PyObject* toPython(const std::string_view &t); 38 | 39 | PyObject* toPython(const std::string &t); 40 | 41 | PyObject* toPython(const char *t); 42 | 43 | PyObject* toPython(const ChipDB::Coord64 &t); 44 | 45 | PyObject* toPython(const ChipDB::Rect64 &t); 46 | 47 | PyObject* toPython(const ChipDB::CellClass &t); 48 | 49 | PyObject* toPython(const ChipDB::CellSubclass &t); 50 | 51 | PyObject* toPython(const ChipDB::SymmetryFlags &t); 52 | 53 | // ******************************************************************************** 54 | // fromPython 55 | // ******************************************************************************** 56 | 57 | bool fromPython(PyObject *obj, int &result); 58 | 59 | bool fromPython(PyObject *obj, std::string &result); 60 | 61 | }; -------------------------------------------------------------------------------- /core/database/database.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include "common/fileutils.h" 6 | #include "common/logging.h" 7 | 8 | #include "dbtypes.h" 9 | #include "properties.hpp" 10 | #include "observer.h" 11 | #include "table.hpp" 12 | #include "namedstorage.h" 13 | #include "net.h" 14 | #include "instance.h" 15 | #include "netlist.h" 16 | #include "enums.h" 17 | #include "netlisttools.h" 18 | #include "techlib.h" 19 | #include "floorplan.h" 20 | #include "design.h" 21 | 22 | namespace LunaCore 23 | { 24 | 25 | struct Database 26 | { 27 | Database() 28 | { 29 | auto pdkInstallPath = getEnvironmentVar("LUNAPNR_PDKINSTALLPATH"); 30 | if (!pdkInstallPath.empty()) 31 | { 32 | if (std::filesystem::is_directory(pdkInstallPath)) 33 | { 34 | m_PDKInstallPath = pdkInstallPath; 35 | } 36 | else 37 | { 38 | Logging::logWarning("LUNAPNR_PDKINSTALLPATH does not point to a valid directory - keeping the default setting.\n"); 39 | } 40 | } 41 | else 42 | { 43 | Logging::logWarning("LUNAPNR_PDKINSTALLPATH not set - keeping the default setting.\n"); 44 | } 45 | }; 46 | 47 | ChipDB::Design m_design; 48 | ChipDB::Properties m_properties; ///< global properties, such as paths etc. 49 | 50 | std::filesystem::path m_PDKInstallPath{"/opt/lunapnr/pdkinstalls"}; 51 | 52 | constexpr static const char *propPDKRoot{"PDKROOT"}; ///< property key for full path to the currently selected PDK 53 | constexpr static const char *propProjectRoot{"PROJECTROOT"}; ///< property key for full path to the project directory 54 | }; 55 | 56 | }; 57 | -------------------------------------------------------------------------------- /core/passes/clearpass.hpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | #include 7 | #include 8 | #include "common/logging.h" 9 | #include "pass.hpp" 10 | 11 | namespace LunaCore::Passes 12 | { 13 | 14 | class ClearPass : public Pass 15 | { 16 | public: 17 | ClearPass() : Pass("clear") 18 | { 19 | registerNamedParameter("all", "", 0, false); 20 | } 21 | 22 | virtual ~ClearPass() = default; 23 | 24 | /** execute a pass given a list of input arguments. 25 | returns true if succesful, else false. 26 | */ 27 | [[nodiscard]] bool execute(Database &database) override 28 | { 29 | if (m_namedParams.contains("all")) 30 | { 31 | database.m_design.clear(); 32 | return true; 33 | } 34 | 35 | return true; 36 | } 37 | 38 | /** 39 | returns help text for a pass. 40 | */ 41 | std::string help() const noexcept override 42 | { 43 | std::stringstream ss; 44 | ss << "clear - clear database\n"; 45 | ss << " clear \n\n"; 46 | ss << " clear type options:\n"; 47 | ss << " -all : clear the database\n"; 48 | ss << "\n"; 49 | return ss.str(); 50 | } 51 | 52 | /** 53 | returns a one-line short help text for a pass. 54 | */ 55 | virtual std::string shortHelp() const noexcept 56 | { 57 | return "clear database"; 58 | } 59 | 60 | /** 61 | Initialize a pass. this is called by registerPass() 62 | */ 63 | bool init() override 64 | { 65 | return true; 66 | } 67 | }; 68 | 69 | 70 | }; 71 | -------------------------------------------------------------------------------- /gui/pdkdialog/pdktile.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "common/pdkinfo.h" 12 | 13 | namespace GUI 14 | { 15 | 16 | class PDKTile : public QWidget 17 | { 18 | Q_OBJECT 19 | public: 20 | PDKTile(const PDKInfo &info, QWidget *parent = nullptr); 21 | 22 | constexpr void setID(int id) noexcept 23 | { 24 | m_id = id; 25 | } 26 | 27 | void paintEvent(QPaintEvent *e) override; 28 | void mousePressEvent(QMouseEvent *e) override; 29 | void setSelected(bool selected = true); 30 | 31 | signals: 32 | void clicked(int id); 33 | 34 | protected: 35 | bool m_selected{false}; 36 | int m_id{-1}; 37 | QLabel *m_title{nullptr}; 38 | QLabel *m_date{nullptr}; 39 | QLabel *m_version{nullptr}; 40 | }; 41 | 42 | class PDKTileList : public QWidget 43 | { 44 | Q_OBJECT 45 | public: 46 | PDKTileList(QWidget *parent = nullptr); 47 | 48 | PDKTile* createTile(const PDKInfo &info); 49 | 50 | PDKTile* at(int index) 51 | { 52 | return m_pdkTiles.at(index); 53 | } 54 | 55 | std::size_t size() const noexcept 56 | { 57 | return m_pdkTiles.size(); 58 | } 59 | 60 | constexpr int selected() const noexcept 61 | { 62 | return m_selected; 63 | } 64 | 65 | signals: 66 | void selectionChanged(int id); 67 | 68 | private slots: 69 | void onTileClicked(int id); 70 | 71 | protected: 72 | int m_selected{-1}; 73 | QVBoxLayout *m_layout{nullptr}; 74 | std::vector m_pdkTiles; 75 | }; 76 | 77 | }; 78 | -------------------------------------------------------------------------------- /gui/models/layerappearancetablemodel.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include "common/layerrenderinfo.h" 8 | #include 9 | #include 10 | 11 | namespace GUI 12 | { 13 | 14 | class LayerAppearanceTableModel : public QAbstractTableModel, public ChipDB::INamedStorageListener 15 | { 16 | public: 17 | LayerAppearanceTableModel(LayerRenderInfoDB *layers = nullptr); 18 | 19 | void setLayers(LayerRenderInfoDB *layers); 20 | 21 | /** return the number of rows in the list */ 22 | int rowCount(const QModelIndex &parent = QModelIndex()) const override; 23 | 24 | /** return the number of columns in the list */ 25 | int columnCount(const QModelIndex &parent = QModelIndex()) const override; 26 | 27 | /** returns various information about enabled/disabled items etc */ 28 | Qt::ItemFlags flags(const QModelIndex &index) const override; 29 | 30 | /** query the data a 'index' position */ 31 | QVariant data(const QModelIndex &index, int role) const override; 32 | 33 | /** query the view/list header information */ 34 | QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; 35 | 36 | void notify(ChipDB::ObjectKey index, NotificationType t) override; 37 | 38 | protected: 39 | void updatePixmapCache(); 40 | 41 | QColor m_lightColor; 42 | QColor m_darkColor; 43 | 44 | LayerRenderInfoDB *m_layers; 45 | 46 | struct PixmapCacheEntry 47 | { 48 | QPixmap m_pixmap; 49 | }; 50 | 51 | std::vector m_pixmapCache; 52 | std::vector m_pixmapObsCache; 53 | }; 54 | 55 | }; 56 | -------------------------------------------------------------------------------- /gui/console/mtstringbuffer.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #include 6 | #include 7 | #include "mtstringbuffer.h" 8 | 9 | using namespace GUI; 10 | 11 | MTStringBuffer::MTStringBuffer(QObject *eventReceiver) : m_eventReceiver(eventReceiver) 12 | { 13 | } 14 | 15 | void MTStringBuffer::print(const std::string &txt) 16 | { 17 | print(Logging::LogType::INFO, txt); 18 | } 19 | 20 | void MTStringBuffer::print(const std::string_view &txt) 21 | { 22 | print(Logging::LogType::INFO, txt); 23 | } 24 | 25 | void MTStringBuffer::print(const Logging::LogType &logType, const std::string &txt) 26 | { 27 | std::lock_guard guard(m_mutex); 28 | m_buffer.push_back(LogString{logType, txt}); 29 | 30 | if (m_eventReceiver != nullptr) 31 | { 32 | auto event = new QEvent(QEvent::User); 33 | QApplication::postEvent(m_eventReceiver, event); 34 | } 35 | } 36 | 37 | void MTStringBuffer::print(const Logging::LogType &logType, const std::string_view &txt) 38 | { 39 | std::lock_guard guard(m_mutex); 40 | m_buffer.push_back(LogString{logType, std::string(txt)}); 41 | 42 | if (m_eventReceiver != nullptr) 43 | { 44 | auto event = new QEvent(QEvent::User); 45 | QApplication::postEvent(m_eventReceiver, event); 46 | } 47 | } 48 | 49 | MTStringBuffer::LogString MTStringBuffer::pop() 50 | { 51 | std::lock_guard guard(m_mutex); 52 | auto logString = m_buffer.front(); 53 | m_buffer.pop_front(); 54 | return logString; 55 | } 56 | 57 | bool MTStringBuffer::containsString() 58 | { 59 | std::lock_guard guard(m_mutex); 60 | return !m_buffer.empty(); 61 | } 62 | -------------------------------------------------------------------------------- /test/core/dotwritertest.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #include "lunacore.h" 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | BOOST_AUTO_TEST_SUITE(DotWriterTest) 15 | 16 | BOOST_AUTO_TEST_CASE(can_write_netlist_to_dot) 17 | { 18 | std::cout << "--== DOT WRITER ==--\n"; 19 | 20 | ChipDB::Design design; 21 | 22 | std::ifstream leffile("test/files/iit_stdcells/lib/tsmc018/lib/iit018_stdcells.lef"); 23 | BOOST_CHECK(leffile.good()); 24 | BOOST_CHECK(ChipDB::LEF::Reader::load(design, leffile)); 25 | 26 | std::ifstream libertyfile("test/files/iit_stdcells/lib/tsmc018/signalstorm/iit018_stdcells.lib"); 27 | BOOST_CHECK(libertyfile.good()); 28 | BOOST_CHECK(ChipDB::Liberty::Reader::load(design, libertyfile)); 29 | 30 | // dump FAX1 cell 31 | auto cellKeyObjPair = design.m_cellLib->lookupCell("FAX1"); 32 | BOOST_CHECK(cellKeyObjPair.isValid()); 33 | 34 | for(auto pinInfo : cellKeyObjPair->m_pins) 35 | { 36 | std::cout << " " << pinInfo->name() << " " << toString(pinInfo->m_iotype) << "\n"; 37 | } 38 | 39 | std::ifstream verilogfile("test/files/verilog/adder8.v"); 40 | BOOST_CHECK(verilogfile.good()); 41 | 42 | BOOST_CHECK(ChipDB::Verilog::Reader::load(design, verilogfile)); 43 | 44 | auto modulePtr = design.m_moduleLib->lookupModule("adder8"); 45 | BOOST_CHECK(modulePtr.isValid()); 46 | 47 | std::ofstream ofile("test/files/results/adder8.dot"); 48 | BOOST_CHECK(ofile.good()); 49 | 50 | LunaCore::Dot::Writer::write(ofile, modulePtr.ptr()); 51 | } 52 | 53 | BOOST_AUTO_TEST_SUITE_END() 54 | -------------------------------------------------------------------------------- /core/passes/flattenpass.hpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | #include 7 | #include 8 | #include "common/logging.h" 9 | #include "pass.hpp" 10 | 11 | namespace LunaCore::Passes 12 | { 13 | 14 | class FlattenPass : public Pass 15 | { 16 | public: 17 | FlattenPass() : Pass("flatten") 18 | { 19 | registerNamedParameter("module", "", 1, true); 20 | } 21 | 22 | virtual ~FlattenPass() = default; 23 | 24 | /** execute a pass given a list of input arguments. 25 | returns true if succesful, else false. 26 | */ 27 | [[nodiscard]] bool execute(Database &database) override 28 | { 29 | if (m_namedParams.contains("module")) 30 | { 31 | Logging::logError("Not implemented yet\n"); 32 | return false; 33 | } 34 | return true; 35 | } 36 | 37 | /** 38 | returns help text for a pass. 39 | */ 40 | std::string help() const noexcept override 41 | { 42 | std::stringstream ss; 43 | ss << "flatten - flatten netlist of module\n"; 44 | ss << " flatten \n\n"; 45 | ss << " argument options:\n"; 46 | ss << " -module : the name of the module to flatten\n"; 47 | ss << "\n"; 48 | return ss.str(); 49 | } 50 | 51 | /** 52 | returns a one-line short help text for a pass. 53 | */ 54 | virtual std::string shortHelp() const noexcept 55 | { 56 | return "flatten netlist of module"; 57 | } 58 | 59 | /** 60 | Initialize a pass. this is called by registerPass() 61 | */ 62 | bool init() override 63 | { 64 | return true; 65 | } 66 | }; 67 | 68 | 69 | }; 70 | -------------------------------------------------------------------------------- /core/database/visitor.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | 8 | namespace ChipDB 9 | { 10 | 11 | // pre-declarations 12 | class Cell; 13 | class Module; 14 | class Instance; 15 | class PinInfo; 16 | class Netlist; 17 | class Net; 18 | class LayerInfo; 19 | 20 | class Visitor 21 | { 22 | public: 23 | virtual void visit(Instance *instance) = 0; 24 | virtual void visit(Cell *cell) = 0; 25 | virtual void visit(Module *module) = 0; 26 | virtual void visit(PinInfo *pin) = 0; 27 | virtual void visit(Netlist *nl) = 0; 28 | virtual void visit(Net *net) = 0; 29 | virtual void visit(LayerInfo *layer) = 0; 30 | }; 31 | 32 | class ConstVisitor 33 | { 34 | public: 35 | virtual void visit(const Instance *instance) = 0; 36 | virtual void visit(const Cell *cell) = 0; 37 | virtual void visit(const Module *module) = 0; 38 | virtual void visit(const PinInfo *pin) = 0; 39 | virtual void visit(const Netlist *nl) = 0; 40 | virtual void visit(const Net *net) = 0; 41 | virtual void visit(const LayerInfo *layer) = 0; 42 | }; 43 | 44 | 45 | /** IMPLEMENT_ACCEPT creates 'virtual void accept(..)' functions for Visitor and ConstVisitor classes */ 46 | #define IMPLEMENT_ACCEPT \ 47 | virtual void accept(Visitor *visitor) { visitor->visit(this); }; \ 48 | virtual void accept(ConstVisitor *visitor) const { visitor->visit(this); }; 49 | 50 | /** IMPLEMENT_ACCEPT_VERRIDE creates 'virtual void accept(..) override' functions for Visitor and ConstVisitor classes */ 51 | #define IMPLEMENT_ACCEPT_OVERRIDE \ 52 | virtual void accept(Visitor *visitor) override { visitor->visit(this); }; \ 53 | virtual void accept(ConstVisitor *visitor) const override { visitor->visit(this); }; 54 | 55 | }; -------------------------------------------------------------------------------- /core/cellplacer/netlistsplitter.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include 8 | #include "qplacertypes.h" 9 | 10 | namespace LunaCore::QPlacer 11 | { 12 | 13 | struct Selector 14 | { 15 | virtual bool operator()(PlacerNodeId id, const PlacerNode &node) = 0; 16 | }; 17 | 18 | struct ExternalNodeOnNetHandler 19 | { 20 | virtual void operator()(const PlacerNodeId extNodeId, const PlacerNode &extdNode, 21 | const PlacerNet &oldNet, 22 | const PlacerNetId newNet, 23 | PlacerNetlist& newNetlist) 24 | { 25 | // default: do nothing. 26 | } 27 | }; 28 | 29 | /** create a new placer netlist from a netlist by selecting 30 | * nodes using a Selector object 31 | */ 32 | 33 | class NetlistSplitter 34 | { 35 | public: 36 | PlacerNetlist createNetlistFromSelection( 37 | const PlacerNetlist &netlist, 38 | Selector &selector, 39 | ExternalNodeOnNetHandler &externalNodeHandler 40 | ); 41 | 42 | PlacerNetlist createNetlistFromSelection( 43 | const PlacerNetlist &netlist, 44 | Selector &selector 45 | ); 46 | 47 | protected: 48 | /** copy a node to the new netlist and return its new node Id */ 49 | PlacerNodeId copyNodeToNewNetlistAndClearConnections(const PlacerNode &node); 50 | PlacerNetId copyNetToNewNetlistAndClearNodes(const PlacerNet &net); 51 | 52 | void addNodeToNet(PlacerNodeId nodeId, PlacerNetId netId); 53 | void addNetToNode(PlacerNetId netId, PlacerNodeId nodeId); 54 | 55 | void removePreviouslyAddedNode(PlacerNetId netId); 56 | 57 | void removeIfDegenerateNet(PlacerNetId netId); 58 | 59 | PlacerNetlist m_newNetlist; 60 | std::vector m_xlat; 61 | }; 62 | 63 | }; -------------------------------------------------------------------------------- /core/database/pin.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #include 6 | #include "pin.h" 7 | 8 | using namespace ChipDB; 9 | 10 | std::string ChipDB::toString(const IOType &iotype) 11 | { 12 | switch(iotype) 13 | { 14 | case IOType::UNKNOWN: 15 | return "UNKNOWN"; 16 | case IOType::INPUT: 17 | return "INPUT"; 18 | case IOType::OUTPUT: 19 | return "OUTPUT"; 20 | case IOType::OUTPUT_TRI: 21 | return "TRI-STATE"; 22 | case IOType::IO: 23 | return "INOUT"; 24 | case IOType::POWER: 25 | return "POWER"; 26 | case IOType::GROUND: 27 | return "GROUND"; 28 | default: 29 | return "?"; 30 | } 31 | }; 32 | 33 | 34 | KeyObjPair PinInfoList::createPin(const std::string &name) 35 | { 36 | KeyObjPair result = find(name); 37 | if (!result.isValid()) 38 | { 39 | m_pins.push_back(std::make_shared(name)); 40 | return {static_cast(m_pins.size()-1), m_pins.back()}; 41 | } 42 | 43 | // return the existing one 44 | return result; 45 | } 46 | 47 | /** access pin directly with bounds checking */ 48 | KeyObjPair PinInfoList::operator[](const std::string &name) 49 | { 50 | return find(name); 51 | } 52 | 53 | /** access pin directly with bounds checking */ 54 | KeyObjPair PinInfoList::operator[](const std::string &name) const 55 | { 56 | return find(name); 57 | } 58 | 59 | KeyObjPair PinInfoList::find(const std::string &name) const 60 | { 61 | ObjectKey key = 0; 62 | for(auto pin : m_pins) 63 | { 64 | if (pin->name() == name) 65 | { 66 | return {key, pin}; 67 | } 68 | 69 | key++; 70 | } 71 | 72 | return {}; 73 | } 74 | -------------------------------------------------------------------------------- /examples/freepdk45.toml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | # SPDX-License-Identifier: GPL-3.0-only 3 | # 4 | # IHP130 PDK for LunaPnR 5 | 6 | title = "NCSU FreePDK 45nm" # title/name the user sees. 7 | name = "freepdk45" # name used to reference the PDK internally. 8 | version = "v0.1" # version the user sees. 9 | installdir = "freepdk45" # installation dir, must be a relative path. 10 | date = "06-09-2023" 11 | copyright = "NCSU" 12 | description = "NCSU 45nm cell library" 13 | icon = "https://eda.ncsu.edu/wp-content/uploads/2017/03/chip-ncsu-eda.png" 14 | 15 | # source locations for the LEF/DEF/Layer etc files. 16 | url = [ 17 | ["https://raw.githubusercontent.com/JulianKemmerer/Drexel-ECEC575/master/Encounter/NangateOpenCellLibrary/Low_Power/Front_End/Liberty/LowPowerOpenCellLibrary_functional.lib", "lpocl_functional.lib"], 18 | ["https://raw.githubusercontent.com/JulianKemmerer/Drexel-ECEC575/master/Encounter/NangateOpenCellLibrary/Front_End/Liberty/NangateOpenCellLibrary_functional.lib", "ocl_functional.lib"], 19 | ["https://raw.githubusercontent.com/JulianKemmerer/Drexel-ECEC575/master/Encounter/NangateOpenCellLibrary/Back_End/lef/NangateOpenCellLibrary.lef", "ocl.lef"], 20 | ["https://raw.githubusercontent.com/JulianKemmerer/Drexel-ECEC575/master/Encounter/NangateOpenCellLibrary/Back_End/lef/NangateOpenCellLibrary.tech.lef", "ocl.tech.lef"] 21 | ] 22 | 23 | # archive extraction instructions, if any. 24 | # the second argument is the archive type 25 | # "tgz", "zip", "bz2", "xz" 26 | extract = [] 27 | 28 | # lef files, technology LEF *must* go first 29 | lef = [ 30 | "ocl.tech.lef", "ocl.lef" 31 | ] 32 | 33 | # liberty files 34 | lib = [ 35 | "ocl_functional.lib", 'lpocl_functional.lib' 36 | ] 37 | 38 | # layer file for the colours and hatch patterns 39 | layerfile = "freepdk45.layers" 40 | -------------------------------------------------------------------------------- /gui/pdkdialog/pdkdialog.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #include "pdkdialog.h" 6 | #include 7 | #include 8 | #include "pdktile.h" 9 | 10 | namespace GUI 11 | { 12 | 13 | PDKDialog::PDKDialog(std::vector &pdks) : m_pdks(pdks) 14 | { 15 | setWindowTitle("Select PDK"); 16 | setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred); 17 | 18 | auto mainLayout = new QVBoxLayout(); 19 | m_tileList = new PDKTileList(); 20 | 21 | for(auto const &pdk : pdks) 22 | { 23 | m_tileList->createTile(pdk); 24 | } 25 | 26 | connect(m_tileList, &PDKTileList::selectionChanged, 27 | this, &PDKDialog::onSelectionChanged); 28 | 29 | m_tileListScroll = new QScrollArea(); 30 | m_tileListScroll->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred); 31 | m_tileListScroll->setWidget(m_tileList); 32 | m_tileListScroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 33 | m_tileListScroll->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); 34 | 35 | mainLayout->addWidget(m_tileListScroll,1); 36 | 37 | m_buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok 38 | | QDialogButtonBox::Cancel); 39 | 40 | m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); 41 | 42 | connect(m_buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); 43 | connect(m_buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); 44 | 45 | mainLayout->addWidget(m_buttonBox, 0, Qt::AlignRight); 46 | 47 | setLayout(mainLayout); 48 | } 49 | 50 | void PDKDialog::onSelectionChanged(int id) 51 | { 52 | if (id >= 0) 53 | { 54 | m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); 55 | } 56 | } 57 | 58 | }; 59 | -------------------------------------------------------------------------------- /gui/widgets/blockcontainer.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "flattogglebutton.h" 13 | #include "clickablelabel.h" 14 | 15 | namespace GUI 16 | { 17 | 18 | class BlockContainer; // pre-declaration 19 | 20 | class BlockContainerHeader : public QFrame 21 | { 22 | Q_OBJECT 23 | public: 24 | BlockContainerHeader(BlockContainer *owner, QWidget *parent = 0); 25 | BlockContainerHeader(const QString &name, BlockContainer *owner, QWidget *parent = 0); 26 | 27 | void setName(const QString &name); 28 | 29 | void addWidget(QWidget *widget); 30 | 31 | bool isFolded() const; 32 | 33 | protected slots: 34 | void onFoldButtonToggled(); 35 | void onLabelClicked(); 36 | 37 | protected: 38 | BlockContainer *m_owner = nullptr; 39 | QHBoxLayout *m_hlayout = nullptr; 40 | FlatToggleButton *m_foldButton = nullptr; 41 | ClickableLabel *m_name = nullptr; 42 | }; 43 | 44 | class BlockContainer : public QWidget 45 | { 46 | Q_OBJECT 47 | public: 48 | BlockContainer(QWidget *parent = 0); 49 | 50 | void addWidget(QWidget *widget, int stretch = 0); 51 | void setBlockName(const QString &name); 52 | 53 | BlockContainerHeader* header() 54 | { 55 | return m_header; 56 | } 57 | 58 | bool isFolded() const; 59 | void setFolded(bool state = true); 60 | 61 | protected slots: 62 | void onHeaderFoldToggled(bool state); 63 | 64 | protected: 65 | bool m_folded = false; 66 | std::vector m_contents; 67 | QVBoxLayout *m_vlayout = nullptr; 68 | QVBoxLayout *m_contentLayout = nullptr; 69 | BlockContainerHeader *m_header = nullptr; 70 | QFrame *m_contentFrame = nullptr; 71 | }; 72 | 73 | }; -------------------------------------------------------------------------------- /core/passes/ctspass.hpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021-2025 Niels Moseley 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-only 4 | 5 | #pragma once 6 | #include 7 | #include 8 | #include "common/logging.h" 9 | #include "pass.hpp" 10 | 11 | namespace LunaCore::Passes 12 | { 13 | 14 | class CTSPass : public Pass 15 | { 16 | public: 17 | CTSPass() : Pass("cts") 18 | { 19 | registerNamedParameter("net", "", 1, false); 20 | } 21 | 22 | virtual ~CTSPass() = default; 23 | 24 | /** execute a pass given a list of input arguments. 25 | returns true if succesful, else false. 26 | */ 27 | [[nodiscard]] bool execute(Database &database) override 28 | { 29 | if (m_namedParams.contains("net")) 30 | { 31 | Logging::logError("Not implemented yet\n"); 32 | return false; 33 | } 34 | else 35 | { 36 | Logging::logError("Missing cts type, use -net\n"); 37 | return false; 38 | } 39 | 40 | return true; 41 | } 42 | 43 | /** 44 | returns help text for a pass. 45 | */ 46 | std::string help() const noexcept override 47 | { 48 | std::stringstream ss; 49 | ss << "cts - clock tree synthesis\n"; 50 | ss << " cts \n\n"; 51 | ss << " check type options:\n"; 52 | ss << " -net : synthesize clock tree for the specified net\n"; 53 | ss << "\n"; 54 | return ss.str(); 55 | } 56 | 57 | /** 58 | returns a one-line short help text for a pass. 59 | */ 60 | virtual std::string shortHelp() const noexcept 61 | { 62 | return "clock tree synthesis"; 63 | } 64 | 65 | /** 66 | Initialize a pass. this is called by registerPass() 67 | */ 68 | bool init() override 69 | { 70 | return true; 71 | } 72 | }; 73 | 74 | 75 | }; 76 | --------------------------------------------------------------------------------