diff --git a/.github/actions/oseda-caching/action.yml b/.github/actions/oseda-caching/action.yml new file mode 100644 index 00000000..d1a09b4a --- /dev/null +++ b/.github/actions/oseda-caching/action.yml @@ -0,0 +1,50 @@ +# Copyright (c) 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +# Author: Philippe Sauter + +name: 'OSEDA Caching' +description: 'Cache OSEDA Docker Images' + +runs: + using: 'composite' + steps: + - name: Get image name from docker-compose + id: get-image + shell: bash + run: | + echo "UID=$(id -u)" >> $GITHUB_ENV + echo "GID=$(id -g)" >> $GITHUB_ENV + IMAGE=$(docker compose config | awk '/image:/{print $2}' | head -n1) + echo "IMAGE_NAME=$IMAGE" >> $GITHUB_ENV + + - name: Restore Docker image cache + id: restore-cache + uses: actions/cache@v4 + with: + path: /tmp/oseda.tar.gz + key: oseda-${{ env.IMAGE_NAME }} + + - name: Check disk usage + shell: bash + run: df -h + + - name: Load cached Docker image + shell: bash + if: steps.restore-cache.outputs.cache-hit == 'true' + run: docker import /tmp/oseda.tar.gz + + - name: Prepare Docker image for caching + shell: bash + if: steps.restore-cache.outputs.cache-hit != 'true' + run: | + docker system prune -af + docker compose pull + df -h + docker save $IMAGE_NAME | pigz -9 -f > /tmp/oseda.tar.gz + df -h + + - name: Check disk usage + shell: bash + run: df -h diff --git a/.github/actions/oseda-cmd/action.yml b/.github/actions/oseda-cmd/action.yml new file mode 100644 index 00000000..512b8532 --- /dev/null +++ b/.github/actions/oseda-cmd/action.yml @@ -0,0 +1,75 @@ +# Copyright (c) 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +# Author: Philippe Sauter + +name: 'OSEDA Command Action' +description: 'Sets up OSEDA environment and runs commands in a Docker container' + +inputs: + cmd: + description: 'Command to run in the OSEDA container' + required: true + image_file_name: + description: 'Name of the artifact to download (default: oseda-image)' + required: false + default: 'oseda-image' + service_name: + description: 'Name of the Docker service (default: from ./docker-compose.yml)' + required: false + default: '' + +runs: + using: 'composite' + steps: + - name: Set up Docker environment + shell: bash + run: | + echo "UID=$(id -u)" >> $GITHUB_ENV + echo "GID=$(id -g)" >> $GITHUB_ENV + + - name: Get image name from docker-compose + id: get-image + shell: bash + run: | + IMAGE=$(docker compose config | awk '/image:/{print $2}' | head -n 1) + if [ -z "$IMAGE" ]; then + echo "ERROR: No image found in docker-compose.yml" + exit 1 + fi + echo "IMAGE_NAME=$IMAGE" >> $GITHUB_ENV + + - name: Download Docker image from cache + continue-on-error: true + uses: actions/cache/restore@v4 + with: + key: oseda-${{ env.IMAGE_NAME }} + path: /tmp/oseda.tar.gz + + - name: Load or pull Docker image + shell: bash + run: | + if [ -f "/tmp/oseda.tar.gz" ]; then + docker import /tmp/oseda.tar.gz + echo "Loaded image $IMAGE_NAME from artifacts/cache" + else + docker compose pull + fi + + - name: Determine service name if not provided + shell: bash + run: | + if [ -z "${{ inputs.service_name }}" ]; then + SERVICE_NAME=$(docker compose config --services | head -n 1) + echo "service_name=$SERVICE_NAME" >> $GITHUB_ENV + else + echo "service_name=${{ inputs.service_name }}" >> $GITHUB_ENV + fi + + - name: Run commands in OSEDA container + shell: bash + run: | + docker compose up -d + docker compose exec ${{ env.service_name }} bash -c "source ~/.bashrc; ${{ inputs.cmd }}" | tee result.log + echo "result_log=$(pwd)/result.log" >> $GITHUB_ENV diff --git a/.github/scripts/check_sim.sh b/.github/scripts/check_sim.sh new file mode 100755 index 00000000..eb7c19fa --- /dev/null +++ b/.github/scripts/check_sim.sh @@ -0,0 +1,45 @@ +#!/bin/bash +# Copyright (c) 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +# Author: Philippe Sauter + +LOG_FILE=$1 + +expected_lines=( + "\[CORE\] Start fetching instructions" + "\[JTAG\] Halting hart 0" + "\[JTAG\] Resumed hart 0" + "\[UART\] Hello World!" + "\[UART\] Result: 0x8940, Cycles: 0xBD" + "\[UART\] Tick" + "\[UART\] Tock" +) + +for line in "${expected_lines[@]}"; do + if ! grep -q "$line" "$LOG_FILE"; then + echo "Error: Expected line not found in the log: '$line'" + exit 1 + fi +done + +tick=$(awk '/\[UART\] Tick/ {print $2+0}' "$LOG_FILE") +tock=$(awk '/\[UART\] Tock/ {print $2+0}' "$LOG_FILE") + +echo "Tick time: ${tick}" +echo "Tock time: ${tock}" + +time_diff=$(echo "scale=2; ($tock - $tick) / 1000000" | bc) +time_diff_ms=$(printf "%.0f" $time_diff) + +# 1.5ms tolerance +if ((time_diff_ms >= 9 && time_diff_ms <= 11)); then + echo "Timer correct: The gap between Tick and Tock is approximately 10ms: ${time_diff}ms." +else + echo "Timer Error: The gap between Tick and Tock is not approximately 10ms: ${time_diff}ms." + exit 1 +fi + +echo "Hello world simulation passed." +exit 0 diff --git a/.github/workflows/full-flow.yml b/.github/workflows/full-flow.yml new file mode 100644 index 00000000..095a4ae1 --- /dev/null +++ b/.github/workflows/full-flow.yml @@ -0,0 +1,49 @@ +# Copyright (c) 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +# Author: Philippe Sauter + +name: Full-flow + +on: + workflow_dispatch: + pull_request: + branches: + - main + release: + types: + - created + +jobs: + backend: + runs-on: ubuntu-latest + timeout-minutes: 180 + steps: + - name: Checkout repository (with submodules) + uses: actions/checkout@v4 + with: + submodules: true + + - name: Run Yosys, OpenROAD and KLayout + uses: ./.github/actions/oseda-cmd + with: + cmd: "make yosys && make openroad && make klayout" + - name: Upload openroad output + uses: actions/upload-artifact@v4 + with: + name: croc-openroad + path: openroad/out + continue-on-error: true + - name: Upload openroad reports + uses: actions/upload-artifact@v4 + with: + name: croc-openroad + path: openroad/reports + continue-on-error: true + - name: Upload gds + uses: actions/upload-artifact@v4 + with: + name: croc-gds + path: klayout/croc_chip.gds + continue-on-error: true diff --git a/.github/workflows/license.yml b/.github/workflows/license.yml new file mode 100644 index 00000000..ccfd37b4 --- /dev/null +++ b/.github/workflows/license.yml @@ -0,0 +1,25 @@ +# Copyright (c) 2022 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +# Author: Jannis Schönleber + +name: lint-license + +on: + workflow_dispatch: + +jobs: + lint-license: + runs-on: ubuntu-latest + steps: + - name: lint license + uses: pulp-platform/pulp-actions/lint-license@v2 + with: + license: | + Copyright \(c\) (\d{4}(-\d{4})?\s)?(ETH Zurich and University of Bologna|lowRISC contributors). + (Solderpad Hardware License, Version 0.51|Licensed under the Apache License, Version 2.0), see LICENSE for details. + SPDX-License-Identifier: (SHL-0.51|Apache-2.0) + exclude_paths: | + deps + include/version.h \ No newline at end of file diff --git a/.github/workflows/short-flow.yml b/.github/workflows/short-flow.yml new file mode 100644 index 00000000..812b6174 --- /dev/null +++ b/.github/workflows/short-flow.yml @@ -0,0 +1,74 @@ +# Copyright (c) 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +# Author: Philippe Sauter + +name: Short Flow + +on: + push: + branches: + - '**' + +jobs: + simulation: + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - name: Checkout repository (with submodules) + uses: actions/checkout@v4 + with: + submodules: true + + - name: Run simulation commands in OSEDA + uses: ./.github/actions/oseda-cmd + with: + cmd: "make sw && make verilator" + - name: Upload built software + uses: actions/upload-artifact@v4 + with: + name: croc-sw + path: sw/bin + continue-on-error: true + - name: Upload waveform + uses: actions/upload-artifact@v4 + with: + name: croc-waveform + path: croc.vcd + continue-on-error: true + + - name: Upload simulation output + uses: actions/upload-artifact@v4 + with: + name: simulation-output + path: ${{ env.result_log }} + - name: Check simulation output + shell: bash + run: ./.github/scripts/check_sim.sh ${{ env.result_log }} + + synthesis: + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - name: Checkout repository (with submodules) + uses: actions/checkout@v4 + with: + submodules: true + + - name: Setup OSEDA container + uses: ./.github/actions/oseda-cmd + with: + cmd: "make yosys && tail -n 40 yosys/reports/*area.rpt" + - name: Upload synthesis reports + uses: actions/upload-artifact@v4 + with: + name: croc-synth-reports + path: yosys/reports + continue-on-error: true + - name: Upload netlist + uses: actions/upload-artifact@v4 + with: + name: croc-netlist + path: yosys/out + continue-on-error: true diff --git a/docker-compose.yml b/docker-compose.yml index fec8e3d8..21415bb8 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,8 +5,6 @@ # Authors: # - Philippe Sauter -version: '3' - services: pulp-docker: image: hpretl/iic-osic-tools:2024.10 @@ -19,4 +17,5 @@ services: stdin_open: true tty: true working_dir: /fosic/designs/croc - entrypoint: /bin/bash + entrypoint: /dockerstartup/scripts/ui_startup.sh + command: --skip bash diff --git a/klayout/def2gds.sh b/klayout/def2gds.sh index a6dd3508..04f09b18 100755 --- a/klayout/def2gds.sh +++ b/klayout/def2gds.sh @@ -1,6 +1,8 @@ #! /bin/bash # klayout batch mode for transferring def to gds +export KLAYOUT=${KLAYOUT:-klayout} + # this directory klayout_dir=$(realpath $(dirname "${BASH_SOURCE[0]}")) root_dir=$(dirname $klayout_dir) diff --git a/openroad/openroad.mk b/openroad/openroad.mk index a8446f69..3495e3d1 100644 --- a/openroad/openroad.mk +++ b/openroad/openroad.mk @@ -41,7 +41,9 @@ $(OR_OUT_FILES): $(NETLIST) $(OR_DIR)/scripts/*.tcl $(OR_DIR)/src/*.tcl $(OR_DIR SAVE="$(SAVE)" \ REPORTS="$(REPORTS)" \ PDK="$(CROC_ROOT)/ihp13/pdk" \ + QT_QPA_PLATFORM=$$(if [ -z "$$DISPLAY" ]; then echo "offscreen"; else echo "$$QT_QPA_PLATFORM"; fi) \ $(OPENROAD) scripts/chip.tcl \ + $$(if [ "$(gui)" = "1" ]; then echo "-gui"; fi) \ -log $(PROJ_NAME).log \ 2>&1 | TZ=UTC gawk '{ print strftime("[%Y-%m-%d %H:%M %Z]"), $$0 }'; diff --git a/start_linux.sh b/start_linux.sh index 4dd03c90..3d361da9 100755 --- a/start_linux.sh +++ b/start_linux.sh @@ -10,8 +10,7 @@ IMG=hpretl/iic-osic-tools:2024.10 docker pull $IMG -env UID=$(id -u) GID=$(id -g) docker-compose run \ +env UID=$(id -u) GID=$(id -g) docker compose run \ -e PS1="\[\033[01;32m\]docker-osic: \[\033[00m\]\[\033[01;34m\]\w\[\033[00m\] $" \ - -e DISPLAY=$DISPLAY \ -v /tmp/.X11-unix:/tmp/.X11-unix \ pulp-docker