blob: fca8141b2cf1de7c4e78795a424cce25c0a96c76 [file] [log] [blame]
#!/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