Skip to content

Commit

Permalink
[tlul,shim] Expand pre_dv to handle arbitrary test cases
Browse files Browse the repository at this point in the history
This commit generalizes the `pre_dv` testbench to arbitrary test cases
and adds an array of tests covering both AES-GCM and its modes of
operation. The process of adding/modify tests is now streamlined
reducing the feedback loop.

Signed-off-by: Andrea Caforio <[email protected]>
  • Loading branch information
andrea-caforio committed Nov 18, 2024
1 parent d592957 commit 59c02d4
Show file tree
Hide file tree
Showing 16 changed files with 5,364 additions and 212 deletions.
47 changes: 39 additions & 8 deletions hw/ip/aes/pre_dv/aes_tlul_shim_tb/README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,43 @@
TLUL/Shim Verilator Testbench
=======================
# TLUL/Shim Verilator Testbench

This directory contains the Verilator testbench for the TLUL shim adapter that is attached
to the AES IP block, run in the GCM mode.
This directory contains the Verilator testbench for the TLUL shim adapter that is attached to the AES IP block.
Out of the box, the testbench contains test vectors for most of the salient use cases, nonetheless extending the testbench with further tests is straightforward as detailed below.

## Current Test Vectors

How to build and run the example
--------------------------------
The `./data` directory contains an array of `.svh` files each of them containing a single set of input stimuli that constitute a test:

```
data
├── gcm_k128_a0_m0.svh # AES-GCM-128 Encryption; 0 AD Bytes; 0 Msg Bytes
├── gcm_k128_a0_m16.svh # AES-GCM-128 Encryption; 0 AD Bytes; 16 Msg Bytes
├── gcm_k128_a20_m60.svh # AES-GCM-128 Encryption/Decryption/Save/Restore; 20 AD Bytes; 60 Msg Bytes
├── gcm_k128_a20_m64.svh # AES-GCM-128 Encryption; 20 AD Bytes; 64 Msg Bytes
├── modes_dec_k128_m64.svh # AES-128 Modes Decryption; 64 Msg Bytes
├── modes_dec_k192_m64.svh # AES-192 Modes Decryption; 64 Msg Bytes
├── modes_dec_k256_m64.svh # AES-256 Modes Decryption; 64 Msg Bytes
├── modes_enc_k128_m64.svh # AES-128 Modes Encryption; 64 Msg Bytes
├── modes_enc_k192_m64.svh # AES-192 Modes Encryption; 64 Msg Bytes
└── modes_enc_k256_m64.svh # AES-256 Modes Encryption; 64 Msg Bytes
```

### Adding/Modifying Tests

Each test vector file `./data/*.svh` starts with a preamble that instruments both the testbench RTL as well as the `c_dpi` model:

```systemverilog
`define AD_LENGTH // Number of AD bytes
`define MSG_LENGTH // Number of Msg bytes
`define NUM_REQUESTS // Total number of requests
```

Here, `NUM_REQUESTS` denotes the number of `read_request`, `write_request` and `c_dpi_load` invocations within the file.
Having written a new test vector file, the `fusesoc` configuration needs to be made aware of it.

1. Add the `.svh` filename to the list of RTL files under `files_rtl/files`.
2. Add the `.svh` filename to the `DREQUESTS_FILE` Verilator variable under `verilator/verilator_options`.

## Building and Running the Verilator Testbench

To build the testbench, execute from the OpenTitan top level:

Expand All @@ -19,11 +50,11 @@ To execute the obtained Verilator binary and with trace generation, run:
./build/lowrisc_dv_verilator_aes_tlul_shim_tb_0/default-verilator/Vaes_tlul_shim_tb --trace
```

Details of the testbench
------------------------
## Details of the testbench

- cpp/aes\_tlul\_shim\_tb.cc: contains main function and instantiation of SimCtrl
- rtl/aes\_tlul\_shim\_tb.sv: contains the testbench logic
- rtl/aes\_tlul\_delayer\_tb.sv: contains an optional delayer module to artificially induce random delays between the Shim and the TLUL bus.
- rtl/aes\_tlul\_shim\_tb_reqs.sv: contains requests (stimuli) that are fed to the testbench.
- rtl/aes\_tlul\_shim\_tb_pkg.sv: contains common parameters and functions.
- data/*: contains test vector files.
12 changes: 12 additions & 0 deletions hw/ip/aes/pre_dv/aes_tlul_shim_tb/aes_tlul_shim_tb.core
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,19 @@ filesets:
- lowrisc:dv:aes_model_dpi
- lowrisc:tlul:adapter_shim
files:
- data/gcm_k128_a20_m60.svh : {is_include_file : true}
- data/gcm_k128_a20_m64.svh : {is_include_file : true}
- data/gcm_k128_a0_m16.svh : {is_include_file : true}
- data/gcm_k128_a0_m0.svh : {is_include_file : true}
- data/modes_enc_k128_m64.svh : {is_include_file : true}
- data/modes_enc_k192_m64.svh : {is_include_file : true}
- data/modes_enc_k256_m64.svh : {is_include_file : true}
- data/modes_dec_k128_m64.svh : {is_include_file : true}
- data/modes_dec_k192_m64.svh : {is_include_file : true}
- data/modes_dec_k256_m64.svh : {is_include_file : true}
- rtl/aes_tlul_shim_tb_pkg.sv
- rtl/aes_tlul_shim_tb_reqs.sv
- rtl/aes_tlul_shim_tb_c_dpi.sv
- rtl/aes_tlul_shim_delayer.sv
- rtl/aes_tlul_shim_tb.sv
file_type: systemVerilogSource
Expand All @@ -38,6 +49,7 @@ targets:
verilator_options:
# Disabling tracing reduces compile times by multiple times, but doesn't have a
# huge influence on runtime performance. (Based on early observations.)
- '-DREQUESTS_FILE=\"gcm_k128_a20_m60.svh\"'
- '--trace'
- '--trace-fst' # this requires -DVM_TRACE_FMT_FST in CFLAGS below!
- '--trace-structs'
Expand Down
110 changes: 110 additions & 0 deletions hw/ip/aes/pre_dv/aes_tlul_shim_tb/data/gcm_k128_a0_m0.svh
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
// Copyright lowRISC contributors (OpenTitan project).
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

// AES-GCM-128 Test Case #1
// https://csrc.nist.rip/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-spec.pdf

// Preamble:
`define AD_LENGTH 0
`define MSG_LENGTH 0
`define NUM_REQUESTS 42

`define REQUESTS shim_request_t requests[`NUM_REQUESTS] = '{ \
c_dpi_load('{ \
operation: AES_ENC, \
mode: AES_GCM, \
key_length: AES_128, \
key: 256'h0000000000000000000000000000000000000000000000000000000000000000, \
iv: 128'h0000000000000000000000000000000000, \
msg: '0, \
ad: '0, \
tag: '0 \
}), \
\
/* Check AES core is idle before writing the control registers */ \
read_request(AES_STATUS_OFFSET, 32'(1'b1) << AES_STATUS_IDLE_OFFSET), \
\
/* Config AES core, config GCM in `INIT` mode */ \
write_request( \
AES_CTRL_SHADOWED_OFFSET, \
32'(0) << AES_CTRL_MANUAL_OPERATION_OFFSET | \
32'(PER_1) << AES_CTRL_PRNG_RESEED_RATE_OFFSET | \
32'(0) << AES_CTRL_SIDELOAD_OFFSET | \
32'(AES_128) << AES_CTRL_KEY_LEN_OFFSET | \
32'(AES_GCM) << AES_CTRL_MODE_OFFSET | \
32'(AES_ENC) << AES_CTRL_OPERATION_OFFSET \
), \
write_request( \
AES_CTRL_SHADOWED_OFFSET, \
32'(0) << AES_CTRL_MANUAL_OPERATION_OFFSET | \
32'(PER_1) << AES_CTRL_PRNG_RESEED_RATE_OFFSET | \
32'(0) << AES_CTRL_SIDELOAD_OFFSET | \
32'(AES_128) << AES_CTRL_KEY_LEN_OFFSET | \
32'(AES_GCM) << AES_CTRL_MODE_OFFSET | \
32'(AES_ENC) << AES_CTRL_OPERATION_OFFSET \
), \
write_request( \
AES_CTRL_GCM_SHADOWED_OFFSET, \
32'(0) << AES_CTRL_GCM_NUM_VALID_BYTES_OFFSET | \
32'(GCM_INIT) << AES_CTRL_GCM_PHASE_OFFSET \
), \
write_request( \
AES_CTRL_GCM_SHADOWED_OFFSET, \
32'(0) << AES_CTRL_GCM_NUM_VALID_BYTES_OFFSET | \
32'(GCM_INIT) << AES_CTRL_GCM_PHASE_OFFSET \
), \
read_request(AES_STATUS_OFFSET, 32'(1'b1) << AES_STATUS_IDLE_OFFSET), \
\
/* Write key registers */ \
write_request(AES_KEY_SHARE0_0_OFFSET, 32'h00000000), \
write_request(AES_KEY_SHARE0_1_OFFSET, 32'h00000000), \
write_request(AES_KEY_SHARE0_2_OFFSET, 32'h00000000), \
write_request(AES_KEY_SHARE0_3_OFFSET, 32'h00000000), \
write_request(AES_KEY_SHARE0_4_OFFSET, 32'h00000000), \
write_request(AES_KEY_SHARE0_5_OFFSET, 32'h00000000), \
write_request(AES_KEY_SHARE0_6_OFFSET, 32'h00000000), \
write_request(AES_KEY_SHARE0_7_OFFSET, 32'h00000000), \
write_request(AES_KEY_SHARE1_0_OFFSET, 32'h00000000), \
write_request(AES_KEY_SHARE1_1_OFFSET, 32'h00000000), \
write_request(AES_KEY_SHARE1_2_OFFSET, 32'h00000000), \
write_request(AES_KEY_SHARE1_3_OFFSET, 32'h00000000), \
write_request(AES_KEY_SHARE1_4_OFFSET, 32'h00000000), \
write_request(AES_KEY_SHARE1_5_OFFSET, 32'h00000000), \
write_request(AES_KEY_SHARE1_6_OFFSET, 32'h00000000), \
write_request(AES_KEY_SHARE1_7_OFFSET, 32'h00000000), \
read_request(AES_STATUS_OFFSET, 32'(1'b1) << AES_STATUS_IDLE_OFFSET), \
\
/* Write IV registers */ \
write_request(AES_IV_0_OFFSET, 32'h00000000), \
write_request(AES_IV_1_OFFSET, 32'h00000000), \
write_request(AES_IV_2_OFFSET, 32'h00000000), \
write_request(AES_IV_3_OFFSET, 32'h00000000), \
read_request(AES_STATUS_OFFSET, 32'(1'b1) << AES_STATUS_IDLE_OFFSET), \
\
/* Config GCM in `TAG` mode and write len(ad) || len(pt) to trigger tag computation */ \
write_request( \
AES_CTRL_GCM_SHADOWED_OFFSET, \
32'(0) << AES_CTRL_GCM_NUM_VALID_BYTES_OFFSET | \
32'(GCM_TAG) << AES_CTRL_GCM_PHASE_OFFSET \
), \
write_request( \
AES_CTRL_GCM_SHADOWED_OFFSET, \
32'(0) << AES_CTRL_GCM_NUM_VALID_BYTES_OFFSET | \
32'(GCM_TAG) << AES_CTRL_GCM_PHASE_OFFSET \
), \
write_request(AES_DATA_IN_0_OFFSET, 32'h00000000), \
write_request(AES_DATA_IN_1_OFFSET, 32'h00000000), \
write_request(AES_DATA_IN_2_OFFSET, 32'h00000000), \
write_request(AES_DATA_IN_3_OFFSET, 32'h00000000), \
read_request(AES_STATUS_OFFSET, 32'(1'b1) << AES_STATUS_OUTPUT_VALID_OFFSET), \
\
/* Read back the authentication tag */ \
read_request(AES_DATA_OUT_0_OFFSET), \
read_request(AES_DATA_OUT_1_OFFSET), \
read_request(AES_DATA_OUT_2_OFFSET), \
read_request(AES_DATA_OUT_3_OFFSET), \
\
read_request(8'h00,, 1'b1), \
read_request(8'h04,, 1'b1) \
};
Loading

0 comments on commit 59c02d4

Please sign in to comment.