diff --git a/.github/workflows/synth-sv.yml b/.github/workflows/synth-sv.yml new file mode 100644 index 0000000..5525477 --- /dev/null +++ b/.github/workflows/synth-sv.yml @@ -0,0 +1,117 @@ +name: synth-sv + +on: + workflow_dispatch: + push: + branches: + - master + pull_request: + branches: + - master + +env: + CIRCT_VERSION: 1.72.0 + CIRCT_ARCHIVE: "circt-full-shared-linux-x64.tar.gz" + DEPENDENCIES_DIR: "deps" + MLIR_TARGETS_PATH: "lib/cmake/mlir/MLIRTargets.cmake" + BUILD_DIR: "build" + UTOPIA_EXECUTABLE: "src/umain" + +jobs: + synthesize-system-verilog: + strategy: + matrix: + kernel: [addconst, matrixmul2, movingsum, muxmul, polynomial2, scalar3] + config: [STUB] + ## A workaround to initialize an empty config array. + exclude: + - config: STUB + include: + ## addconst configs. + - kernel: addconst + config: add_int_2 + ## matrixmul configs. + - kernel: matrixmul2 + config: add_int_2_mul_int3 + ## movingsum configs. + - kernel: movingsum + config: add_int_2 + - kernel: movingsum + config: add_int_8 + ## muxmul configs. + - kernel: muxmul + config: add_int_2_mul_int3 + ## polynomial2 configs. + - kernel: polynomial2 + config: add_int_2_mul_int3 + - kernel: polynomial2 + config: add_int_8_mul_int15 + ## scalar3 configs. + - kernel: scalar3 + config: add_int_2_mul_int3 + + runs-on: ubuntu-latest + env: + MODULE_OUTPUT_PATH: "output.sv" + LIBRARY_OUTPUT_PATH: "lib.sv" + steps: + - name: Check out repository code + uses: actions/checkout@v4 + + - name: Download APT dependencies + run: | + sudo apt update + sudo apt install build-essential clang cmake g++ gcc liblpsolve55-dev lld make ninja-build libctemplate-dev verilator + + - name: Download and configure CIRCT & LLVM + env: + CIRCT_SOURCE: "https://github.com/llvm/circt/releases/download/firtool-${{env.CIRCT_VERSION}}/${{env.CIRCT_ARCHIVE}}" + CIRCT_DIR: "firtool-${{env.CIRCT_VERSION}}" + run: | + mkdir "${{env.DEPENDENCIES_DIR}}" + cd "${{env.DEPENDENCIES_DIR}}" + wget "${{env.CIRCT_SOURCE}}" + tar -xvf "${{env.CIRCT_ARCHIVE}}" + sed -i 's'/\ + 'foreach(_target "LLVMSupport" "LLVMCore" "LLVMMC" "LLVMTarget" "LLVMAsmParser" "LLVMBinaryFormat" '\ + '"LLVMBitReader" "LLVMBitWriter" "LLVMFrontendOpenMP" "LLVMTransformUtils" "LLVMTargetParser" "LLVMIRReader" '\ + '"LLVMipo" "LLVMLinker" "LLVMPasses" "LLVMMCParser" "LLVMLineEditor" "LLVMTableGen" "LLVMCoroutines" "LLVMExecutionEngine" '\ + '"LLVMObject" "LLVMOrcJIT" "LLVMJITLink" "LLVMAnalysis" "LLVMAggressiveInstCombine" "LLVMInstCombine" "LLVMScalarOpts" '\ + '"LLVMVectorize" "LLVMX86CodeGen" "LLVMX86Desc" "LLVMX86Info" "LLVMX86AsmParser" "LLVMX86Disassembler" "CIRCTAffineToLoopSchedule" '\ + '"CIRCTArcToLLVM" "CIRCTCalyxToFSM" "CIRCTCalyxToHW" "CIRCTCalyxNative" "CIRCTCombToArith" "CIRCTCombToLLVM" "CIRCTCombToSMT" '\ + '"CIRCTConvertToArcs" "CIRCTDCToHW" "CIRCTExportChiselInterface" "CIRCTExportVerilog" "CIRCTFIRRTLToHW" "CIRCTFSMToSV" '\ + '"CIRCTHandshakeToDC" "CIRCTHandshakeToHW" "CIRCTHWArithToHW" "CIRCTHWToLLHD" "CIRCTHWToLLVM" "CIRCTHWToBTOR2" "CIRCTHWToSMT" '\ + '"CIRCTHWToSV" "CIRCTHWToSystemC" "CIRCTLLHDToLLVM" "CIRCTLoopScheduleToCalyx" "CIRCTMooreToCore" "CIRCTPipelineToHW" "CIRCTSCFToCalyx" '\ + '"CIRCTSeqToSV" "CIRCTSimToSV" "CIRCTCFToHandshake" "CIRCTVerifToSMT" "CIRCTVerifToSV" "CIRCTExportFIRRTL" "CIRCTComb" '\ + '"CIRCTCombTransforms" "CIRCTDebug" "CIRCTESI" "CIRCTFIRRTL" "CIRCTImportFIRFile" "CIRCTMSFT" "CIRCTMSFTTransforms" "CIRCTHW" '\ + '"CIRCTLLHD" "CIRCTMoore" "CIRCTOM" "CIRCTOMEvaluator" "CIRCTSeq" "CIRCTSeqTransforms" "CIRCTSV" "CIRCTSVTransforms" "CIRCTFSM" '\ + '"CIRCTFSMTransforms" "CIRCTHandshake" "CIRCTHandshakeTransforms" "CIRCTHWArith" "CIRCTVerif" "CIRCTLTL" "CIRCTEmit" "CIRCTFirtool" )'\ + /\ + 'foreach(_target "LLVMSupport" "LLVMCore" "LLVMMC" "LLVMTarget" "LLVMAsmParser" "LLVMBinaryFormat" "LLVMBitReader" "LLVMBitWriter" '\ + '"LLVMFrontendOpenMP" "LLVMTransformUtils" "LLVMTargetParser" "LLVMIRReader" "LLVMipo" "LLVMLinker" "LLVMPasses" "LLVMMCParser" '\ + '"LLVMLineEditor" "LLVMTableGen" "LLVMCoroutines" "LLVMExecutionEngine" "LLVMObject" "LLVMOrcJIT" "LLVMJITLink" "LLVMAnalysis" '\ + '"LLVMAggressiveInstCombine" "LLVMInstCombine" "LLVMScalarOpts" "LLVMVectorize" "LLVMX86CodeGen" "LLVMX86Desc" "LLVMX86Info" '\ + '"LLVMX86AsmParser" "LLVMX86Disassembler")/' "${{env.CIRCT_DIR}}/${{env.MLIR_TARGETS_PATH}}" + cd "${{github.workspace}}" + + - name: Configure Utopia HLS build + env: + CIRCT_DIR: "firtool-${{env.CIRCT_VERSION}}" + run: | + cmake -S . -B "${{env.BUILD_DIR}}" -G Ninja -DCMAKE_CXX_COMPILER=clang++ \ + -DCMAKE_PREFIX_PATH="${{github.workspace}}/${{env.DEPENDENCIES_DIR}}/${{env.CIRCT_DIR}}" \ + -DSRC_FILES="${{github.workspace}}/examples/${{matrix.kernel}}/${{matrix.kernel}}.cpp" + + - name: Build Utopia HLS + run: | + cmake --build "${{env.BUILD_DIR}}" + + - name: Run SystemVerilog modules generation + run: | + "${{env.BUILD_DIR}}/${{env.UTOPIA_EXECUTABLE}}" hls --config \ + "${{github.workspace}}/examples/${{matrix.kernel}}/${{matrix.config}}.json" \ + -l --out-sv "${{env.MODULE_OUTPUT_PATH}}" --out-sv-lib "${{env.LIBRARY_OUTPUT_PATH}}" + + - name: Run Verilator + run: | + verilator --lint-only -Wall -Wno-DECLFILENAME "${{env.MODULE_OUTPUT_PATH}}" "${{env.LIBRARY_OUTPUT_PATH}}" diff --git a/README.md b/README.md index 8cec3a0..4d5de9c 100644 --- a/README.md +++ b/README.md @@ -276,9 +276,13 @@ For example, given subdirectory `polynomial2`, the compilation and execution com ```bash cmake -S . -B build -G Ninja -DCMAKE_PREFIX_PATH=~/firtool-1.72.0 -DSRC_FILES="~/utopia-hls/examples/polynomial2/polynomial2.cpp" cmake --build build -build/src/umain hls --config examples/polynomial2/polynomial2.json -a --out-sv output +build/src/umain hls --config examples/polynomial2/add_int_2_mul_int3.json -a --out-sv output ``` +The execution command is going to pass a JSON configuration file (with 2 and 3 pipeline stages for integer addition +and multiplication respectively) to Utopia HLS, resulting in the creation of the file `output`, containing a SystemVerilog +module for Polynomial2 kernel with a greedy ASAP-scheduling. + ## DFCxx Documentation WORK IN PROGRESS diff --git a/examples/addconst/addconst.json b/examples/addconst/add_int_2.json similarity index 100% rename from examples/addconst/addconst.json rename to examples/addconst/add_int_2.json diff --git a/examples/idct/add_int_1_sub_int_1_mul_int_3.json b/examples/idct/add_int_1_sub_int_1_mul_int_3.json new file mode 100644 index 0000000..19d272c --- /dev/null +++ b/examples/idct/add_int_1_sub_int_1_mul_int_3.json @@ -0,0 +1,5 @@ +{ + "ADD_INT": 1, + "SUB_INT": 1, + "MUL_INT": 3 +} diff --git a/examples/idct/idct.json b/examples/idct/idct.json deleted file mode 100644 index a1b4704..0000000 --- a/examples/idct/idct.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "MUL_INT": 3, - "ADD_INT": 1, - "SUB_INT": 1 -} diff --git a/examples/matrixmul2/add_int_2_mul_int3.json b/examples/matrixmul2/add_int_2_mul_int3.json new file mode 100644 index 0000000..da7ea74 --- /dev/null +++ b/examples/matrixmul2/add_int_2_mul_int3.json @@ -0,0 +1,4 @@ +{ + "ADD_INT": 2, + "MUL_INT": 3 +} diff --git a/examples/matrixmul2/matrixmul2.json b/examples/matrixmul2/matrixmul2.json deleted file mode 100644 index 5be4a3a..0000000 --- a/examples/matrixmul2/matrixmul2.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "MUL_INT": 3, - "ADD_INT": 2 -} diff --git a/examples/movingsum/movingsum.json b/examples/movingsum/add_int_2.json similarity index 100% rename from examples/movingsum/movingsum.json rename to examples/movingsum/add_int_2.json diff --git a/examples/movingsum/add_int_8.json b/examples/movingsum/add_int_8.json new file mode 100644 index 0000000..8c0c11a --- /dev/null +++ b/examples/movingsum/add_int_8.json @@ -0,0 +1,3 @@ +{ + "ADD_INT": 8 +} diff --git a/examples/muxmul/add_int_2_mul_int3.json b/examples/muxmul/add_int_2_mul_int3.json new file mode 100644 index 0000000..da7ea74 --- /dev/null +++ b/examples/muxmul/add_int_2_mul_int3.json @@ -0,0 +1,4 @@ +{ + "ADD_INT": 2, + "MUL_INT": 3 +} diff --git a/examples/muxmul/muxmul.json b/examples/muxmul/muxmul.json deleted file mode 100644 index 5be4a3a..0000000 --- a/examples/muxmul/muxmul.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "MUL_INT": 3, - "ADD_INT": 2 -} diff --git a/examples/polynomial2/add_int_2_mul_int3.json b/examples/polynomial2/add_int_2_mul_int3.json new file mode 100644 index 0000000..da7ea74 --- /dev/null +++ b/examples/polynomial2/add_int_2_mul_int3.json @@ -0,0 +1,4 @@ +{ + "ADD_INT": 2, + "MUL_INT": 3 +} diff --git a/examples/polynomial2/add_int_8_mul_int15.json b/examples/polynomial2/add_int_8_mul_int15.json new file mode 100644 index 0000000..9f1d750 --- /dev/null +++ b/examples/polynomial2/add_int_8_mul_int15.json @@ -0,0 +1,4 @@ +{ + "ADD_INT": 8, + "MUL_INT": 15 +} diff --git a/examples/polynomial2/polynomial2.json b/examples/polynomial2/polynomial2.json deleted file mode 100644 index 5be4a3a..0000000 --- a/examples/polynomial2/polynomial2.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "MUL_INT": 3, - "ADD_INT": 2 -} diff --git a/examples/scalar3/add_int_2_mul_int3.json b/examples/scalar3/add_int_2_mul_int3.json new file mode 100644 index 0000000..da7ea74 --- /dev/null +++ b/examples/scalar3/add_int_2_mul_int3.json @@ -0,0 +1,4 @@ +{ + "ADD_INT": 2, + "MUL_INT": 3 +} diff --git a/examples/scalar3/scalar3.json b/examples/scalar3/scalar3.json deleted file mode 100644 index 5be4a3a..0000000 --- a/examples/scalar3/scalar3.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "MUL_INT": 3, - "ADD_INT": 2 -} diff --git a/test/model/dfcxx/idct.cpp b/test/model/dfcxx/idct.cpp index b49770b..a9c31b1 100644 --- a/test/model/dfcxx/idct.cpp +++ b/test/model/dfcxx/idct.cpp @@ -17,8 +17,8 @@ TEST(DFCxx, IdctAsap) { IDCT kernel; DFLatencyConfig config = { {dfcxx::ADD_INT, 1}, + {dfcxx::SUB_INT, 1}, {dfcxx::MUL_INT, 3}, - {dfcxx::SUB_INT, 1} }; EXPECT_EQ(kernel.compile(config, nullDevicePath, dfcxx::ASAP), true); } @@ -29,8 +29,8 @@ TEST(DFCxx, IdctAsap) { // IDCT kernel; // DFLatencyConfig config = { // {dfcxx::ADD_INT, 1}, -// {dfcxx::MUL_INT, 3}, -// {dfcxx::SUB_INT, 1} +// {dfcxx::SUB_INT, 1}, +// {dfcxx::MUL_INT, 3} // }; // EXPECT_EQ(kernel.compile(config, nullDevicePath, dfcxx::Linear), true); // }