From c74672c8630a8014dcf7b364ef5ef47d8af16934 Mon Sep 17 00:00:00 2001 From: Kolos Koblasz Date: Tue, 21 Apr 2026 09:29:54 +0100 Subject: [PATCH 1/3] [rom_ctrl_dv, vendoring] rom_ctrl dv dependencies added * The required dependencies added to: hw/vendor/lowrisc_ip.vendor.hjson * Patch file created to apply necessary modifications to rom_ctrl cfg files * rom_ctrl UVM TB simplified and patched to enable fewer modules vendored in as dependencies * rom_ctrl dv needs sram_scrambler_pkg.sv as a patch file to enable reduced number of vendored in modules. Signed-off-by: Kolos Koblasz --- hw/vendor/lowrisc_ip.vendor.hjson | 4 +- .../0002-kmac_app_agent_rom_ctrl_dv.patch | 60 +++ .../rom_ctrl/0001_Path_And_Tool_Fixes.patch | 117 ++++++ .../0002_DV_Simplify_Dependency_Fixes.patch | 15 + .../rom_ctrl/0003_Sram_Scrambler_Added.patch | 374 ++++++++++++++++++ 5 files changed, 568 insertions(+), 2 deletions(-) create mode 100644 hw/vendor/patches/lowrisc_ip/dv_sv/0002-kmac_app_agent_rom_ctrl_dv.patch create mode 100644 hw/vendor/patches/lowrisc_ip/rom_ctrl/0001_Path_And_Tool_Fixes.patch create mode 100644 hw/vendor/patches/lowrisc_ip/rom_ctrl/0002_DV_Simplify_Dependency_Fixes.patch create mode 100644 hw/vendor/patches/lowrisc_ip/rom_ctrl/0003_Sram_Scrambler_Added.patch diff --git a/hw/vendor/lowrisc_ip.vendor.hjson b/hw/vendor/lowrisc_ip.vendor.hjson index bc0717cd..cb570f5d 100644 --- a/hw/vendor/lowrisc_ip.vendor.hjson +++ b/hw/vendor/lowrisc_ip.vendor.hjson @@ -29,9 +29,9 @@ // Hardware IP blocks. {from: "hw/ip/i2c", to: "ip/i2c", patch_dir: "i2c"}, // I^2C controller/target - {from: "hw/ip/lc_ctrl", to: "ip/lc_ctrl"}, // Dependency of crossbar and power manager. - {from: "hw/ip/rom_ctrl", to: "ip/rom_ctrl"}, // Read-only memory. {from: "hw/ip/kmac", to: "ip/kmac"}, // kmac. + {from: "hw/ip/lc_ctrl", to: "ip/lc_ctrl"}, // Dependency of crossbar and power manager. + {from: "hw/ip/rom_ctrl", to: "ip/rom_ctrl", patch_dir: "rom_ctrl"}, // Read-only memory. {from: "hw/ip/rv_core_ibex", to: "ip/rv_core_pkg", patch_dir: "rv_core_pkg"}, // RISC-V core package. {from: "hw/ip/rv_timer", to: "ip/rv_timer", patch_dir: "rv_timer"}, // Timer. {from: "hw/ip/spi_device", to: "ip/spi_device", patch_dir: "spi_device"}, // SPI device. diff --git a/hw/vendor/patches/lowrisc_ip/dv_sv/0002-kmac_app_agent_rom_ctrl_dv.patch b/hw/vendor/patches/lowrisc_ip/dv_sv/0002-kmac_app_agent_rom_ctrl_dv.patch new file mode 100644 index 00000000..3100bcd4 --- /dev/null +++ b/hw/vendor/patches/lowrisc_ip/dv_sv/0002-kmac_app_agent_rom_ctrl_dv.patch @@ -0,0 +1,60 @@ +diff --git a/kmac_app_agent/kmac_app_agent.core b/kmac_app_agent/kmac_app_agent.core +index 79527cc..acaf70c 100644 +--- a/kmac_app_agent/kmac_app_agent.core ++++ b/kmac_app_agent/kmac_app_agent.core +@@ -10,7 +10,6 @@ filesets: + - lowrisc:dv:dv_utils + - lowrisc:dv:dv_lib + - lowrisc:dv:push_pull_agent +- - lowrisc:ip:keymgr_pkg + - lowrisc:ip:kmac_pkg + files: + - kmac_app_agent_pkg.sv +diff --git a/kmac_app_agent/kmac_app_agent_pkg.sv b/kmac_app_agent/kmac_app_agent_pkg.sv +index d1b3586..572b536 100644 +--- a/kmac_app_agent/kmac_app_agent_pkg.sv ++++ b/kmac_app_agent/kmac_app_agent_pkg.sv +@@ -7,7 +7,6 @@ package kmac_app_agent_pkg; + import uvm_pkg::*; + import dv_utils_pkg::*; + import dv_lib_pkg::*; +- import keymgr_pkg::*; + import push_pull_agent_pkg::*; + + // macro includes +@@ -15,9 +14,10 @@ package kmac_app_agent_pkg; + `include "dv_macros.svh" + + // parameters +- parameter int KMAC_REQ_DATA_WIDTH = keymgr_pkg::KmacDataIfWidth // data width +- + keymgr_pkg::KmacDataIfWidth / 8 // data mask width +- + 1; // bit last ++ parameter int KmacDataIfWidth = 64; // keymgr_pkg::KmacDataIfWidth ++ parameter int KMAC_REQ_DATA_WIDTH = KmacDataIfWidth // data width ++ + KmacDataIfWidth / 8 // data mask width ++ + 1; // bit last + + `define CONNECT_DATA_WIDTH .HostDataWidth(kmac_app_agent_pkg::KMAC_REQ_DATA_WIDTH) + +diff --git a/kmac_app_agent/kmac_app_intf.sv b/kmac_app_agent/kmac_app_intf.sv +index 8fe2c41..b5c926c 100644 +--- a/kmac_app_agent/kmac_app_intf.sv ++++ b/kmac_app_agent/kmac_app_intf.sv +@@ -5,8 +5,6 @@ + // verilog_lint: waive interface-name-style + interface kmac_app_intf (input clk, input rst_n); + +- import keymgr_pkg::*; +- + dv_utils_pkg::if_mode_e if_mode; // interface mode - Host or Device + + // interface pins used to connect with DUT +@@ -60,7 +58,7 @@ interface kmac_app_intf (input clk, input rst_n); + clk, !rst_n || if_mode == dv_utils_pkg::Host) + + // Check strb is aligned to LSB, for example: if strb[1]==0, strb[$:2] should be 0 too +- for (genvar k = 1; k < KmacDataIfWidth / 8 - 1; k++) begin : gen_strb_check ++ for (genvar k = 1; k < kmac_app_agent_pkg::KmacDataIfWidth / 8 - 1; k++) begin : gen_strb_check + `ASSERT(StrbAlignLSB_A, kmac_data_req.valid && kmac_data_req.strb[k] === 0 |-> + kmac_data_req.strb[k+1] === 0, + clk, !rst_n || if_mode == dv_utils_pkg::Host) diff --git a/hw/vendor/patches/lowrisc_ip/rom_ctrl/0001_Path_And_Tool_Fixes.patch b/hw/vendor/patches/lowrisc_ip/rom_ctrl/0001_Path_And_Tool_Fixes.patch new file mode 100644 index 00000000..7c44ff89 --- /dev/null +++ b/hw/vendor/patches/lowrisc_ip/rom_ctrl/0001_Path_And_Tool_Fixes.patch @@ -0,0 +1,117 @@ +diff --git a/data/rom_ctrl_testplan.hjson b/data/rom_ctrl_testplan.hjson +index 71e2a2d..db8d78a 100644 +--- a/data/rom_ctrl_testplan.hjson ++++ b/data/rom_ctrl_testplan.hjson +@@ -3,14 +3,14 @@ + // SPDX-License-Identifier: Apache-2.0 + { + name: "rom_ctrl" +- import_testplans: ["hw/dv/tools/dvsim/testplans/csr_testplan.hjson", +- "hw/dv/tools/dvsim/testplans/alert_test_testplan.hjson", +- "hw/dv/tools/dvsim/testplans/mem_testplan.hjson", +- "hw/dv/tools/dvsim/testplans/passthru_mem_intg_testplan.hjson", +- "hw/dv/tools/dvsim/testplans/tl_device_access_types_testplan.hjson", +- "hw/dv/tools/dvsim/testplans/sec_cm_fsm_testplan.hjson", +- "hw/dv/tools/dvsim/testplans/stress_all_with_reset_testplan.hjson", +- "hw/dv/tools/dvsim/testplans/sec_cm_count_testplan.hjson", ++ import_testplans: ["hw/vendor/lowrisc_ip/dv/tools/dvsim/testplans/csr_testplan.hjson", ++ "hw/vendor/lowrisc_ip/dv/tools/dvsim/testplans/alert_test_testplan.hjson", ++ "hw/vendor/lowrisc_ip/dv/tools/dvsim/testplans/mem_testplan.hjson", ++ "hw/vendor/lowrisc_ip/dv/tools/dvsim/testplans/passthru_mem_intg_testplan.hjson", ++ "hw/vendor/lowrisc_ip/dv/tools/dvsim/testplans/tl_device_access_types_testplan.hjson", ++ "hw/vendor/lowrisc_ip/dv/tools/dvsim/testplans/sec_cm_fsm_testplan.hjson", ++ "hw/vendor/lowrisc_ip/dv/tools/dvsim/testplans/stress_all_with_reset_testplan.hjson", ++ "hw/vendor/lowrisc_ip/dv/tools/dvsim/testplans/sec_cm_count_testplan.hjson", + "rom_ctrl_sec_cm_testplan.hjson"] + testpoints: [ + { +diff --git a/dv/env/rom_ctrl_bkdr_util.core b/dv/env/rom_ctrl_bkdr_util.core +index 42e75ec..70a2dd6 100644 +--- a/dv/env/rom_ctrl_bkdr_util.core ++++ b/dv/env/rom_ctrl_bkdr_util.core +@@ -13,6 +13,8 @@ filesets: + - lowrisc:dv:crypto_dpi_prince:0.1 + - lowrisc:dv:crypto_dpi_present:0.1 + - lowrisc:prim:secded:0.1 ++ - lowrisc:dv:digestpp_dpi:0.1 ++ - lowrisc:ip:kmac_pkg + - lowrisc:dv:sram_ctrl_bkdr_util + files: + - rom_ctrl_bkdr_util_pkg.sv +diff --git a/dv/rom_ctrl_32kB_sim_cfg.hjson b/dv/rom_ctrl_32kB_sim_cfg.hjson +index 941e953..a0b4a0a 100644 +--- a/dv/rom_ctrl_32kB_sim_cfg.hjson ++++ b/dv/rom_ctrl_32kB_sim_cfg.hjson +@@ -7,7 +7,7 @@ + variant: 32kB + + // Import the base rom_ctrl sim_cfg file +- import_cfgs: ["{proj_root}/hw/ip/rom_ctrl/dv/rom_ctrl_base_sim_cfg.hjson"] ++ import_cfgs: ["{proj_root}/hw/vendor/lowrisc_ip/ip/rom_ctrl/dv/rom_ctrl_base_sim_cfg.hjson"] + + build_opts: ["+define+ROM_BYTE_ADDR_WIDTH=15"] + } +diff --git a/dv/rom_ctrl_base_sim_cfg.hjson b/dv/rom_ctrl_base_sim_cfg.hjson +index 9062c0f..228a0ec 100644 +--- a/dv/rom_ctrl_base_sim_cfg.hjson ++++ b/dv/rom_ctrl_base_sim_cfg.hjson +@@ -12,30 +12,30 @@ + tb: tb + + // Simulator used to sign off this block +- tool: vcs ++ tool: xcelium + + // Fusesoc core file used for building the file list. + fusesoc_core: lowrisc:dv:rom_ctrl_sim:0.1 + + // Testplan hjson file. +- testplan: "{proj_root}/hw/ip/rom_ctrl/data/rom_ctrl_testplan.hjson" ++ testplan: "{proj_root}/hw/vendor/lowrisc_ip/ip/rom_ctrl/data/rom_ctrl_testplan.hjson" + + // RAL spec - used to generate the RAL model. +- ral_spec: "{proj_root}/hw/ip/rom_ctrl/data/rom_ctrl.hjson" ++ ral_spec: "{proj_root}/hw/vendor/lowrisc_ip/ip/rom_ctrl/data/rom_ctrl.hjson" + + // Import additional common sim cfg files. + import_cfgs: [// Project wide common sim cfg file +- "{proj_root}/hw/dv/tools/dvsim/common_sim_cfg.hjson", ++ "{proj_root}/hw/vendor/lowrisc_ip/dv/tools/dvsim/common_sim_cfg.hjson", + // Config files to get the correct flags for crypto_dpi_prince +- "{proj_root}/hw/ip/prim/dv/prim_prince/crypto_dpi_prince/crypto_dpi_prince_sim_opts.hjson", ++ "{proj_root}/hw/vendor/lowrisc_ip/ip/prim/dv/prim_prince/crypto_dpi_prince/crypto_dpi_prince_sim_opts.hjson", + // Common CIP test lists +- "{proj_root}/hw/dv/tools/dvsim/tests/csr_tests.hjson", +- "{proj_root}/hw/dv/tools/dvsim/tests/mem_tests.hjson", +- "{proj_root}/hw/dv/tools/dvsim/tests/alert_test.hjson", +- "{proj_root}/hw/dv/tools/dvsim/tests/tl_access_tests.hjson", +- "{proj_root}/hw/dv/tools/dvsim/tests/passthru_mem_intg_tests.hjson", +- "{proj_root}/hw/dv/tools/dvsim/tests/sec_cm_tests.hjson", +- "{proj_root}/hw/dv/tools/dvsim/tests/stress_tests.hjson"] ++ "{proj_root}/hw/vendor/lowrisc_ip/dv/tools/dvsim/tests/csr_tests.hjson", ++ "{proj_root}/hw/vendor/lowrisc_ip/dv/tools/dvsim/tests/mem_tests.hjson", ++ "{proj_root}/hw/vendor/lowrisc_ip/dv/tools/dvsim/tests/alert_test.hjson", ++ "{proj_root}/hw/vendor/lowrisc_ip/dv/tools/dvsim/tests/tl_access_tests.hjson", ++ "{proj_root}/hw/vendor/lowrisc_ip/dv/tools/dvsim/tests/passthru_mem_intg_tests.hjson", ++ "{proj_root}/hw/vendor/lowrisc_ip/dv/tools/dvsim/tests/sec_cm_tests.hjson", ++ "{proj_root}/hw/vendor/lowrisc_ip/dv/tools/dvsim/tests/stress_tests.hjson"] + + en_build_modes: ["{tool}_crypto_dpi_prince_build_opts"] + +@@ -58,13 +58,13 @@ + } + { + name: cover_reg_top_vcs_cov_cfg_file +- value: "-cm_hier {proj_root}/hw/dv/tools/vcs/cover_reg_top.cfg+{proj_root}/hw/ip/rom_ctrl/dv/cov/cover_reg_top.cfg" ++ value: "-cm_hier {proj_root}/hw/vendor/lowrisc_ip/dv/tools/vcs/cover_reg_top.cfg+{proj_root}/hw/vendor/lowrisc_ip/ip/rom_ctrl/dv/cov/cover_reg_top.cfg" + } + ] + + // Add ROM_CTRL specific exclusion files. +- vcs_cov_excl_files: ["{proj_root}/hw/ip/rom_ctrl/dv/cov/rom_ctrl_cov_unr_excl.el", +- "{proj_root}/hw/ip/rom_ctrl/dv/cov/rom_ctrl_cov_excl.el"] ++ vcs_cov_excl_files: ["{proj_root}/hw/vendor/lowrisc_ip/ip/rom_ctrl/dv/cov/rom_ctrl_cov_unr_excl.el", ++ "{proj_root}/hw/vendor/lowrisc_ip/ip/rom_ctrl/dv/cov/rom_ctrl_cov_excl.el"] + + // Default UVM test and seq class name. + uvm_test: rom_ctrl_base_test diff --git a/hw/vendor/patches/lowrisc_ip/rom_ctrl/0002_DV_Simplify_Dependency_Fixes.patch b/hw/vendor/patches/lowrisc_ip/rom_ctrl/0002_DV_Simplify_Dependency_Fixes.patch new file mode 100644 index 00000000..b4484980 --- /dev/null +++ b/hw/vendor/patches/lowrisc_ip/rom_ctrl/0002_DV_Simplify_Dependency_Fixes.patch @@ -0,0 +1,15 @@ +diff --git a/dv/env/rom_ctrl_bkdr_util.core b/dv/env/rom_ctrl_bkdr_util.core +index 70a2dd6..6cfdfbc 100644 +--- a/dv/env/rom_ctrl_bkdr_util.core ++++ b/dv/env/rom_ctrl_bkdr_util.core +@@ -15,8 +15,9 @@ filesets: + - lowrisc:prim:secded:0.1 + - lowrisc:dv:digestpp_dpi:0.1 + - lowrisc:ip:kmac_pkg +- - lowrisc:dv:sram_ctrl_bkdr_util ++ - lowrisc:dv:mem_bkdr_util + files: ++ - sram_scrambler_pkg.sv + - rom_ctrl_bkdr_util_pkg.sv + - rom_ctrl_bkdr_util.sv: {is_include_file: true} + file_type: systemVerilogSource diff --git a/hw/vendor/patches/lowrisc_ip/rom_ctrl/0003_Sram_Scrambler_Added.patch b/hw/vendor/patches/lowrisc_ip/rom_ctrl/0003_Sram_Scrambler_Added.patch new file mode 100644 index 00000000..509dea39 --- /dev/null +++ b/hw/vendor/patches/lowrisc_ip/rom_ctrl/0003_Sram_Scrambler_Added.patch @@ -0,0 +1,374 @@ +diff --git a/dv/env/sram_scrambler_pkg.sv b/dv/env/sram_scrambler_pkg.sv +new file mode 100644 +index 0000000..a76718d +--- /dev/null ++++ b/dv/env/sram_scrambler_pkg.sv +@@ -0,0 +1,368 @@ ++// Copyright lowRISC contributors (OpenTitan project). ++// Licensed under the Apache License, Version 2.0, see LICENSE for details. ++// SPDX-License-Identifier: Apache-2.0 ++ ++//////////////////////////////////////////// ++// SRAM address and data scrambling logic // ++/////////////////////////////////////////// ++// ++// There are a few general things to note here: ++// ++// - SRAM data scrambling relies on a reduced-round PRINCE cipher, plus a custom substitution ++// and permutation network loosely based off of PRESENT. ++// ++// - SRAM address scrambling relies solely on the custom substitution and permutation network. ++// ++// - The custom subst/perm network used for data scrambling operates at byte granularity, ++// while for address scrambling it operates at a granularity of the address width. ++// ++// - For DV purposes we can safely rely on the PRESENT sboxes, as nightly regressions are ++// completely passing plus the sboxes in `prim_cipher_pkg` are copied directly from the ++// PRESENT specifications. ++// This has the side effect of allowing us to avoid duplication of the sboxes, which lowers the ++// probability of an error in translation. ++ ++package sram_scrambler_pkg; ++ ++ import uvm_pkg::*; ++ import bus_params_pkg::BUS_AW; ++ import crypto_dpi_prince_pkg::*; ++ import prim_cipher_pkg::*; ++ ++ `include "uvm_macros.svh" ++ ++ string path = "sram_scrambler_pkg"; ++ ++ // Fixed key size - PRINCE cipher operates on a 128-bit key, ++ // and the same key is used for all parallel cipher instances. ++ parameter int SRAM_KEY_WIDTH = 128; ++ ++ // Fixed data block size - PRINCE cipher operates on 64-bit data blocks. ++ parameter int SRAM_BLOCK_WIDTH = 64; ++ ++ parameter int NUM_PRINCE_ROUNDS_HALF_MAX = 5; ++ parameter int NUM_SP_ROUNDS = 2; ++ ++ // Create a generic typedef for dynamic array of logic to be able to return these values. ++ typedef logic state_t[]; ++ ++ // The sboxes operate on nibbles. ++ // ++ // If `WIDTH % 4 != 0`, the uppermost bits will get shifted to lower positions ++ // during either the `flip_vector` or `perm_layer` stage of the network, ++ // so it is guaranteed that all bits will eventually go through an sbox. ++ function automatic state_t sbox_layer(state_t state, int width, bit inv); ++ logic state_out[] = new[width](state); ++ logic [3:0] sbox_in; ++ logic [3:0] sbox_out; ++ for (int i = 0; i < width / 4; i++) begin ++ // `with` syntax is currently unsupported by Verible, ++ // uncomment once support has been added ++ // ++ //sbox_in = {<< {state with [i*4 +: 4]}}; ++ for (int j = 0; j < 4; j++) begin ++ sbox_in[j] = state[i*4 + j]; ++ end ++ ++ if (inv) begin ++ sbox_out = prim_cipher_pkg::PRESENT_SBOX4_INV[sbox_in]; ++ end else begin ++ sbox_out = prim_cipher_pkg::PRESENT_SBOX4[sbox_in]; ++ end ++ ++ for (int j = 0; j < 4; j++) begin ++ state_out[i*4 + j] = sbox_out[j]; ++ end ++ end ++ return state_out; ++ endfunction : sbox_layer ++ ++ // Reverse the input bit vector. ++ function automatic state_t flip_vector(state_t state); ++ return {<< {state}}; ++ endfunction : flip_vector ++ ++ // Permutation layer - all even indexed bits move to the lower half, ++ // and all odd indexed bits move to the top half. ++ function automatic state_t perm_layer(state_t state, int width, bit inv); ++ logic state_out[] = new[width](state); ++ for (int i = 0; i < width / 2; i++) begin ++ if (inv) begin ++ state_out[i * 2] = state[i]; ++ state_out[i * 2 + 1] = state[i + width / 2]; ++ end else begin ++ state_out[i] = state[i * 2]; ++ state_out[i + width / 2] = state[i * 2 + 1]; ++ end ++ end ++ return state_out; ++ endfunction : perm_layer ++ ++ // Performs NUM_SP_ROUNDS full encryption rounds ++ function automatic state_t sp_encrypt(state_t data, int width, state_t key); ++ logic state[] = new[width](data); ++ for (int i = 0; i < NUM_SP_ROUNDS; i++) begin ++ // xor the data and key ++ for (int j = 0; j < width; j++) begin ++ state[j] = state[j] ^ key[j]; ++ end ++ // sbox layer ++ state = sbox_layer(state, width, 0); ++ // flip the bit vector ++ state = flip_vector(state); ++ // permutation layer ++ state = perm_layer(state, width, 0); ++ end ++ // final xor ++ for (int i = 0; i < width; i++) begin ++ state[i] = state[i] ^ key[i]; ++ end ++ return state; ++ endfunction : sp_encrypt ++ ++ // Performs NUM_SP_ROUNDS full decryption rounds ++ function automatic state_t sp_decrypt(state_t data, int width, state_t key); ++ logic state[] = new[width](data); ++ for (int i = 0; i < NUM_SP_ROUNDS; i++) begin ++ // xor data and key ++ for (int j = 0; j < width; j++) begin ++ state[j] = state[j] ^ key[j]; ++ end ++ // permutation layer ++ state = perm_layer(state, width, 1); ++ // flip bit vector ++ state = flip_vector(state); ++ // sbox layer ++ state = sbox_layer(state, width, 1'b1); ++ end ++ // final xor ++ for (int i = 0; i < width; i++) begin ++ state[i] = state[i] ^ key[i]; ++ end ++ return state; ++ endfunction : sp_decrypt ++ ++ // Generates the 64-bit keystream that is XORed with the data to obtain a ciphertext. ++ // Assumes that the data is at most 64 bits wide. ++ // ++ // Should not be called directly. ++ function automatic state_t gen_keystream(logic addr[], int addr_width, ++ logic key[], logic nonce[], ++ int num_prince_rounds_half = 3); ++ logic [NUM_PRINCE_ROUNDS_HALF_MAX-1:0][SRAM_BLOCK_WIDTH-1:0] prince_result_arr; ++ ++ logic [SRAM_BLOCK_WIDTH-1:0] prince_plaintext; ++ logic [SRAM_KEY_WIDTH-1:0] prince_key; ++ logic [SRAM_BLOCK_WIDTH-1:0] prince_result; ++ ++ logic iv[] = new[SRAM_BLOCK_WIDTH]; ++ logic key_out[] = new[SRAM_BLOCK_WIDTH]; ++ ++ // IV is composed of nonce concatenated with address ++ for (int i = 0; i < addr_width; i++) begin ++ iv[i] = addr[i]; ++ end ++ for (int i = 0; i < SRAM_BLOCK_WIDTH - addr_width; i++) begin ++ iv[addr_width + i] = nonce[i]; ++ end ++ ++ //for (int i = 0; i < SRAM_BLOCK_WIDTH - addr_width; i++) begin ++ // iv[addr_width + i] = nonce[i]; ++ //end ++ ++ // convert arrays to packed vectors before invoking prince DPI model ++ prince_plaintext = {<< {iv}}; ++ // `with` syntax is currently unsupported by Verible, ++ // uncomment once support has been added ++ // ++ // prince_key = {<< {key with [0 +: SRAM_KEY_WIDTH]}}; ++ for (int i = 0; i < SRAM_KEY_WIDTH; i++) begin ++ prince_key[i] = key[i]; ++ end ++ ++ crypto_dpi_prince_pkg::sv_dpi_prince_encrypt(.plaintext(prince_plaintext), ++ .key(prince_key), ++ .old_key_schedule(0), ++ .ciphertext(prince_result_arr)); ++ prince_result = prince_result_arr[num_prince_rounds_half-1]; ++ ++ key_out = {<< {prince_result}}; ++ ++ return key_out; ++ endfunction : gen_keystream ++ ++ // Encrypts the target SRAM address using the custom S&P network. ++ function automatic state_t encrypt_sram_addr(logic addr[], int addr_width, ++ logic full_nonce[]); ++ ++ logic nonce[] = new[addr_width]; ++ logic encrypted_addr[] = new[addr_width]; ++ ++ // The address encryption nonce is the same width as the address, ++ // and is constructed from the top addr_width bits of the full nonce. ++ // ++ // `with` syntax is currently unsupported by Verible, ++ // uncomment once support has been added ++ // ++ // nonce = {>> {full_nonce with [SRAM_BLOCK_WIDTH - addr_width +: addr_width]}}; ++ for (int i = 0; i < addr_width; i++) begin ++ nonce[i] = full_nonce[SRAM_BLOCK_WIDTH - addr_width + i]; ++ end ++ encrypted_addr = sp_encrypt(addr, addr_width, nonce); ++ return encrypted_addr; ++ ++ endfunction : encrypt_sram_addr ++ ++ // Decrypts the target SRAM address using the custom S&P network. ++ function automatic state_t decrypt_sram_addr(logic addr[], int addr_width, ++ logic full_nonce[]); ++ ++ logic nonce[] = new[addr_width]; ++ logic encrypted_addr[] = new[addr_width]; ++ ++ // The address encryption nonce is the same width as the address, ++ // and is constructed from the top addr_width bits of the full nonce. ++ // ++ // `with` syntax is currently unsupported by Verible, ++ // uncomment once support has been added ++ // ++ // nonce = {>> {full_nonce with [SRAM_BLOCK_WIDTH - addr_width +: addr_width]}}; ++ for (int i = 0; i < addr_width; i++) begin ++ nonce[i] = full_nonce[SRAM_BLOCK_WIDTH - addr_width + i]; ++ end ++ ++ encrypted_addr = sp_decrypt(addr, addr_width, nonce); ++ return encrypted_addr; ++ ++ endfunction : decrypt_sram_addr ++ ++ // SRAM data encryption is more involved, we need to run up to 5 half rounds of PRINCE on the ++ // nonce and key and then XOR the result with the data. ++ // ++ // Optionally, the XORed data can be passed through the S&P network. ++ function automatic state_t encrypt_sram_data(logic data[], int data_width, int sp_width, ++ logic addr[], int addr_width, ++ logic key[], logic nonce[], ++ int num_prince_rounds_half = 3, ++ bit use_sp_layer = 0); ++ logic keystream[] = new[SRAM_BLOCK_WIDTH]; ++ logic data_enc[] = new[data_width]; ++ logic byte_to_enc[] = new[8]; ++ logic enc_byte[] = new[8]; ++ logic zero_key[] = new[data_width]; ++ int ks_width = (data_width < 64) ? data_width : 64; ++ ++ // the key used for byte diffusion is all-zero. ++ for (int i = 0; i < data_width; i++) begin ++ zero_key[i] = '0; ++ end ++ ++ // Generate the keystream ++ keystream = gen_keystream(addr, addr_width, key, nonce, num_prince_rounds_half); ++ ++ // XOR keystream with input data ++ // Assumes ks_width <= 64. ++ for (int i = 0; i < data_width; i++) begin ++ data_enc[i] = data[i] ^ keystream[i % ks_width]; ++ end ++ ++ if (use_sp_layer) begin ++ if (data_width == sp_width) begin ++ // pass the entire word through the subst/perm network at once (the next cases would give the ++ // same results too, but this should be a bit more efficient) ++ data_enc = sp_encrypt(data_enc, data_width, zero_key); ++ end else if (sp_width == 8) begin ++ // pass each byte of the encoded result through the subst/perm network (special case of the ++ // general code below) ++ for (int i = 0; i < data_width / 8; i++) begin ++ byte_to_enc = data_enc[i*8 +: 8]; ++ enc_byte = sp_encrypt(byte_to_enc, 8, zero_key); ++ data_enc[i*8 +: 8] = enc_byte; ++ end ++ end else begin ++ // divide the word into sp_width chunks to pass it through the subst/perm network ++ for (int chunk_lsb = 0; chunk_lsb < data_width; chunk_lsb += sp_width) begin ++ int bits_remaining = data_width - chunk_lsb; ++ int chunk_width = (bits_remaining < sp_width) ? bits_remaining : sp_width; ++ logic chunk[] = new[chunk_width]; ++ ++ for (int j = 0; j < chunk_width; j++) begin ++ chunk[j] = data_enc[chunk_lsb + j]; ++ end ++ chunk = sp_encrypt(chunk, chunk_width, zero_key); ++ for (int j = 0; j < chunk_width; j++) begin ++ data_enc[chunk_lsb + j] = chunk[j]; ++ end ++ end ++ end ++ end ++ return data_enc; ++ ++ endfunction : encrypt_sram_data ++ ++ function automatic state_t decrypt_sram_data(logic data[], int data_width, int sp_width, ++ logic addr[], int addr_width, ++ logic key[], logic nonce[], ++ int num_prince_rounds_half = 3, ++ bit use_sp_layer = 0); ++ logic keystream[] = new[SRAM_BLOCK_WIDTH]; ++ logic data_dec[] = new[data_width]; ++ logic byte_to_dec[] = new[8]; ++ logic dec_byte[] = new[8]; ++ logic zero_key[] = new[data_width]; ++ int ks_width = (data_width < 64) ? data_width : 64; ++ ++ // the key used for byte diffusion is all-zero. ++ for (int i = 0; i < data_width; i++) begin ++ zero_key[i] = '0; ++ end ++ ++ // Generate the keystream ++ keystream = gen_keystream(addr, addr_width, key, nonce, num_prince_rounds_half); ++ ++ if (use_sp_layer) begin ++ if (data_width == sp_width) begin ++ // pass the entire word through the subst/perm network at once (the next cases would give the ++ // same results too, but this should be a bit more efficient) ++ data_dec = sp_decrypt(data, data_width, zero_key); ++ end else if (sp_width == 8) begin ++ // pass each byte of the data through the subst/perm network (special case of the general code ++ // below) ++ for (int i = 0; i < data_width / 8; i++) begin ++ byte_to_dec = data[i*8 +: 8]; ++ dec_byte = sp_decrypt(byte_to_dec, 8, zero_key); ++ data_dec[i*8 +: 8] = dec_byte; ++ end ++ end else begin ++ // divide the word into sp_width chunks to pass it through the subst/perm network ++ for (int chunk_lsb = 0; chunk_lsb < data_width; chunk_lsb += sp_width) begin ++ int bits_remaining = data_width - chunk_lsb; ++ int chunk_width = (bits_remaining < sp_width) ? bits_remaining : sp_width; ++ logic chunk[] = new[chunk_width]; ++ ++ for (int j = 0; j < chunk_width; j++) begin ++ chunk[j] = data[chunk_lsb + j]; ++ end ++ chunk = sp_decrypt(chunk, chunk_width, zero_key); ++ for (int j = 0; j < chunk_width; j++) begin ++ data_dec[chunk_lsb + j] = chunk[j]; ++ end ++ end ++ end ++ ++ // XOR result data with the keystream ++ for (int i = 0; i < data_width; i++) begin ++ data_dec[i] = data_dec[i] ^ keystream[i % ks_width]; ++ end ++ end else begin ++ // XOR result data with the keystream ++ for (int i = 0; i < data_width; i++) begin ++ data_dec[i] = data[i] ^ keystream[i % ks_width]; ++ end ++ end ++ ++ return data_dec; ++ ++ endfunction : decrypt_sram_data ++ ++endpackage : sram_scrambler_pkg From 96c8c65d346d44a5522257d681c9107b7fb52e56 Mon Sep 17 00:00:00 2001 From: Kolos Koblasz Date: Mon, 27 Apr 2026 12:43:20 +0100 Subject: [PATCH 2/3] [rom_ctrl, vendoring] Vendored and patched files added * kmac_app_agent modifications added * rom_ctrl modifications added Signed-off-by: Kolos Koblasz --- .../dv/sv/kmac_app_agent/kmac_app_agent.core | 1 - .../sv/kmac_app_agent/kmac_app_agent_pkg.sv | 8 +- .../dv/sv/kmac_app_agent/kmac_app_intf.sv | 4 +- .../ip/rom_ctrl/data/rom_ctrl_testplan.hjson | 16 +- .../rom_ctrl/dv/env/rom_ctrl_bkdr_util.core | 5 +- .../ip/rom_ctrl/dv/env/sram_scrambler_pkg.sv | 368 ++++++++++++++++++ .../rom_ctrl/dv/rom_ctrl_32kB_sim_cfg.hjson | 2 +- .../rom_ctrl/dv/rom_ctrl_base_sim_cfg.hjson | 30 +- 8 files changed, 401 insertions(+), 33 deletions(-) create mode 100644 hw/vendor/lowrisc_ip/ip/rom_ctrl/dv/env/sram_scrambler_pkg.sv diff --git a/hw/vendor/lowrisc_ip/dv/sv/kmac_app_agent/kmac_app_agent.core b/hw/vendor/lowrisc_ip/dv/sv/kmac_app_agent/kmac_app_agent.core index 79527ccb..acaf70c5 100644 --- a/hw/vendor/lowrisc_ip/dv/sv/kmac_app_agent/kmac_app_agent.core +++ b/hw/vendor/lowrisc_ip/dv/sv/kmac_app_agent/kmac_app_agent.core @@ -10,7 +10,6 @@ filesets: - lowrisc:dv:dv_utils - lowrisc:dv:dv_lib - lowrisc:dv:push_pull_agent - - lowrisc:ip:keymgr_pkg - lowrisc:ip:kmac_pkg files: - kmac_app_agent_pkg.sv diff --git a/hw/vendor/lowrisc_ip/dv/sv/kmac_app_agent/kmac_app_agent_pkg.sv b/hw/vendor/lowrisc_ip/dv/sv/kmac_app_agent/kmac_app_agent_pkg.sv index d1b35860..572b5364 100644 --- a/hw/vendor/lowrisc_ip/dv/sv/kmac_app_agent/kmac_app_agent_pkg.sv +++ b/hw/vendor/lowrisc_ip/dv/sv/kmac_app_agent/kmac_app_agent_pkg.sv @@ -7,7 +7,6 @@ package kmac_app_agent_pkg; import uvm_pkg::*; import dv_utils_pkg::*; import dv_lib_pkg::*; - import keymgr_pkg::*; import push_pull_agent_pkg::*; // macro includes @@ -15,9 +14,10 @@ package kmac_app_agent_pkg; `include "dv_macros.svh" // parameters - parameter int KMAC_REQ_DATA_WIDTH = keymgr_pkg::KmacDataIfWidth // data width - + keymgr_pkg::KmacDataIfWidth / 8 // data mask width - + 1; // bit last + parameter int KmacDataIfWidth = 64; // keymgr_pkg::KmacDataIfWidth + parameter int KMAC_REQ_DATA_WIDTH = KmacDataIfWidth // data width + + KmacDataIfWidth / 8 // data mask width + + 1; // bit last `define CONNECT_DATA_WIDTH .HostDataWidth(kmac_app_agent_pkg::KMAC_REQ_DATA_WIDTH) diff --git a/hw/vendor/lowrisc_ip/dv/sv/kmac_app_agent/kmac_app_intf.sv b/hw/vendor/lowrisc_ip/dv/sv/kmac_app_agent/kmac_app_intf.sv index 8fe2c411..b5c926cb 100644 --- a/hw/vendor/lowrisc_ip/dv/sv/kmac_app_agent/kmac_app_intf.sv +++ b/hw/vendor/lowrisc_ip/dv/sv/kmac_app_agent/kmac_app_intf.sv @@ -5,8 +5,6 @@ // verilog_lint: waive interface-name-style interface kmac_app_intf (input clk, input rst_n); - import keymgr_pkg::*; - dv_utils_pkg::if_mode_e if_mode; // interface mode - Host or Device // interface pins used to connect with DUT @@ -60,7 +58,7 @@ interface kmac_app_intf (input clk, input rst_n); clk, !rst_n || if_mode == dv_utils_pkg::Host) // Check strb is aligned to LSB, for example: if strb[1]==0, strb[$:2] should be 0 too - for (genvar k = 1; k < KmacDataIfWidth / 8 - 1; k++) begin : gen_strb_check + for (genvar k = 1; k < kmac_app_agent_pkg::KmacDataIfWidth / 8 - 1; k++) begin : gen_strb_check `ASSERT(StrbAlignLSB_A, kmac_data_req.valid && kmac_data_req.strb[k] === 0 |-> kmac_data_req.strb[k+1] === 0, clk, !rst_n || if_mode == dv_utils_pkg::Host) diff --git a/hw/vendor/lowrisc_ip/ip/rom_ctrl/data/rom_ctrl_testplan.hjson b/hw/vendor/lowrisc_ip/ip/rom_ctrl/data/rom_ctrl_testplan.hjson index 71e2a2d7..db8d78a4 100644 --- a/hw/vendor/lowrisc_ip/ip/rom_ctrl/data/rom_ctrl_testplan.hjson +++ b/hw/vendor/lowrisc_ip/ip/rom_ctrl/data/rom_ctrl_testplan.hjson @@ -3,14 +3,14 @@ // SPDX-License-Identifier: Apache-2.0 { name: "rom_ctrl" - import_testplans: ["hw/dv/tools/dvsim/testplans/csr_testplan.hjson", - "hw/dv/tools/dvsim/testplans/alert_test_testplan.hjson", - "hw/dv/tools/dvsim/testplans/mem_testplan.hjson", - "hw/dv/tools/dvsim/testplans/passthru_mem_intg_testplan.hjson", - "hw/dv/tools/dvsim/testplans/tl_device_access_types_testplan.hjson", - "hw/dv/tools/dvsim/testplans/sec_cm_fsm_testplan.hjson", - "hw/dv/tools/dvsim/testplans/stress_all_with_reset_testplan.hjson", - "hw/dv/tools/dvsim/testplans/sec_cm_count_testplan.hjson", + import_testplans: ["hw/vendor/lowrisc_ip/dv/tools/dvsim/testplans/csr_testplan.hjson", + "hw/vendor/lowrisc_ip/dv/tools/dvsim/testplans/alert_test_testplan.hjson", + "hw/vendor/lowrisc_ip/dv/tools/dvsim/testplans/mem_testplan.hjson", + "hw/vendor/lowrisc_ip/dv/tools/dvsim/testplans/passthru_mem_intg_testplan.hjson", + "hw/vendor/lowrisc_ip/dv/tools/dvsim/testplans/tl_device_access_types_testplan.hjson", + "hw/vendor/lowrisc_ip/dv/tools/dvsim/testplans/sec_cm_fsm_testplan.hjson", + "hw/vendor/lowrisc_ip/dv/tools/dvsim/testplans/stress_all_with_reset_testplan.hjson", + "hw/vendor/lowrisc_ip/dv/tools/dvsim/testplans/sec_cm_count_testplan.hjson", "rom_ctrl_sec_cm_testplan.hjson"] testpoints: [ { diff --git a/hw/vendor/lowrisc_ip/ip/rom_ctrl/dv/env/rom_ctrl_bkdr_util.core b/hw/vendor/lowrisc_ip/ip/rom_ctrl/dv/env/rom_ctrl_bkdr_util.core index 42e75ec2..6cfdfbc2 100644 --- a/hw/vendor/lowrisc_ip/ip/rom_ctrl/dv/env/rom_ctrl_bkdr_util.core +++ b/hw/vendor/lowrisc_ip/ip/rom_ctrl/dv/env/rom_ctrl_bkdr_util.core @@ -13,8 +13,11 @@ filesets: - lowrisc:dv:crypto_dpi_prince:0.1 - lowrisc:dv:crypto_dpi_present:0.1 - lowrisc:prim:secded:0.1 - - lowrisc:dv:sram_ctrl_bkdr_util + - lowrisc:dv:digestpp_dpi:0.1 + - lowrisc:ip:kmac_pkg + - lowrisc:dv:mem_bkdr_util files: + - sram_scrambler_pkg.sv - rom_ctrl_bkdr_util_pkg.sv - rom_ctrl_bkdr_util.sv: {is_include_file: true} file_type: systemVerilogSource diff --git a/hw/vendor/lowrisc_ip/ip/rom_ctrl/dv/env/sram_scrambler_pkg.sv b/hw/vendor/lowrisc_ip/ip/rom_ctrl/dv/env/sram_scrambler_pkg.sv new file mode 100644 index 00000000..a76718d2 --- /dev/null +++ b/hw/vendor/lowrisc_ip/ip/rom_ctrl/dv/env/sram_scrambler_pkg.sv @@ -0,0 +1,368 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +//////////////////////////////////////////// +// SRAM address and data scrambling logic // +/////////////////////////////////////////// +// +// There are a few general things to note here: +// +// - SRAM data scrambling relies on a reduced-round PRINCE cipher, plus a custom substitution +// and permutation network loosely based off of PRESENT. +// +// - SRAM address scrambling relies solely on the custom substitution and permutation network. +// +// - The custom subst/perm network used for data scrambling operates at byte granularity, +// while for address scrambling it operates at a granularity of the address width. +// +// - For DV purposes we can safely rely on the PRESENT sboxes, as nightly regressions are +// completely passing plus the sboxes in `prim_cipher_pkg` are copied directly from the +// PRESENT specifications. +// This has the side effect of allowing us to avoid duplication of the sboxes, which lowers the +// probability of an error in translation. + +package sram_scrambler_pkg; + + import uvm_pkg::*; + import bus_params_pkg::BUS_AW; + import crypto_dpi_prince_pkg::*; + import prim_cipher_pkg::*; + + `include "uvm_macros.svh" + + string path = "sram_scrambler_pkg"; + + // Fixed key size - PRINCE cipher operates on a 128-bit key, + // and the same key is used for all parallel cipher instances. + parameter int SRAM_KEY_WIDTH = 128; + + // Fixed data block size - PRINCE cipher operates on 64-bit data blocks. + parameter int SRAM_BLOCK_WIDTH = 64; + + parameter int NUM_PRINCE_ROUNDS_HALF_MAX = 5; + parameter int NUM_SP_ROUNDS = 2; + + // Create a generic typedef for dynamic array of logic to be able to return these values. + typedef logic state_t[]; + + // The sboxes operate on nibbles. + // + // If `WIDTH % 4 != 0`, the uppermost bits will get shifted to lower positions + // during either the `flip_vector` or `perm_layer` stage of the network, + // so it is guaranteed that all bits will eventually go through an sbox. + function automatic state_t sbox_layer(state_t state, int width, bit inv); + logic state_out[] = new[width](state); + logic [3:0] sbox_in; + logic [3:0] sbox_out; + for (int i = 0; i < width / 4; i++) begin + // `with` syntax is currently unsupported by Verible, + // uncomment once support has been added + // + //sbox_in = {<< {state with [i*4 +: 4]}}; + for (int j = 0; j < 4; j++) begin + sbox_in[j] = state[i*4 + j]; + end + + if (inv) begin + sbox_out = prim_cipher_pkg::PRESENT_SBOX4_INV[sbox_in]; + end else begin + sbox_out = prim_cipher_pkg::PRESENT_SBOX4[sbox_in]; + end + + for (int j = 0; j < 4; j++) begin + state_out[i*4 + j] = sbox_out[j]; + end + end + return state_out; + endfunction : sbox_layer + + // Reverse the input bit vector. + function automatic state_t flip_vector(state_t state); + return {<< {state}}; + endfunction : flip_vector + + // Permutation layer - all even indexed bits move to the lower half, + // and all odd indexed bits move to the top half. + function automatic state_t perm_layer(state_t state, int width, bit inv); + logic state_out[] = new[width](state); + for (int i = 0; i < width / 2; i++) begin + if (inv) begin + state_out[i * 2] = state[i]; + state_out[i * 2 + 1] = state[i + width / 2]; + end else begin + state_out[i] = state[i * 2]; + state_out[i + width / 2] = state[i * 2 + 1]; + end + end + return state_out; + endfunction : perm_layer + + // Performs NUM_SP_ROUNDS full encryption rounds + function automatic state_t sp_encrypt(state_t data, int width, state_t key); + logic state[] = new[width](data); + for (int i = 0; i < NUM_SP_ROUNDS; i++) begin + // xor the data and key + for (int j = 0; j < width; j++) begin + state[j] = state[j] ^ key[j]; + end + // sbox layer + state = sbox_layer(state, width, 0); + // flip the bit vector + state = flip_vector(state); + // permutation layer + state = perm_layer(state, width, 0); + end + // final xor + for (int i = 0; i < width; i++) begin + state[i] = state[i] ^ key[i]; + end + return state; + endfunction : sp_encrypt + + // Performs NUM_SP_ROUNDS full decryption rounds + function automatic state_t sp_decrypt(state_t data, int width, state_t key); + logic state[] = new[width](data); + for (int i = 0; i < NUM_SP_ROUNDS; i++) begin + // xor data and key + for (int j = 0; j < width; j++) begin + state[j] = state[j] ^ key[j]; + end + // permutation layer + state = perm_layer(state, width, 1); + // flip bit vector + state = flip_vector(state); + // sbox layer + state = sbox_layer(state, width, 1'b1); + end + // final xor + for (int i = 0; i < width; i++) begin + state[i] = state[i] ^ key[i]; + end + return state; + endfunction : sp_decrypt + + // Generates the 64-bit keystream that is XORed with the data to obtain a ciphertext. + // Assumes that the data is at most 64 bits wide. + // + // Should not be called directly. + function automatic state_t gen_keystream(logic addr[], int addr_width, + logic key[], logic nonce[], + int num_prince_rounds_half = 3); + logic [NUM_PRINCE_ROUNDS_HALF_MAX-1:0][SRAM_BLOCK_WIDTH-1:0] prince_result_arr; + + logic [SRAM_BLOCK_WIDTH-1:0] prince_plaintext; + logic [SRAM_KEY_WIDTH-1:0] prince_key; + logic [SRAM_BLOCK_WIDTH-1:0] prince_result; + + logic iv[] = new[SRAM_BLOCK_WIDTH]; + logic key_out[] = new[SRAM_BLOCK_WIDTH]; + + // IV is composed of nonce concatenated with address + for (int i = 0; i < addr_width; i++) begin + iv[i] = addr[i]; + end + for (int i = 0; i < SRAM_BLOCK_WIDTH - addr_width; i++) begin + iv[addr_width + i] = nonce[i]; + end + + //for (int i = 0; i < SRAM_BLOCK_WIDTH - addr_width; i++) begin + // iv[addr_width + i] = nonce[i]; + //end + + // convert arrays to packed vectors before invoking prince DPI model + prince_plaintext = {<< {iv}}; + // `with` syntax is currently unsupported by Verible, + // uncomment once support has been added + // + // prince_key = {<< {key with [0 +: SRAM_KEY_WIDTH]}}; + for (int i = 0; i < SRAM_KEY_WIDTH; i++) begin + prince_key[i] = key[i]; + end + + crypto_dpi_prince_pkg::sv_dpi_prince_encrypt(.plaintext(prince_plaintext), + .key(prince_key), + .old_key_schedule(0), + .ciphertext(prince_result_arr)); + prince_result = prince_result_arr[num_prince_rounds_half-1]; + + key_out = {<< {prince_result}}; + + return key_out; + endfunction : gen_keystream + + // Encrypts the target SRAM address using the custom S&P network. + function automatic state_t encrypt_sram_addr(logic addr[], int addr_width, + logic full_nonce[]); + + logic nonce[] = new[addr_width]; + logic encrypted_addr[] = new[addr_width]; + + // The address encryption nonce is the same width as the address, + // and is constructed from the top addr_width bits of the full nonce. + // + // `with` syntax is currently unsupported by Verible, + // uncomment once support has been added + // + // nonce = {>> {full_nonce with [SRAM_BLOCK_WIDTH - addr_width +: addr_width]}}; + for (int i = 0; i < addr_width; i++) begin + nonce[i] = full_nonce[SRAM_BLOCK_WIDTH - addr_width + i]; + end + encrypted_addr = sp_encrypt(addr, addr_width, nonce); + return encrypted_addr; + + endfunction : encrypt_sram_addr + + // Decrypts the target SRAM address using the custom S&P network. + function automatic state_t decrypt_sram_addr(logic addr[], int addr_width, + logic full_nonce[]); + + logic nonce[] = new[addr_width]; + logic encrypted_addr[] = new[addr_width]; + + // The address encryption nonce is the same width as the address, + // and is constructed from the top addr_width bits of the full nonce. + // + // `with` syntax is currently unsupported by Verible, + // uncomment once support has been added + // + // nonce = {>> {full_nonce with [SRAM_BLOCK_WIDTH - addr_width +: addr_width]}}; + for (int i = 0; i < addr_width; i++) begin + nonce[i] = full_nonce[SRAM_BLOCK_WIDTH - addr_width + i]; + end + + encrypted_addr = sp_decrypt(addr, addr_width, nonce); + return encrypted_addr; + + endfunction : decrypt_sram_addr + + // SRAM data encryption is more involved, we need to run up to 5 half rounds of PRINCE on the + // nonce and key and then XOR the result with the data. + // + // Optionally, the XORed data can be passed through the S&P network. + function automatic state_t encrypt_sram_data(logic data[], int data_width, int sp_width, + logic addr[], int addr_width, + logic key[], logic nonce[], + int num_prince_rounds_half = 3, + bit use_sp_layer = 0); + logic keystream[] = new[SRAM_BLOCK_WIDTH]; + logic data_enc[] = new[data_width]; + logic byte_to_enc[] = new[8]; + logic enc_byte[] = new[8]; + logic zero_key[] = new[data_width]; + int ks_width = (data_width < 64) ? data_width : 64; + + // the key used for byte diffusion is all-zero. + for (int i = 0; i < data_width; i++) begin + zero_key[i] = '0; + end + + // Generate the keystream + keystream = gen_keystream(addr, addr_width, key, nonce, num_prince_rounds_half); + + // XOR keystream with input data + // Assumes ks_width <= 64. + for (int i = 0; i < data_width; i++) begin + data_enc[i] = data[i] ^ keystream[i % ks_width]; + end + + if (use_sp_layer) begin + if (data_width == sp_width) begin + // pass the entire word through the subst/perm network at once (the next cases would give the + // same results too, but this should be a bit more efficient) + data_enc = sp_encrypt(data_enc, data_width, zero_key); + end else if (sp_width == 8) begin + // pass each byte of the encoded result through the subst/perm network (special case of the + // general code below) + for (int i = 0; i < data_width / 8; i++) begin + byte_to_enc = data_enc[i*8 +: 8]; + enc_byte = sp_encrypt(byte_to_enc, 8, zero_key); + data_enc[i*8 +: 8] = enc_byte; + end + end else begin + // divide the word into sp_width chunks to pass it through the subst/perm network + for (int chunk_lsb = 0; chunk_lsb < data_width; chunk_lsb += sp_width) begin + int bits_remaining = data_width - chunk_lsb; + int chunk_width = (bits_remaining < sp_width) ? bits_remaining : sp_width; + logic chunk[] = new[chunk_width]; + + for (int j = 0; j < chunk_width; j++) begin + chunk[j] = data_enc[chunk_lsb + j]; + end + chunk = sp_encrypt(chunk, chunk_width, zero_key); + for (int j = 0; j < chunk_width; j++) begin + data_enc[chunk_lsb + j] = chunk[j]; + end + end + end + end + return data_enc; + + endfunction : encrypt_sram_data + + function automatic state_t decrypt_sram_data(logic data[], int data_width, int sp_width, + logic addr[], int addr_width, + logic key[], logic nonce[], + int num_prince_rounds_half = 3, + bit use_sp_layer = 0); + logic keystream[] = new[SRAM_BLOCK_WIDTH]; + logic data_dec[] = new[data_width]; + logic byte_to_dec[] = new[8]; + logic dec_byte[] = new[8]; + logic zero_key[] = new[data_width]; + int ks_width = (data_width < 64) ? data_width : 64; + + // the key used for byte diffusion is all-zero. + for (int i = 0; i < data_width; i++) begin + zero_key[i] = '0; + end + + // Generate the keystream + keystream = gen_keystream(addr, addr_width, key, nonce, num_prince_rounds_half); + + if (use_sp_layer) begin + if (data_width == sp_width) begin + // pass the entire word through the subst/perm network at once (the next cases would give the + // same results too, but this should be a bit more efficient) + data_dec = sp_decrypt(data, data_width, zero_key); + end else if (sp_width == 8) begin + // pass each byte of the data through the subst/perm network (special case of the general code + // below) + for (int i = 0; i < data_width / 8; i++) begin + byte_to_dec = data[i*8 +: 8]; + dec_byte = sp_decrypt(byte_to_dec, 8, zero_key); + data_dec[i*8 +: 8] = dec_byte; + end + end else begin + // divide the word into sp_width chunks to pass it through the subst/perm network + for (int chunk_lsb = 0; chunk_lsb < data_width; chunk_lsb += sp_width) begin + int bits_remaining = data_width - chunk_lsb; + int chunk_width = (bits_remaining < sp_width) ? bits_remaining : sp_width; + logic chunk[] = new[chunk_width]; + + for (int j = 0; j < chunk_width; j++) begin + chunk[j] = data[chunk_lsb + j]; + end + chunk = sp_decrypt(chunk, chunk_width, zero_key); + for (int j = 0; j < chunk_width; j++) begin + data_dec[chunk_lsb + j] = chunk[j]; + end + end + end + + // XOR result data with the keystream + for (int i = 0; i < data_width; i++) begin + data_dec[i] = data_dec[i] ^ keystream[i % ks_width]; + end + end else begin + // XOR result data with the keystream + for (int i = 0; i < data_width; i++) begin + data_dec[i] = data[i] ^ keystream[i % ks_width]; + end + end + + return data_dec; + + endfunction : decrypt_sram_data + +endpackage : sram_scrambler_pkg diff --git a/hw/vendor/lowrisc_ip/ip/rom_ctrl/dv/rom_ctrl_32kB_sim_cfg.hjson b/hw/vendor/lowrisc_ip/ip/rom_ctrl/dv/rom_ctrl_32kB_sim_cfg.hjson index 941e953b..a0b4a0ac 100644 --- a/hw/vendor/lowrisc_ip/ip/rom_ctrl/dv/rom_ctrl_32kB_sim_cfg.hjson +++ b/hw/vendor/lowrisc_ip/ip/rom_ctrl/dv/rom_ctrl_32kB_sim_cfg.hjson @@ -7,7 +7,7 @@ variant: 32kB // Import the base rom_ctrl sim_cfg file - import_cfgs: ["{proj_root}/hw/ip/rom_ctrl/dv/rom_ctrl_base_sim_cfg.hjson"] + import_cfgs: ["{proj_root}/hw/vendor/lowrisc_ip/ip/rom_ctrl/dv/rom_ctrl_base_sim_cfg.hjson"] build_opts: ["+define+ROM_BYTE_ADDR_WIDTH=15"] } diff --git a/hw/vendor/lowrisc_ip/ip/rom_ctrl/dv/rom_ctrl_base_sim_cfg.hjson b/hw/vendor/lowrisc_ip/ip/rom_ctrl/dv/rom_ctrl_base_sim_cfg.hjson index 9062c0ff..228a0ece 100644 --- a/hw/vendor/lowrisc_ip/ip/rom_ctrl/dv/rom_ctrl_base_sim_cfg.hjson +++ b/hw/vendor/lowrisc_ip/ip/rom_ctrl/dv/rom_ctrl_base_sim_cfg.hjson @@ -12,30 +12,30 @@ tb: tb // Simulator used to sign off this block - tool: vcs + tool: xcelium // Fusesoc core file used for building the file list. fusesoc_core: lowrisc:dv:rom_ctrl_sim:0.1 // Testplan hjson file. - testplan: "{proj_root}/hw/ip/rom_ctrl/data/rom_ctrl_testplan.hjson" + testplan: "{proj_root}/hw/vendor/lowrisc_ip/ip/rom_ctrl/data/rom_ctrl_testplan.hjson" // RAL spec - used to generate the RAL model. - ral_spec: "{proj_root}/hw/ip/rom_ctrl/data/rom_ctrl.hjson" + ral_spec: "{proj_root}/hw/vendor/lowrisc_ip/ip/rom_ctrl/data/rom_ctrl.hjson" // Import additional common sim cfg files. import_cfgs: [// Project wide common sim cfg file - "{proj_root}/hw/dv/tools/dvsim/common_sim_cfg.hjson", + "{proj_root}/hw/vendor/lowrisc_ip/dv/tools/dvsim/common_sim_cfg.hjson", // Config files to get the correct flags for crypto_dpi_prince - "{proj_root}/hw/ip/prim/dv/prim_prince/crypto_dpi_prince/crypto_dpi_prince_sim_opts.hjson", + "{proj_root}/hw/vendor/lowrisc_ip/ip/prim/dv/prim_prince/crypto_dpi_prince/crypto_dpi_prince_sim_opts.hjson", // Common CIP test lists - "{proj_root}/hw/dv/tools/dvsim/tests/csr_tests.hjson", - "{proj_root}/hw/dv/tools/dvsim/tests/mem_tests.hjson", - "{proj_root}/hw/dv/tools/dvsim/tests/alert_test.hjson", - "{proj_root}/hw/dv/tools/dvsim/tests/tl_access_tests.hjson", - "{proj_root}/hw/dv/tools/dvsim/tests/passthru_mem_intg_tests.hjson", - "{proj_root}/hw/dv/tools/dvsim/tests/sec_cm_tests.hjson", - "{proj_root}/hw/dv/tools/dvsim/tests/stress_tests.hjson"] + "{proj_root}/hw/vendor/lowrisc_ip/dv/tools/dvsim/tests/csr_tests.hjson", + "{proj_root}/hw/vendor/lowrisc_ip/dv/tools/dvsim/tests/mem_tests.hjson", + "{proj_root}/hw/vendor/lowrisc_ip/dv/tools/dvsim/tests/alert_test.hjson", + "{proj_root}/hw/vendor/lowrisc_ip/dv/tools/dvsim/tests/tl_access_tests.hjson", + "{proj_root}/hw/vendor/lowrisc_ip/dv/tools/dvsim/tests/passthru_mem_intg_tests.hjson", + "{proj_root}/hw/vendor/lowrisc_ip/dv/tools/dvsim/tests/sec_cm_tests.hjson", + "{proj_root}/hw/vendor/lowrisc_ip/dv/tools/dvsim/tests/stress_tests.hjson"] en_build_modes: ["{tool}_crypto_dpi_prince_build_opts"] @@ -58,13 +58,13 @@ } { name: cover_reg_top_vcs_cov_cfg_file - value: "-cm_hier {proj_root}/hw/dv/tools/vcs/cover_reg_top.cfg+{proj_root}/hw/ip/rom_ctrl/dv/cov/cover_reg_top.cfg" + value: "-cm_hier {proj_root}/hw/vendor/lowrisc_ip/dv/tools/vcs/cover_reg_top.cfg+{proj_root}/hw/vendor/lowrisc_ip/ip/rom_ctrl/dv/cov/cover_reg_top.cfg" } ] // Add ROM_CTRL specific exclusion files. - vcs_cov_excl_files: ["{proj_root}/hw/ip/rom_ctrl/dv/cov/rom_ctrl_cov_unr_excl.el", - "{proj_root}/hw/ip/rom_ctrl/dv/cov/rom_ctrl_cov_excl.el"] + vcs_cov_excl_files: ["{proj_root}/hw/vendor/lowrisc_ip/ip/rom_ctrl/dv/cov/rom_ctrl_cov_unr_excl.el", + "{proj_root}/hw/vendor/lowrisc_ip/ip/rom_ctrl/dv/cov/rom_ctrl_cov_excl.el"] // Default UVM test and seq class name. uvm_test: rom_ctrl_base_test From c094c6d020489fd05b59983d4d0c8fdbad19a5e2 Mon Sep 17 00:00:00 2001 From: Kolos Koblasz Date: Tue, 21 Apr 2026 10:47:34 +0100 Subject: [PATCH 3/3] [rom_ctrl, top_sim] Temporary rom_ctrl cfg files updated * hw/top_chip/dv/mocha_sim_cfgs.hjson modified to point at the real rom_ctrl configuration files * temporary config files deleted Signed-off-by: Kolos Koblasz --- hw/top_chip/dv/mocha_sim_cfgs.hjson | 2 +- .../tmp_sim_cfg/rom_ctrl_32kB_sim_cfg.hjson | 13 -- .../tmp_sim_cfg/rom_ctrl_base_sim_cfg.hjson | 112 ------------------ 3 files changed, 1 insertion(+), 126 deletions(-) delete mode 100644 hw/top_chip/tmp_sim_cfg/rom_ctrl_32kB_sim_cfg.hjson delete mode 100644 hw/top_chip/tmp_sim_cfg/rom_ctrl_base_sim_cfg.hjson diff --git a/hw/top_chip/dv/mocha_sim_cfgs.hjson b/hw/top_chip/dv/mocha_sim_cfgs.hjson index 1b2bb1d2..df6e44a6 100644 --- a/hw/top_chip/dv/mocha_sim_cfgs.hjson +++ b/hw/top_chip/dv/mocha_sim_cfgs.hjson @@ -30,7 +30,7 @@ "{proj_root}/hw/vendor/lowrisc_ip/ip/i2c/dv/i2c_sim_cfg.hjson", "{proj_root}/hw/top_chip/ip/xbar_peri/dv/autogen/xbar_peri_sim_cfg.hjson", "{proj_root}/hw/top_chip/ip_autogen/gpio/dv/gpio_sim_cfg.hjson", - "{proj_root}/hw/top_chip/tmp_sim_cfg/rom_ctrl_32kB_sim_cfg.hjson", + "{proj_root}/hw/vendor/lowrisc_ip/ip/rom_ctrl/dv/rom_ctrl_32kB_sim_cfg.hjson", "{proj_root}/hw/top_chip/tmp_sim_cfg/rv_dm_use_jtag_interface_sim_cfg.hjson", // Top-level IPs. diff --git a/hw/top_chip/tmp_sim_cfg/rom_ctrl_32kB_sim_cfg.hjson b/hw/top_chip/tmp_sim_cfg/rom_ctrl_32kB_sim_cfg.hjson deleted file mode 100644 index 56f66b6e..00000000 --- a/hw/top_chip/tmp_sim_cfg/rom_ctrl_32kB_sim_cfg.hjson +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright lowRISC contributors (OpenTitan project). -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 - -{ - // Name of the sim cfg variant - variant: 32kB - - // Import the base rom_ctrl sim_cfg file - import_cfgs: ["{proj_root}/hw/top_chip/tmp_sim_cfg/rom_ctrl_base_sim_cfg.hjson"] - - build_opts: ["+define+ROM_BYTE_ADDR_WIDTH=15"] -} diff --git a/hw/top_chip/tmp_sim_cfg/rom_ctrl_base_sim_cfg.hjson b/hw/top_chip/tmp_sim_cfg/rom_ctrl_base_sim_cfg.hjson deleted file mode 100644 index da6ff373..00000000 --- a/hw/top_chip/tmp_sim_cfg/rom_ctrl_base_sim_cfg.hjson +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright lowRISC contributors (OpenTitan project). -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 -{ - // Name of the sim cfg - typically same as the name of the DUT. - name: rom_ctrl - - // Top level dut name (sv module). - dut: rom_ctrl - - // Top level testbench name (sv module). - tb: tb - - // Simulator used to sign off this block - tool: xcelium - - // Fusesoc core file used for building the file list. - fusesoc_core: lowrisc:dv:rom_ctrl_sim:0.1 - - // Testplan hjson file. - testplan: "{proj_root}/hw/ip/rom_ctrl/data/rom_ctrl_testplan.hjson" - - // RAL spec - used to generate the RAL model. - ral_spec: "{proj_root}/hw/ip/rom_ctrl/data/rom_ctrl.hjson" - - // Import additional common sim cfg files. - import_cfgs: [// Project wide common sim cfg file - "{proj_root}/hw/vendor/lowrisc_ip/dv/tools/dvsim/common_sim_cfg.hjson", - // Config files to get the correct flags for crypto_dpi_prince - "{proj_root}/hw/vendor/lowrisc_ip/ip/prim/dv/prim_prince/crypto_dpi_prince/crypto_dpi_prince_sim_opts.hjson", - // Common CIP test lists - "{proj_root}/hw/vendor/lowrisc_ip/dv/tools/dvsim/tests/csr_tests.hjson", - "{proj_root}/hw/vendor/lowrisc_ip/dv/tools/dvsim/tests/mem_tests.hjson", - "{proj_root}/hw/vendor/lowrisc_ip/dv/tools/dvsim/tests/alert_test.hjson", - "{proj_root}/hw/vendor/lowrisc_ip/dv/tools/dvsim/tests/tl_access_tests.hjson", - "{proj_root}/hw/vendor/lowrisc_ip/dv/tools/dvsim/tests/passthru_mem_intg_tests.hjson", - "{proj_root}/hw/vendor/lowrisc_ip/dv/tools/dvsim/tests/sec_cm_tests.hjson", - "{proj_root}/hw/vendor/lowrisc_ip/dv/tools/dvsim/tests/stress_tests.hjson"] - - en_build_modes: ["{tool}_crypto_dpi_prince_build_opts"] - - // Add additional tops for simulation. - sim_tops: ["rom_ctrl_bind", "rom_ctrl_cov_bind", - "sec_cm_prim_sparse_fsm_flop_bind", "sec_cm_prim_onehot_check_bind", - "sec_cm_prim_count_bind"] - - // Default iterations for all tests - each test entry can override this. - reseed: 50 - - overrides: [ - // Override the default scratch directory and rel_path to take variant into account - { - name: scratch_path - value: "{scratch_base_path}/{name}_{variant}-{flow}-{tool}" - } - { - name: rel_path - value: "hw/ip/{name}_{variant}/dv" - } - { - name: cover_reg_top_vcs_cov_cfg_file - value: "-cm_hier {proj_root}/hw/dv/tools/vcs/cover_reg_top.cfg+{proj_root}/hw/ip/rom_ctrl/dv/cov/cover_reg_top.cfg" - } - ] - - // Add ROM_CTRL specific exclusion files. - vcs_cov_excl_files: ["{proj_root}/hw/ip/rom_ctrl/dv/cov/rom_ctrl_cov_unr_excl.el", - "{proj_root}/hw/ip/rom_ctrl/dv/cov/rom_ctrl_cov_excl.el"] - - // Default UVM test and seq class name. - uvm_test: rom_ctrl_base_test - uvm_test_seq: rom_ctrl_base_vseq - - // Enable cdc instrumentation. - run_opts: ["+cdc_instrumentation_enabled=1"] - - // List of test specifications. - tests: [ - { - name: rom_ctrl_smoke - uvm_test_seq: rom_ctrl_smoke_vseq - reseed: 10 - } - { - name: rom_ctrl_stress_all - uvm_test_seq: rom_ctrl_stress_all_vseq - run_opts: ["+test_timeout_ns=1000000000"] - } - { - name: rom_ctrl_max_throughput_chk - uvm_test_seq: rom_ctrl_throughput_vseq - run_opts: ["+zero_delays=1"] - } - { - name: rom_ctrl_corrupt_sig_fatal_chk - uvm_test_seq: rom_ctrl_corrupt_sig_fatal_chk_vseq - run_opts: ["+test_timeout_ns=1000000000"] - } - { - name: rom_ctrl_kmac_err_chk - uvm_test_seq: rom_ctrl_kmac_err_chk_vseq - } - ] - - // List of regressions. - regressions: [ - { - name: smoke - tests: ["rom_ctrl_smoke"] - } - ] -}