| #!/bin/bash |
| # Copyright lowRISC contributors. |
| # Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| # SPDX-License-Identifier: Apache-2.0 |
| |
| |
| # Utility script to load ROM contents into FPGA bitstream. |
| # Usage: |
| # cd $REPO_TOP |
| # ./util/fpga/splice_rom.sh |
| # |
| # The updated bitstream is located at the same place as the original Vivado bitstream e.g. at |
| # $REPO_TOP/build/lowrisc_systems_chip_earlgrey_cw310_0.1/synth-vivado/ |
| # lowrisc_systems_chip_earlgrey_cw310_0.1.bit |
| # |
| # A copy of the original bitstream is created at e.g. at |
| # $REPO_TOP/build/lowrisc_systems_chip_earlgrey_cw310_0.1/synth-vivado/ |
| # lowrisc_systems_chip_earlgrey_cw310_0.1.bit.orig |
| set -e |
| |
| . util/build_consts.sh |
| |
| function usage() { |
| cat << USAGE |
| Utility script to load ROM contents into the FPGA bitstream. |
| |
| Usage: $0 [-t TARGET_BOARD] [-T TARGET_TOP] [-b DV | PROD] |
| |
| - t: Target board: cw310, cw305. |
| - T: Target top: earlgrey. |
| - b: ROM binary, set to either DV or PROD. |
| |
| ROM binary targets (-b): |
| - DV: sw/device/lib/testing/test_rom |
| - PROD: sw/device/silicon_creator/rom |
| |
| USAGE |
| } |
| |
| # Change these variables when using the script for a different top level and/or FPGA board. |
| FLAGS_TARGET_BOARD="cw310" |
| FLAGS_TARGET_TOP="earlgrey" |
| FLAGS_BIN="DV" |
| |
| # `getopts` usage |
| # - The initial colon in the optstring is to suppress the default error |
| # handling. |
| # - The remaining options are specified in alphabetical order, and the case |
| # statement should match this order. |
| # - Only options that take an argument should have a following colon. |
| # - The case statement contains two additional cases: |
| # - when `$flag` = `?`, this is an unexpected option. |
| # - when `$flag` = `:`, this is the case that a flag which requires an |
| # argument is not provided one. In both cases, `$OPTARG` contains the |
| # relevant parsed option. |
| # - After option parsing is finished, we `shift` by `$OPTIND - 1` so that the |
| # remaining (unprocessed) arguments are in `$@` (and $1, $2, $3 etc.). |
| while getopts ':b:t:T:' flag; do |
| case "${flag}" in |
| b) FLAGS_BIN="${OPTARG}";; |
| t) FLAGS_TARGET_BOARD="${OPTARG}";; |
| T) FLAGS_TARGET_TOP="${OPTARG}";; |
| \?) echo "Unexpected option: -${OPTARG}" >&2 |
| usage |
| exit 1 |
| ;; |
| :) echo "Option -${OPTARG} requires an argument" >&2 |
| usage |
| exit 1 |
| ;; |
| *) echo "Internal Error: Unhandled option: -${flag}" >&2 |
| exit 1 |
| ;; |
| esac |
| done |
| shift $((OPTIND - 1)) |
| |
| # We do not accept additional arguments. |
| if [[ "$#" -gt 0 ]]; then |
| echo "Unexpected arguments:" "$@" >&2 |
| exit 1 |
| fi |
| |
| TARGET_PREFIX="" |
| if [[ ${FLAGS_BIN} == "DV" ]]; then |
| TARGET_PREFIX="sw/device/lib/testing/test_rom/test_rom" |
| elif [[ ${FLAGS_BIN} == "PROD" ]]; then |
| TARGET_PREFIX="sw/device/silicon_creator/rom/rom" |
| else |
| echo "Invalid -b option: ${FLAGS_BIN}; expected DV or PROD." >&2 |
| exit 1 |
| fi |
| |
| TARGET_BOARD="${FLAGS_TARGET_BOARD}" |
| TARGET_TOP="${FLAGS_TARGET_TOP}" |
| TARGET_FILE_EXT=".scr.39.vmem" |
| TARGET="${BIN_DIR}/${TARGET_PREFIX}_fpga_${TARGET_BOARD}" |
| TARGET_PATH="${TARGET}${TARGET_FILE_EXT}" |
| |
| FPGA_BIN_DIR="${BIN_DIR}/hw/top_${TARGET_TOP}" |
| FPGA_BIT_NAME="lowrisc_systems_chip_${TARGET_TOP}_${TARGET_BOARD}_0.1" |
| |
| # Make sure all inputs are available. |
| if [[ ! -f "${TARGET_PATH}" ]]; then |
| echo "Unable to find ROM base image ${TARGET_PATH}." >&2 |
| exit 1 |
| fi |
| |
| if [[ ! -f "${FPGA_BIN_DIR}/rom.mmi" ]]; then |
| echo "Unable to find ${FPGA_BIN_DIR}/rom.mmi." >&2 |
| exit 1 |
| fi |
| |
| if [[ ! -f "${FPGA_BIN_DIR}/${FPGA_BIT_NAME}.bit" ]]; then |
| echo "Unable to find ${FPGA_BIN_DIR}/${FPGA_BIT_NAME}.bit." >&2 |
| exit 1 |
| fi |
| |
| # Create the Vivado image for splicing. |
| hw/ip/rom_ctrl/util/gen_vivado_mem_image.py \ |
| "${TARGET_PATH}" \ |
| "${TARGET}.updatemem.mem" \ |
| --swap-nibbles |
| |
| # Splice the ROM. |
| # The --debug flag is undocumented and causes updatemem to print out the INIT_XX |
| # values of the four BRAM cells. These values are also oberservable when opening |
| # the implemented design in Vivado and then inspecting the cell properties of |
| # the corresponding BRAM cells. This information is very useful when debugging |
| # the splicing flow. |
| updatemem -force --meminfo "${FPGA_BIN_DIR}/rom.mmi" \ |
| --data "${TARGET}.updatemem.mem" \ |
| --bit "${FPGA_BIN_DIR}/${FPGA_BIT_NAME}.bit" --proc dummy \ |
| --out "${FPGA_BIN_DIR}/${FPGA_BIT_NAME}.splice.bit" \ |
| --debug |
| |
| mv ${FPGA_BIN_DIR}/${FPGA_BIT_NAME}.bit ${FPGA_BIN_DIR}/${FPGA_BIT_NAME}.bit.orig |
| |
| # Rename to the canonical bitstream output name to simplify interaction with |
| # other tools, and create a copy with a .splice suffix to be able to |
| # export the artifact in CI. |
| mv ${FPGA_BIN_DIR}/${FPGA_BIT_NAME}.splice.bit ${FPGA_BIN_DIR}/${FPGA_BIT_NAME}.bit |
| cp ${FPGA_BIN_DIR}/${FPGA_BIT_NAME}.bit ${FPGA_BIN_DIR}/${FPGA_BIT_NAME}.bit.splice |