diff --git a/.github/workflows/pd.yml b/.github/workflows/pd.yml new file mode 100644 index 000000000..8b8af45db --- /dev/null +++ b/.github/workflows/pd.yml @@ -0,0 +1,87 @@ +name: Trigger Physical Design Workflow +on: + pull_request: + types: + - opened + - synchronize + - reopened + - ready_for_review + - labeled +env: + USER: runner + +# Cancel the current workflow when new commit pushed +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number }} + cancel-in-progress: true + +jobs: + test-emit: + if: '! github.event.pull_request.draft' + name: "Test elaborate" + runs-on: [self-hosted, linux, nixos] + strategy: + fail-fast: false + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} + - name: "Test elaborate" + run: | + configArray=( $(ls configgen/generated | sed 's/\.json$//') ) + for cfg in "${configArray[@]}"; do + echo "Building .#t1.${cfg}.ip.rtl" + if ! nix build ".#t1.${cfg}.ip.rtl" -L; then + failed_rtl_configs+=("${cfg}.ip") + fi + if ! nix run ".#ci-helper" -- runOMTests --config ${cfg}; then + failed_om+=("${cfg}") + fi + done + if [ -n "${failed_rtl_configs[*]}" ]; then + echo -e "## Failed RTL\n" >> "$GITHUB_STEP_SUMMARY" + for cfg in "${failed_rtl_configs[@]}"; do + echo "* ${cfg}" >> $GITHUB_STEP_SUMMARY + done + echo -e "## Failed RTL\n" >> "$GITHUB_STEP_SUMMARY" + for cfg in "${failed_om[@]}"; do + echo "* ${cfg}" >> $GITHUB_STEP_SUMMARY + done + printf "\n" >> $GITHUB_STEP_SUMMARY + fi + + physical-design-report: + name: "Request physical design report" + if: ${{ success() && (contains(github.event.pull_request.labels.*.name, 'PD-Lane') || contains(github.event.pull_request.labels.*.name, 'PD-Lane-DBG'))}} + runs-on: ubuntu-latest + needs: [test-emit] + steps: + - name: "Request report" + env: + # Use env key can help us inspect the data + JSON_CTX: ${{ toJson(github.event.pull_request.labels.*.name) }} + run: | + # GitHub `toJson` will pretty print JSON and causing multiple line escape issue + # So we have to redirect it to file here + printf "$JSON_CTX" > _ctx.json + pdType=$(jq -r 'map(select(. | test("^PD-Lane.*"))) | .[0]' _ctx.json) + if [[ -z "$pdType" ]] || [[ "$pdType" == "null" ]]; then + echo "Unable to filter Physical Design type" + exit 1 + fi + + commitSha="${{ github.event.pull_request.head.sha }}" + prId="${{ github.event.pull_request.number }}" + jq -n \ + --arg commit_sha "$commitSha" \ + --arg pr_id "$prId" \ + --arg pd_type "$pdType" \ + '{"event_type":"ci_success","client_payload":{"commit_sha": $commit_sha,"pr_id": $pr_id, "pd_type": $pd_type }}' \ + > payload.json + curl -L \ + -X POST \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer ${{ secrets.T1_INHOUSE_PAT }}" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + "${{ secrets.T1_INHOUSE_URL }}" \ + -d '@payload.json' diff --git a/.github/workflows/trace.yml b/.github/workflows/trace.yml new file mode 100644 index 000000000..07d675386 --- /dev/null +++ b/.github/workflows/trace.yml @@ -0,0 +1,60 @@ +name: Compile Wave Trace +on: + pull_request: + types: + - opened + - synchronize + - reopened + - ready_for_review + - labeled +env: + USER: runner + +# Cancel the current workflow when new commit pushed +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number }} + cancel-in-progress: true + +jobs: + gen-test-plan: + if: '! github.event.pull_request.draft' + name: "Generate test plan" + runs-on: [self-hosted, linux, nixos] + outputs: + testplan: ${{ steps.get-all-configs.outputs.out }} + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} + - id: "get-all-configs" + run: echo "out=$(nix run .#ci-helper generateTestPlan)" > $GITHUB_OUTPUT + + build-vcs-emulators: + name: "Build VCS trace emulators" + needs: [gen-test-plan] + runs-on: [self-hosted, linux, nixos, BIGRAM] + strategy: + fail-fast: false + matrix: ${{ fromJSON(needs.gen-test-plan.outputs.testplan) }} + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} + - name: "Build vcs emulator" + run: | + nix build '.#t1.${{ matrix.config }}.ip.vcs-emu-trace' --impure --no-link --cores 64 + + # In the future, we may choose Verdi for trace, and left verilator trace only for performance evaluation + build-verilator-trace-emulators: + name: "Build verilator trace emulators" + needs: [gen-test-plan] + runs-on: [self-hosted, linux, nixos, BIGRAM] + strategy: + fail-fast: false + matrix: ${{ fromJSON(needs.gen-test-plan.outputs.testplan) }} + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} + - name: "Build verilator emulator with trace" + run: nix build '.#t1.${{ matrix.config }}.ip.verilator-emu-trace' -L --no-link --cores 64 \ No newline at end of file diff --git a/.github/workflows/vcs.yml b/.github/workflows/vcs.yml index 09ab3ec9a..82b9dcf76 100644 --- a/.github/workflows/vcs.yml +++ b/.github/workflows/vcs.yml @@ -1,4 +1,4 @@ -name: VCS +name: VCS Test on: pull_request: types: @@ -100,5 +100,5 @@ jobs: ref: ${{ github.head_ref }} - name: "Print step summary" run: | - nix run ".#ci-helper" -- postCI --failed-tests-file-path ./failed-tests.md --emuType vcs + nix run ".#ci-helper" -- postCI --failed-tests-file-path ./failed-tests.md --emu-type vcs cat ./failed-tests.md >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/pr.yml b/.github/workflows/verilator.yml similarity index 55% rename from .github/workflows/pr.yml rename to .github/workflows/verilator.yml index 94a3f19cc..f8b2a60b7 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/verilator.yml @@ -1,4 +1,4 @@ -name: PR +name: Verilator Test on: pull_request: types: @@ -69,87 +69,6 @@ jobs: echo -n matrix= >> "$GITHUB_OUTPUT" nix run ".#ci-helper" -- generateCiMatrix --runnersAmount "$RUNNERS" >> "$GITHUB_OUTPUT" - build-trace-emulators: - name: "Build trace emulator" - needs: [gen-test-plan] - runs-on: [self-hosted, linux, nixos] - strategy: - fail-fast: false - matrix: ${{ fromJSON(needs.gen-test-plan.outputs.testplan) }} - steps: - - uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.head.sha }} - - name: "Build verilator emulator with trace" - run: nix build '.#t1.${{ matrix.config }}.ip.verilator-emu-trace' -L --no-link --cores 64 - - test-emit: - if: '! github.event.pull_request.draft' - name: "Test elaborate" - runs-on: [self-hosted, linux, nixos] - strategy: - fail-fast: false - steps: - - uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.head.sha }} - - name: "Test elaborate" - run: | - configArray=( $(ls configgen/generated | sed 's/\.json$//') ) - for cfg in "${configArray[@]}"; do - echo "Building .#t1.${cfg}.ip.rtl" - if ! nix build ".#t1.${cfg}.ip.rtl" -L; then - failed_rtl_configs+=("${cfg}.ip") - fi - echo "Building .#t1.${cfg}.subsystem.rtl" - if ! nix build ".#t1.${cfg}.subsystem.rtl" -L; then - failed_rtl_configs+=("${cfg}.subsystem") - fi - done - if [ -n "${failed_rtl_configs[*]}" ]; then - echo -e "## Failed RTL\n" >> "$GITHUB_STEP_SUMMARY" - for cfg in "${failed_rtl_configs[@]}"; do - echo "* ${cfg}" >> $GITHUB_STEP_SUMMARY - done - printf "\n" >> $GITHUB_STEP_SUMMARY - fi - - physical-design-report: - name: "Request physical design report" - if: ${{ success() && (contains(github.event.pull_request.labels.*.name, 'PD-Lane') || contains(github.event.pull_request.labels.*.name, 'PD-Lane-DBG'))}} - runs-on: ubuntu-latest - needs: [test-emit] - steps: - - name: "Request report" - env: - # Use env key can help us inspect the data - JSON_CTX: ${{ toJson(github.event.pull_request.labels.*.name) }} - run: | - # GitHub `toJson` will pretty print JSON and causing multiple line escape issue - # So we have to redirect it to file here - printf "$JSON_CTX" > _ctx.json - pdType=$(jq -r 'map(select(. | test("^PD-Lane.*"))) | .[0]' _ctx.json) - if [[ -z "$pdType" ]] || [[ "$pdType" == "null" ]]; then - echo "Unable to filter Physical Design type" - exit 1 - fi - - commitSha="${{ github.event.pull_request.head.sha }}" - prId="${{ github.event.pull_request.number }}" - jq -n \ - --arg commit_sha "$commitSha" \ - --arg pr_id "$prId" \ - --arg pd_type "$pdType" \ - '{"event_type":"ci_success","client_payload":{"commit_sha": $commit_sha,"pr_id": $pr_id, "pd_type": $pd_type }}' \ - > payload.json - curl -L \ - -X POST \ - -H "Accept: application/vnd.github+json" \ - -H "Authorization: Bearer ${{ secrets.T1_INHOUSE_PAT }}" \ - -H "X-GitHub-Api-Version: 2022-11-28" \ - "${{ secrets.T1_INHOUSE_URL }}" \ - -d '@payload.json' - run-testcases: name: "Run testcases" needs: [gen-matrix] @@ -164,9 +83,6 @@ jobs: - name: "Run testcases" run: | nix run ".#ci-helper" -- runTests --jobs "${{ matrix.jobs }}" - - name: "Run OM tests" - run: | - nix run ".#ci-helper" -- runOMTests --jobs "${{ matrix.jobs }}" report: name: "Report CI result" diff --git a/script/ci/src/Main.scala b/script/ci/src/Main.scala index b6b4c7c59..8564ce6b2 100644 --- a/script/ci/src/Main.scala +++ b/script/ci/src/Main.scala @@ -157,7 +157,7 @@ object Main: val Array(config, caseName) = testName.split(",") println("\n") Logger.info( - s"${BOLD}[${index + 1}/${allJobs.length}]${RESET} Running VCS for test case $caseName with config $config" + s"${BOLD}[${index + 1}/${allJobs.length}]${RESET} Simulating test case $caseName with config $config" ) val testAttr = testType.toLowerCase() match @@ -175,7 +175,7 @@ object Main: ) catch case _ => - Logger.error(s"emulation for config $config, case $caseName fail") + Logger.error(s"Emulation for config $config, case $caseName fail") println("-" * 50) println(os.proc("nix", "log", testAttr).call().out) println("-" * 50) @@ -185,9 +185,11 @@ object Main: val testSuccess = os.read(testResultPath / "offline-check-status").trim() == "0" if !testSuccess then - Logger.error(s"Offline check for $caseName ($config) failed") + Logger.error(s"Offline check FAILED for $caseName ($config)") allFailedTest :+ s"t1.$config.cases.$caseName" - else allFailedTest + else + Logger.info(s"Offline check PASS for $caseName ($config)") + allFailedTest end findFailedTests val failedTests = findFailedTests() @@ -200,35 +202,33 @@ object Main: @main def runOMTests( - jobs: String + config: String ): Unit = - val configs = jobs.split(";").map(_.split(",")(0)) - configs.distinct.foreach: config => - Seq("omreader", "emu-omreader").foreach: target => - val command = Seq( - "nix", - "run", - s".#t1.$config.ip.$target", - "--", - "run", - "--dump-methods" - ) - println("\n") - Logger.info( - s"Running OM test with command $BOLD'${command.mkString(" ")}'$RESET" - ) - val outputs = os.proc(command).call().out.trim() - Logger.trace(s"Outputs:\n${outputs}") + Seq("omreader", "verilator-emu-omreader", "vcs-emu-omreader").foreach: target => + val command = Seq( + "nix", + "run", + s".#t1.$config.ip.$target", + "--", + "run", + "--dump-methods" + ) + println("\n") + Logger.info( + s"Running OM test with command $BOLD'${command.mkString(" ")}'$RESET" + ) + val outputs = os.proc(command).call().out.trim() + Logger.trace(s"Outputs:\n${outputs}") - Seq("vlen =", "dlen =").foreach: keyword => - if outputs.contains(keyword) then - Logger.info( - s"Keyword $BOLD'$keyword'$RESET found - ${GREEN}Pass!$RESET" - ) - else - Logger.fatal( - s"Keyword $BOLD'$keyword'$RESET not found - ${RED}Fail!$RESET" - ) + Seq("vlen =", "dlen =").foreach: keyword => + if outputs.contains(keyword) then + Logger.info( + s"Keyword $BOLD'$keyword'$RESET found - ${GREEN}Pass!$RESET" + ) + else + Logger.fatal( + s"Keyword $BOLD'$keyword'$RESET not found - ${RED}Fail!$RESET" + ) end runOMTests // PostCI do the below four things: @@ -245,7 +245,10 @@ object Main: name = "cycle-update-file-path", doc = "specify the cycle update markdown file output path" ) cycleUpdateFilePath: Option[String], - emuType: String = "verilator" + @arg( + name = "emu-type", + doc = "Specify emulation type" + ) emuType: String = "verilator" ) = val failedTestsFile = os.Path(failedTestsFilePath, os.pwd) os.write.over(failedTestsFile, "## Failed Tests\n") @@ -268,8 +271,12 @@ object Main: s".#t1.$config.cases._allEmuResult" case "vcs" => s".#t1.$config.cases._allVCSEmuResult" case _ => Logger.fatal(s"Invalid test type ${emuType}") - val emuResultPath = - os.Path(nixResolvePath(s".#t1.$config.cases._allEmuResult")) + val emuResultPath = os.Path(nixResolvePath( + resultAttr, + if emuType.toLowerCase() == "vcs" then + Seq("--impure") + else Seq() + )) Logger.info("Collecting failed tests") os.walk(emuResultPath) diff --git a/tests/make-emu-result.nix b/tests/make-emu-result.nix index 514a67bbb..a8540f806 100644 --- a/tests/make-emu-result.nix +++ b/tests/make-emu-result.nix @@ -163,11 +163,17 @@ let postCheck = '' set +e + echo "[nix] Checking VCS event log" "${verilator-emu}/bin/offline" \ --elf-file ${testCase}/bin/${testCase.pname}.elf \ --log-file $rtlEventOutPath \ --log-level ERROR &> $out/offline-check-journal printf "$?" > $out/offline-check-status + if [ "$(cat $out/offline-check-status)" == "0" ]; then + echo "[nix] VCS difftest PASS" + else + echo "[nix] VCS difftest FAIL" + fi set -e '';