Skip to content

Commit

Permalink
[sw] Introduce link-time dependency injection
Browse files Browse the repository at this point in the history
This change unifies the two existing Meson tres into one by introducing
"link time dependency injection," described in lowRISC#1162.

Signed-off-by: Miguel Young de la Sota <mcyoung@google.com>
  • Loading branch information
mcy authored and gkelly committed Feb 18, 2020
1 parent fd4bb81 commit 76526c3
Show file tree
Hide file tree
Showing 43 changed files with 546 additions and 404 deletions.
5 changes: 2 additions & 3 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,7 @@ jobs:
- bash: |
. util/build_consts.sh
./meson_init.sh -A
ninja -C "$(sw_obj_dir sim-verilator)" all
ninja -C "$(sw_obj_dir fpga)" all
ninja -C "$OBJ_DIR" all
displayName: 'Build embedded targets'
- template: 'ci/upload-artifacts-template.yml'
parameters:
Expand Down Expand Up @@ -260,7 +259,7 @@ jobs:
mkdir -p "$OBJ_DIR/hw"
mkdir -p "$BIN_DIR/hw/top_earlgrey"
BOOTROM_VMEM="$BIN_DIR/sw/device/fpga/boot_rom/boot_rom.vmem"
BOOTROM_VMEM="$BIN_DIR/sw/device/boot_rom/boot_rom_fpga_nexysvideo.vmem"
test -f "$BOOTROM_VMEM"
. /opt/xilinx/Vivado/2018.3/settings64.sh
Expand Down
14 changes: 7 additions & 7 deletions ci/run_verilator_pytest.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,19 @@ set -e
. util/build_consts.sh

readonly VERILATED_SYSTEM_DEFAULT="build/lowrisc_systems_top_earlgrey_verilator_0.1/sim-verilator/Vtop_earlgrey_verilator"
readonly SW_BUILD_DEFAULT="$(sw_bin_dir sim-verilator)"
readonly SW_BUILD_DEFAULT="$DEV_BIN_DIR"

VERILATED_SYSTEM_PATH="${VERILATED_SYSTEM_PATH:-$VERILATED_SYSTEM_DEFAULT}"
SW_BUILD_PATH="${SW_BUILD_PATH:-$SW_BUILD_DEFAULT}"

BOOT_ROM_TARGET="boot_rom/boot_rom.elf"
BOOT_ROM_TARGET="boot_rom/boot_rom_sim_verilator.elf"

TEST_TARGETS=(
"examples/hello_usbdev/hello_usbdev.elf"
"tests/aes/aes_test.elf"
"tests/flash_ctrl/flash_test.elf"
"tests/hmac/sha256_test.elf"
"tests/rv_timer/rv_timer_test.elf"
"examples/hello_usbdev/hello_usbdev_sim_verilator.elf"
"tests/aes/aes_test_sim_verilator.elf"
"tests/flash_ctrl/flash_test_sim_verilator.elf"
"tests/hmac/sha256_test_sim_verilator.elf"
"tests/rv_timer/rv_timer_test_sim_verilator.elf"
)

if [[ ! -z ${MAKE_BUILD+x} ]]; then
Expand Down
4 changes: 2 additions & 2 deletions doc/rm/ref_manual_fpga.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,9 @@ The loading output is also shown.
```console
$ cd ${REPO_TOP}
$ ./meson_init.sh
$ ninja -C build-out/sw/fpga all
$ ninja -C build-out
$ build-bin/sw/host/spiflash/spiflash \
--input build-bin/sw/device/fpga/examples/hello_world/hello_world.bin
--input build-bin/sw/device/examples/hello_world/hello_world_fpga_nexysvideo.bin

Running SPI flash update.
Image divided into 6 frames.
Expand Down
10 changes: 5 additions & 5 deletions doc/ug/getting_started_fpga.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ To build it:
```console
$ cd $REPO_TOP
$ ./meson_init.sh
$ ninja -C build-out/sw/fpga sw/device/boot_rom/boot_rom_export
$ ninja -C build-out sw/device/boot_rom/boot_rom_export_fpga_nexysvideo
```

In the following example we synthesize the Earl Grey design for the Nexys Video board using Xilinx Vivado 2018.3.
Expand All @@ -42,7 +42,7 @@ In the following example we synthesize the Earl Grey design for the Nexys Video
$ . /tools/xilinx/Vivado/2018.3/settings64.sh
$ cd $REPO_TOP
$ ./meson_init.sh
$ ninja -C build-out/sw/fpga sw/device/boot_rom/boot_rom_export
$ ninja -C build-out sw/device/boot_rom/boot_rom_export_fpga_nexysvideo
$ fusesoc --cores-root . run --target=synth lowrisc:systems:top_earlgrey_nexysvideo
```

Expand Down Expand Up @@ -123,10 +123,10 @@ Please follow the steps shown below.
```console
$ cd ${REPO_TOP}
$ ./meson_init.sh
$ ninja -C build-out/sw/fpga sw/device/examples/hello_world/hello_world_export
$ ninja -C build-out/sw/fpga sw/host/spiflash/spiflash_export
$ ninja -C build-out sw/device/examples/hello_world/hello_world_export_fpga_nexysvideo
$ ninja -C build-out sw/host/spiflash/spiflash_export
$ build-bin/sw/host/spiflash/spiflash \
--input build-bin/sw/device/fpga/examples/hello_world/hello_world.bin
--input build-bin/sw/device/fpga/examples/hello_world/hello_world_fpga_nexysvideo.bin
```

which should report how the binary is split into frames:
Expand Down
24 changes: 14 additions & 10 deletions doc/ug/getting_started_sw.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,16 @@ $ cd $REPO_TOP
$ ./meson_init.sh

# Build the two targets we care about, specifically.
$ ninja -C build-out/sw/fpga sw/device/boot_rom/boot_rom_export
$ ninja -C build-out/sw/fpga sw/device/examples/hello_world/hello_world_export
$ ninja -C build-out sw/device/boot_rom/boot_rom_export_fpga_nexysvideo
$ ninja -C build-out sw/device/examples/hello_world/hello_world_export_fpga_nexysvideo

# Build *everything*.
$ ninja -C build-out/sw/fpga all
# Build *everything*, including targets for other devices.
$ ninja -C build-out all
```

Note that specific targets are followed by the device they are built for.
OpenTitan needs to link the same device executable for multiple devices, so each executable target is duplicated one for each device we support.

If your RISC-V toolchain isn't located in the default `/tools/riscv` location you use the `TOOLCHAIN_PATH` environment variable to set a different location before running `meson_init.sh`:

```console
Expand All @@ -43,11 +46,12 @@ The locations of `build-{out,bin}` can be controled by setting the `$BUILD_ROOT`
`./meson_init.sh` itself is idempotent, but this behavior can be changed with additional flags; see `./meson_init.sh` for more information.
For this reason, most examples involving Meson will include a call to `./meson_init.sh`, but you will rarely need to run it more than once per checkout.

Building an executable `foo` destined to run on an OpenTitan device (i.e., under `sw/device`) will output the following files under `build-bin/sw/device`:
* `foo.elf`: the linked program, in ELF format.
* `foo.bin`: the linked program, as a plain binary with ELF debug information removed.
* `foo.dis`: the disassembled program with inline source code.
* `foo.vmem`: a Verilog memory file which can be read by `$readmemh()` in Verilog code.
Building an executable `foo` destined to run on the OpenTitan device `$DEVICE` will output the following files under `build-bin/sw/device`:
* `foo_$DEVICE.elf`: the linked program, in ELF format.
* `foo_$DEVICE.bin`: the linked program, as a plain binary with ELF debug information removed.
* `foo_$DEVICE.dis`: the disassembled program with inline source code.
* `foo_$DEVICE.vmem`: a Verilog memory file which can be read by `$readmemh()` in Verilog code.

In general, this executable is built by building the `foo_export_$DEVICE` target.

Building an executable destined to run on a host machine (i.e., under `sw/host`) will output a host excecutable under `build-bin/sw/host`, which can be run directly.
Currently, each "platform" (`fpga`, `sim-verilator`, etc) have their own copies of all host targets; this is a limitation of our Meson setup, and they are otherwise indistinguishable.
6 changes: 3 additions & 3 deletions doc/ug/getting_started_verilator.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ For more information on building software targets refer to the [Software Getting
```console
$ cd $REPO_TOP
$ ./meson_init.sh
$ ninja -C build-out/sw/sim-verilator all
$ ninja -C build-out all
```

Now the simulation can be run.
Expand All @@ -40,8 +40,8 @@ The programs listed after `--meminit` are loaded into the system's specified mem
```console
$ cd $REPO_TOP
$ build/lowrisc_systems_top_earlgrey_verilator_0.1/sim-verilator/Vtop_earlgrey_verilator \
--meminit=rom,build-bin/sw/device/sim-verilator/boot_rom/boot_rom.elf \
--meminit=flash,build-bin/sw/device/sim-verilator/examples/hello_world/hello_world.elf
--meminit=rom,build-bin/sw/device/boot_rom/boot_rom_sim_verilator.elf \
--meminit=flash,build-bin/sw/device/examples/hello_world/hello_world_sim_verilator.elf
```

To stop the simulation press CTRL-c.
Expand Down
11 changes: 0 additions & 11 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,11 @@ project(
],
)

target = get_option('target')
if target == 'undef'
error('target option not set. Please run meson with a valid build target option.')
endif

ot_version = get_option('ot_version')
if ot_version == 'undef'
error('ot_version option not set. Please run meson with a valid OpenTitan version option.')
endif

if target == 'sim-verilator'
# TODO: Consider using extra args array if using this flag globally is no
# longer OK.
add_project_arguments('-DSIMULATION', language: 'c')
endif

dev_bin_dir = get_option('dev_bin_dir')
host_bin_dir = get_option('host_bin_dir')
if dev_bin_dir == 'undef' or host_bin_dir == 'undef'
Expand Down
46 changes: 20 additions & 26 deletions meson_init.sh
Original file line number Diff line number Diff line change
Expand Up @@ -120,30 +120,24 @@ function purge_includes() {
perl -pi -e 's#-I[^/][^@ ]+ # #g' -- "$ninja_file"
}

for platform in ${PLATFORMS[@]}; do
obj_dir="$(sw_obj_dir "$platform")"
reconf="${FLAGS_reconfigure}"

if [[ ! -d "$obj_dir" ]]; then
echo "Output directory for $platform does not exist at $obj_dir; creating." >&2
mkdir -p "$obj_dir"
reconf=""
elif [[ -z "$reconf" ]]; then
echo "Output directory for $platform already exists at $obj_dir; skipping." >&2
continue
fi
reconf="${FLAGS_reconfigure}"

if [[ ! -d "$OBJ_DIR" ]]; then
echo "Output directory does not exist at $OBJ_DIR; creating." >&2
mkdir -p "$OBJ_DIR"
reconf=""
elif [[ -z "$reconf" ]]; then
echo "Output directory already exists at $OBJ_DIR; skipping." >&2
continue
fi

bin_dir="$(sw_bin_dir "$platform")"
mkdir -p "$bin_dir"

set -x
meson $reconf \
-Dtarget="$platform" \
-Dot_version="$OT_VERSION" \
-Ddev_bin_dir="$bin_dir" \
-Dhost_bin_dir="$HOST_BIN_DIR" \
--cross-file="$CROSS_FILE" \
"$obj_dir"
{ set +x; } 2>/dev/null
purge_includes "$obj_dir"
done
mkdir -p "$DEV_BIN_DIR"
set -x
meson $reconf \
-Dot_version="$OT_VERSION" \
-Ddev_bin_dir="$DEV_BIN_DIR" \
-Dhost_bin_dir="$HOST_BIN_DIR" \
--cross-file="$CROSS_FILE" \
"$OBJ_DIR"
{ set +x; } 2>/dev/null
purge_includes "$OBJ_DIR"
11 changes: 0 additions & 11 deletions meson_options.txt
Original file line number Diff line number Diff line change
@@ -1,14 +1,3 @@
option(
'target',
type: 'combo',
choices: [
'sim-verilator',
'fpga',
'undef',
],
value: 'undef',
)

option(
'dev_bin_dir',
type: 'string',
Expand Down
4 changes: 2 additions & 2 deletions sw/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ For example, to build the OpenTitan executable located at `sw/device/examples/he
```console
$ cd "$REPO_TOP"
$ ./meson_init.sh
$ ninja -C build-out/sw/fpga sw/device/examples/hello_world/hello_world_export
$ ninja -C build-out sw/device/examples/hello_world/hello_world_export_fpga_nexysvideo
```

The resulting binaries will be located at `build-bin/sw/device/fpga/examples/hello_world`. For more information, check out [the relevant User Guide](../doc/ug/getting_started_sw.md).
The resulting binaries will be located at `build-bin/sw/device/examples/hello_world`. For more information, check out [the relevant User Guide](../doc/ug/getting_started_sw.md).

The location of the RISC-V toolchain is /tools/riscv by default.
If your toolchain is located elsewhere set the `TOOLCHAIN_PATH` to that path before running `meson_init.sh`
Expand Down
4 changes: 2 additions & 2 deletions sw/device/benchmarks/coremark/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ To build CoreMark under meson:
```sh
cd "${REPO_TOP}"
./meson_init.sh
ninja -C build-out/sw/${TARGET} sw/device/benchmarks/coremark/coremark_export
ninja -C build-out sw/device/benchmarks/coremark/coremark_export_${DEVICE}
```

Where ${TARGET} is one of 'sim-verilator' or 'fpga'
Where ${DEVICE} is one of 'sim_verilator' or 'fpga_nexysvideo'

This will give you a .bin and .elf file (suitable for either spiflash or
giving directly to `--meminit` for Verilator) which can be found in
Expand Down
91 changes: 47 additions & 44 deletions sw/device/benchmarks/coremark/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -2,50 +2,53 @@
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0

if target == 'sim-verilator'
coremark_iterations = 1
else
coremark_iterations = 100
endif
foreach device_name, device_lib : sw_lib_arch_core_devices
if device_name == 'sim_verilator'
coremark_iterations = 1
else
coremark_iterations = 100
endif

coremark_top_earlgrey_elf = executable(
'coremark_top_earlgrey',
sources: [
'top_earlgrey/core_portme.c',
'top_earlgrey/ee_printf.c',
vendor_coremark_base_files,
],
name_suffix: 'elf',
dependencies: [
sw_lib_uart,
sw_lib_mem,
riscv_crt,
],
# Set up coremark-specific defines.
c_args: [
'-DITERATIONS=@0@'.format(coremark_iterations),
'-DPERFORMANCE_RUN=1',
'-DTOTAL_DATA_SIZE=2000',
'-DMAIN_HAS_NOARGC=1',
],
)
coremark_top_earlgrey_elf = executable(
'coremark_top_earlgrey_' + device_name,
sources: [
'top_earlgrey/core_portme.c',
'top_earlgrey/ee_printf.c',
vendor_coremark_base_files,
],
name_suffix: 'elf',
dependencies: [
sw_lib_uart,
sw_lib_mem,
riscv_crt,
device_lib,
],
# Set up coremark-specific defines.
c_args: [
'-DITERATIONS=@0@'.format(coremark_iterations),
'-DPERFORMANCE_RUN=1',
'-DTOTAL_DATA_SIZE=2000',
'-DMAIN_HAS_NOARGC=1',
],
)

coremark_top_earlgrey_embedded = custom_target(
'coremark_top_earlgrey',
command: make_embedded_target,
input: coremark_top_earlgrey_elf,
output: make_embedded_target_outputs,
build_by_default: true,
)
coremark_top_earlgrey_embedded = custom_target(
'coremark_top_earlgrey_' + device_name,
command: make_embedded_target,
input: coremark_top_earlgrey_elf,
output: make_embedded_target_outputs,
build_by_default: true,
)

custom_target(
'coremark_top_earlgrey_export',
command: export_embedded_target,
input: [
coremark_top_earlgrey_elf,
coremark_top_earlgrey_embedded,
],
output: 'coremark_top_earlgrey_export',
build_always_stale: true,
build_by_default: true,
)
custom_target(
'coremark_top_earlgrey_export_' + device_name,
command: export_embedded_target,
input: [
coremark_top_earlgrey_elf,
coremark_top_earlgrey_embedded,
],
output: 'coremark_top_earlgrey_export_' + device_name,
build_always_stale: true,
build_by_default: true,
)
endforeach
3 changes: 2 additions & 1 deletion sw/device/benchmarks/coremark/top_earlgrey/core_portme.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/
#include "sw/device/benchmarks/coremark/top_earlgrey/core_portme.h"

#include "sw/device/lib/arch/device.h"
#include "sw/device/lib/base/stdasm.h"
#include "sw/vendor/eembc_coremark/coremark.h"

Expand Down Expand Up @@ -106,7 +107,7 @@ ee_u32 default_num_contexts = 1;
Test for some common mistakes.
*/
void portable_init(core_portable *p, int *argc, char *argv[]) {
uart_init(UART_BAUD_RATE);
uart_init(kUartBaudrate);

if (sizeof(ee_ptr_int) != sizeof(ee_u8 *)) {
ee_printf(
Expand Down
3 changes: 2 additions & 1 deletion sw/device/boot_rom/boot_rom.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include "sw/device/boot_rom/bootstrap.h"
#include "sw/device/boot_rom/chip_info.h" // Generated.
#include "sw/device/lib/arch/device.h"
#include "sw/device/lib/base/stdasm.h"
#include "sw/device/lib/common.h"
#include "sw/device/lib/flash_ctrl.h"
Expand All @@ -27,7 +28,7 @@ extern struct {

void _boot_start(void) {
pinmux_init();
uart_init(UART_BAUD_RATE);
uart_init(kUartBaudrate);
uart_send_str((char *)chip_info);

int bootstrap_err = bootstrap();
Expand Down
Loading

0 comments on commit 76526c3

Please sign in to comment.