blob: d7785ec288aaebfd70dc3b5ef863f658631875f9 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
#ifndef OPENTITAN_SW_DEVICE_LIB_TESTING_OTBN_TESTUTILS_H_
#define OPENTITAN_SW_DEVICE_LIB_TESTING_OTBN_TESTUTILS_H_
#include "sw/device/lib/base/mmio.h"
#include "sw/device/lib/dif/dif_base.h"
#include "sw/device/lib/dif/dif_otbn.h"
/**
* @file
* @brief OpenTitan Big Number Accelerator (OTBN) driver
*/
/**
* Information about an embedded OTBN application image.
*
* All pointers reference data in the normal CPU address space.
*
* Use `OTBN_DECLARE_APP_SYMBOLS()` together with `OTBN_APP_T_INIT()` to
* initialize this structure.
*/
typedef struct otbn_app {
/**
* Start of OTBN instruction memory.
*/
const uint8_t *imem_start;
/**
* End of OTBN instruction memory.
*/
const uint8_t *imem_end;
/**
* Start of initialized OTBN data memory.
*
* Data in this section is copied into DMEM when the app is loaded.
*/
const uint8_t *dmem_data_start;
/**
* End of initialized OTBN data memory.
*/
const uint8_t *dmem_data_end;
} otbn_app_t;
/**
* The address of an OTBN symbol as seen by OTBN
*
* Use `OTBN_DECLARE_SYMBOL_ADDR()` together with `OTBN_ADDR_T_INIT()` to
* initialize this type.
*/
typedef uint32_t otbn_addr_t;
/**
* Generate the prefix to add to an OTBN symbol name used on the Ibex side
*
* The result is a pointer to Ibex's rodata that should be used to initialise
* memory for that symbol.
*
* This is needed by the OTBN driver to support DMEM/IMEM ranges but
* application code shouldn't need to use this. Use the `otbn_addr_t` type and
* supporting macros instead.
*/
#define OTBN_SYMBOL_PTR(app_name, sym) _otbn_local_app_##app_name##_##sym
/**
* Generate the prefix to add to an OTBN symbol name used on the OTBN side
*
* The result is a pointer whose integer value is the address by which the
* symbol should be accessed in OTBN memory.
*
* This is an internal macro used in `OTBN_DECLARE_SYMBOL_ADDR` and
* `OTBN_ADDR_T_INIT` but application code shouldn't need to use it directly.
*/
#define OTBN_SYMBOL_ADDR(app_name, sym) _otbn_remote_app_##app_name##_##sym
/**
* Makes a symbol in the OTBN application image available.
*
* This is needed by the OTBN driver to support DMEM/IMEM ranges but
* application code shouldn't need to use this. To get access to OTBN
* addresses, use `OTBN_DECLARE_SYMBOL_ADDR` instead.
*/
#define OTBN_DECLARE_SYMBOL_PTR(app_name, symbol_name) \
extern const uint8_t OTBN_SYMBOL_PTR(app_name, symbol_name)[]
/**
* Makes the OTBN address of a symbol in the OTBN application available.
*
* Symbols are typically function or data pointers, i.e. labels in assembly
* code. Unlike OTBN_DECLARE_SYMBOL_PTR, this will work for symbols in the .bss
* section (which exist on the OTBN side, even though they don't have backing
* data on Ibex).
*
* Use this macro instead of manually declaring the symbols as symbol names
* might change.
*
* @param app_name Name of the application the function is contained in.
* @param symbol_name Name of the symbol (function, label).
*/
#define OTBN_DECLARE_SYMBOL_ADDR(app_name, symbol_name) \
extern const uint8_t OTBN_SYMBOL_ADDR(app_name, symbol_name)[]
/**
* Makes an embedded OTBN application image available for use.
*
* Make symbols available that indicate the start and the end of instruction
* and data memory regions, as they are stored in the device memory.
*
* Use this macro instead of manually declaring the symbols as symbol names
* might change.
*
* @param app_name Name of the application to load, which is typically the
* name of the main (assembly) source file.
*/
#define OTBN_DECLARE_APP_SYMBOLS(app_name) \
OTBN_DECLARE_SYMBOL_PTR(app_name, _imem_start); \
OTBN_DECLARE_SYMBOL_PTR(app_name, _imem_end); \
OTBN_DECLARE_SYMBOL_PTR(app_name, _dmem_data_start); \
OTBN_DECLARE_SYMBOL_PTR(app_name, _dmem_data_end)
/**
* Initializes the OTBN application information structure.
*
* After making all required symbols from the application image available
* through `OTBN_DECLARE_APP_SYMBOLS()`, use this macro to initialize an
* `otbn_app_t` struct with those symbols.
*
* @param app_name Name of the application to load.
* @see OTBN_DECLARE_APP_SYMBOLS()
*/
#define OTBN_APP_T_INIT(app_name) \
((otbn_app_t){ \
.imem_start = OTBN_SYMBOL_PTR(app_name, _imem_start), \
.imem_end = OTBN_SYMBOL_PTR(app_name, _imem_end), \
.dmem_data_start = OTBN_SYMBOL_PTR(app_name, _dmem_data_start), \
.dmem_data_end = OTBN_SYMBOL_PTR(app_name, _dmem_data_end), \
})
/**
* Initializes an `otbn_addr_t`.
*/
#define OTBN_ADDR_T_INIT(app_name, symbol_name) \
((uint32_t)OTBN_SYMBOL_ADDR(app_name, symbol_name))
/**
* (Re-)loads the application into OTBN.
*
* Load the application image with both instruction and data segments into OTBN.
*
* @param otbn The context object.
* @param app The application to load into OTBN.
*/
void otbn_testutils_load_app(const dif_otbn_t *otbn, const otbn_app_t app);
/**
* Starts the OTBN execute operation.
*
* Use `otbn_testutils_wait_for_done()` to wait for execution to complete.
*
* @param otbn The context object.
*/
void otbn_testutils_execute(const dif_otbn_t *otbn);
/**
* Waits for OTBN to be done with the current operation.
*
* Polls the status register until OTBN is idle. Produces a CHECK-fail if OTBN
* is or becomes locked. Checks that the final error bits match expectations.
*
* @param otbn The context object.
* @param expected_err_bits Expected error bits.
*/
void otbn_testutils_wait_for_done(const dif_otbn_t *otbn,
dif_otbn_err_bits_t expected_err_bits);
/**
* Copies data from the CPU memory to OTBN data memory.
*
* @param otbn The context object.
* @param len_bytes Number of bytes to copy.
* @param dest Address of the destination in OTBN's data memory.
* @param src Source of the data to copy.
*/
void otbn_testutils_write_data(const dif_otbn_t *otbn, size_t len_bytes,
const void *src, otbn_addr_t dest);
/**
* Copies data from OTBN's data memory to CPU memory.
*
* @param otbn The context object.
* @param len_bytes The number of bytes to copy.
* @param src The address in OTBN data memory to copy from.
* @param[out] dest The destination of the copied data in main memory
* (preallocated).
*/
void otbn_testutils_read_data(const dif_otbn_t *otbn, size_t len_bytes,
otbn_addr_t src, void *dest);
/**
* Writes a LOG_INFO message with the contents of each 256b DMEM word.
*
* @param otbn The context object.
* @param max_addr The highest address to dump. Set to 0 to output the whole
* DMEM. Must be a multiple of WLEN.
*/
void otbn_testutils_dump_dmem(const dif_otbn_t *otbn, uint32_t max_addr);
#endif // OPENTITAN_SW_DEVICE_LIB_TESTING_OTBN_TESTUTILS_H_