diff --git a/dawn/CMakeLists.txt b/dawn/CMakeLists.txt index 75c72e4d1..88108d9ce 100644 --- a/dawn/CMakeLists.txt +++ b/dawn/CMakeLists.txt @@ -26,7 +26,7 @@ unset(__VERSION_LIST) project(Dawn VERSION ${__DAWN_VERSION} HOMEPAGE_URL https://meteoswiss-apn.github.io/dawn/ - LANGUAGES CXX C + LANGUAGES CXX ) unset(__DAWN_VERSION) @@ -176,18 +176,6 @@ endif() add_subdirectory(src) -# Only build examples if BUILD_EXAMPLES and main project, or DAWN_BUILD_EXAMPLES is on -if((CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME OR DAWN_BUILD_EXAMPLES) AND BUILD_EXAMPLES) - set(${PROJECT_NAME}_EXAMPLES ON) -else() - set(${PROJECT_NAME}_EXAMPLES OFF) -endif() -mark_as_advanced(${PROJECT_NAME}_EXAMPLES) - -if(${PROJECT_NAME}_EXAMPLES) - add_subdirectory(examples) -endif() - if(${PROJECT_NAME}_TESTING) add_subdirectory(test) endif() diff --git a/dawn/cmake/FetchCxxopts.cmake b/dawn/cmake/FetchCxxopts.cmake index 0a44820e9..2c9808522 100644 --- a/dawn/cmake/FetchCxxopts.cmake +++ b/dawn/cmake/FetchCxxopts.cmake @@ -1,3 +1,17 @@ +##===------------------------------------------------------------------------------*- CMake -*-===## +## _ +## | | +## __| | __ ___ ___ ___ +## / _` |/ _` \ \ /\ / / '_ | +## | (_| | (_| |\ V V /| | | | +## \__,_|\__,_| \_/\_/ |_| |_| - Compiler Toolchain +## +## +## This file is distributed under the MIT License (MIT). +## See LICENSE.txt for details. +## +##===------------------------------------------------------------------------------------------===## + if(NOT TARGET cxxopts::cxxopts) if(NOT INCLUDE_CXXOPTS) message(STATUS "Fetching cxxopts...") diff --git a/dawn/cmake/HasUnstructuredDeps.cmake b/dawn/cmake/HasUnstructuredDeps.cmake new file mode 100644 index 000000000..9d6bd5f89 --- /dev/null +++ b/dawn/cmake/HasUnstructuredDeps.cmake @@ -0,0 +1,41 @@ +##===------------------------------------------------------------------------------*- CMake -*-===## +## _ +## | | +## __| | __ ___ ___ ___ +## / _` |/ _` \ \ /\ / / '_ | +## | (_| | (_| |\ V V /| | | | +## \__,_|\__,_| \_/\_/ |_| |_| - Compiler Toolchain +## +## +## This file is distributed under the MIT License (MIT). +## See LICENSE.txt for details. +## +##===------------------------------------------------------------------------------------------===## + +if (NOT DEFINED HAS_UNSTRUCTURED_DEPS) + + set(HAS_UNSTRUCTURED_DEPS OFF CACHE BOOL "True if Dawn has detected necessary dependencies for supporting unstructured grids.") + mark_as_advanced(HAS_UNSTRUCTURED_DEPS) + + if(DAWN_REQUIRE_UNSTRUCTURED_TESTING) + find_package(eckit REQUIRED) + find_package(atlas REQUIRED) + else() + find_package(eckit QUIET) + if(NOT eckit_FOUND) + message(STATUS "Could NOT locate eckit.") + endif() + find_package(atlas QUIET) + if(NOT atlas_FOUND) + message(STATUS "Could NOT locate atlas.") + endif() + endif() + + if(atlas_FOUND AND eckit_FOUND) + message(STATUS "Found atlas and eckit. Setting HAS_UNSTRUCTURED_DEPS=ON.") + set(HAS_UNSTRUCTURED_DEPS ON) + else() + set(STATUS "Cound not find dependencies for unstructured support.") + endif() + +endif() diff --git a/dawn/examples/CMakeLists.txt b/dawn/examples/CMakeLists.txt deleted file mode 100644 index 53d920fdd..000000000 --- a/dawn/examples/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ -##===------------------------------------------------------------------------------*- CMake -*-===## -## _ -## | | -## __| | __ ___ ___ ___ -## / _` |/ _` \ \ /\ / / '_ | -## | (_| | (_| |\ V V /| | | | -## \__,_|\__,_| \_/\_/ |_| |_| - Compiler Toolchain -## -## -## This file is distributed under the MIT License (MIT). -## See LICENSE.txt for details. -## -##===------------------------------------------------------------------------------------------===## - -add_subdirectory(cpp) diff --git a/dawn/examples/cpp/CMakeLists.txt b/dawn/examples/cpp/CMakeLists.txt deleted file mode 100644 index f4de0770d..000000000 --- a/dawn/examples/cpp/CMakeLists.txt +++ /dev/null @@ -1,16 +0,0 @@ -##===------------------------------------------------------------------------------*- CMake -*-===## -## _ -## | | -## __| | __ ___ ___ ___ -## / _` |/ _` \ \ /\ / / '_ | -## | (_| | (_| |\ V V /| | | | -## \__,_|\__,_| \_/\_/ |_| |_| - Compiler Toolchain -## -## -## This file is distributed under the MIT License (MIT). -## See LICENSE.txt for details. -## -##===------------------------------------------------------------------------------------------===## - -add_executable(sir-to-iir SIRToIIR.cpp) -target_link_libraries(sir-to-iir DawnC) diff --git a/dawn/examples/cpp/SIRToIIR.cpp b/dawn/examples/cpp/SIRToIIR.cpp deleted file mode 100644 index 45dccaa3b..000000000 --- a/dawn/examples/cpp/SIRToIIR.cpp +++ /dev/null @@ -1,41 +0,0 @@ -//===--------------------------------------------------------------------------------*- C++ -*-===// -// _ -// | | -// __| | __ ___ ___ ___ -// / _` |/ _` \ \ /\ / / '_ | -// | (_| | (_| |\ V V /| | | | -// \__,_|\__,_| \_/\_/ |_| |_| - Compiler Toolchain -// -// -// This file is distributed under the MIT License (MIT). -// See LICENSE.txt for details. -// -//===------------------------------------------------------------------------------------------===// -#include -#include -#include -#include -#include - -int main(int argc, char* argv[]) { - if(argc != 2) { - std::cerr << "Usage: " << argv[0] << " " << std::endl; - return 1; - } - - std::ifstream inputFile(argv[1]); - if(!inputFile.is_open()) - return 1; - - std::stringstream ss; - ss << inputFile.rdbuf(); - - auto options = dawnOptionsCreate(); - auto entry = dawnOptionsEntryCreateInteger(1); - dawnOptionsSet(options, "SerializeIIR", entry); - - auto str = ss.str(); - dawnCompile(str.c_str(), str.length(), options); - - return 0; -} diff --git a/dawn/examples/cpp/copystencil.sir b/dawn/examples/cpp/copystencil.sir deleted file mode 100644 index ebb3e012f..000000000 Binary files a/dawn/examples/cpp/copystencil.sir and /dev/null differ diff --git a/dawn/examples/python/copy_stencil.py b/dawn/examples/python/copy_stencil.py index 7f1e107a9..78003dad3 100644 --- a/dawn/examples/python/copy_stencil.py +++ b/dawn/examples/python/copy_stencil.py @@ -54,7 +54,9 @@ def main(args: argparse.Namespace): ] ) - vertical_region_stmt = sir_utils.make_vertical_region_decl_stmt(body_ast, interval, SIR.VerticalRegion.Forward) + vertical_region_stmt = sir_utils.make_vertical_region_decl_stmt( + body_ast, interval, SIR.VerticalRegion.Forward + ) sir = sir_utils.make_sir( OUTPUT_FILE, @@ -63,7 +65,10 @@ def main(args: argparse.Namespace): sir_utils.make_stencil( OUTPUT_NAME, sir_utils.make_ast([vertical_region_stmt]), - [sir_utils.make_field("in", sir_utils.make_field_dimensions_cartesian()), sir_utils.make_field("out", sir_utils.make_field_dimensions_cartesian())], + [ + sir_utils.make_field("in", sir_utils.make_field_dimensions_cartesian()), + sir_utils.make_field("out", sir_utils.make_field_dimensions_cartesian()), + ], ) ], ) @@ -73,7 +78,7 @@ def main(args: argparse.Namespace): sir_utils.pprint(sir) # compile - code = dawn4py.compile(sir, backend="cuda") + code = dawn4py.compile(sir, backend=dawn4py.CodeGenBackend.CUDA) # write to file print(f"Writing generated code to '{OUTPUT_PATH}'") @@ -82,8 +87,15 @@ def main(args: argparse.Namespace): if __name__ == "__main__": - parser = argparse.ArgumentParser(description="Generate a simple copy-shift stencil using Dawn compiler") + parser = argparse.ArgumentParser( + description="Generate a simple copy-shift stencil using Dawn compiler" + ) parser.add_argument( - "-v", "--verbose", dest="verbose", action="store_true", default=False, help="Print the generated SIR", + "-v", + "--verbose", + dest="verbose", + action="store_true", + default=False, + help="Print the generated SIR", ) main(parser.parse_args()) diff --git a/dawn/examples/python/unstructured_stencil.py b/dawn/examples/python/unstructured_stencil.py index 78ea144d6..5b07bbc15 100644 --- a/dawn/examples/python/unstructured_stencil.py +++ b/dawn/examples/python/unstructured_stencil.py @@ -85,7 +85,7 @@ def main(args: argparse.Namespace): sir_utils.pprint(sir) # compile - code = dawn4py.compile(sir, backend="c++-naive-ico") + code = dawn4py.compile(sir, backend=dawn4py.CodeGenBackend.CXXNaiveIco) # write to file print(f"Writing generated code to '{OUTPUT_PATH}'") diff --git a/dawn/examples/tutorial/.gitignore b/dawn/examples/tutorial/.gitignore new file mode 100644 index 000000000..ecb7a6efc --- /dev/null +++ b/dawn/examples/tutorial/.gitignore @@ -0,0 +1,8 @@ +build/ +dawn-tutorial-venv/ +laplacian_stencil_cxx_naive.cpp +laplacian_stencil_from_python.cpp +laplacian_stencil_from_python.sir +laplacian_stencil_from_toolchain.cpp +in.vtk +out.vtk diff --git a/dawn/examples/tutorial/README.md b/dawn/examples/tutorial/README.md index 6b56891dc..23c34ff26 100644 --- a/dawn/examples/tutorial/README.md +++ b/dawn/examples/tutorial/README.md @@ -1,24 +1,24 @@ # Getting Started using GTClang & dawn -In this tutorial the basic usage of **GTClang** will be demonstrated using a simple example. We will compile and execute the same stencil three times: once starting from a stencil written with the **GTClang** DSL, once starting by using Python to write SIR, and once handing over SIR to dawn using C++. +In this tutorial the basic usage of the dawn and gtclang executables will be demonstrated using a simple example. +We will compile and execute the same stencil three times: once starting from a stencil written with the gtclang DSL, once starting by using Python to write SIR, and once handing over SIR to dawn using C++. + #### Prerequisites -For section one of this tutorial, ensure to have a GTClang executable available. The README in the GTClang subdirectory has instructions on how to build this project. -To ensure to have a compatible GridTools version for subsequent parts of the tutorial, set the `GTCLANG_ENABLE_GRIDTOOLS=ON` flag while building. -Section two expects the required headers to be installed in the default install-directory of dawn. This is achieved by installing dawn with the bundle. -See the README [here](../../README.md) for instructions on how to build dawn. +Dawn and gtclang should be built with `ENABLE_TESTING=ON` to ensure GridTools support is added. +See the README [here](../../README.md) for instructions on how to do that. +The third part requires python to be built. +This should be automatic if a python installation is detected, but you can ensure this is done by setting `DAWN_REQUIRE_PYTHON=ON` when configuring the project. -Section three requires a python installation of dawn. The instructions on how to build this can be found [here](../../src/dawn4py/README.md) +The instructions below also rely on the build and/or installation `bin/` directories of dawn and gtclang to be added to the shell's `PATH` environment variable. ## 1. Writing a Stencil in the GTClang SIR and Compiling the Stencil -For the purpose of this exercise, we will write a simple finite difference stencil to find the laplacian of a function. In **GTClang** this can be achieved using very few lines of code, demonstrated in `laplacian_stencil.cpp`: +For the purpose of this exercise, we will write a simple finite difference stencil to find the Laplacian of a function. +This can be achieved using very few lines of code using the gtclang DSL dialect, demonstrated in [laplacian_stencil.cpp](laplacian_stencil.cpp) file: -``` -globals { - //grid spacing - double dx; -}; +```c++ +globals { double dx; }; stencil laplacian_stencil { storage_ij out_field; @@ -26,90 +26,127 @@ stencil laplacian_stencil { Do() { vertical_region(k_start, k_end) { out_field[i,j] = (-4*in_field[i,j] + in_field[i+1,j] + in_field[i-1,j] + in_field[i,j-1] + in_field[i,j+1])/(dx*dx); - } - } -}; +} } }; ``` -**GTClang** allows a simplification for indices which are not offset. So, `in_field[i+1,j]` could be written simply as `in_field[i+1]`. Center accesses can be dropped altogether. `in_field[i,j]` can be `in_field`. +This code defines two fields, which are the arguments to the stencil. +The variable `dx` is the grid spacing and is read-only (during the stencil run), which is modelled as a global in GTClang. +Observe how close the actual Laplacian stencil is to the numerical formula (c.f. for example [wikipedia](https://en.wikipedia.org/wiki/Finite_difference#Finite_difference_in_several_variables)), which close to no boiler plate. -This code defines two fields which will serve as the arguments to the stencil. The variable `dx` is the grid spacing and is read-only (during the stencil run), which is modelled as a global in **GTClang**. Observe how close the actual Laplacian stencil is to the numerical formula (c.f. for example [wikipedia](https://en.wikipedia.org/wiki/Finite_difference#Finite_difference_in_several_variables)), which close to no boiler plate. Save the stencil as `laplacian_stencil.cpp`. +The gtclang DSL allows a simplification for indices which are not offset. +So, `in_field[i+1,j]` could be written simply as `in_field[i+1]`. +Center accesses can be omitted altogether. `in_field[i,j]` can be `in_field`. -For the purpose of this tutorial we are going to use the `C++-naive` backend. To compile the stencil use: -``` -./gtclang -backend=c++-naive laplacian_stencil.cpp -o laplacian_stencil_cxx_naive.cpp +For the purpose of this tutorial we are going to use the `c++-naive` backend. To compile the stencil to C++ code run +```bash +dawn/dawn/examples/tutorial $ gtclang laplacian_stencil.cpp -backend=c++-naive -o laplacian_stencil_cxx_naive.cpp ``` +Make sure this file is generated in the `dawn/dawn/examples/tutorial` diretory, as the next step looks for that file there. + ## 2. Writing and Compiling the Driver Code -**GTClang** output a c++11-compliant source file. This code reads in a field `in_field`, applies the stencil, and writes the result into `out_field`. To use this, we need a driver. For the purpose of this exercise we are going initialize `in_field` to a wave function `in(x,y) = sin(x)*sin(y)`, since the Laplacian of this is the same wave again, but with inverted phase and twice the amplitude, and thus easy to check. The driver code is located in `laplacian_driver.cpp` and should be straightforward. The actual stencil launch is just one line: +The gtclang executable ran the compiler and code generation, and output a C++11-compliant source file. +This `dawn_generated::cxxnaive::laplacian_stencil::run(out_field, in_field)` method reads in a field `in_field`, applies the stencil, and writes the result into `out_field`. +To demonstrate this we will need a driver around this. +For the purpose of this exercise we are going initialize `in_field` pointwise to a wave function `in(x,y) = sin(x)*sin(y)`, since the Laplacian of this is the same wave again, but with inverted phase and twice the amplitude, and therefore easy to check. +The driver code is located in [`laplacian_driver.cpp`](laplacian_driver.cpp) and should be straightforward to understand. +The stencil launch is just one line: -``` +```c++ +// Create class instance dawn_generated::cxxnaive::laplacian_stencil laplacian_naive(dom, out, in); +// Set global laplacian_naive.set_dx(dx); -laplacian_naive.run(out, in); //launch stencil +// Run the stencil +laplacian_naive.run(out, in); ``` -the run method could now be called in a time loop, for example to simulate diffusion. To facilitate the compilation, a `CMakeLists.txt` file has been provided. To compile the code: +The run method could be called in a time loop, for example to simulate diffusion. +To facilitate the compilation, a `CMakeLists.txt` file has been provided. To compile the code: -``` -mkdir build && cd build && cmake .. && make +```bash +dawn/dawn/examples/tutorial $ cmake -S . -B build -DDawn_DIR=/lib/cmake/Dawn +dawn/dawn/examples/tutorial $ cmake --build build ``` -This will place an executable called `laplacian_driver` in the tutorial directory. When that executable is run, two `vtk` files will be written. Those can be viewed using [ParaView](https://www.paraview.org/). `in.vtk` shows the initial conditions. If `out.vtk` is loaded on top, the inversion of phase and twofold increase in amplitude can clearly be seen, as well as the halos around the domain, which would overlap with a "neighboring" MPI rank in practical implementations. +If Protobuf and GridTools were not built as a bundle with Dawn and GTClang, then `Protobuf_DIR` and `GridTools_DIR` may need to also be specified. - +This will place an executable called `laplacian_driver` in the tutorial directory. +Run it: -## 3. Use Python to generate SIR - -Another option to use **dawn** without having to rely on the **GTClang** DSL is to use the Python interface provided. - -To do this start by loading the virtual environment: -``` -cd .. -source ../.project_venv/bin/activate -``` -and run the stencil-file: -``` -python laplacian_stencil.py -v +```bash +dawn/dawn/examples/tutorial $ build/laplacian_driver ``` +When that executable is run, two `vtk` files will be written. +Those can be viewed using [ParaView](https://www.paraview.org/). `in.vtk` shows the initial conditions. +If `out.vtk` is loaded on top, the inversion of phase and twofold increase in amplitude can clearly be seen, as well as the halos around the domain, which would overlap with a "neighboring" MPI rank in practical implementations. -The python file will do three things: + -1) Print the SIR generated within to `stdout` -2) The python exploits the c interface to **dawn** (which is easily callable from python) to compile the SIR to C++ code, using the C++ naive backend again (`laplacian_stencil_from_python.cpp`). -3) Write the SIR to disk in binary form (`laplacian_stencil_from_python.sir`) +## 3. Use Python to generate SIR -You can check that the generated code is in fact equal to the code generated using the **GTClang** DSL from the example above by changing line `6` from +Another option to use dawn without having to rely on the gtclang DSL is to use the Python interface provided to directly construct the stencil intermediate representation. -``` -#include "laplacian_stencil_cxx_naive.cpp" +To do this, start by creating a virtual environment and installing the dawn package into it +```bash +dawn/dawn/examples/tutorial $ python3 -m venv dawn-tutorial-venv +dawn/dawn/examples/tutorial $ source dawn-tutorial-venv/bin/activate +dawn/dawn/examples/tutorial $ pip install /dawn ``` -to +The `setup.py` file should detect that you already built Dawn with `DAWN_REQUIRE_PYTHON` and will use that shared library instead of recompiling everything again. +Then run the python script [`laplacian_stencil.py`](laplacian_stencil.py): +```bash +dawn/dawn/examples/tutorial $ python laplacian_stencil.py -v ``` -#include "laplacian_stencil_from_python.cpp" + +The python file will do three things: + +1. Print the generated SIR within to `stdout` if `-v` or `--verbose` is passed +2. Call the optimizer and generate code using the C++ naive backend (`laplacian_stencil_from_python.cpp`) +3. Write the SIR to disk in json form (`laplacian_stencil_from_python.sir`) + +You can check that the generated code is in fact equal to the code generated using the gtclang DSL from the example above by changing the include line: + +```c++ +- #include "laplacian_stencil_cxx_naive.cpp" ++ #include "laplacian_stencil_from_python.cpp" ``` then re-compile and re-run the driver -``` -make && ./laplacian-driver +```bash +dawn/dawn/examples/tutorial $ cmake --build build +dawn/dawn/examples/tutorial $ build/laplacian-_driver ``` -The python file can roughly be divided into three sections. The bulk of the AST of the stencil is generated in function `create_vertical_region_stmt`, providing the equivalent information as presented in the **gtclang** stencil. To this end, the builder in `dawn/python/dawn/sir.py` is leveraged. The following lines then deal with writing of the SIR to file and setting up the options to launch the dawn compiler. +The python file `laplacian_stencil.py` can roughly be divided into three sections. +The bulk of the AST of the stencil is generated in function `create_vertical_region_stmt`, providing the equivalent information as presented in the gtclang stencil. +To this end, the builder in `dawn/python/dawn/sir.py` is leveraged. +The lines following that then deal with writing of the SIR to file and setting up the options to launch the dawn compiler. -## 4. Generate code from SIR using dawn from C++ +## 4. Generate code from SIR using dawn-opt -As a final exercise, the C interface to dawn is again used to compile the same example. This time, however, the interface is called from a C++ file. It might not be directly clear why one would want to do such a thing. The use case for this option would be to be able to leverage **dawn** coming from a different frontend than **GTClang**. In this situation, the SIR could be produced by means of protobuf (located in `/dawn/src/dawn/SIR/proto/`). However, this example will use the SIR written to disk by the preceding example, so please make sure that you followed along beforehand. Switch to the cpp example and build the `dawn_standalone` binary: +As a final exercise, the `dawn-opt` and `dawn-codegen` programs will be used to generate the same example, this time from the SIR saved to disk by the previous tutorial section, `laplacian_stencil_from_python.sir`. +```bash +dawn/dawn/examples/tutorial $ dawn-opt laplacian_stencil_from_python.sir | dawn-codegen --backend=c++-naive -o laplacian_stencil_from_toolchain.cpp ``` -cd cpp -mkdir build && cd $_ -cmake .. && make && cd .. -build/dawn_standalone ../laplacian_stencil_from_python.sir + +The `dawn-opt` command runs the optiizer, generating an optimizer internal intermediate representation (IIR), then pipes that to `dawn-codegen` which generates the C++ code. +Again, you can make sure that the code is still equivalent to our reference by modifying the driver code, simply replace: + +```c++ +- #include "laplacian_stencil_cxx_naive.cpp" ++ #include "laplacian_stencil_from_toolchain.cpp" ``` -consider opening the file `dawn_standalone.cpp` to see whats happening: the binary SIR written by the last example is deserialized and the C interface to dawn is called to generate C++-naive code once again. Again, you can make sure that the code is still equivalent to our reference by modifying the driver code, simply replace `#include "laplacian_stencil_cxx_naive.cpp` by `cpp/laplacian_stencil_from_standalone.cpp`. +and recompile: + +```bash +dawn/dawn/examples/tutorial $ cmake --build build +dawn/dawn/examples/tutorial $ build/laplacian_driver +``` diff --git a/dawn/examples/tutorial/cpp/CMakeLists.txt b/dawn/examples/tutorial/cpp/CMakeLists.txt deleted file mode 100644 index de9613473..000000000 --- a/dawn/examples/tutorial/cpp/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -cmake_minimum_required(VERSION 3.13) -project(dawn_standalone LANGUAGES CXX) - -find_package(Dawn REQUIRED) - -add_executable(dawn_standalone dawn_standalone.cpp) -target_link_libraries(dawn_standalone PUBLIC Dawn::DawnCShared) diff --git a/dawn/examples/tutorial/cpp/dawn_standalone.cpp b/dawn/examples/tutorial/cpp/dawn_standalone.cpp deleted file mode 100644 index 2e4039143..000000000 --- a/dawn/examples/tutorial/cpp/dawn_standalone.cpp +++ /dev/null @@ -1,59 +0,0 @@ -//===--------------------------------------------------------------------------------*- C++ -*-===// -// _ -// | | -// __| | __ ___ ___ ___ -// / _` |/ _` \ \ /\ / / '_ | -// | (_| | (_| |\ V V /| | | | -// \__,_|\__,_| \_/\_/ |_| |_| - Compiler Toolchain -// -// -// This file is distributed under the MIT License (MIT). -// See LICENSE.txt for details. -// -//===------------------------------------------------------------------------------------------===// -#include "dawn-c/Compiler.h" -#include "dawn-c/Options.h" -#include "dawn-c/TranslationUnit.h" -#include -#include -#include -#include - -int main(int argc, char* argv[]) { - if(argc != 2) { - std::cerr << "Usage: " << argv[0] << " " << std::endl; - return 1; - } - - std::ifstream inputFile(argv[1]); - if(!inputFile.is_open()) { - std::cerr << "Could not open file: " << argv[1] << std::endl; - return 1; - } - - std::stringstream ss; - ss << inputFile.rdbuf(); - - auto options = dawnOptionsCreate(); - auto backend = dawnOptionsEntryCreateString("c++-naive"); - dawnOptionsSet(options, "Backend", backend); - - auto str = ss.str(); - auto translationUnit = dawnCompile(str.c_str(), str.length(), options); - - std::ofstream ofs("laplacian_stencil_from_standalone.cpp"); - - char** ppDefines; - int numPPDefines; - dawnTranslationUnitGetPPDefines(translationUnit, &ppDefines, &numPPDefines); - for(int i = 0; i < numPPDefines; i++) { - ofs << ppDefines[i] << "\n"; - } - - ofs << dawnTranslationUnitGetGlobals(translationUnit); - ofs << dawnTranslationUnitGetStencil(translationUnit, "laplacian_stencil"); - - ofs.close(); - - return 0; -} diff --git a/dawn/examples/tutorial/laplacian_driver.cpp b/dawn/examples/tutorial/laplacian_driver.cpp index b4b0865a0..2956d1709 100644 --- a/dawn/examples/tutorial/laplacian_driver.cpp +++ b/dawn/examples/tutorial/laplacian_driver.cpp @@ -9,8 +9,8 @@ // 2. Generated by starting by using Python to write SIR // #include "laplacian_stencil_from_python.cpp" -// 3. Generated by handing over SIR to dawn using C++ -// #include "cpp/laplacian_stencil_from_standalone.cpp" +// 3. Generated by handing over SIR to dawn using the toolchain executables +// #include "laplacian_stencil_from_toolchain.cpp" #include diff --git a/dawn/examples/tutorial/laplacian_stencil.cpp b/dawn/examples/tutorial/laplacian_stencil.cpp index 097d90802..15066522b 100644 --- a/dawn/examples/tutorial/laplacian_stencil.cpp +++ b/dawn/examples/tutorial/laplacian_stencil.cpp @@ -1,22 +1,10 @@ -#include "gtclang_dsl_defs/gtclang_dsl.hpp" - -using namespace gtclang::dsl; - -globals { - // grid spacing - double dx; -}; +globals { double dx; }; stencil laplacian_stencil { - // output fields - storage out_field; - // input fields - storage in_field; - + storage_ij out_field; + storage_ij in_field; Do() { vertical_region(k_start, k_end) { - // finite difference laplacian, c.f. - // https://en.wikipedia.org/wiki/Finite_difference#Finite_difference_in_several_variables out_field[i, j] = (-4 * in_field[i, j] + in_field[i + 1, j] + in_field[i - 1, j] + in_field[i, j - 1] + in_field[i, j + 1]) / (dx * dx); diff --git a/dawn/examples/tutorial/laplacian_stencil.py b/dawn/examples/tutorial/laplacian_stencil.py index 00f2b3cb3..c46a3a081 100644 --- a/dawn/examples/tutorial/laplacian_stencil.py +++ b/dawn/examples/tutorial/laplacian_stencil.py @@ -54,7 +54,9 @@ def main(args: argparse.Namespace): sir_utils.make_binary_operator( sir_utils.make_field_access_expr("in", [0, 0, 0]), "*", - sir_utils.make_literal_access_expr("-4.0", sir_utils.BuiltinType.Float), + sir_utils.make_literal_access_expr( + "-4.0", sir_utils.BuiltinType.Float + ), ), "+", sir_utils.make_binary_operator( @@ -83,7 +85,9 @@ def main(args: argparse.Namespace): ] ) - vertical_region_stmt = sir_utils.make_vertical_region_decl_stmt(body_ast, interval, SIR.VerticalRegion.Forward) + vertical_region_stmt = sir_utils.make_vertical_region_decl_stmt( + body_ast, interval, SIR.VerticalRegion.Forward + ) stencils_globals = sir_utils.GlobalVariableMap() stencils_globals.map["dx"].double_value = 0.0 @@ -95,7 +99,10 @@ def main(args: argparse.Namespace): sir_utils.make_stencil( OUTPUT_NAME, sir_utils.make_ast([vertical_region_stmt]), - [sir_utils.make_field("out"), sir_utils.make_field("in")], + [ + sir_utils.make_field("out", sir_utils.make_field_dimensions_cartesian()), + sir_utils.make_field("in", sir_utils.make_field_dimensions_cartesian()), + ], ) ], global_variables=stencils_globals, @@ -107,11 +114,11 @@ def main(args: argparse.Namespace): # serialize the SIR to file sir_file = open("./laplacian_stencil_from_python.sir", "wb") - sir_file.write(sir.SerializeToString()) + sir_file.write(sir_utils.to_json(sir)) sir_file.close() # compile - code = dawn4py.compile(sir, backend="c++-naive") + code = dawn4py.compile(sir, backend=dawn4py.CodeGenBackend.CXXNaive) # write to file print(f"Writing generated code to '{OUTPUT_PATH}'") @@ -120,8 +127,15 @@ def main(args: argparse.Namespace): if __name__ == "__main__": - parser = argparse.ArgumentParser(description="Generate a simple laplace stencil using Dawn compiler") + parser = argparse.ArgumentParser( + description="Generate a simple laplace stencil using Dawn compiler" + ) parser.add_argument( - "-v", "--verbose", dest="verbose", action="store_true", default=False, help="Print the generated SIR", + "-v", + "--verbose", + dest="verbose", + action="store_true", + default=False, + help="Print the generated SIR", ) main(parser.parse_args()) diff --git a/dawn/scripts/refactor/.gitignore b/dawn/scripts/.gitignore similarity index 100% rename from dawn/scripts/refactor/.gitignore rename to dawn/scripts/.gitignore diff --git a/dawn/scripts/_dawn4py.cpp.in b/dawn/scripts/_dawn4py.cpp.in new file mode 100644 index 000000000..431f789cc --- /dev/null +++ b/dawn/scripts/_dawn4py.cpp.in @@ -0,0 +1,91 @@ +#include "dawn/SIR/SIR.h" +#include "dawn/IIR/StencilInstantiation.h" + +#include "dawn/Serialization/SIRSerializer.h" +#include "dawn/Serialization/IIRSerializer.h" + +#include "dawn/Compiler/Driver.h" +#include "dawn/CodeGen/Driver.h" + +#include +#include +#include + +#include +#include + +namespace py = ::pybind11; + +PYBIND11_MODULE(_dawn4py, m) { + m.doc() = "Dawn DSL toolchain"; // optional module docstring + + // Enumerations + {{ SIRSerializerFormat }} + {{ IIRSerializerFormat }} + + {{ PassGroup }} + {{ CodeGenBackend }} + + // Options structs + {{ OptimizerOptions }} + {{ CodeGenOptions }} + + m.def("default_pass_groups", &dawn::defaultPassGroups, + "Return a list of default optimizer pass groups"); + + m.def("run_optimizer_sir", [](const std::string& sir, + dawn::SIRSerializer::Format format, + const std::list& groups, + const dawn::Options& options) { + return dawn::run(sir, format, groups, options); + }, + "Lower the stencil IR to a stencil instantiation map and (optionally) run optimization passes.", + "A list of default optimization passes is returned from default_pass_groups().", + py::arg("sir"), + py::arg("format") = dawn::SIRSerializer::Format::Byte, + py::arg("groups") = std::list(), + py::arg("options") = dawn::Options() + ); + + m.def("run_optimizer_iir", [](const std::map& stencilInstantiationMap, + dawn::IIRSerializer::Format format, + const std::list& groups, + const dawn::Options& options) { + return dawn::run(stencilInstantiationMap, format, groups, options); + }, + "Optimize the stencil instantiation map.", + "A list of default optimization passes is returned from default_pass_groups().", + py::arg("stencil_instantiation_map"), + py::arg("format") = dawn::IIRSerializer::Format::Byte, + py::arg("groups") = std::list(), + py::arg("options") = dawn::Options() + ); + + m.def("run_codegen", [](const std::map& stencilInstantiationMap, + dawn::IIRSerializer::Format format, + dawn::codegen::Backend backend, + const dawn::codegen::Options& options) { + return dawn::codegen::run(stencilInstantiationMap, format, backend, options); + }, + "Generate code from the stencil instantiation map.", + py::arg("stencil_instantiation_map"), + py::arg("format") = dawn::IIRSerializer::Format::Byte, + py::arg("backend") = dawn::codegen::Backend::GridTools, + py::arg("options") = dawn::codegen::Options() + ); + + m.def("compile_sir", [](const std::string& sir, dawn::SIRSerializer::Format format, + const std::list& groups, const dawn::Options& optimizerOptions, + dawn::codegen::Backend backend, const dawn::codegen::Options& codegenOptions) { + return dawn::compile(sir, format, groups, optimizerOptions, backend, codegenOptions); + }, + "Compile the stencil IR: lower, optimize, and generate code.", + "Runs the default_pass_groups() unless the 'groups' argument is passed.", + py::arg("sir"), + py::arg("format") = dawn::SIRSerializer::Format::Byte, + py::arg("groups") = dawn::defaultPassGroups(), + py::arg("optimizer_options") = dawn::Options(), + py::arg("backend") = dawn::codegen::Backend::GridTools, + py::arg("codegen_options") = dawn::codegen::Options() + ); +} diff --git a/dawn/scripts/make_pybind11_sources.py b/dawn/scripts/make_pybind11_sources.py new file mode 100644 index 000000000..a1f4ce574 --- /dev/null +++ b/dawn/scripts/make_pybind11_sources.py @@ -0,0 +1,321 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +##===-----------------------------------------------------------------------------*- Python -*-===## +## _ +## | | +## __| | __ ___ ___ ___ +## / _` |/ _` \ \ /\ / / '_ | +## | (_| | (_| |\ V V /| | | | +## \__,_|\__,_| \_/\_/ |_| |_| - Compiler Toolchain +## +## +## This file is distributed under the MIT License (MIT). +## See LICENSE.txt for details. +## +##===------------------------------------------------------------------------------------------===## + +from collections import namedtuple +import numbers +import os +import re +import subprocess + +THIS_DIR = os.path.dirname(__file__) +DAWN_CPP_SRC_ROOT = os.path.join(THIS_DIR, os.pardir, "src", "dawn") +DAWN4PY_MODULE_DIR = os.path.join(THIS_DIR, os.pardir, "src", "dawn4py") +TEMPLATE_FILE = os.path.join(THIS_DIR, "_dawn4py.cpp.in") +OUTPUT_FILE = os.path.join(DAWN4PY_MODULE_DIR, "_dawn4py.cpp") + +_CPP_TO_PYTHON_TYPE_MAPPING = {"std::string": str} + + +# define OPT(TYPE, NAME, DEFAULT_VALUE, OPTION, OPTION_SHORT, HELP, VALUE_NAME, HAS_VALUE, F_GROUP) +opt_regexp = re.compile( + r'(?!//)\s*OPT\(\s*(?P[^,]+)\s*,\s*(?P[^,]+)\s*,\s*(?P[^,]+)\s*,\s*"(?P