blob: b0990474630eadec06cf8b7eeb5150155618c991 [file] [log] [blame]
#!/bin/bash
#
# Copyright 2020 Google LLC
#
# 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
#
# https://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.
export C_PREFIX="riscv32-unknown-elf-"
export IREE_PREFIX="riscv32-unknown-elf-"
export IREE_ARCH="rv32imf"
export RUST_PREFIX="riscv32-unknown-linux-gnu"
# NB: $(CANTRIP_SRC_DIR)/apps/system/rust.cmake forces riscv32imac for
# the target when building Rust code
export CANTRIP_TARGET_ARCH="riscv32-unknown-elf"
# Shodan's toolchains are setup specially, just setup the environment.
export RUSTDIR="${CACHE}/rust_toolchain"
export CARGO_HOME="${RUSTDIR}"
export RUSTUP_HOME="${RUSTDIR}"
export PATH="${RUSTDIR}/bin:${PATH}"
export OPENTITAN_GEN_DIR="${CANTRIP_OUT_DIR}/opentitan-gen/include/opentitan"
export OPENTITAN_SOURCE="${ROOTDIR}/hw/opentitan-upstream"
# Some build.rs files use the regtool crate which needs to know where to find
# regtool.py.
export REGTOOL="${OPENTITAN_SOURCE}/util/regtool.py"
# The following files are the input to regtool.py
export I2S_HJSON="${ROOTDIR}/hw/matcha/hw/top_matcha/ip/i2s/data/i2s.hjson"
export MBOX_HJSON="${ROOTDIR}/hw/matcha/hw/top_matcha/ip/tlul_mailbox/data/tlul_mailbox.hjson"
export ML_TOP_HJSON="${ROOTDIR}/hw/matcha/hw/top_matcha/ip/ml_top/data/ml_top.hjson"
export TIMER_HJSON="${OPENTITAN_GEN_DIR}/rv_timer.hjson"
export UART_HJSON="${OPENTITAN_SOURCE}/hw/ip/uart/data/uart.hjson"
export VC_TOP_HJSON="${ROOTDIR}/hw/matcha/hw/top_matcha/ip/vc_top/data/vc_top.hjson"
# Input for topgen_matcha.py to generate hw configuration
export TOP_MATCHA_HJSON="${ROOTDIR}/hw/matcha/hw/top_matcha/data/top_matcha.hjson"
# Standard locations of Nexus configs and binaries
export OT_TOOL="${ROOTDIR}/out/opentitantool"
export NEXUS_JSON="${ROOTDIR}/out/nexus.json"
export NEXUS_SPI_PASSTHRU="${ROOTDIR}/out/spi_passthrough_fpga_nexus.bin"
function parting_messages() {
if [[ ! -d "${RUSTDIR}" ]] ||
[[ ! -d "${ROOTDIR}/cache/toolchain" ]] ||
[[ ! -d "${ROOTDIR}/cache/toolchain_iree_rv32imf" ]] ||
[[ ! -d "${ROOTDIR}/cache/renode" ]]; then
echo
echo '!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!'
echo You have missing tools. Please run \'m prereqs\' followed
echo by \'m tools\' to install them.
echo '!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!'
echo
[[ -d "${RUSTDIR}" ]] || echo "${RUSTDIR} is missing!"
[[ -d "${ROOTDIR}/cache/toolchain" ]] || echo "${ROOTDIR}/cache/toolchain is missing"
[[ -d "${ROOTDIR}/cache/toolchain_iree_rv32imf" ]] || echo "${ROOTDIR}/cache/toolchain_iree_rv32imf is missing!"
[[ -d "${ROOTDIR}/cache/renode" ]] || echo "${ROOTDIR}/cache/renode is missing!"
fi
echo Run \'set-nexus-id NN\' to set your Nexus board ID
}
function sim_kelvin
{
# Run the ELF/Bin program with kelvin_sim
local bin_file="$(realpath $1)"
local magic_bytes="$(xxd -p -l 4 ${bin_file})"
local -a flags=()
local is_elf=false
if [[ ${magic_bytes} == "7f454c46" ]]; then
is_elf=true
else
flags+=("--entry_point 0 ")
fi
if [[ "$2" == "debug" ]]; then
flags+=("-i")
if [[ "${is_elf}" == false ]]; then
echo "debug mode only works on ELF files"
return 1
fi
fi
("${OUT}/kelvin/sim/kelvin_sim" "${bin_file}" ${flags[@]})
}
function sim_kelvin_renode
{
# Run the Bin program with renode
local bin_file="$(realpath $1)"
local command="start;"
(cd "${ROOTDIR}" && renode -e "\$bin=@${bin_file}; i @sim/config/kelvin.resc; \
${command} sysbus.ml_top_controlblock WriteDoubleWord 0xc 0" \
--disable-xwt --console)
}
function set-nexus-id
{
local nexus_id="${1}"; shift
if [[ -z "${nexus_id}" ]]; then
(
echo "Usage: set-nexus-id <NN>"
echo
echo "Sets the target Nexus board to run on. Must be a two digit number"
echo
) | fmt
return 1
fi
if [[ "${#nexus_id}" -ne 2 ]]; then
echo "Nexus number must be two digits"
return 1
fi
export NEXUS_ID="${nexus_id}"
# TODO(b/316200811) track down all the places we use a different variable name:
export NEXUS_BOARD="${nexus_id}"
export FPGA_BOARD_ID="${nexus_id}"
}
function opentitantool
{
# Run built opentitantool with standard flags
if [[ -z "${NEXUS_ID}" ]]; then
echo "Run set-nexus-id first"
return 1
fi
"${OT_TOOL}" --conf "${NEXUS_JSON}" --interface nexus --usb-serial \
"Nexus-FTDI-${NEXUS_ID}" "$@"
}
function nexus_reset
{
# Reset nexus board
if [[ -z "${NEXUS_ID}" ]]; then
echo "Run set-nexus-id first"
return 1
fi
opentitantool gpio write RESET true
opentitantool gpio write RESET false
opentitantool gpio write RESET true
}
function nexus_flash
{
# Write tar file to nexus SPI flash and verify
local flash_tar="$(realpath $1)"
if [[ -z "${flash_tar}" ]]; then
(
echo "Usage: nexus_flash path/to/file.tar"
echo
echo "Writes tar file to Nexus SPI flash for booting."
echo
) | fmt
return 1
fi
if [[ -z "${NEXUS_ID}" ]]; then
echo "Run set-nexus-id first"
return 1
fi
if [[ ! -f "${NEXUS_SPI_PASSTHRU}" ]]; then
echo "INFO: spi_passthrough binary not found at ${NEXUS_SPI_PASSTHRU}"
echo "running `m spi_passthrough` to build it"
m spi_passthrough
if [[ "$?" -ne 0 ]]; then
echo "ERROR: Unable to find or build spi_passthrough!"
return 1
fi
fi
nexus_reset
local read_size="$(du -b ${flash_tar} | awk '{print $1}')"
local erase_size="$(du -b ${flash_tar} \
| awk '{ print $1 + (n - $1 % n) % n }' n=262144)"
echo "Program SPI using ${NEXUS_SPI_PASSTHRU} on board ${NEXUS_ID}"
opentitantool bootstrap "${NEXUS_SPI_PASSTHRU}"
opentitantool spi block-erase --start 0 --length "${erase_size}"
opentitantool spi program --start 0 "${flash_tar}"
local readback_file="$(mktemp -d)/$(basename ${flash_tar}).readback"
opentitantool spi read --start 0 --length "${read_size}" "${readback_file}"
diff "${flash_tar}" "${readback_file}"
if [[ "$?" -ne 0 ]]; then
echo "ERROR: Nexus flash verify failed!"
return 1
fi
rm "${readback_file}"
nexus_reset
}
function nexus_clear_flash
{
# Clear the first page of the SPI flash to prevent restarting from the
# loaded program at the next reset.
if [[ -z "${NEXUS_ID}" ]]; then
echo "Run set-nexus-id first"
return 1
fi
echo "Clearing nexus SPI flash"
nexus_reset
opentitantool bootstrap "${NEXUS_SPI_PASSTHRU}"
opentitantool spi block-erase --start 0 --length 262144
}
function nexus_mcu_write() {
# Slowly send characters to the Nexus MCU
if [[ -z "${NEXUS_ID}" ]]; then
echo "Run set-nexus-id first"
return 1
fi
local string="$1"
local length="${#string}"
for ((i = 0; i < length; i++)); do
local char="${string:i:1}"
echo -n "$char" > "/dev/Nexus-FTDI-${NEXUS_ID}-MCU-UART"
sleep 0.5
done
echo -e "\r" > "/dev/Nexus-FTDI-${NEXUS_ID}-MCU-UART"
}
function nexus_load_bitstream
{
# Load bitstream file onto Nexus FPGA
local bitstream_path="$(realpath $1)"
if [[ -z "${bitstream_path}" ]]; then
(
echo "Usage: nexus_load_bitstream path/to/file.bit"
echo
echo "Loads bitstream file onto Nexus FPGA"
echo "This command may ask you for the Nexus SOM root password"
echo
) | fmt
return 1
fi
if [[ -z "${NEXUS_ID}" ]]; then
echo "Run set-nexus-id first"
return 1
fi
if [[ ! -f "${bitstream_path}" ]]; then
echo "ERROR: bitstream not found at ${bitstream_path}"
return 1
fi
# Issue a no-op command to flush the character buffer in case it isn't empty
nexus_mcu_write "help"
scp "${bitstream_path}" "root@nexus${NEXUS_ID}:/mnt/mmcp1/"
nexus_mcu_write "camera_powerdown"
sleep 5
local bitstream_name="$(basename ${bitstream_path})"
ssh "root@nexus${NEXUS_ID}" "/mnt/mmcp1/zturn -d a /mnt/mmcp1/${bitstream_name}"
nexus_mcu_write "camera_powerup"
}
function nexus_boot
{
# Boot the Nexus board. If flashed, will boot from flash
# This command is a synomym for `opentitantool boot`
opentitantool boot
}
function nexus_bootstrap
{
# Bootstrap a binary on the Nexus board
local binary="$(realpath $1)"
if [[ -z "${binary}" ]]; then
(
echo "Usage: nexus_flash path/to/file.bin"
echo
echo "Run a binary on the nexus board."
echo
) | fmt
return 1
fi
opentitantool bootstrap "${binary}"
}