diff --git a/.github/workflows/user_project_ci.yml b/.github/workflows/user_project_ci.yml index 87f7d3ee0..6da2f6329 100644 --- a/.github/workflows/user_project_ci.yml +++ b/.github/workflows/user_project_ci.yml @@ -8,7 +8,7 @@ on: workflow_dispatch: jobs: - download_caravel: + download_deps: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 @@ -33,95 +33,71 @@ jobs: run: | sudo mkdir -p ${{ env.PDK_ROOT }} sudo chown -R $USER:$USER ${{ env.PDK_ROOT }} - make install + make setup + cd ${{ env.MCW_ROOT }} + rm -rf gds maglef openlane spi LICENSE manifest docs litex lvs .git cd ${{ env.CARAVEL_ROOT }} rm -rf gds maglef openlane spi LICENSE manifest .git - name: Tarball Caravel run: | - tar -cf /tmp/caravel.tar -C $CARAVEL_ROOT . + tar -cf /tmp/caravel.tar -C ${{ env.CARAVEL_ROOT }} . - name: Upload Caravel Tarball uses: actions/upload-artifact@v2 with: name: caravel-tarball path: /tmp/caravel.tar - - download_deps: - runs-on: ubuntu-latest - strategy: - matrix: - targets: ["pdk-with-volare", "install_mcw", "openlane", "setup-timing-scripts", "precheck"] - needs: [download_caravel] - steps: - - uses: actions/checkout@v2 - - name: Set up QEMU - uses: docker/setup-qemu-action@v1 + - name: Tarball mgmt_core_wrapper + run: | + tar -cf /tmp/mgmt_core_wrapper.tar -C ${{ env.MCW_ROOT }} . - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 + - name: Upload mgmt_core_wrapper Tarball + uses: actions/upload-artifact@v2 + with: + name: mgmt_core_wrapper-tarball + path: /tmp/mgmt_core_wrapper.tar - - name: Setup Environment Variables + - name: Tarball openlane run: | - echo "PDK_ROOT=$GITHUB_WORKSPACE/pdk" >> $GITHUB_ENV - echo "OPENLANE_ROOT=$GITHUB_WORKSPACE/openlane_src" >> $GITHUB_ENV - echo "CARAVEL_ROOT=$GITHUB_WORKSPACE/caravel" >> $GITHUB_ENV - echo "MCW_ROOT=$GITHUB_WORKSPACE/mgmt_core_wrapper" >> $GITHUB_ENV - echo "TIMING_ROOT=$GITHUB_WORKSPACE/timing-scripts" >> $GITHUB_ENV - echo "PRECHECK_ROOT=$GITHUB_WORKSPACE/mpw_precheck" >> $GITHUB_ENV - echo "MPW_TAG=main" >> $GITHUB_ENV - - - name: Get dependencies name - run: | - if [[ "${{ matrix.targets }}" == "install_mcw" ]]; then - echo "dep_name=mgmt_core_wrapper" >> $GITHUB_ENV - echo "dep_root=${{ env.MCW_ROOT }}" >> $GITHUB_ENV - elif [[ "${{ matrix.targets }}" == "openlane" ]]; then - echo "dep_name=openlane" >> $GITHUB_ENV - echo "dep_root=${{ env.OPENLANE_ROOT }}" >> $GITHUB_ENV - elif [[ "${{ matrix.targets }}" == "pdk-with-volare" ]]; then - echo "dep_name=pdk" >> $GITHUB_ENV - echo "dep_root=${{ env.PDK_ROOT }}" >> $GITHUB_ENV - elif [[ "${{ matrix.targets }}" == "setup-timing-scripts" ]]; then - echo "dep_name=timing-scripts" >> $GITHUB_ENV - echo "dep_root=${{ env.TIMING_ROOT }}" >> $GITHUB_ENV - elif [[ "${{ matrix.targets }}" == "precheck" ]]; then - echo "dep_name=precheck" >> $GITHUB_ENV - echo "dep_root=${{ env.PRECHECK_ROOT }}" >> $GITHUB_ENV - fi + tar -cf /tmp/openlane.tar -C ${{ env.OPENLANE_ROOT }} . - - name: Download caravel Tarball - uses: actions/download-artifact@v2 + - name: Upload openlane Tarball + uses: actions/upload-artifact@v2 with: - name: caravel-tarball - path: /tmp + name: openlane-tarball + path: /tmp/openlane.tar - - name: Unpack caravel Tarball + - name: Tarball pdk run: | - sudo mkdir -p ${{ env.CARAVEL_ROOT }} - sudo chown -R $USER:$USER ${{ env.CARAVEL_ROOT }} - tar -xf /tmp/caravel.tar -C $CARAVEL_ROOT . + tar -cf /tmp/pdk.tar -C ${{ env.PDK_ROOT }} . - - name: Install dependencies + - name: Upload pdk Tarball + uses: actions/upload-artifact@v2 + with: + name: pdk-tarball + path: /tmp/pdk.tar + + - name: Tarball timing_scripts run: | - sudo mkdir -p ${{ env.PDK_ROOT }} - sudo chown -R $USER:$USER ${{ env.PDK_ROOT }} - make ${{ matrix.targets }} - if [[ "${{ env.dep_name }}" == "mgmt_core_wrapper" ]]; then - cd ${{ env.dep_root }} - rm -rf gds maglef openlane spi LICENSE manifest docs litex lvs .git - fi + tar -cf /tmp/timing-scripts.tar -C ${{ env.TIMING_ROOT }} . - - name: Tarball Dependencies + - name: Upload timing_scripts Tarball + uses: actions/upload-artifact@v2 + with: + name: timing-scripts-tarball + path: /tmp/timing-scripts.tar + + - name: Tarball precheck run: | - tar -cf /tmp/${{ env.dep_name }}.tar -C ${{ env.dep_root }} . + tar -cf /tmp/precheck.tar -C ${{ env.PRECHECK_ROOT }} . - - name: Upload Dependencies Tarball + - name: Upload precheck Tarball uses: actions/upload-artifact@v2 with: - name: ${{ env.dep_name }}-tarball - path: /tmp/${{ env.dep_name }}.tar + name: precheck-tarball + path: /tmp/precheck.tar hardening: timeout-minutes: 720 @@ -177,10 +153,11 @@ jobs: - name: Harden using Openlane run: | + curl https://raw.githubusercontent.com/efabless/central_CI/main/tools.json > tool_versions.json python3 $GITHUB_WORKSPACE/.github/scripts/get_designs.py --design $GITHUB_WORKSPACE for word in $(cat harden_sequence.txt); do echo "CURRENT_DESIGN=${word}" >> $GITHUB_ENV - make $word + DISABLE_VERSION_CHECK=1 make $word done rm -rf openlane/user_proj_example/runs openlane/user_project_wrapper/runs pdk openlane_src caravel mgmt_core_wrapper timing-scripts mpw_precheck @@ -272,7 +249,7 @@ jobs: - name: install cocotb run: | - make setup-cocotb + DISABLE_VERSION_CHECK=1 make setup-cocotb - name: run RTL verification run: | @@ -449,12 +426,13 @@ jobs: - name: Run STA run: | + curl https://raw.githubusercontent.com/efabless/central_CI/main/tools.json > tool_versions.json export CUP_ROOT=$GITHUB_WORKSPACE export PROJECT_ROOT=$GITHUB_WORKSPACE cd $CUP_ROOT - make extract-parasitics - make create-spef-mapping - make caravel-sta + DISABLE_VERSION_CHECK=1 make extract-parasitics + DISABLE_VERSION_CHECK=1 make create-spef-mapping + DISABLE_VERSION_CHECK=1 make caravel-sta tar -cf /tmp/timing.tar $CUP_ROOT/signoff/caravel/openlane-signoff/timing find $CUP_ROOT/signoff/caravel/openlane-signoff/timing/*/ -name "summary.log" | head -n1 \ | xargs head -n5 | tail -n1 > $CUP_ROOT/signoff/caravel/openlane-signoff/timing/all-summary.rpt @@ -469,91 +447,3 @@ jobs: echo "STA run passed" exit 0 fi - - # GL-verification: - # timeout-minutes: 720 - # runs-on: ubuntu-latest - # strategy: - # matrix: - # pdk: ["sky130A", "sky130B"] - # needs: [download_deps] - # steps: - # - uses: actions/checkout@v2 - - # - name: Set up QEMU - # uses: docker/setup-qemu-action@v1 - - # - name: Set up Docker Buildx - # uses: docker/setup-buildx-action@v1 - - # - name: Export ENVIRONMENT VARIABLES - # run: | - # echo "PDK=${{ matrix.pdk }}" >> $GITHUB_ENV - # echo "PDKPATH=$GITHUB_WORKSPACE/pdk/${{ matrix.pdk }}" >> $GITHUB_ENV - # echo "PDK_ROOT=$GITHUB_WORKSPACE/pdk" >> $GITHUB_ENV - # echo "OPENLANE_ROOT=$GITHUB_WORKSPACE/openlane_src" >> $GITHUB_ENV - # echo "CARAVEL_ROOT=$GITHUB_WORKSPACE/caravel" >> $GITHUB_ENV - # echo "MCW_ROOT=$GITHUB_WORKSPACE/mgmt_core_wrapper" >> $GITHUB_ENV - # echo "TIMING_ROOT=$GITHUB_WORKSPACE/timing-scripts" >> $GITHUB_ENV - # echo "PRECHECK_ROOT=$GITHUB_WORKSPACE/mpw_precheck" >> $GITHUB_ENV - # echo "MPW_TAG=main" >> $GITHUB_ENV - - # - name: Download PDK Tarball - # uses: actions/download-artifact@v2 - # with: - # name: pdk-tarball - # path: /tmp - - # - name: Unpack PDK Tarball - # run: | - # sudo mkdir -p ${{ env.PDK_ROOT }} - # sudo chown -R $USER:$USER ${{ env.PDK_ROOT }} - # tar -xf /tmp/pdk.tar -C $PDK_ROOT . - - # - name: Download caravel Tarball - # uses: actions/download-artifact@v2 - # with: - # name: caravel-tarball - # path: /tmp - - # - name: Unpack caravel Tarball - # run: | - # sudo mkdir -p ${{ env.CARAVEL_ROOT }} - # sudo chown -R $USER:$USER ${{ env.CARAVEL_ROOT }} - # tar -xf /tmp/caravel.tar -C $CARAVEL_ROOT . - - # - name: Download mgmt_core_wrapper Tarball - # uses: actions/download-artifact@v2 - # with: - # name: mgmt_core_wrapper-tarball - # path: /tmp - - # - name: Unpack mgmt_core_wrapper Tarball - # run: | - # sudo mkdir -p ${{ env.MCW_ROOT }} - # sudo chown -R $USER:$USER ${{ env.MCW_ROOT }} - # tar -xf /tmp/mgmt_core_wrapper.tar -C $MCW_ROOT . - - # # - name: Download Design Tarball - # # uses: actions/download-artifact@v2 - # # with: - # # name: design-tarball - # # path: /tmp - - # # - name: Unpack Design Tarball - # # run: | - # # sudo mkdir -p $GITHUB_WORKSPACE - # # sudo chown -R $USER:$USER $GITHUB_WORKSPACE - # # tar -xf /tmp/design.tar -C $GITHUB_WORKSPACE . - - # - name: install cocotb - # run: | - # make setup-cocotb - - # - name: run RTL verification - # run: | - # cd $GITHUB_WORKSPACE/verilog/dv/cocotb && $GITHUB_WORKSPACE/venv-cocotb/bin/caravel_cocotb -tl user_proj_tests/user_proj_tests_gl.yaml -verbosity debug --CI -tag gl_verification - # cnt=$(grep -c "failed" "$GITHUB_WORKSPACE/verilog/dv/cocotb/sim/gl_verification/runs.log") - # if ! [[ $cnt ]]; then cnt=0; fi - # if [[ $cnt -eq 1 ]]; then exit 0; fi - # exit 2 diff --git a/Makefile b/Makefile index ab649a1e0..98ec8ee50 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ MAKEFLAGS+=--warn-undefined-variables export CARAVEL_ROOT?=$(PWD)/caravel -PRECHECK_ROOT?=${HOME}/mpw_precheck +export PRECHECK_ROOT?=${HOME}/mpw_precheck export MCW_ROOT?=$(PWD)/mgmt_core_wrapper SIM?=RTL @@ -38,33 +38,10 @@ endif export OPENLANE_ROOT?=$(PWD)/dependencies/openlane_src export PDK_ROOT?=$(PWD)/dependencies/pdks export DISABLE_LVS?=0 +export DISABLE_VERSION_CHECK?=0 export ROOTLESS -ifeq ($(PDK),sky130A) - SKYWATER_COMMIT=f70d8ca46961ff92719d8870a18a076370b85f6c - export OPEN_PDKS_COMMIT?=78b7bc32ddb4b6f14f76883c2e2dc5b5de9d1cbc - export OPENLANE_TAG?=2023.07.19-1 - MPW_TAG ?= mpw-9g - -ifeq ($(CARAVEL_LITE),1) - CARAVEL_NAME := caravel-lite - CARAVEL_REPO := https://github.com/efabless/caravel-lite - CARAVEL_TAG := $(MPW_TAG) -else - CARAVEL_NAME := caravel - CARAVEL_REPO := https://github.com/efabless/caravel - CARAVEL_TAG := $(MPW_TAG) -endif - -endif - -ifeq ($(PDK),sky130B) - SKYWATER_COMMIT=f70d8ca46961ff92719d8870a18a076370b85f6c - export OPEN_PDKS_COMMIT?=78b7bc32ddb4b6f14f76883c2e2dc5b5de9d1cbc - export OPENLANE_TAG?=2023.07.19-1 - MPW_TAG ?= mpw-9g - ifeq ($(CARAVEL_LITE),1) CARAVEL_NAME := caravel-lite CARAVEL_REPO := https://github.com/efabless/caravel-lite @@ -75,7 +52,6 @@ else CARAVEL_TAG := $(MPW_TAG) endif -endif ifeq ($(PDK),gf180mcuD) @@ -92,16 +68,9 @@ endif # Include Caravel Makefile Targets .PHONY: % : check-caravel %: - export CARAVEL_ROOT=$(CARAVEL_ROOT) && export MPW_TAG=$(MPW_TAG) && $(MAKE) -f $(CARAVEL_ROOT)/Makefile $@ - -.PHONY: install -install: - if [ -d "$(CARAVEL_ROOT)" ]; then\ - echo "Deleting exisiting $(CARAVEL_ROOT)" && \ - rm -rf $(CARAVEL_ROOT) && sleep 2;\ + @if [ -d "$(CARAVEL_ROOT)" ]; then \ + export CARAVEL_ROOT=$(CARAVEL_ROOT) && $(MAKE) -f $(CARAVEL_ROOT)/Makefile $@; \ fi - echo "Installing $(CARAVEL_NAME).." - git clone -b $(CARAVEL_TAG) $(CARAVEL_REPO) $(CARAVEL_ROOT) --depth=1 # Install DV setup .PHONY: simenv @@ -114,14 +83,53 @@ simenv-cocotb: docker pull efabless/dv:cocotb .PHONY: setup -setup: check_dependencies install check-env install_mcw openlane pdk-with-volare setup-timing-scripts setup-cocotb precheck +setup: print_message clean_log check-python check_dependencies install-volare + @./venv/bin/$(PYTHON_BIN) -m pip install --upgrade --no-cache-dir requests >> setup.log + @./venv/bin/$(PYTHON_BIN) -u scripts/get_tools.py --openlane_root $(OPENLANE_ROOT) --precheck_root $(PRECHECK_ROOT) --pdk_root $(PDK_ROOT) --caravel_root $(CARAVEL_ROOT) --mcw_root $(MCW_ROOT) --timing_root $(TIMING_ROOT) + @echo "installing cocotb..." + @$(MAKE) setup-cocotb >> setup.log + @echo "installation complete" + +.PHONY: install-volare +install-volare: + @rm -rf ./venv >> setup.log + @$(PYTHON_BIN) -m venv ./venv >> setup.log + @./venv/bin/$(PYTHON_BIN) -m pip install --upgrade --no-cache-dir pip >> setup.log + @./venv/bin/$(PYTHON_BIN) -m pip install --upgrade --no-cache-dir volare >> setup.log + +.PHONY: check-python +check-python: +ifeq ($(shell which python3),) +$(error Please install python 3.8+) +endif # Openlane blocks=$(shell cd openlane && find * -maxdepth 0 -type d) .PHONY: $(blocks) -$(blocks): % : +$(blocks): % : check_versions $(MAKE) -C openlane $* +# Openlane open last step gui using klayout +blocks=$(shell cd openlane && find * -maxdepth 0 -type d) +.PHONY: open-gui-% +open-gui-% : + $(MAKE) -C openlane open-gui-$* + +# Openlane open last step gui using openroad +blocks=$(shell cd openlane && find * -maxdepth 0 -type d) +.PHONY: open-odb-gui-% +open-odb-gui-% : + $(MAKE) -C openlane open-odb-gui-$* + +.PHONY: clean_log +clean_log: + @rm -f setup.log + +.PHONY: print_message +print_message: + @echo "Setting up caravel_user_project environment..." + @echo "To check for installation logs, please see setup.log" + dv_patterns=$(shell cd verilog/dv && find * -maxdepth 0 -type d) cocotb-dv_patterns=$(shell cd verilog/dv/cocotb && find . -name "*.c" | sed -e 's|^.*/||' -e 's/.c//') dv-targets-rtl=$(dv_patterns:%=verify-%-rtl) @@ -195,16 +203,6 @@ make_what=setup $(blocks) $(dv-targets-rtl) $(dv-targets-gl) $(dv-targets-gl-sdf what: # $(make_what) -# Install Openlane -.PHONY: openlane -openlane: - @if [ "$$(realpath $${OPENLANE_ROOT})" = "$$(realpath $$(pwd)/openlane)" ]; then\ - echo "OPENLANE_ROOT is set to '$$(pwd)/openlane' which contains openlane config files"; \ - echo "Please set it to a different directory"; \ - exit 1; \ - fi - cd openlane && $(MAKE) openlane - #### Not sure if the targets following are of any use # Create symbolic links to caravel's main files @@ -230,47 +228,82 @@ update_caravel: check-caravel uninstall: rm -rf $(CARAVEL_ROOT) +# Install Caravel +.PHONY: install +install: clean_log check-python check_dependencies install-volare + @./venv/bin/$(PYTHON_BIN) -m pip install --upgrade --no-cache-dir requests >> setup.log + @./venv/bin/$(PYTHON_BIN) -u scripts/get_tools.py --openlane_root $(OPENLANE_ROOT) --precheck_root $(PRECHECK_ROOT) --pdk_root $(PDK_ROOT) --caravel_root $(CARAVEL_ROOT) --mcw_root $(MCW_ROOT) --timing_root $(TIMING_ROOT) --tool caravel + +# Install mgmt_core_wrapper +.PHONY: install_mcw +install_mcw: clean_log check-python check_dependencies install-volare + @./venv/bin/$(PYTHON_BIN) -m pip install --upgrade --no-cache-dir requests >> setup.log + @./venv/bin/$(PYTHON_BIN) -u scripts/get_tools.py --openlane_root $(OPENLANE_ROOT) --precheck_root $(PRECHECK_ROOT) --pdk_root $(PDK_ROOT) --caravel_root $(CARAVEL_ROOT) --mcw_root $(MCW_ROOT) --timing_root $(TIMING_ROOT) --tool mgmt_core_wrapper + +# Install pdk-with-volare +.PHONY: pdk-with-volare +pdk-with-volare: clean_log check-python check_dependencies install-volare + @./venv/bin/$(PYTHON_BIN) -m pip install --upgrade --no-cache-dir requests >> setup.log + @./venv/bin/$(PYTHON_BIN) -u scripts/get_tools.py --openlane_root $(OPENLANE_ROOT) --precheck_root $(PRECHECK_ROOT) --pdk_root $(PDK_ROOT) --caravel_root $(CARAVEL_ROOT) --mcw_root $(MCW_ROOT) --timing_root $(TIMING_ROOT) --tool pdk + +# Install openlane +.PHONY: openlane +openlane: clean_log check-python check_dependencies install-volare + @./venv/bin/$(PYTHON_BIN) -m pip install --upgrade --no-cache-dir requests >> setup.log + @./venv/bin/$(PYTHON_BIN) -u scripts/get_tools.py --openlane_root $(OPENLANE_ROOT) --precheck_root $(PRECHECK_ROOT) --pdk_root $(PDK_ROOT) --caravel_root $(CARAVEL_ROOT) --mcw_root $(MCW_ROOT) --timing_root $(TIMING_ROOT) --tool OpenLane + + +# Install timing-scripts +.PHONY: setup-timing-scripts +setup-timing-scripts: clean_log check-python check_dependencies install-volare + @./venv/bin/$(PYTHON_BIN) -m pip install --upgrade --no-cache-dir requests >> setup.log + @./venv/bin/$(PYTHON_BIN) -u scripts/get_tools.py --openlane_root $(OPENLANE_ROOT) --precheck_root $(PRECHECK_ROOT) --pdk_root $(PDK_ROOT) --caravel_root $(CARAVEL_ROOT) --mcw_root $(MCW_ROOT) --timing_root $(TIMING_ROOT) --tool timing_scripts + -# Install Pre-check -# Default installs to the user home directory, override by "export PRECHECK_ROOT=" +# Install precheck .PHONY: precheck -precheck: - if [ -d "$(PRECHECK_ROOT)" ]; then\ - echo "Deleting exisiting $(PRECHECK_ROOT)" && \ - rm -rf $(PRECHECK_ROOT) && sleep 2;\ - fi - @echo "Installing Precheck.." - @git clone --depth=1 --branch $(MPW_TAG) https://github.com/efabless/mpw_precheck.git $(PRECHECK_ROOT) - @docker pull efabless/mpw_precheck:latest +precheck: clean_log check-python check_dependencies install-volare + @./venv/bin/$(PYTHON_BIN) -m pip install --upgrade --no-cache-dir requests >> setup.log + @./venv/bin/$(PYTHON_BIN) -u scripts/get_tools.py --openlane_root $(OPENLANE_ROOT) --precheck_root $(PRECHECK_ROOT) --pdk_root $(PDK_ROOT) --caravel_root $(CARAVEL_ROOT) --mcw_root $(MCW_ROOT) --timing_root $(TIMING_ROOT) --tool precheck -.PHONY: run-precheck -run-precheck: check-pdk check-precheck - @if [ "$$DISABLE_LVS" = "1" ]; then\ - $(eval INPUT_DIRECTORY := $(shell pwd)) \ - cd $(PRECHECK_ROOT) && \ - docker run -it -v $(PRECHECK_ROOT):$(PRECHECK_ROOT) \ - -v $(INPUT_DIRECTORY):$(INPUT_DIRECTORY) \ - -v $(PDK_ROOT):$(PDK_ROOT) \ - -e INPUT_DIRECTORY=$(INPUT_DIRECTORY) \ - -e PDK_PATH=$(PDK_ROOT)/$(PDK) \ - -e PDK_ROOT=$(PDK_ROOT) \ - -e PDKPATH=$(PDKPATH) \ - -u $(shell id -u $(USER)):$(shell id -g $(USER)) \ - efabless/mpw_precheck:latest bash -c "cd $(PRECHECK_ROOT) ; python3 mpw_precheck.py --input_directory $(INPUT_DIRECTORY) --pdk_path $(PDK_ROOT)/$(PDK) license makefile default documentation consistency gpio_defines xor magic_drc klayout_feol klayout_beol klayout_offgrid klayout_met_min_ca_density klayout_pin_label_purposes_overlapping_drawing klayout_zeroarea"; \ + +.PHONY: check_versions +check_versions: + @if [ "$$DISABLE_VERSION_CHECK" = "1" ]; then\ + echo "Skipping version check"; \ else \ - $(eval INPUT_DIRECTORY := $(shell pwd)) \ - cd $(PRECHECK_ROOT) && \ - docker run -it -v $(PRECHECK_ROOT):$(PRECHECK_ROOT) \ - -v $(INPUT_DIRECTORY):$(INPUT_DIRECTORY) \ - -v $(PDK_ROOT):$(PDK_ROOT) \ - -e INPUT_DIRECTORY=$(INPUT_DIRECTORY) \ - -e PDK_PATH=$(PDK_ROOT)/$(PDK) \ - -e PDK_ROOT=$(PDK_ROOT) \ - -e PDKPATH=$(PDKPATH) \ - -u $(shell id -u $(USER)):$(shell id -g $(USER)) \ - efabless/mpw_precheck:latest bash -c "cd $(PRECHECK_ROOT) ; python3 mpw_precheck.py --input_directory $(INPUT_DIRECTORY) --pdk_path $(PDK_ROOT)/$(PDK)"; \ + ./venv/bin/$(PYTHON_BIN) -u scripts/compare_versions.py; \ fi +.PHONY: run-precheck +run-precheck: check_versions check-pdk check-precheck + $(eval INPUT_DIRECTORY := $(shell pwd)) \ + cd $(PRECHECK_ROOT) && \ + docker run -it -v $(PRECHECK_ROOT):$(PRECHECK_ROOT) \ + -v $(INPUT_DIRECTORY):$(INPUT_DIRECTORY) \ + -v $(PDK_ROOT):$(PDK_ROOT) \ + -e INPUT_DIRECTORY=$(INPUT_DIRECTORY) \ + -e PDK_PATH=$(PDK_ROOT)/$(PDK) \ + -e PDK_ROOT=$(PDK_ROOT) \ + -e PDKPATH=$(PDKPATH) \ + -u $(shell id -u $(USER)):$(shell id -g $(USER)) \ + efabless/mpw_precheck:latest bash -c "cd $(PRECHECK_ROOT) ; python3 mpw_precheck.py --input_directory $(INPUT_DIRECTORY) --pdk_path $(PDK_ROOT)/$(PDK) --private"; \ + + +.PHONY: run-precheck-no-lvs +run-precheck-no-lvs: check_versions check-pdk check-precheck + $(eval INPUT_DIRECTORY := $(shell pwd)) \ + cd $(PRECHECK_ROOT) && \ + docker run -it -v $(PRECHECK_ROOT):$(PRECHECK_ROOT) \ + -v $(INPUT_DIRECTORY):$(INPUT_DIRECTORY) \ + -v $(PDK_ROOT):$(PDK_ROOT) \ + -e INPUT_DIRECTORY=$(INPUT_DIRECTORY) \ + -e PDK_PATH=$(PDK_ROOT)/$(PDK) \ + -e PDK_ROOT=$(PDK_ROOT) \ + -e PDKPATH=$(PDKPATH) \ + -u $(shell id -u $(USER)):$(shell id -g $(USER)) \ + efabless/mpw_precheck:latest bash -c "cd $(PRECHECK_ROOT) ; python3 mpw_precheck.py --input_directory $(INPUT_DIRECTORY) --pdk_path $(PDK_ROOT)/$(PDK) license makefile consistency gpio_defines xor magic_drc klayout_feol klayout_beol klayout_offgrid klayout_met_min_ca_density klayout_pin_label_purposes_overlapping_drawing klayout_zeroarea oeb"; \ + BLOCKS = $(shell cd lvs && find * -maxdepth 0 -type d) LVS_BLOCKS = $(foreach block, $(BLOCKS), lvs-$(block)) @@ -317,20 +350,14 @@ check_dependencies: mkdir $(PWD)/dependencies; \ fi +# export CARAVEL_COMMIT=$(shell python3 scripts/get_tools.py) + export CUP_ROOT=$(shell pwd) export TIMING_ROOT?=$(shell pwd)/dependencies/timing-scripts export PROJECT_ROOT=$(CUP_ROOT) timing-scripts-repo=https://github.com/efabless/timing-scripts.git -$(TIMING_ROOT): - @mkdir -p $(CUP_ROOT)/dependencies - @git clone $(timing-scripts-repo) $(TIMING_ROOT) - -.PHONY: setup-timing-scripts -setup-timing-scripts: $(TIMING_ROOT) - @( cd $(TIMING_ROOT) && git pull ) - @#( cd $(TIMING_ROOT) && git fetch && git checkout $(MPW_TAG); ) .PHONY: install-caravel-cocotb install-caravel-cocotb: @@ -370,7 +397,7 @@ $(cocotb-dv-targets-gl): cocotb-verify-%-gl: exit 1 .PHONY: create-spef-mapping -create-spef-mapping: ./verilog/gl/user_project_wrapper.v +create-spef-mapping: check_versions ./verilog/gl/user_project_wrapper.v docker run \ --rm \ $(USER_ARGS) \ @@ -390,7 +417,7 @@ create-spef-mapping: ./verilog/gl/user_project_wrapper.v .PHONY: extract-parasitics -extract-parasitics: ./verilog/gl/user_project_wrapper.v +extract-parasitics: check_versions ./verilog/gl/user_project_wrapper.v docker run \ --rm \ $(USER_ARGS) \ @@ -412,9 +439,20 @@ extract-parasitics: ./verilog/gl/user_project_wrapper.v @$(MAKE) -C $(TIMING_ROOT) -f $(TIMING_ROOT)/timing.mk rcx-user_project_wrapper @cat ./tmp-macros-list @rm ./tmp-macros-list - + + +ifeq ($(wildcard ./tool_versions.json),) +# File doesn't exist +export OPENLANE_TAG= +export OPEN_PDKS_COMMIT= +else +# File exists +export OPENLANE_TAG=$(shell python3 ./scripts/export_env.py OpenLane) +export OPEN_PDKS_COMMIT=$(shell python3 ./scripts/export_env.py pdk) +endif + .PHONY: caravel-sta -caravel-sta: ./env/spef-mapping.tcl +caravel-sta: check_versions ./env/spef-mapping.tcl @$(MAKE) -C $(TIMING_ROOT) -f $(TIMING_ROOT)/timing.mk caravel-timing-typ -j3 @$(MAKE) -C $(TIMING_ROOT) -f $(TIMING_ROOT)/timing.mk caravel-timing-fast -j3 @$(MAKE) -C $(TIMING_ROOT) -f $(TIMING_ROOT)/timing.mk caravel-timing-slow -j3 diff --git a/docs/source/index.rst b/docs/source/index.rst index bb272cbbc..400302666 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -59,7 +59,7 @@ Prerequisites - Docker: `Linux `_ || `Windows `_ || `Mac with Intel Chip `_ || `Mac with M1 Chip `_ -- Python 3.6+ with PIP +- Python 3.8+ with PIP Quickstart @@ -116,6 +116,22 @@ Starting your project .. For an example of hardening a project please refer to `Hardening the User Project using OpenLane`_. . + + * In case a failure happens, view the last generated layout before failure: + - Last generated def file using klayout: + + .. code:: bash + + make open-gui- + .. + + - Last generated odb file using openroad-gui: + + .. code:: bash + + make open-odb-gui- + .. + #. Integrate modules into the user_project_wrapper diff --git a/openlane/Makefile b/openlane/Makefile index d2a52864c..dc72ba52e 100644 --- a/openlane/Makefile +++ b/openlane/Makefile @@ -37,6 +37,9 @@ openlane_cmd = \ -ignore_mismatches" openlane_cmd_interactive = "flow.tcl -it -file $$(realpath ./$*/interactive.tcl)" +openlane_gui_klayout_cmd = "python3 $(OPENLANE_ROOT)/gui.py --viewer klayout --format def $$(realpath ./$*/runs/$*)" +openlane_gui_openroad_cmd = "python3 $(OPENLANE_ROOT)/gui.py --viewer openroad --format odb $$(realpath ./$*/runs/$*)" + docker_mounts = \ -v $$(realpath $(PWD)/..):$$(realpath $(PWD)/..) \ -v $(PDK_ROOT):$(PDK_ROOT) \ @@ -50,6 +53,13 @@ docker_env = \ -e CARAVEL_ROOT=$(CARAVEL_ROOT) \ -e OPENLANE_RUN_TAG=$(OPENLANE_RUN_TAG) +docker_extra_args = \ + -e DISPLAY=$(DISPLAY) \ + -v /tmp/.X11-unix:/tmp/.X11-unix \ + -v $(HOME)/.Xauthority:/.Xauthority \ + --network host \ + --security-opt seccomp=unconfined + ifneq ($(MCW_ROOT),) docker_env += -e MCW_ROOT=$(MCW_ROOT) docker_mounts += -v $(MCW_ROOT):$(MCW_ROOT) @@ -102,3 +112,14 @@ ifeq ($(OPENLANE_ROOT),) @echo "Please export OPENLANE_ROOT" @exit 1 endif + +.PHONY: open-gui-% +open-gui-%: + $(docker_run) $(docker_extra_args) \ + $(OPENLANE_IMAGE_NAME) sh -c $(openlane_gui_klayout_cmd) + +.PHONY: open-odb-gui-% +open-odb-gui-%: + $(docker_run) $(docker_extra_args) \ + $(OPENLANE_IMAGE_NAME) sh -c $(openlane_gui_openroad_cmd) + diff --git a/scripts/compare_versions.py b/scripts/compare_versions.py new file mode 100644 index 000000000..4b4fdd3c9 --- /dev/null +++ b/scripts/compare_versions.py @@ -0,0 +1,49 @@ +# SPDX-FileCopyrightText: 2023 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +import os +import requests +import json + + +def compare_json(tool_versions_json_path): + try: + # Get the upstream JSON from the URL + upstream_url = 'https://raw.githubusercontent.com/efabless/central_CI/main/tools.json' + response = requests.get(upstream_url) + if response.status_code != 200: + raise ValueError(f'Failed to get upstream JSON from {upstream_url}: {response.status_code}') + upstream_json = response.json() + + if os.path.isfile(tool_versions_json_path): + with open(tool_versions_json_path, 'r') as tool_versions_file: + tool_versions_json = json.load(tool_versions_file) + else: + print("Couldn't find tool_versions.json, please run make setup") + exit(1) + + # Compare the two JSON objects + if upstream_json == tool_versions_json: + print("The upstream JSON is the same as tool_versions.json") + else: + print("The upstream JSON is different from tool_versions.json, please update by running make setup") + exit(1) + except requests.exceptions.RequestException as e: + print("An error occurred while fetching data") + print("Please check your internet connection.") + exit(1) + + +compare_json("./tool_versions.json") \ No newline at end of file diff --git a/scripts/export_env.py b/scripts/export_env.py new file mode 100644 index 000000000..a45fbdb90 --- /dev/null +++ b/scripts/export_env.py @@ -0,0 +1,41 @@ +# SPDX-FileCopyrightText: 2023 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +import argparse +import json + + +def print_commit(tool_name): + with open('tool_versions.json', 'r') as file: + tool_versions_json = json.load(file) + + if tool_name in tool_versions_json: + commit = tool_versions_json[tool_name]['commit'] + print(commit) + else: + print("Invalid tool name") + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('tool_name', help='Name of the tool to print the commit for') + args = parser.parse_args() + + print_commit(args.tool_name) + + +if __name__ == '__main__': + main() diff --git a/scripts/get_tools.py b/scripts/get_tools.py new file mode 100644 index 000000000..6767095d6 --- /dev/null +++ b/scripts/get_tools.py @@ -0,0 +1,155 @@ +# SPDX-FileCopyrightText: 2023 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +import argparse +import json +import os +import shutil +import subprocess +import tarfile +import requests +import volare +from rich.progress import ( + Progress, + TextColumn, + BarColumn, + MofNCompleteColumn, + TimeElapsedColumn, +) + + +def parse_json_file(url): + """Parses a JSON file from the given URL. + + Args: + url: The URL of the JSON file. + + Returns: + A Python dictionary containing the parsed JSON data. + """ + + response = requests.get(url) + if response.status_code != 200: + raise ValueError(f'Failed to get JSON data from {url}: {response.status_code}') + + data = response.json() + json_data = json.dumps(data, indent=4) + # Write the JSON data to a file + with open('tool_versions.json', 'w') as file: + file.write(json_data) + return data + + +def download_tools(openlane_root, precheck_root, pdk_root, caravel_root, mcw_root, timing_root, tool): + """Downloads the tools from the upstream GitHub repo. + """ + url = 'https://raw.githubusercontent.com/efabless/central_CI/main/tools.json' + data = parse_json_file(url) + f = open("setup.log", "a") + with Progress(TextColumn("[progress.description]{task.description}"), BarColumn(), MofNCompleteColumn(), TimeElapsedColumn()) as progress: + if tool: + task = progress.add_task("[cyan]Downloading Tools...", total=1) + else: + task = progress.add_task("[cyan]Downloading Tools...", total=6) + for key, value in data.items(): + if tool and key != tool: + continue + if key == "OpenLane": + progress.update(task, description="[cyan]Downloading OpenLane...") + download_tar("OpenLane", value['commit'], value['url'], openlane_root) + progress.update(task, description="[cyan]Downloading OpenLane Docker...") + os.environ['OPENLANE_IMAGE_NAME'] = f"efabless/openlane:{value['commit']}" + os.environ['IMAGE_NAME'] = f"efabless/openlane:{value['commit']}" + subprocess.run(["make", "pull-openlane"], cwd=openlane_root, env=os.environ, stderr=subprocess.STDOUT, text=True, check=True, stdout=f) + print("OpenLane downloaded successfully") + progress.update(task, advance=1) + elif key == "pdk": + progress.update(task, description="[cyan]Downloading pdk...") + progress.stop() + volare.enable(pdk_root, "sky130", value['commit']) + progress.start() + progress.update(task, advance=1) + elif key == "precheck": + progress.update(task, description="[cyan]Downloading mpw_precheck...") + download_tar("precheck", value['commit'], value['url'], precheck_root) + print("mpw_precheck downloaded successfully") + progress.update(task, advance=1) + elif key == "caravel": + progress.update(task, description="[cyan]Downloading caravel...") + download_tar("caravel", value['commit'], value['url'], caravel_root) + print("caravel downloaded successfully") + progress.update(task, advance=1) + elif key == "mgmt_core_wrapper": + progress.update(task, description="[cyan]Downloading mgmt_core_wrapper...") + download_tar("mgmt_core_wrapper", value['commit'], value['url'], mcw_root) + print("mgmt_core_wrapper downloaded successfully") + progress.update(task, advance=1) + elif key == "timing_scripts": + progress.update(task, description="[cyan]Downloading timing_scripts...") + download_tar("timing_scripts", value['commit'], value['url'], timing_root) + print("timing_scripts downloaded successfully") + progress.update(task, advance=1) + + +def download_tar(tool, version, url, tool_path): + if os.path.isdir(tool_path): + shutil.rmtree(tool_path) + os.makedirs(tool_path) + name = url.split("/")[-1] + owner = url.split("/")[-2] + # print(f"downloading {tool}") + response = requests.get(f'{url}/tarball/{version}') + if response.status_code != 200: + raise Exception(f"Failed to download {tool}") + with open(f'{os.path.dirname(tool_path)}/{version}.tar.gz', 'wb') as file: + file.write(response.content) + # print(f"extracting {os.path.dirname(tool_path)}/{version}.tar.gz") + + tar = tarfile.open(f'{os.path.dirname(tool_path)}/{version}.tar.gz', 'r:gz') + tar.extractall(path=os.path.dirname(tool_path)) + tar.close() + os.rename(f'{os.path.dirname(tool_path)}/{owner}-{name}-{version[0:7]}', f'{tool_path}') + os.remove(f'{os.path.dirname(tool_path)}/{version}.tar.gz') + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('--openlane_root', required=True, + help='Path to the OpenLANE root directory') + parser.add_argument('--precheck_root', required=True, + help='Path to the Precheck root directory') + parser.add_argument('--pdk_root', required=True, + help='Path to the PDK root directory') + parser.add_argument('--caravel_root', required=True, + help='Path to the Caravel root directory') + parser.add_argument('--mcw_root', required=True, + help='Path to the Mgmt Core Wrapper root directory') + parser.add_argument('--timing_root', required=True, + help='Path to the Timing Scripts root directory') + parser.add_argument('--tool', required=False, + help='Name of the tool to download') + + args = parser.parse_args() + download_tools(openlane_root=args.openlane_root, + precheck_root=args.precheck_root, + pdk_root=args.pdk_root, + caravel_root=args.caravel_root, + mcw_root=args.mcw_root, + timing_root=args.timing_root, + tool=args.tool) + + +if __name__ == '__main__': + main()