From 8aa5df8a30dfc265522541c551fa242d586d407d Mon Sep 17 00:00:00 2001 From: Martin Velay Date: Wed, 6 Nov 2024 15:12:40 +0000 Subject: [PATCH] [tmp_dir] Signed-off-by: Martin Velay --- hw/ip/hmac/dv copy/README.md | 151 +++ hw/ip/hmac/dv copy/cov/hmac_cov_excl.el | 25 + hw/ip/hmac/dv copy/cov/hmac_unr_excl.el | 526 ++++++++++ hw/ip/hmac/dv copy/cryptoc_dpi/LICENSE | 177 ++++ hw/ip/hmac/dv copy/cryptoc_dpi/README.md | 27 + hw/ip/hmac/dv copy/cryptoc_dpi/cryptoc_dpi.c | 200 ++++ .../hmac/dv copy/cryptoc_dpi/cryptoc_dpi.core | 32 + .../dv copy/cryptoc_dpi/cryptoc_dpi_pkg.sv | 118 +++ .../hmac/dv copy/cryptoc_dpi/hash-internal.h | 59 ++ hw/ip/hmac/dv copy/cryptoc_dpi/hmac.c | 115 +++ hw/ip/hmac/dv copy/cryptoc_dpi/hmac.h | 51 + hw/ip/hmac/dv copy/cryptoc_dpi/hmac_wrap.c | 52 + hw/ip/hmac/dv copy/cryptoc_dpi/hmac_wrap.h | 36 + hw/ip/hmac/dv copy/cryptoc_dpi/main.c | 102 ++ hw/ip/hmac/dv copy/cryptoc_dpi/sha.c | 133 +++ hw/ip/hmac/dv copy/cryptoc_dpi/sha.h | 43 + hw/ip/hmac/dv copy/cryptoc_dpi/sha256.c | 156 +++ hw/ip/hmac/dv copy/cryptoc_dpi/sha256.h | 41 + hw/ip/hmac/dv copy/cryptoc_dpi/sha384.c | 53 + hw/ip/hmac/dv copy/cryptoc_dpi/sha384.h | 41 + hw/ip/hmac/dv copy/cryptoc_dpi/sha512.c | 193 ++++ hw/ip/hmac/dv copy/cryptoc_dpi/sha512.h | 41 + hw/ip/hmac/dv copy/cryptoc_dpi/util.c | 25 + hw/ip/hmac/dv copy/cryptoc_dpi/util.h | 23 + hw/ip/hmac/dv copy/doc/tb.svg | 1 + hw/ip/hmac/dv copy/env/hmac_env.core | 51 + hw/ip/hmac/dv copy/env/hmac_env.sv | 37 + hw/ip/hmac/dv copy/env/hmac_env_cfg.sv | 47 + hw/ip/hmac/dv copy/env/hmac_env_cov.sv | 164 +++ hw/ip/hmac/dv copy/env/hmac_env_pkg.sv | 222 ++++ hw/ip/hmac/dv copy/env/hmac_if.sv | 13 + hw/ip/hmac/dv copy/env/hmac_scoreboard.sv | 945 ++++++++++++++++++ .../env/seq_lib/hmac_back_pressure_vseq.sv | 43 + .../dv copy/env/seq_lib/hmac_base_vseq.sv | 819 +++++++++++++++ .../dv copy/env/seq_lib/hmac_burst_wr_vseq.sv | 24 + .../dv copy/env/seq_lib/hmac_common_vseq.sv | 63 ++ .../env/seq_lib/hmac_datapath_stress_vseq.sv | 50 + .../dv copy/env/seq_lib/hmac_error_vseq.sv | 29 + .../dv copy/env/seq_lib/hmac_long_msg_vseq.sv | 30 + .../dv copy/env/seq_lib/hmac_smoke_vseq.sv | 256 +++++ .../env/seq_lib/hmac_stress_all_vseq.sv | 54 + .../seq_lib/hmac_test_vectors_hmac_vseq.sv | 34 + .../env/seq_lib/hmac_test_vectors_sha_vseq.sv | 153 +++ .../dv copy/env/seq_lib/hmac_vseq_list.sv | 16 + .../env/seq_lib/hmac_wipe_secret_vseq.sv | 42 + hw/ip/hmac/dv copy/hmac_sim.core | 29 + hw/ip/hmac/dv copy/hmac_sim_cfg.hjson | 169 ++++ hw/ip/hmac/dv copy/sva/hmac_bind.sv | 23 + hw/ip/hmac/dv copy/sva/hmac_sva.core | 38 + hw/ip/hmac/dv copy/tb/tb.sv | 65 ++ hw/ip/hmac/dv copy/tests/hmac_base_test.sv | 23 + hw/ip/hmac/dv copy/tests/hmac_test.core | 19 + hw/ip/hmac/dv copy/tests/hmac_test_pkg.sv | 21 + 53 files changed, 5900 insertions(+) create mode 100644 hw/ip/hmac/dv copy/README.md create mode 100644 hw/ip/hmac/dv copy/cov/hmac_cov_excl.el create mode 100644 hw/ip/hmac/dv copy/cov/hmac_unr_excl.el create mode 100644 hw/ip/hmac/dv copy/cryptoc_dpi/LICENSE create mode 100644 hw/ip/hmac/dv copy/cryptoc_dpi/README.md create mode 100644 hw/ip/hmac/dv copy/cryptoc_dpi/cryptoc_dpi.c create mode 100644 hw/ip/hmac/dv copy/cryptoc_dpi/cryptoc_dpi.core create mode 100644 hw/ip/hmac/dv copy/cryptoc_dpi/cryptoc_dpi_pkg.sv create mode 100644 hw/ip/hmac/dv copy/cryptoc_dpi/hash-internal.h create mode 100644 hw/ip/hmac/dv copy/cryptoc_dpi/hmac.c create mode 100644 hw/ip/hmac/dv copy/cryptoc_dpi/hmac.h create mode 100644 hw/ip/hmac/dv copy/cryptoc_dpi/hmac_wrap.c create mode 100644 hw/ip/hmac/dv copy/cryptoc_dpi/hmac_wrap.h create mode 100644 hw/ip/hmac/dv copy/cryptoc_dpi/main.c create mode 100644 hw/ip/hmac/dv copy/cryptoc_dpi/sha.c create mode 100644 hw/ip/hmac/dv copy/cryptoc_dpi/sha.h create mode 100644 hw/ip/hmac/dv copy/cryptoc_dpi/sha256.c create mode 100644 hw/ip/hmac/dv copy/cryptoc_dpi/sha256.h create mode 100644 hw/ip/hmac/dv copy/cryptoc_dpi/sha384.c create mode 100644 hw/ip/hmac/dv copy/cryptoc_dpi/sha384.h create mode 100644 hw/ip/hmac/dv copy/cryptoc_dpi/sha512.c create mode 100644 hw/ip/hmac/dv copy/cryptoc_dpi/sha512.h create mode 100644 hw/ip/hmac/dv copy/cryptoc_dpi/util.c create mode 100644 hw/ip/hmac/dv copy/cryptoc_dpi/util.h create mode 100644 hw/ip/hmac/dv copy/doc/tb.svg create mode 100644 hw/ip/hmac/dv copy/env/hmac_env.core create mode 100644 hw/ip/hmac/dv copy/env/hmac_env.sv create mode 100644 hw/ip/hmac/dv copy/env/hmac_env_cfg.sv create mode 100644 hw/ip/hmac/dv copy/env/hmac_env_cov.sv create mode 100644 hw/ip/hmac/dv copy/env/hmac_env_pkg.sv create mode 100644 hw/ip/hmac/dv copy/env/hmac_if.sv create mode 100644 hw/ip/hmac/dv copy/env/hmac_scoreboard.sv create mode 100644 hw/ip/hmac/dv copy/env/seq_lib/hmac_back_pressure_vseq.sv create mode 100644 hw/ip/hmac/dv copy/env/seq_lib/hmac_base_vseq.sv create mode 100644 hw/ip/hmac/dv copy/env/seq_lib/hmac_burst_wr_vseq.sv create mode 100644 hw/ip/hmac/dv copy/env/seq_lib/hmac_common_vseq.sv create mode 100644 hw/ip/hmac/dv copy/env/seq_lib/hmac_datapath_stress_vseq.sv create mode 100644 hw/ip/hmac/dv copy/env/seq_lib/hmac_error_vseq.sv create mode 100644 hw/ip/hmac/dv copy/env/seq_lib/hmac_long_msg_vseq.sv create mode 100644 hw/ip/hmac/dv copy/env/seq_lib/hmac_smoke_vseq.sv create mode 100644 hw/ip/hmac/dv copy/env/seq_lib/hmac_stress_all_vseq.sv create mode 100644 hw/ip/hmac/dv copy/env/seq_lib/hmac_test_vectors_hmac_vseq.sv create mode 100644 hw/ip/hmac/dv copy/env/seq_lib/hmac_test_vectors_sha_vseq.sv create mode 100644 hw/ip/hmac/dv copy/env/seq_lib/hmac_vseq_list.sv create mode 100644 hw/ip/hmac/dv copy/env/seq_lib/hmac_wipe_secret_vseq.sv create mode 100644 hw/ip/hmac/dv copy/hmac_sim.core create mode 100644 hw/ip/hmac/dv copy/hmac_sim_cfg.hjson create mode 100644 hw/ip/hmac/dv copy/sva/hmac_bind.sv create mode 100644 hw/ip/hmac/dv copy/sva/hmac_sva.core create mode 100644 hw/ip/hmac/dv copy/tb/tb.sv create mode 100644 hw/ip/hmac/dv copy/tests/hmac_base_test.sv create mode 100644 hw/ip/hmac/dv copy/tests/hmac_test.core create mode 100644 hw/ip/hmac/dv copy/tests/hmac_test_pkg.sv diff --git a/hw/ip/hmac/dv copy/README.md b/hw/ip/hmac/dv copy/README.md new file mode 100644 index 0000000000000..b47d5c3c7ecbd --- /dev/null +++ b/hw/ip/hmac/dv copy/README.md @@ -0,0 +1,151 @@ +# HMAC DV document + +## Goals +* **DV** + * Verify all HMAC IP features by running dynamic simulations with a SV/UVM based testbench + * Develop and run all tests based on the [testplan](#testplan) below towards closing code and functional coverage on the IP and all of its sub-modules +* **FPV** + * Verify TileLink device protocol compliance with an SVA based testbench + +## Current status +* [Design & verification stage](../../../README.md) + * [HW development stages](../../../../doc/project_governance/development_stages.md) +* [Simulation results](https://reports.opentitan.org/hw/ip/hmac/dv/latest/report.html) + +## Design features +For detailed information on HMAC design features, please see the +[HMAC design specification](../README.md). + +## Testbench architecture +HMAC testbench has been constructed based on the +[CIP testbench architecture](../../../dv/sv/cip_lib/README.md). + +### Block diagram +![Block diagram](./doc/tb.svg) + +### Top level testbench +Top level testbench is located at `hw/ip/hmac/dv/tb/tb.sv`. It instantiates the +HMAC DUT module `hw/ip/hmac/rtl/hmac.sv`. In addition, it instantiates the following +interfaces and sets their handle into `uvm_config_db`: +* [Clock and reset interface](../../../dv/sv/common_ifs/README.md) +* [TileLink host interface](../../../dv/sv/tl_agent/README.md) +* Interrupts ([`pins_if`](../../../dv/sv/common_ifs/README.md)) + +### Common DV utility components +The following utilities provide generic helper tasks and functions to perform activities that are common across the project: +* [dv_utils_pkg](../../../dv/sv/dv_utils/README.md) +* [csr_utils_pkg](../../../dv/sv/csr_utils/README.md) + +### Global types & methods +All common types and methods defined at the package level can be found in `env/hmac_env_pkg`. +Some of them in use are: +```systemverilog +parameter uint32 HMAC_MSG_FIFO_DEPTH = 16; +parameter uint32 HMAC_MSG_FIFO_DEPTH_BYTES = HMAC_MSG_FIFO_DEPTH * 4; +parameter uint32 HMAC_MSG_FIFO_SIZE = 2048; +``` + +### TL_agent +HMAC instantiates (handled in CIP base env) [tl_agent](../../../dv/sv/tl_agent/README.md) +which provides the ability to drive and independently monitor random traffic via +TL host interface into HMAC device. + +### UVM RAL Model +The HMAC RAL model is created with the [`ralgen`](../../../dv/tools/ralgen/README.md) FuseSoC generator script automatically when the simulation is at the build stage. + +It can be created manually by invoking [`regtool`](../../../../util/reggen/doc/setup_and_use.md): + +### Reference models +To check the correctness of the output for SHA256 and HMAC, the testbench uses +the [C reference model](https://github.com/lowRISC/opentitan/blob/master/hw/ip/hmac/dv/cryptoc_dpi/README.md). +Messages and keys generated by constrained random test sequences are passed on to the +reference model. Then the hmac scoreboard will compare the reference model's expected +digest data with the DUT output. + +### Stimulus strategy +#### Test sequences +All test sequences reside in `hw/ip/hmac/dv/env/seq_lib`. The `hmac_base_vseq` +virtual sequence is extended from `cip_base_vseq` and serves as a starting point. +All test sequences are extended from `hmac_base_vseq`. It provides commonly used handles, +variables, functions and tasks that the test sequences can simple use / call. +Some of the most commonly used tasks / functions are as follows: +* `hmac_init` : initialize hmac settings including configurations and interrupt + enables +* `csr_rd_digest` : read digest values from the CSR registers +* `wr_key` : write key values into the CSR registers +* `wr_msg` : write messages into the hmac_msg_fifo +* `burst_wr_msg` : burst write messages into the hmac_msg_fifo +* `compare_digest` : compare the read digest result with the expected values +* `save_and_restore`: execute Save and Restore as described in the [SW Guide](https://opentitan.org/book/hw/ip/hmac/doc/programmers_guide.html#saving-and-restoring-the-context) + +##### Standard test vectors +Besides constrained random test sequences, HMAC test sequences also include standard SHA-2 256 and +HMAC test vectors from [NIST](https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/Secure-Hashing#shavs) +and [IETF](https://tools.ietf.org/html/rfc4868) to test SHA-2 256/384/512 and HMAC using SHA-2 256/(384/512 TODO #22932)) +with 256-bit keys. The standard test vectors provide messages, keys (for the keyed HMAC tests only), and expected +results. The expected results are used to verify the DUT outputs. + +#### Functional coverage +To ensure high quality constrained random stimulus, it is necessary to develop +functional coverage model. The following covergroups have been developed to prove +that the test intent has been adequately met: +* `cfg_cg`: covers configuration registers in HMAC +* `status_cg`: covers status registers in HMAC +* `msg_len_cg`: covers streamed-in message length in HMAC +* `err_code_cg`: covers possible error codes raising +* `wr_config_during_hash_cg`: covers writing CFG register during ongoing HASH +* `wr_key_during_hash_cg`: covers writing KEY register during ongoing HASH +* `wr_key_during_sha_only_cg`: covers writing key length should be seamless while HMAC disabled +* `wr_msg_during_hash_cg`: covers writing a message while HASH is ongoing +* `trig_rst_during_hash_cg`: covers triggering a reset during HASH is ongoing +* `rd_digest_during_hmac_en_cg`: covers read and check DIGEST while HMAC is enabled/disabled +* `save_and_restore_cg`: covers Save and Restore with: same context, different contexts and only stop/continue without saving and restoring + +### Self-checking strategy +#### Scoreboard +The `hmac_scoreboard` is primarily used for end to end checking. It creates the +following analysis ports to retrieve the data monitored by corresponding +interface agents: +* tl_a_chan_fifo: tl address channel +* tl_d_chan_fifo: tl data channel + +Hmac scoreboard monitors all hmac valid CSR registers, hmac msg_fifo (addr: +'h800 to 'hfff), and interrupt pins. + +For a write transaction, during the address channel, CSR values are updated in +RAL. Msg_fifo values are updated to an internal msg queue. Once the data +finishes streaming, hmac scoreboard will input the msg queue to the C model and +calculate the expected output, then update the corresponding RAL registers. + +For a read transaction, during the address channel, for status related CSRs +(such as fifo_full, fifo_empty, etc), hmac will predict its value according to +the cycle accurate model. During the data channel, hmac scoreboard will compare +the read data with expected data in RAL. + +##### Scoreboard cycle accurate checking model +Hmac scoreboard contains a cycle accurate checking to model the hmac +internal message fifo. It has two pointers(`hmac_wr_cnt` and `hmac_wr_cnt`) to simulate the +read and write of the hmac internal message fifo. These two pointers are updated at the +negedge of the clock cycle to avoid glitch. Read pointer is incremented one +clock cycle after the write pointer (except if HMAC is enabled, then read will +first wait 80 clock cycles for the key padding). Hmac fifo full is asserted when +`hmac_wr_cnt - hmac_wr_cnt == 16`. Hmac fifo depth is checked against the difference +between `hmac_wr_cnt` and `hmac_rd_cnt`. + +#### Assertions +* TLUL assertions: The `tb/hmac_bind.sv` binds the `tlul_assert` + [assertions](../../tlul/doc/TlulProtocolChecker.md) to hmac to ensure TileLink interface protocol compliance. +* Unknown checks on DUT outputs: The RTL has assertions to ensure all outputs are initialized to known values after coming out of reset. + +## Building and running tests +We are using our in-house developed +[regression tool](../../../../util/dvsim/README.md) for building and running our tests and regressions. +Please take a look at the link for detailed information on the usage, capabilities, features and known +issues. +Here's how to run a smoke test: +```console +$ $REPO_TOP/util/dvsim/dvsim.py $REPO_TOP/hw/ip/hmac/dv/hmac_sim_cfg.hjson -i hmac_smoke +``` + +## Testplan +[Testplan](../data/hmac_testplan.hjson) diff --git a/hw/ip/hmac/dv copy/cov/hmac_cov_excl.el b/hw/ip/hmac/dv copy/cov/hmac_cov_excl.el new file mode 100644 index 0000000000000..e4f09b1f70408 --- /dev/null +++ b/hw/ip/hmac/dv copy/cov/hmac_cov_excl.el @@ -0,0 +1,25 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +//================================================== +// This file contains the Excluded objects +// Generated By User: gdessouky +// Format Version: 2 +// Date: Sat Jul 6 04:05:21 2024 +// ExclMode: default +//================================================== +CHECKSUM: "1683432060 1171249183" +INSTANCE: tb.dut.u_prim_sha2_512.gen_multimode_logic.u_prim_sha2_multimode.u_pad +Fsm st_q "1171249183" +ANNOTATION: "[INVALID] Intend to remove transition" +Transition StLenHi->StFifoReceive "4->1" +Fsm st_q "1171249183" +ANNOTATION: "[INVALID] Intend to remove transition" +Transition StPad80->StFifoReceive "2->1" +Fsm st_q "1171249183" +ANNOTATION: "[INVALID] Intend to remove transition" +Transition StPad00->StFifoReceive "3->1" +Fsm st_q "1171249183" +ANNOTATION: "[INVALID] Intend to remove transition" +Transition StLenLo->StFifoReceive "5->1" diff --git a/hw/ip/hmac/dv copy/cov/hmac_unr_excl.el b/hw/ip/hmac/dv copy/cov/hmac_unr_excl.el new file mode 100644 index 0000000000000..91486341d1e75 --- /dev/null +++ b/hw/ip/hmac/dv copy/cov/hmac_unr_excl.el @@ -0,0 +1,526 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +//================================================== +// This file contains the Excluded objects +// Generated By User: gdessouky +// Format Version: 2 +// Date: Wed Jul 3 13:15:42 2024 +// ExclMode: default +//================================================== +CHECKSUM: "3215070453 3446030929" +INSTANCE: tb.dut.u_tlul_adapter.u_reqfifo.gen_normal_fifo.u_fifo_cnt +ANNOTATION: "VC_COV_UNR" +Block 19 "4019242409" "wptr_wrap_cnt_q <= (wptr_wrap_cnt_q + {{(WrapPtrW - 1) {1'b0}}, 1'b1});" +ANNOTATION: "VC_COV_UNR" +Block 28 "1113085816" "rptr_wrap_cnt_q <= (rptr_wrap_cnt_q + {{(WrapPtrW - 1) {1'b0}}, 1'b1});" +CHECKSUM: "3215070453 3446030929" +INSTANCE: tb.dut.u_tlul_adapter.u_sramreqfifo.gen_normal_fifo.u_fifo_cnt +ANNOTATION: "VC_COV_UNR" +Block 17 "3979759716" "wptr_wrap_cnt_q <= wptr_wrap_set_cnt;" +ANNOTATION: "VC_COV_UNR" +Block 19 "4019242409" "wptr_wrap_cnt_q <= (wptr_wrap_cnt_q + {{(WrapPtrW - 1) {1'b0}}, 1'b1});" +ANNOTATION: "VC_COV_UNR" +Block 26 "483722483" "rptr_wrap_cnt_q <= rptr_wrap_set_cnt;" +ANNOTATION: "VC_COV_UNR" +Block 28 "1113085816" "rptr_wrap_cnt_q <= (rptr_wrap_cnt_q + {{(WrapPtrW - 1) {1'b0}}, 1'b1});" +CHECKSUM: "3215070453 3446030929" +INSTANCE: tb.dut.u_tlul_adapter.u_rspfifo.gen_normal_fifo.u_fifo_cnt +ANNOTATION: "VC_COV_UNR" +Block 17 "3979759716" "wptr_wrap_cnt_q <= wptr_wrap_set_cnt;" +ANNOTATION: "VC_COV_UNR" +Block 19 "4019242409" "wptr_wrap_cnt_q <= (wptr_wrap_cnt_q + {{(WrapPtrW - 1) {1'b0}}, 1'b1});" +ANNOTATION: "VC_COV_UNR" +Block 26 "483722483" "rptr_wrap_cnt_q <= rptr_wrap_set_cnt;" +ANNOTATION: "VC_COV_UNR" +Block 28 "1113085816" "rptr_wrap_cnt_q <= (rptr_wrap_cnt_q + {{(WrapPtrW - 1) {1'b0}}, 1'b1});" +CHECKSUM: "1683432060 1534820498" +INSTANCE: tb.dut.u_prim_sha2_512.gen_multimode_logic.u_prim_sha2_multimode.u_pad +ANNOTATION: "VC_COV_UNR" +Block 18 "2176176162" "shaf_rdata_o = 64'b0;" +ANNOTATION: "VC_COV_UNR" +Block 29 "2770610340" "shaf_rdata_o = 64'b0;" +ANNOTATION: "VC_COV_UNR" +Block 34 "513215732" "shaf_rdata_o = '0;" +ANNOTATION: "VC_COV_UNR" +Block 71 "3587469932" "st_d = StIdle;" +CHECKSUM: "581497987 468855081" +INSTANCE: tb.dut +ANNOTATION: "VC_COV_UNR" +Block 20 "1101501256" ";" +CHECKSUM: "3287391918 3078508350" +INSTANCE: tb.dut.u_packer +ANNOTATION: "VC_COV_UNR" +Block 10 "1981125856" "g_pos_nodup.pos_d = pos_q;" +ANNOTATION: "VC_COV_UNR" +Block 34 "3749211527" "stored_data_next = stored_data;" +ANNOTATION: "VC_COV_UNR" +Block 50 "523577107" "flush_st_next = FlushIdle;" +CHECKSUM: "7115036 2343666246" +INSTANCE: tb.dut.u_tlul_adapter.u_sramreqfifo +ANNOTATION: "VC_COV_UNR" +Block 12 "4186874349" "gen_normal_fifo.storage[0] <= wdata_i;" +CHECKSUM: "7115036 1564321354" +INSTANCE: tb.dut.u_tlul_adapter.u_rspfifo +ANNOTATION: "VC_COV_UNR" +Block 12 "4186874349" "gen_normal_fifo.storage[0] <= wdata_i;" +CHECKSUM: "1475951854 461242378" +INSTANCE: tb.dut.u_hmac +ANNOTATION: "VC_COV_UNR" +Block 32 "2978480067" "sha_msg_len = '0;" +ANNOTATION: "VC_COV_UNR" +Block 47 "3613731929" "txcount_d = (message_length_i + '0);" +ANNOTATION: "VC_COV_UNR" +Block 105 "3587469932" "st_d = StIdle;" +CHECKSUM: "662936270 1595222364" +INSTANCE: tb.dut.u_tlul_adapter +ANNOTATION: "VC_COV_UNR" +Block 21 "2813655191" "d_valid = rspfifo_rvalid;" +CHECKSUM: "2418056030 2871354623" +INSTANCE: tb.dut.u_prim_sha2_512.gen_multimode_logic.u_prim_sha2_multimode +ANNOTATION: "VC_COV_UNR" +Block 97 "3077716447" "fifo_st_d = FifoIdle;" +ANNOTATION: "VC_COV_UNR" +Block 123 "1772964417" "init_hash = 1'b1;" +ANNOTATION: "VC_COV_UNR" +Block 125 "1516031695" "sha_st_d = ShaIdle;" +CHECKSUM: "1882961916 1049371248" +INSTANCE: tb.dut.u_prim_sha2_512 +ANNOTATION: "VC_COV_UNR" +Block 24 "1072749762" "if ((gen_multimode_logic.word_part_count_q == 2'b10))" +ANNOTATION: "VC_COV_UNR" +Block 25 "3703619186" "fifo_rready_o = 1'b0;" +ANNOTATION: "VC_COV_UNR" +Block 26 "2708543991" "gen_multimode_logic.sha_process = 1'b1;" +ANNOTATION: "VC_COV_UNR" +Block 28 "3436685377" "if ((sha_ready == 1'b1))" +ANNOTATION: "VC_COV_UNR" +Block 29 "11139230" "gen_multimode_logic.word_part_reset = 1'b1;" +ANNOTATION: "VC_COV_UNR" +Block 42 "202154550" "gen_multimode_logic.word_valid = 1'b1;" +ANNOTATION: "VC_COV_UNR" +Block 43 "300500644" "gen_multimode_logic.word_part_reset = 1'b1;" +ANNOTATION: "VC_COV_UNR" +Block 46 "986927486" "gen_multimode_logic.word_valid = 1'b0;" +CHECKSUM: "2418056030 1581044118" +INSTANCE: tb.dut.u_prim_sha2_512.gen_multimode_logic.u_prim_sha2_multimode +Fsm sha_st_q "2028159779" +ANNOTATION: "VC_COV_UNR" +Transition ShaUpdateDigest->ShaCompress "2->1" +CHECKSUM: "1475951854 4104162662" +INSTANCE: tb.dut.u_hmac +ANNOTATION: "VC_COV_UNR" +Condition 6 "1372971442" "(sel_msglen == SelOPadMsg) 1 -1" (1 "0") +ANNOTATION: "VC_COV_UNR" +Condition 20 "557912432" "(fifo_wsel_o && fifo_wvalid_o) 1 -1" (1 "01") +ANNOTATION: "VC_COV_UNR" +Condition 20 "557912432" "(fifo_wsel_o && fifo_wvalid_o) 1 -1" (2 "10") +ANNOTATION: "VC_COV_UNR" +Condition 30 "4257555494" "(txcnt_eq_blksz && (txcount >= sha_message_length_o) && reg_hash_stop_q && (round_q == Inner)) 1 -1" (4 "1110") +ANNOTATION: "VC_COV_UNR" +Condition 76 "4232775480" "(sha_rready_i && sha_rvalid_o) 1 -1" (2 "10") +CHECKSUM: "581497987 244163478" +INSTANCE: tb.dut +ANNOTATION: "VC_COV_UNR" +Condition 31 "421359957" "(reg_hash_process & sha_en & cfg_block & ((~invalid_config))) 1 -1" (2 "1011") +ANNOTATION: "VC_COV_UNR" +Condition 31 "421359957" "(reg_hash_process & sha_en & cfg_block & ((~invalid_config))) 1 -1" (4 "1110") +ANNOTATION: "VC_COV_UNR" +Condition 41 "1585050789" "(msg_fifo_req & ((~msg_fifo_we))) 1 -1" (3 "11") +ANNOTATION: "VC_COV_UNR" +Condition 45 "551143601" "(msg_fifo_req & msg_fifo_we & ((~hmac_fifo_wsel)) & msg_allowed) 1 -1" (2 "1011") +ANNOTATION: "VC_COV_UNR" +Condition 64 "2180223097" "(((!reg_fifo_wvalid)) && ((!fifo_rvalid)) && hmac_core_idle && sha_core_idle) 1 -1" (1 "0111") +CHECKSUM: "7115036 2825631531" +INSTANCE: tb.dut.u_tlul_adapter.u_sramreqfifo +ANNOTATION: "VC_COV_UNR" +Condition 1 "2400173860" "(((~full_o)) & ((~gen_normal_fifo.under_rst))) 1 -1" (1 "01") +ANNOTATION: "VC_COV_UNR" +Condition 2 "1709501387" "(((~gen_normal_fifo.empty)) & ((~gen_normal_fifo.under_rst))) 1 -1" (2 "10") +ANNOTATION: "VC_COV_UNR" +Condition 2 "1709501387" "(((~gen_normal_fifo.empty)) & ((~gen_normal_fifo.under_rst))) 1 -1" (3 "11") +ANNOTATION: "VC_COV_UNR" +Condition 3 "786039886" "(wvalid_i & wready_o & ((~gen_normal_fifo.under_rst))) 1 -1" (2 "101") +ANNOTATION: "VC_COV_UNR" +Condition 3 "786039886" "(wvalid_i & wready_o & ((~gen_normal_fifo.under_rst))) 1 -1" (3 "110") +ANNOTATION: "VC_COV_UNR" +Condition 3 "786039886" "(wvalid_i & wready_o & ((~gen_normal_fifo.under_rst))) 1 -1" (4 "111") +ANNOTATION: "VC_COV_UNR" +Condition 4 "1324655787" "(rvalid_o & rready_i & ((~gen_normal_fifo.under_rst))) 1 -1" (1 "011") +ANNOTATION: "VC_COV_UNR" +Condition 4 "1324655787" "(rvalid_o & rready_i & ((~gen_normal_fifo.under_rst))) 1 -1" (2 "101") +ANNOTATION: "VC_COV_UNR" +Condition 4 "1324655787" "(rvalid_o & rready_i & ((~gen_normal_fifo.under_rst))) 1 -1" (3 "110") +ANNOTATION: "VC_COV_UNR" +Condition 4 "1324655787" "(rvalid_o & rready_i & ((~gen_normal_fifo.under_rst))) 1 -1" (4 "111") +ANNOTATION: "VC_COV_UNR" +Condition 5 "742492426" "(gen_normal_fifo.empty ? (5'(0)) : gen_normal_fifo.rdata_int) 1 -1" (1 "0") +CHECKSUM: "7115036 3686475193" +INSTANCE: tb.dut.u_msg_fifo +ANNOTATION: "VC_COV_UNR" +Condition 2 "1709501387" "(((~gen_normal_fifo.empty)) & ((~gen_normal_fifo.under_rst))) 1 -1" (2 "10") +ANNOTATION: "VC_COV_UNR" +Condition 3 "786039886" "(wvalid_i & wready_o & ((~gen_normal_fifo.under_rst))) 1 -1" (3 "110") +ANNOTATION: "VC_COV_UNR" +Condition 4 "1324655787" "(rvalid_o & rready_i & ((~gen_normal_fifo.under_rst))) 1 -1" (1 "011") +ANNOTATION: "VC_COV_UNR" +Condition 4 "1324655787" "(rvalid_o & rready_i & ((~gen_normal_fifo.under_rst))) 1 -1" (3 "110") +CHECKSUM: "7115036 2432857915" +INSTANCE: tb.dut.u_tlul_adapter.u_rspfifo +ANNOTATION: "VC_COV_UNR" +Condition 1 "2400173860" "(((~full_o)) & ((~gen_normal_fifo.under_rst))) 1 -1" (1 "01") +ANNOTATION: "VC_COV_UNR" +Condition 2 "1709501387" "(((~gen_normal_fifo.empty)) & ((~gen_normal_fifo.under_rst))) 1 -1" (2 "10") +ANNOTATION: "VC_COV_UNR" +Condition 2 "1709501387" "(((~gen_normal_fifo.empty)) & ((~gen_normal_fifo.under_rst))) 1 -1" (3 "11") +ANNOTATION: "VC_COV_UNR" +Condition 3 "786039886" "(wvalid_i & wready_o & ((~gen_normal_fifo.under_rst))) 1 -1" (2 "101") +ANNOTATION: "VC_COV_UNR" +Condition 3 "786039886" "(wvalid_i & wready_o & ((~gen_normal_fifo.under_rst))) 1 -1" (3 "110") +ANNOTATION: "VC_COV_UNR" +Condition 3 "786039886" "(wvalid_i & wready_o & ((~gen_normal_fifo.under_rst))) 1 -1" (4 "111") +ANNOTATION: "VC_COV_UNR" +Condition 4 "1324655787" "(rvalid_o & rready_i & ((~gen_normal_fifo.under_rst))) 1 -1" (1 "011") +ANNOTATION: "VC_COV_UNR" +Condition 4 "1324655787" "(rvalid_o & rready_i & ((~gen_normal_fifo.under_rst))) 1 -1" (2 "101") +ANNOTATION: "VC_COV_UNR" +Condition 4 "1324655787" "(rvalid_o & rready_i & ((~gen_normal_fifo.under_rst))) 1 -1" (3 "110") +ANNOTATION: "VC_COV_UNR" +Condition 4 "1324655787" "(rvalid_o & rready_i & ((~gen_normal_fifo.under_rst))) 1 -1" (4 "111") +ANNOTATION: "VC_COV_UNR" +Condition 5 "1937111844" "((gen_normal_fifo.fifo_empty && wvalid_i) ? wdata_i : gen_normal_fifo.storage_rdata) 1 -1" (2 "1") +ANNOTATION: "VC_COV_UNR" +Condition 6 "4208363759" "(gen_normal_fifo.fifo_empty && wvalid_i) 1 -1" (1 "01") +ANNOTATION: "VC_COV_UNR" +Condition 6 "4208363759" "(gen_normal_fifo.fifo_empty && wvalid_i) 1 -1" (3 "11") +ANNOTATION: "VC_COV_UNR" +Condition 7 "1531674702" "(gen_normal_fifo.fifo_empty & ((~wvalid_i))) 1 -1" (1 "01") +ANNOTATION: "VC_COV_UNR" +Condition 7 "1531674702" "(gen_normal_fifo.fifo_empty & ((~wvalid_i))) 1 -1" (2 "10") +ANNOTATION: "VC_COV_UNR" +Condition 8 "568568669" "(gen_normal_fifo.empty ? (40'(0)) : gen_normal_fifo.rdata_int) 1 -1" (1 "0") +CHECKSUM: "7115036 3923796707" +INSTANCE: tb.dut.u_tlul_adapter.u_reqfifo +ANNOTATION: "VC_COV_UNR" +Condition 2 "1709501387" "(((~gen_normal_fifo.empty)) & ((~gen_normal_fifo.under_rst))) 1 -1" (2 "10") +ANNOTATION: "VC_COV_UNR" +Condition 3 "786039886" "(wvalid_i & wready_o & ((~gen_normal_fifo.under_rst))) 1 -1" (2 "101") +ANNOTATION: "VC_COV_UNR" +Condition 3 "786039886" "(wvalid_i & wready_o & ((~gen_normal_fifo.under_rst))) 1 -1" (3 "110") +ANNOTATION: "VC_COV_UNR" +Condition 4 "1324655787" "(rvalid_o & rready_i & ((~gen_normal_fifo.under_rst))) 1 -1" (1 "011") +ANNOTATION: "VC_COV_UNR" +Condition 4 "1324655787" "(rvalid_o & rready_i & ((~gen_normal_fifo.under_rst))) 1 -1" (3 "110") +CHECKSUM: "662936270 1214284494" +INSTANCE: tb.dut.u_tlul_adapter +ANNOTATION: "VC_COV_UNR" +Condition 2 "3455933711" "(reqfifo_rdata.op == OpRead) 1 -1" (2 "1") +ANNOTATION: "VC_COV_UNR" +Condition 4 "3638058042" "(rspfifo_rdata.error | reqfifo_rdata.error) 1 -1" (1 "00") +ANNOTATION: "VC_COV_UNR" +Condition 4 "3638058042" "(rspfifo_rdata.error | reqfifo_rdata.error) 1 -1" (3 "10") +ANNOTATION: "VC_COV_UNR" +Condition 8 "3066913128" "(intg_error | rsp_fifo_error | sramreqfifo_error | reqfifo_error | intg_error_q) 1 -1" (2 "00001") +ANNOTATION: "VC_COV_UNR" +Condition 13 "1155425989" "(wr_attr_error | wr_vld_error | rd_vld_error | instr_error | tlul_error | intg_error) 1 -1" (4 "000100") +ANNOTATION: "VC_COV_UNR" +Condition 13 "1155425989" "(wr_attr_error | wr_vld_error | rd_vld_error | instr_error | tlul_error | intg_error) 1 -1" (7 "100000") +ANNOTATION: "VC_COV_UNR" +Condition 16 "3623514242" "(req_o & gnt_i) 1 -1" (1 "01") +ANNOTATION: "VC_COV_UNR" +Condition 17 "1378572318" "(d_valid & reqfifo_rvalid & rspfifo_rvalid & (reqfifo_rdata.op == OpRead)) 1 -1" (1 "0111") +ANNOTATION: "VC_COV_UNR" +Condition 17 "1378572318" "(d_valid & reqfifo_rvalid & rspfifo_rvalid & (reqfifo_rdata.op == OpRead)) 1 -1" (2 "1011") +ANNOTATION: "VC_COV_UNR" +Condition 17 "1378572318" "(d_valid & reqfifo_rvalid & rspfifo_rvalid & (reqfifo_rdata.op == OpRead)) 1 -1" (4 "1110") +ANNOTATION: "VC_COV_UNR" +Condition 17 "1378572318" "(d_valid & reqfifo_rvalid & rspfifo_rvalid & (reqfifo_rdata.op == OpRead)) 1 -1" (5 "1111") +ANNOTATION: "VC_COV_UNR" +Condition 19 "1059982851" "((vld_rd_rsp & ((~d_error))) ? rspfifo_rdata.data : error_blanking_data) 1 -1" (2 "1") +ANNOTATION: "VC_COV_UNR" +Condition 20 "2807788926" "(vld_rd_rsp & ((~d_error))) 1 -1" (2 "10") +ANNOTATION: "VC_COV_UNR" +Condition 20 "2807788926" "(vld_rd_rsp & ((~d_error))) 1 -1" (3 "11") +ANNOTATION: "VC_COV_UNR" +Condition 21 "561780173" "((vld_rd_rsp && reqfifo_rdata.error) ? error_blanking_integ : (vld_rd_rsp ? rspfifo_rdata.data_intg : prim_secded_pkg::SecdedInv3932ZeroEcc)) 1 -1" (2 "1") +ANNOTATION: "VC_COV_UNR" +Condition 22 "3130851184" "(vld_rd_rsp && reqfifo_rdata.error) 1 -1" (2 "10") +ANNOTATION: "VC_COV_UNR" +Condition 22 "3130851184" "(vld_rd_rsp && reqfifo_rdata.error) 1 -1" (3 "11") +ANNOTATION: "VC_COV_UNR" +Condition 23 "2942914969" "(vld_rd_rsp ? rspfifo_rdata.data_intg : prim_secded_pkg::SecdedInv3932ZeroEcc) 1 -1" (2 "1") +ANNOTATION: "VC_COV_UNR" +Condition 30 "3680494467" "(d_valid && d_error) 1 -1" (1 "01") +ANNOTATION: "VC_COV_UNR" +Condition 31 "3680494467" "((gnt_i | missed_err_gnt_q) & reqfifo_wready & sramreqfifo_wready & sramreqaddrfifo_wready) 1 -1" (3 "1101") +ANNOTATION: "VC_COV_UNR" +Condition 33 "3190027871" "(tl_i_int.a_valid & reqfifo_wready & ((~error_internal))) 1 -1" (1 "011") +ANNOTATION: "VC_COV_UNR" +Condition 38 "721931741" "(sram_ack & ((~we_o))) 1 -1" (3 "11") +ANNOTATION: "VC_COV_UNR" +Condition 39 "927800449" "(rvalid_i & reqfifo_rvalid) 1 -1" (2 "10") +ANNOTATION: "VC_COV_UNR" +Condition 39 "927800449" "(rvalid_i & reqfifo_rvalid) 1 -1" (3 "11") +ANNOTATION: "VC_COV_UNR" +Condition 40 "4228513916" "(((reqfifo_rdata.op == OpRead) & ((~reqfifo_rdata.error))) ? reqfifo_rready : 1'b0) 1 -1" (2 "1") +ANNOTATION: "VC_COV_UNR" +Condition 41 "1188394860" "((reqfifo_rdata.op == OpRead) & ((~reqfifo_rdata.error))) 1 -1" (3 "11") +ANNOTATION: "vcs_gen_start:i=0:vcs_gen_end:VC_COV_UNR" +Condition 44 "1762788283" "(((|wmask_intg)) & ((|wdata_intg))) 1 -1" (1 "01") +CHECKSUM: "1882961916 2084194233" +INSTANCE: tb.dut.u_prim_sha2_512 +ANNOTATION: "VC_COV_UNR" +Condition 8 "1438483432" "(gen_multimode_logic.word_part_count_q == 2'b1) 1 -1" (1 "0") +ANNOTATION: "VC_COV_UNR" +Condition 11 "2753310321" "(gen_multimode_logic.word_part_count_q == 2'b10) 1 -1" (1 "0") +ANNOTATION: "VC_COV_UNR" +Condition 11 "2753310321" "(gen_multimode_logic.word_part_count_q == 2'b10) 1 -1" (2 "1") +ANNOTATION: "VC_COV_UNR" +Condition 12 "2064886934" "(hash_process_i || gen_multimode_logic.process_flag_q) 1 -1" (1 "00") +ANNOTATION: "VC_COV_UNR" +Condition 12 "2064886934" "(hash_process_i || gen_multimode_logic.process_flag_q) 1 -1" (2 "01") +ANNOTATION: "VC_COV_UNR" +Condition 12 "2064886934" "(hash_process_i || gen_multimode_logic.process_flag_q) 1 -1" (3 "10") +ANNOTATION: "VC_COV_UNR" +Condition 13 "1630160661" "(sha_ready == 1'b1) 1 -1" (1 "0") +ANNOTATION: "VC_COV_UNR" +Condition 13 "1630160661" "(sha_ready == 1'b1) 1 -1" (2 "1") +ANNOTATION: "VC_COV_UNR" +Condition 17 "2486319864" "((gen_multimode_logic.word_part_count_q == 2'b1) && (hash_process_i || gen_multimode_logic.process_flag_q)) 1 -1" (1 "01") +ANNOTATION: "VC_COV_UNR" +Condition 22 "3280633812" "((gen_multimode_logic.word_part_count_q == 2'b10) && (hash_process_i || gen_multimode_logic.process_flag_q)) 1 -1" (1 "01") +ANNOTATION: "VC_COV_UNR" +Condition 22 "3280633812" "((gen_multimode_logic.word_part_count_q == 2'b10) && (hash_process_i || gen_multimode_logic.process_flag_q)) 1 -1" (2 "10") +ANNOTATION: "VC_COV_UNR" +Condition 22 "3280633812" "((gen_multimode_logic.word_part_count_q == 2'b10) && (hash_process_i || gen_multimode_logic.process_flag_q)) 1 -1" (3 "11") +ANNOTATION: "VC_COV_UNR" +Condition 23 "4027350021" "(gen_multimode_logic.word_part_count_q == 2'b10) 1 -1" (2 "1") +ANNOTATION: "VC_COV_UNR" +Condition 24 "3431001949" "(hash_process_i || gen_multimode_logic.process_flag_q) 1 -1" (2 "01") +ANNOTATION: "VC_COV_UNR" +Condition 24 "3431001949" "(hash_process_i || gen_multimode_logic.process_flag_q) 1 -1" (3 "10") +ANNOTATION: "VC_COV_UNR" +Condition 25 "3602449630" "(sha_ready == 1'b1) 1 -1" (1 "0") +ANNOTATION: "VC_COV_UNR" +Condition 25 "3602449630" "(sha_ready == 1'b1) 1 -1" (2 "1") +ANNOTATION: "VC_COV_UNR" +Condition 26 "2499130408" "(gen_multimode_logic.word_part_count_q == 2'b10) 1 -1" (2 "1") +CHECKSUM: "1746381268 1271541636" +INSTANCE: tb.dut.u_reg.u_socket +ANNOTATION: "VC_COV_UNR" +Condition 3 "118253128" "(tl_t_o.a_valid & tl_t_i.a_ready) 1 -1" (1 "01") +CHECKSUM: "74367784 3785313510" +INSTANCE: tb.dut.u_reg.u_reg_if +ANNOTATION: "VC_COV_UNR" +Condition 18 "3340270436" "(addr_align_err | malformed_meta_err | tl_err | instr_error | intg_error) 1 -1" (5 "01000") +CHECKSUM: "4255502330 3274445021" +INSTANCE: tb.dut.u_reg.u_intr_state_fifo_empty +ANNOTATION: "VC_COV_UNR" +Condition 1 "2397158838" "(wr_en ? wr_data : qs) 1 -1" (1 "0") +CHECKSUM: "3215070453 33318353" +INSTANCE: tb.dut.u_tlul_adapter.u_reqfifo.gen_normal_fifo.u_fifo_cnt +ANNOTATION: "VC_COV_UNR" +Condition 1 "2532211833" "(incr_wptr_i & (wptr_o == 1'((Depth - 1)))) 1 -1" (2 "10") +ANNOTATION: "VC_COV_UNR" +Condition 3 "2597027294" "(incr_rptr_i & (rptr_o == 1'((Depth - 1)))) 1 -1" (2 "10") +ANNOTATION: "VC_COV_UNR" +Condition 8 "1599734576" "((wptr_wrap_msb == rptr_wrap_msb) ? ((1'(wptr_o) - 1'(rptr_o))) : (((1'(Depth) - 1'(rptr_o)) + 1'(wptr_o)))) 1 -1" (1 "0") +ANNOTATION: "VC_COV_UNR" +Condition 9 "446195871" "(wptr_wrap_msb == rptr_wrap_msb) 1 -1" (1 "0") +CHECKSUM: "3215070453 33318353" +INSTANCE: tb.dut.u_tlul_adapter.u_sramreqfifo.gen_normal_fifo.u_fifo_cnt +ANNOTATION: "VC_COV_UNR" +Condition 1 "2532211833" "(incr_wptr_i & (wptr_o == 1'((Depth - 1)))) 1 -1" (2 "10") +ANNOTATION: "VC_COV_UNR" +Condition 1 "2532211833" "(incr_wptr_i & (wptr_o == 1'((Depth - 1)))) 1 -1" (3 "11") +ANNOTATION: "VC_COV_UNR" +Condition 3 "2597027294" "(incr_rptr_i & (rptr_o == 1'((Depth - 1)))) 1 -1" (2 "10") +ANNOTATION: "VC_COV_UNR" +Condition 3 "2597027294" "(incr_rptr_i & (rptr_o == 1'((Depth - 1)))) 1 -1" (3 "11") +ANNOTATION: "VC_COV_UNR" +Condition 5 "3619927060" "(wptr_wrap_cnt_q == (rptr_wrap_cnt_q ^ {1'b1, {(WrapPtrW - 1) {1'b0}}})) 1 -1" (2 "1") +ANNOTATION: "VC_COV_UNR" +Condition 7 "687544961" "(full_o ? (1'(Depth)) : ((wptr_wrap_msb == rptr_wrap_msb) ? ((1'(wptr_o) - 1'(rptr_o))) : (((1'(Depth) - 1'(rptr_o)) + 1'(wptr_o))))) 1 -1" (2 "1") +ANNOTATION: "VC_COV_UNR" +Condition 8 "1599734576" "((wptr_wrap_msb == rptr_wrap_msb) ? ((1'(wptr_o) - 1'(rptr_o))) : (((1'(Depth) - 1'(rptr_o)) + 1'(wptr_o)))) 1 -1" (1 "0") +ANNOTATION: "VC_COV_UNR" +Condition 9 "446195871" "(wptr_wrap_msb == rptr_wrap_msb) 1 -1" (1 "0") +CHECKSUM: "3215070453 33318353" +INSTANCE: tb.dut.u_tlul_adapter.u_rspfifo.gen_normal_fifo.u_fifo_cnt +ANNOTATION: "VC_COV_UNR" +Condition 1 "2532211833" "(incr_wptr_i & (wptr_o == 1'((Depth - 1)))) 1 -1" (2 "10") +ANNOTATION: "VC_COV_UNR" +Condition 1 "2532211833" "(incr_wptr_i & (wptr_o == 1'((Depth - 1)))) 1 -1" (3 "11") +ANNOTATION: "VC_COV_UNR" +Condition 3 "2597027294" "(incr_rptr_i & (rptr_o == 1'((Depth - 1)))) 1 -1" (2 "10") +ANNOTATION: "VC_COV_UNR" +Condition 3 "2597027294" "(incr_rptr_i & (rptr_o == 1'((Depth - 1)))) 1 -1" (3 "11") +ANNOTATION: "VC_COV_UNR" +Condition 5 "3619927060" "(wptr_wrap_cnt_q == (rptr_wrap_cnt_q ^ {1'b1, {(WrapPtrW - 1) {1'b0}}})) 1 -1" (2 "1") +ANNOTATION: "VC_COV_UNR" +Condition 7 "687544961" "(full_o ? (1'(Depth)) : ((wptr_wrap_msb == rptr_wrap_msb) ? ((1'(wptr_o) - 1'(rptr_o))) : (((1'(Depth) - 1'(rptr_o)) + 1'(wptr_o))))) 1 -1" (2 "1") +ANNOTATION: "VC_COV_UNR" +Condition 8 "1599734576" "((wptr_wrap_msb == rptr_wrap_msb) ? ((1'(wptr_o) - 1'(rptr_o))) : (((1'(Depth) - 1'(rptr_o)) + 1'(wptr_o)))) 1 -1" (1 "0") +ANNOTATION: "VC_COV_UNR" +Condition 9 "446195871" "(wptr_wrap_msb == rptr_wrap_msb) 1 -1" (1 "0") +CHECKSUM: "2418056030 4021692964" +INSTANCE: tb.dut.u_prim_sha2_512.gen_multimode_logic.u_prim_sha2_multimode +ANNOTATION: "VC_COV_UNR" +Condition 13 "31187075" "(fifo_st_q == FifoWait) 1 -1" (2 "1") +ANNOTATION: "VC_COV_UNR" +Condition 16 "355936152" "(((!run_hash)) && update_w_from_fifo) 1 -1" (1 "01") +ANNOTATION: "VC_COV_UNR" +Condition 18 "2862662814" "((digest_mode_flag_q == SHA2_384) || (digest_mode_flag_q == SHA2_512)) 1 -1" (1 "00") +ANNOTATION: "VC_COV_UNR" +Condition 27 "51049318" "(digest_mode_i == SHA2_512) 1 -1" (1 "0") +CHECKSUM: "1683432060 1830963071" +INSTANCE: tb.dut.u_prim_sha2_512.gen_multimode_logic.u_prim_sha2_multimode.u_pad +ANNOTATION: "VC_COV_UNR" +Condition 9 "2254482736" "(((digest_mode_flag_q == SHA2_384) || (digest_mode_flag_q == SHA2_512)) ? message_length_i[127:64] : '0) 1 -1" (1 "0") +ANNOTATION: "VC_COV_UNR" +Condition 10 "2629868682" "((digest_mode_flag_q == SHA2_384) || (digest_mode_flag_q == SHA2_512)) 1 -1" (1 "00") +ANNOTATION: "VC_COV_UNR" +Condition 16 "69940414" "(((digest_mode_flag_q == SHA2_384) || (digest_mode_flag_q == SHA2_512)) ? message_length_i[63:0] : '0) 1 -1" (1 "0") +ANNOTATION: "VC_COV_UNR" +Condition 17 "512427268" "((digest_mode_flag_q == SHA2_384) || (digest_mode_flag_q == SHA2_512)) 1 -1" (1 "00") +ANNOTATION: "VC_COV_UNR" +Condition 33 "2683661957" "(shaf_rready_i && ((!txcnt_eq_1a0))) 1 -1" (2 "10") +CHECKSUM: "1475951854 4264787725" +INSTANCE: tb.dut.u_hmac +ANNOTATION: "VC_COV_UNR" +Branch 11 "3517354206" "(!hmac_en_i)" (8) "(!hmac_en_i) 0,0,-,-,0,-,-,-" +ANNOTATION: "VC_COV_UNR" +Branch 13 "901324856" "clr_txcount" (4) "clr_txcount 0,1,default,-" +ANNOTATION: "VC_COV_UNR" +Branch 17 "72303213" "(!rst_ni)" (3) "(!rst_ni) 0,0,0" +ANNOTATION: "VC_COV_UNR" +Branch 19 "3063077316" "st_q" (17) "st_q default,-,-,-,-,-,-,-,-,-,-" +CHECKSUM: "581497987 3137485356" +INSTANCE: tb.dut +ANNOTATION: "VC_COV_UNR" +Branch 4 "2459060006" "done_state_q" (8) "done_state_q DoneAwaitHashComplete ,-,-,-,-,0" +ANNOTATION: "VC_COV_UNR" +Branch 4 "2459060006" "done_state_q" (9) "done_state_q default,-,-,-,-,-" +CHECKSUM: "7115036 4143698547" +INSTANCE: tb.dut.u_tlul_adapter.u_rspfifo +ANNOTATION: "VC_COV_UNR" +Branch 0 "4156807255" "(gen_normal_fifo.fifo_empty && wvalid_i)" (0) "(gen_normal_fifo.fifo_empty && wvalid_i) 1" +ANNOTATION: "VC_COV_UNR" +Branch 1 "3867317506" "gen_normal_fifo.empty" (1) "gen_normal_fifo.empty 0" +CHECKSUM: "7115036 1676778748" +INSTANCE: tb.dut.u_tlul_adapter.u_sramreqfifo +ANNOTATION: "VC_COV_UNR" +Branch 0 "3867317506" "gen_normal_fifo.empty" (1) "gen_normal_fifo.empty 0" +ANNOTATION: "VC_COV_UNR" +Branch 2 "2429929352" "gen_normal_fifo.fifo_incr_wptr" (0) "gen_normal_fifo.fifo_incr_wptr 1" +CHECKSUM: "662936270 1924774061" +INSTANCE: tb.dut.u_tlul_adapter +ANNOTATION: "VC_COV_UNR" +Branch 1 "3662748946" "(vld_rd_rsp & (~d_error))" (0) "(vld_rd_rsp & (~d_error)) 1" +ANNOTATION: "VC_COV_UNR" +Branch 2 "1058271942" "(vld_rd_rsp && reqfifo_rdata.error)" (0) "(vld_rd_rsp && reqfifo_rdata.error) 1,-" +ANNOTATION: "VC_COV_UNR" +Branch 2 "1058271942" "(vld_rd_rsp && reqfifo_rdata.error)" (1) "(vld_rd_rsp && reqfifo_rdata.error) 0,1" +ANNOTATION: "VC_COV_UNR" +Branch 4 "1984420262" "((reqfifo_rdata.op == OpRead) & (~reqfifo_rdata.error))" (0) "((reqfifo_rdata.op == OpRead) & (~reqfifo_rdata.error)) 1" +ANNOTATION: "VC_COV_UNR" +Branch 6 "744749108" "reqfifo_rvalid" (1) "reqfifo_rvalid 1,0,1" +CHECKSUM: "3287391918 1653597412" +INSTANCE: tb.dut.u_packer +ANNOTATION: "VC_COV_UNR" +Branch 4 "1475310489" "{ack_in, ack_out}" (4) "{ack_in, ack_out} default" +ANNOTATION: "VC_COV_UNR" +Branch 7 "154724253" "flush_st" (4) "flush_st default,-,-" +ANNOTATION: "VC_COV_UNR" +Branch 8 "1280311922" "{ack_in, ack_out}" (6) "{ack_in, ack_out} default,-,-" +CHECKSUM: "1882961916 2351169394" +INSTANCE: tb.dut.u_prim_sha2_512 +ANNOTATION: "VC_COV_UNR" +Branch 1 "1380881604" "(sha_en_i && fifo_rvalid_i)" (10) "(sha_en_i && fifo_rvalid_i) 1,0,-,-,-,-,0,-,-,1,1,-,-,-,-,-,-,-,-,-" +ANNOTATION: "VC_COV_UNR" +Branch 1 "1380881604" "(sha_en_i && fifo_rvalid_i)" (11) "(sha_en_i && fifo_rvalid_i) 1,0,-,-,-,-,0,-,-,1,0,-,-,-,-,-,-,-,-,-" +ANNOTATION: "VC_COV_UNR" +Branch 1 "1380881604" "(sha_en_i && fifo_rvalid_i)" (12) "(sha_en_i && fifo_rvalid_i) 1,0,-,-,-,-,0,-,-,1,-,1,-,-,-,-,-,-,-,-" +ANNOTATION: "VC_COV_UNR" +Branch 1 "1380881604" "(sha_en_i && fifo_rvalid_i)" (13) "(sha_en_i && fifo_rvalid_i) 1,0,-,-,-,-,0,-,-,1,-,0,-,-,-,-,-,-,-,-" +ANNOTATION: "VC_COV_UNR" +Branch 1 "1380881604" "(sha_en_i && fifo_rvalid_i)" (14) "(sha_en_i && fifo_rvalid_i) 1,0,-,-,-,-,0,-,-,0,-,-,-,-,-,-,-,-,-,-" +ANNOTATION: "VC_COV_UNR" +Branch 1 "1380881604" "(sha_en_i && fifo_rvalid_i)" (19) "(sha_en_i && fifo_rvalid_i) 0,-,-,-,-,-,-,-,-,-,-,-,1,0,0,-,0,1,1,-" +ANNOTATION: "VC_COV_UNR" +Branch 1 "1380881604" "(sha_en_i && fifo_rvalid_i)" (20) "(sha_en_i && fifo_rvalid_i) 0,-,-,-,-,-,-,-,-,-,-,-,1,0,0,-,0,1,0,-" +ANNOTATION: "VC_COV_UNR" +Branch 1 "1380881604" "(sha_en_i && fifo_rvalid_i)" (21) "(sha_en_i && fifo_rvalid_i) 0,-,-,-,-,-,-,-,-,-,-,-,1,0,0,-,0,0,-,1" +CHECKSUM: "1746381268 3161287359" +INSTANCE: tb.dut.u_reg.u_socket +ANNOTATION: "VC_COV_UNR" +Branch 4 "3202860295" "(!rst_ni)" (2) "(!rst_ni) 0,1,0,-" +CHECKSUM: "4255502330 3554514034" +INSTANCE: tb.dut.u_reg.u_intr_state_fifo_empty +ANNOTATION: "VC_COV_UNR" +Branch 0 "3759852512" "wr_en" (1) "wr_en 0" +ANNOTATION: "VC_COV_UNR" +Branch 1 "1017474648" "(!rst_ni)" (2) "(!rst_ni) 0,0" +CHECKSUM: "3215070453 1827096802" +INSTANCE: tb.dut.u_tlul_adapter.u_reqfifo.gen_normal_fifo.u_fifo_cnt +ANNOTATION: "VC_COV_UNR" +Branch 0 "721764659" "full_o" (2) "full_o 0,0" +ANNOTATION: "VC_COV_UNR" +Branch 1 "2417346495" "(!rst_ni)" (3) "(!rst_ni) 0,0,0,1" +ANNOTATION: "VC_COV_UNR" +Branch 2 "456961687" "(!rst_ni)" (3) "(!rst_ni) 0,0,0,1" +CHECKSUM: "3215070453 1827096802" +INSTANCE: tb.dut.u_tlul_adapter.u_sramreqfifo.gen_normal_fifo.u_fifo_cnt +ANNOTATION: "VC_COV_UNR" +Branch 0 "721764659" "full_o" (0) "full_o 1,-" +ANNOTATION: "VC_COV_UNR" +Branch 0 "721764659" "full_o" (2) "full_o 0,0" +ANNOTATION: "VC_COV_UNR" +Branch 1 "2417346495" "(!rst_ni)" (2) "(!rst_ni) 0,0,1,-" +ANNOTATION: "VC_COV_UNR" +Branch 1 "2417346495" "(!rst_ni)" (3) "(!rst_ni) 0,0,0,1" +ANNOTATION: "VC_COV_UNR" +Branch 2 "456961687" "(!rst_ni)" (2) "(!rst_ni) 0,0,1,-" +ANNOTATION: "VC_COV_UNR" +Branch 2 "456961687" "(!rst_ni)" (3) "(!rst_ni) 0,0,0,1" +CHECKSUM: "3215070453 1827096802" +INSTANCE: tb.dut.u_tlul_adapter.u_rspfifo.gen_normal_fifo.u_fifo_cnt +ANNOTATION: "VC_COV_UNR" +Branch 0 "721764659" "full_o" (0) "full_o 1,-" +ANNOTATION: "VC_COV_UNR" +Branch 0 "721764659" "full_o" (2) "full_o 0,0" +ANNOTATION: "VC_COV_UNR" +Branch 1 "2417346495" "(!rst_ni)" (2) "(!rst_ni) 0,0,1,-" +ANNOTATION: "VC_COV_UNR" +Branch 1 "2417346495" "(!rst_ni)" (3) "(!rst_ni) 0,0,0,1" +ANNOTATION: "VC_COV_UNR" +Branch 2 "456961687" "(!rst_ni)" (2) "(!rst_ni) 0,0,1,-" +ANNOTATION: "VC_COV_UNR" +Branch 2 "456961687" "(!rst_ni)" (3) "(!rst_ni) 0,0,0,1" +CHECKSUM: "2418056030 1412398065" +INSTANCE: tb.dut.u_prim_sha2_512.gen_multimode_logic.u_prim_sha2_multimode +ANNOTATION: "VC_COV_UNR" +Branch 8 "1542743970" "fifo_st_q" (8) "fifo_st_q default,-,-,-,-,-" +ANNOTATION: "VC_COV_UNR" +Branch 13 "1372229723" "sha_st_q" (5) "sha_st_q ShaUpdateDigest ,-,-,-,1" +ANNOTATION: "VC_COV_UNR" +Branch 13 "1372229723" "sha_st_q" (7) "sha_st_q default,-,-,-,-" +ANNOTATION: "VC_COV_UNR" +Branch 15 "3667506510" "wipe_secret_i" (5) "wipe_secret_i 0,0,0,1,0,0,-" +ANNOTATION: "VC_COV_UNR" +Branch 16 "1234001942" "(!rst_ni)" (2) "(!rst_ni) 0,0" +CHECKSUM: "1683432060 2352190167" +INSTANCE: tb.dut.u_prim_sha2_512.gen_multimode_logic.u_prim_sha2_multimode.u_pad +ANNOTATION: "VC_COV_UNR" +Branch 5 "2629563645" "sel_data" (5) "sel_data Pad80 ,1,default,-,-,-,-,-,-" +ANNOTATION: "VC_COV_UNR" +Branch 5 "2629563645" "sel_data" (14) "sel_data Pad80 ,0,-,1,default,-,-,-,-" +ANNOTATION: "VC_COV_UNR" +Branch 5 "2629563645" "sel_data" (19) "sel_data LenHi ,-,-,-,-,0,0,-,-" +ANNOTATION: "VC_COV_UNR" +Branch 5 "2629563645" "sel_data" (22) "sel_data LenLo ,-,-,-,-,-,-,0,0" +ANNOTATION: "VC_COV_UNR" +Branch 5 "2629563645" "sel_data" (23) "sel_data default,-,-,-,-,-,-,-,-" +ANNOTATION: "VC_COV_UNR" +Branch 8 "199737855" "st_q" (21) "st_q default,-,-,-,-,-,-,-,-,-,-,-,-,-" diff --git a/hw/ip/hmac/dv copy/cryptoc_dpi/LICENSE b/hw/ip/hmac/dv copy/cryptoc_dpi/LICENSE new file mode 100644 index 0000000000000..f433b1a53f5b8 --- /dev/null +++ b/hw/ip/hmac/dv copy/cryptoc_dpi/LICENSE @@ -0,0 +1,177 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS diff --git a/hw/ip/hmac/dv copy/cryptoc_dpi/README.md b/hw/ip/hmac/dv copy/cryptoc_dpi/README.md new file mode 100644 index 0000000000000..1229ded9c60aa --- /dev/null +++ b/hw/ip/hmac/dv copy/cryptoc_dpi/README.md @@ -0,0 +1,27 @@ +### Cryptoc library (SHA, SHA256, SHA384, SHA512 and HMAC) +This cryptoc library has been pulled from open source Chromium repo: +```git clone https://chromium.googlesource.com/chromiumos/third_party/cryptoc``` + +This directory contains the following stand-alone crypto implementations: +sha, sha256 and hmac (using sha and sha256) + +These implemenations have no stl or OpenSSL dependencies and are +endian-neutral. + +The sha*.*, hmac.* and util.* sources are in their original, unmodified state. +The only modification is the path to header. + +The rest is sourced natively. + +## Cryptoc-dpi extensions for dv +The hmac_wrap.* sources have been newly added to include functions that take +arbitrary length msg and key as arguments and return the final HMAC digest. This +is a missing piece in the original hmac.* sources picked up from the above repo. + +The cryptoc_dpi.c contains DPI-C wrapper functions exported to SV so that they +can be called from testbenches. It does DPI-C specific processing to the input +and output args required to be able to call the pure C cryptoc library +functions. + +The cryptoc_dpi_pkg.sv contains the DPI-C imports for the C functions and extra +SV wrapper functions that call the imported DPI-C wrapper functions. diff --git a/hw/ip/hmac/dv copy/cryptoc_dpi/cryptoc_dpi.c b/hw/ip/hmac/dv copy/cryptoc_dpi/cryptoc_dpi.c new file mode 100644 index 0000000000000..f4fcca19e041a --- /dev/null +++ b/hw/ip/hmac/dv copy/cryptoc_dpi/cryptoc_dpi.c @@ -0,0 +1,200 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#include +#include +#include +#include + +#include "hmac.h" +#include "hmac_wrap.h" +#include "sha.h" +#include "sha256.h" +#include "sha384.h" +#include "sha512.h" + +// SystemVerilog DPI definitions +#include "svdpi.h" + +// Gather the elements of the open array to form a C-style array of contiguous +// bytes +static uint8_t *collect_bytes(const svOpenArrayHandle arg, uint64_t len) { + // Note: alas when passed an open array that is empty we are unable even to + // query svSize() of the single dimension without inducing a E,MEMALC + // error from xcelium, so we must pass supplied with the length. + assert(len > 0u); + + assert(1 == svDimensions(arg)); + assert(len <= svSize(arg, 1)); + + uint8_t *arr = (uint8_t *)malloc(len); + if (arr) { + const svBitVecVal *ptr = (svBitVecVal *)svGetArrayPtr(arg); + if (ptr) { + // C-style layout + for (uint64_t idx = 0u; idx < len; ++idx) { + arr[idx] = (uint8_t)ptr[idx]; + } + } else { + // The implementation-independent way to access open arrays is to use the + // SystemVerilog array bounds/indexes. + const int high = svHigh(arg, 1); + const int low = svLow(arg, 1); + + printf("bounds [%d:%d]\n", high, low); + + for (int idx = low; idx <= high; ++idx) { + uint8_t *ptr = (uint8_t *)svGetArrElemPtr1(arg, idx); + assert(ptr); + arr[idx] = (uint8_t)*ptr; + } + } + } + + return arr; +} + +extern void c_dpi_SHA_hash(const svOpenArrayHandle msg, uint64_t len, + uint32_t hash[8]) { + if (len > 0u) { + uint8_t *arr = collect_bytes(msg, len); + assert(arr); + + // compute SHA hash + SHA_hash(arr, len, (uint8_t *)hash); + + free(arr); + } +} + +extern void c_dpi_SHA256_hash(const svOpenArrayHandle msg, uint64_t len, + uint32_t hash[8]) { + if (len > 0u) { + uint8_t *arr = collect_bytes(msg, len); + assert(arr); + + // compute SHA256 hash + SHA256_hash(arr, len, (uint8_t *)hash); + + free(arr); + } else { + // compute SHA256 hash when msg is empty + SHA256_hash(NULL, 0u, (uint8_t *)hash); + } +} + +extern void c_dpi_SHA384_hash(const svOpenArrayHandle msg, uint64_t len, + uint32_t hash[12]) { + if (len > 0u) { + uint8_t *arr = collect_bytes(msg, len); + assert(arr); + + // compute SHA384 hash + SHA384_hash(arr, len, (uint8_t *)hash); + + free(arr); + } else { + // compute SHA384 hash when msg is empty + SHA384_hash(NULL, 0u, (uint8_t *)hash); + } +} + +extern void c_dpi_SHA512_hash(const svOpenArrayHandle msg, uint64_t len, + uint32_t hash[16]) { + if (len > 0u) { + uint8_t *arr = collect_bytes(msg, len); + assert(arr); + + // compute SHA512 hash + SHA512_hash(arr, len, (uint8_t *)hash); + + free(arr); + } else { + // compute SHA512 hash when msg is empty + SHA512_hash(NULL, 0u, (uint8_t *)hash); + } +} + +extern void c_dpi_HMAC_SHA(const svOpenArrayHandle key, uint64_t key_len, + const svOpenArrayHandle msg, uint64_t msg_len, + uint32_t hmac[8]) { + if (msg_len > 0u) { + uint8_t *msg_arr = collect_bytes(msg, msg_len); + assert(msg_arr); + + uint8_t *key_arr = collect_bytes(key, key_len); + assert(key_arr); + + // compute SHA hash + HMAC_SHA(key_arr, key_len, msg_arr, msg_len, (uint8_t *)hmac); + + free(msg_arr); + free(key_arr); + } +} + +extern void c_dpi_HMAC_SHA256(const svOpenArrayHandle key, uint64_t key_len, + const svOpenArrayHandle msg, uint64_t msg_len, + uint32_t hmac[8]) { + uint8_t *key_arr = collect_bytes(key, key_len); + assert(key_arr); + + if (msg_len > 0u) { + uint8_t *msg_arr = collect_bytes(msg, msg_len); + assert(msg_arr); + + // compute SHA256 hash + HMAC_SHA256(key_arr, key_len, msg_arr, msg_len, (uint8_t *)hmac); + + free(msg_arr); + } else { + // compute SHA256 hash when msg is empty + HMAC_SHA256(key_arr, key_len, NULL, 0u, (uint8_t *)hmac); + } + + free(key_arr); +} +extern void c_dpi_HMAC_SHA384(const svOpenArrayHandle key, uint64_t key_len, + const svOpenArrayHandle msg, uint64_t msg_len, + uint32_t hmac[12]) { + uint8_t *key_arr = collect_bytes(key, key_len); + assert(key_arr); + + if (msg_len > 0u) { + uint8_t *msg_arr = collect_bytes(msg, msg_len); + assert(msg_arr); + + // compute SHA384 hash + HMAC_SHA384(key_arr, key_len, msg_arr, msg_len, (uint8_t *)hmac); + + free(msg_arr); + } else { + // compute SHA384 hash when msg is empty + HMAC_SHA384(key_arr, key_len, NULL, 0u, (uint8_t *)hmac); + } + + free(key_arr); +} + +extern void c_dpi_HMAC_SHA512(const svOpenArrayHandle key, uint64_t key_len, + const svOpenArrayHandle msg, uint64_t msg_len, + uint32_t hmac[16]) { + uint8_t *key_arr = collect_bytes(key, key_len); + assert(key_arr); + + if (msg_len > 0u) { + uint8_t *msg_arr = collect_bytes(msg, msg_len); + assert(msg_arr); + + // compute SHA512 hash + HMAC_SHA512(key_arr, key_len, msg_arr, msg_len, (uint8_t *)hmac); + + free(msg_arr); + } else { + // compute SHA512 hash when msg is empty + HMAC_SHA512(key_arr, key_len, NULL, 0u, (uint8_t *)hmac); + } + + free(key_arr); +} diff --git a/hw/ip/hmac/dv copy/cryptoc_dpi/cryptoc_dpi.core b/hw/ip/hmac/dv copy/cryptoc_dpi/cryptoc_dpi.core new file mode 100644 index 0000000000000..53b0ba4ca39a5 --- /dev/null +++ b/hw/ip/hmac/dv copy/cryptoc_dpi/cryptoc_dpi.core @@ -0,0 +1,32 @@ +CAPI=2: +#Copyright lowRISC contributors (OpenTitan project). +#Licensed under the Apache License, Version 2.0, see LICENSE for details. +#SPDX - License - Identifier : Apache - 2.0 +name: "lowrisc:dv:cryptoc_dpi:0.1" +description: "SHA / HASH Crypto implementations in C from Chromium open source repo" +filesets: + files_dv: + files: + - hash-internal.h: {file_type: cSource, is_include_file: true} + - sha.h: {file_type: cSource, is_include_file: true} + - sha256.h: {file_type: cSource, is_include_file: true} + - sha384.h: {file_type: cSource, is_include_file: true} + - sha512.h: {file_type: cSource, is_include_file: true} + - util.h: {file_type: cSource, is_include_file: true} + - hmac.h: {file_type: cSource, is_include_file: true} + - hmac_wrap.h: {file_type: cSource, is_include_file: true} + - util.c: {file_type: cSource} + - sha.c: {file_type: cSource} + - sha256.c: {file_type: cSource} + - sha384.c: {file_type: cSource} + - sha512.c: {file_type: cSource} + - hmac.c: {file_type: cSource} + - hmac_wrap.c: {file_type: cSource} + - cryptoc_dpi.c: {file_type: cSource} + - cryptoc_dpi_pkg.sv: {file_type: systemVerilogSource} + file_type: cSource + +targets: + default: + filesets: + - files_dv diff --git a/hw/ip/hmac/dv copy/cryptoc_dpi/cryptoc_dpi_pkg.sv b/hw/ip/hmac/dv copy/cryptoc_dpi/cryptoc_dpi_pkg.sv new file mode 100644 index 0000000000000..7e0a6fb67b5d7 --- /dev/null +++ b/hw/ip/hmac/dv copy/cryptoc_dpi/cryptoc_dpi_pkg.sv @@ -0,0 +1,118 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +package cryptoc_dpi_pkg; + // dep packages + import uvm_pkg::*; + + // macro includes + `include "uvm_macros.svh" + + // DPI-C imports + // + // Note: alas we must supply the array lengths as additional parameters to appease xcelium + // which would otherwise raise E,MEMALC when the DPI-C code even tries to invoke + // svSize(msg, 1) on an empty one-dimensional array. + import "DPI-C" context function void c_dpi_SHA_hash(input bit[7:0] msg[], + input longint unsigned len, + output int unsigned hash[8]); + + import "DPI-C" context function void c_dpi_SHA256_hash(input bit[7:0] msg[], + input longint unsigned len, + output int unsigned hash[8]); + + import "DPI-C" context function void c_dpi_SHA384_hash(input bit[7:0] msg[], + input longint unsigned len, + output int unsigned hash[12]); + + import "DPI-C" context function void c_dpi_SHA512_hash(input bit[7:0] msg[], + input longint unsigned len, + output int unsigned hash[16]); + + import "DPI-C" context function void c_dpi_HMAC_SHA(input bit[7:0] key[], + input longint unsigned key_len, + input bit[7:0] msg[], + input longint unsigned msg_len, + output int unsigned hmac[8]); + + import "DPI-C" context function void c_dpi_HMAC_SHA256(input bit[7:0] key[], + input longint unsigned key_len, + input bit[7:0] msg[], + input longint unsigned msg_len, + output int unsigned hmac[8]); + + import "DPI-C" context function void c_dpi_HMAC_SHA384(input bit[7:0] key[], + input longint unsigned key_len, + input bit[7:0] msg[], + input longint unsigned msg_len, + output int unsigned hmac[12]); + + import "DPI-C" context function void c_dpi_HMAC_SHA512(input bit[7:0] key[], + input longint unsigned key_len, + input bit[7:0] msg[], + input longint unsigned msg_len, + output int unsigned hmac[16]); + + // sv wrapper functions + function automatic void sv_dpi_get_sha_digest(input bit[7:0] msg[], + output int unsigned hash[8]); + c_dpi_SHA_hash(msg, msg.size(), hash); + endfunction + + function automatic void sv_dpi_get_sha256_digest(input bit[7:0] msg[], + output int unsigned hash[8]); + c_dpi_SHA256_hash(msg, msg.size(), hash); + endfunction + + function automatic void sv_dpi_get_sha384_digest(input bit[7:0] msg[], + output int unsigned hash[12]); + c_dpi_SHA384_hash(msg, msg.size(), hash); + endfunction + + function automatic void sv_dpi_get_sha512_digest(input bit[7:0] msg[], + output int unsigned hash[16]); + c_dpi_SHA512_hash(msg, msg.size(), hash); + endfunction + + function automatic void sv_dpi_get_hmac_sha(input bit[31:0] key[], + input bit[7:0] msg[], + output int unsigned hmac[8]); + bit [7:0] ckey[]; + int ckey_size_bytes = $bits(key) / 8; + ckey = new[ckey_size_bytes]; + {>>{ckey}} = key; + c_dpi_HMAC_SHA(ckey, ckey.size(), msg, msg.size(), hmac); + endfunction + + function automatic void sv_dpi_get_hmac_sha256(input bit[31:0] key[], + input bit[7:0] msg[], + output int unsigned hmac[8]); + bit [7:0] ckey[]; + int ckey_size_bytes = $bits(key) / 8; + ckey = new[ckey_size_bytes]; + {>>{ckey}} = key; + c_dpi_HMAC_SHA256(ckey, ckey.size(), msg, msg.size(), hmac); + endfunction + + function automatic void sv_dpi_get_hmac_sha384(input bit[31:0] key[], + input bit[7:0] msg[], + output int unsigned hmac[12]); + bit [7:0] ckey[]; + int ckey_size_bytes = $bits(key) / 8; + ckey = new[ckey_size_bytes]; + {>>{ckey}} = key; + c_dpi_HMAC_SHA384(ckey, ckey.size(), msg, msg.size(), hmac); + endfunction + + function automatic void sv_dpi_get_hmac_sha512(input bit[31:0] key[], + input bit[7:0] msg[], + output int unsigned hmac[16]); + bit [7:0] ckey[]; + int ckey_size_bytes = $bits(key) / 8; + ckey = new[ckey_size_bytes]; + {>>{ckey}} = key; + c_dpi_HMAC_SHA512(ckey, ckey.size(), msg, msg.size(), hmac); + endfunction + +endpackage diff --git a/hw/ip/hmac/dv copy/cryptoc_dpi/hash-internal.h b/hw/ip/hmac/dv copy/cryptoc_dpi/hash-internal.h new file mode 100644 index 0000000000000..bb89ff3c98774 --- /dev/null +++ b/hw/ip/hmac/dv copy/cryptoc_dpi/hash-internal.h @@ -0,0 +1,59 @@ +// Copyright 2016 Google Inc. +// +// 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 +// +// http://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. +#ifndef OPENTITAN_HW_IP_HMAC_DV_CRYPTOC_DPI_HASH_INTERNAL_H_ +#define OPENTITAN_HW_IP_HMAC_DV_CRYPTOC_DPI_HASH_INTERNAL_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +// SHA-384 and SHA-512 are required in some uses of cryptoc_dpi +#define SHA512_SUPPORT + +struct HASH_CTX; // forward decl + +typedef struct HASH_VTAB { + void (*const init)(struct HASH_CTX *); + void (*const update)(struct HASH_CTX *, const void *, size_t); + const uint8_t *(*const final)(struct HASH_CTX *); + const uint8_t *(*const hash)(const void *, size_t, uint8_t *); + unsigned int size; +} HASH_VTAB; + +typedef struct HASH_CTX { + const HASH_VTAB *f; + uint64_t count; +#ifndef SHA512_SUPPORT + uint8_t buf[64]; + uint32_t state[8]; // upto SHA2-256 +#else + uint8_t buf[128]; + uint64_t state[8]; // upto SHA2-512 +#endif +} HASH_CTX; + +#define HASH_init(ctx) (ctx)->f->init(ctx) +#define HASH_update(ctx, data, len) (ctx)->f->update(ctx, data, len) +#define HASH_final(ctx) (ctx)->f->final(ctx) +#define HASH_hash(data, len, digest) (ctx)->f->hash(data, len, digest) +#define HASH_size(ctx) (ctx)->f->size + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif // OPENTITAN_HW_IP_HMAC_DV_CRYPTOC_DPI_HASH_INTERNAL_H_ diff --git a/hw/ip/hmac/dv copy/cryptoc_dpi/hmac.c b/hw/ip/hmac/dv copy/cryptoc_dpi/hmac.c new file mode 100644 index 0000000000000..6030e375db5f4 --- /dev/null +++ b/hw/ip/hmac/dv copy/cryptoc_dpi/hmac.c @@ -0,0 +1,115 @@ +// Copyright 2016 Google Inc. +// +// 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 +// +// http://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. +#include "hmac.h" + +#include + +#include "sha.h" +#include "sha256.h" +#include "sha384.h" +#include "sha512.h" +#include "util.h" + +static void HMAC_init(HMAC_CTX *ctx, const void *key, unsigned int len) { + unsigned int i; + memset(&ctx->opad[0], 0, sizeof(ctx->opad)); + + if (len > sizeof(ctx->opad)) { + HASH_init(&ctx->hash); + HASH_update(&ctx->hash, key, len); + memcpy(&ctx->opad[0], HASH_final(&ctx->hash), HASH_size(&ctx->hash)); + } else { + memcpy(&ctx->opad[0], key, len); + } + + for (i = 0; i < sizeof(ctx->opad); ++i) { + ctx->opad[i] ^= 0x36; + } + + HASH_init(&ctx->hash); + HASH_update(&ctx->hash, ctx->opad, sizeof(ctx->opad)); // hash ipad + + for (i = 0; i < sizeof(ctx->opad); ++i) { + ctx->opad[i] ^= (0x36 ^ 0x5c); + } +} + +static void HMAC_init_LITE(LITE_HMAC_CTX *ctx, const void *key, + unsigned int len) { + unsigned int i; + memset(&ctx->opad[0], 0, sizeof(ctx->opad)); + + if (len > sizeof(ctx->opad)) { + HASH_init(&ctx->hash); + HASH_update(&ctx->hash, key, len); + memcpy(&ctx->opad[0], HASH_final(&ctx->hash), HASH_size(&ctx->hash)); + } else { + memcpy(&ctx->opad[0], key, len); + } + + for (i = 0; i < sizeof(ctx->opad); ++i) { + ctx->opad[i] ^= 0x36; + } + + HASH_init(&ctx->hash); + HASH_update(&ctx->hash, ctx->opad, sizeof(ctx->opad)); // hash ipad + + for (i = 0; i < sizeof(ctx->opad); ++i) { + ctx->opad[i] ^= (0x36 ^ 0x5c); + } +} + +void HMAC_SHA_init(LITE_HMAC_CTX *ctx, const void *key, unsigned int len) { + SHA_init(&ctx->hash); + HMAC_init(ctx, key, len); +} + +void HMAC_SHA256_init(LITE_HMAC_CTX *ctx, const void *key, unsigned int len) { + SHA256_init(&ctx->hash); + HMAC_init_LITE(ctx, key, len); +} + +void HMAC_SHA384_init(HMAC_CTX *ctx, const void *key, unsigned int len) { + SHA384_init(&ctx->hash); + HMAC_init(ctx, key, len); +} + +void HMAC_SHA512_init(HMAC_CTX *ctx, const void *key, unsigned int len) { + SHA512_init(&ctx->hash); + HMAC_init(ctx, key, len); +} + +const uint8_t *HMAC_final_LITE(LITE_HMAC_CTX *ctx) { + uint8_t digest[32]; // upto SHA2-256 + memcpy(digest, HASH_final(&ctx->hash), + (HASH_size(&ctx->hash) <= sizeof(digest) ? HASH_size(&ctx->hash) + : sizeof(digest))); + HASH_init(&ctx->hash); + HASH_update(&ctx->hash, ctx->opad, sizeof(ctx->opad)); + HASH_update(&ctx->hash, digest, HASH_size(&ctx->hash)); + always_memset(&ctx->opad[0], 0, sizeof(ctx->opad)); // wipe key + return HASH_final(&ctx->hash); +} + +const uint8_t *HMAC_final(HMAC_CTX *ctx) { + uint8_t digest[64]; // upto SHA2-512 + memcpy(digest, HASH_final(&ctx->hash), + (HASH_size(&ctx->hash) <= sizeof(digest) ? HASH_size(&ctx->hash) + : sizeof(digest))); + HASH_init(&ctx->hash); + HASH_update(&ctx->hash, ctx->opad, sizeof(ctx->opad)); + HASH_update(&ctx->hash, digest, HASH_size(&ctx->hash)); + always_memset(&ctx->opad[0], 0, sizeof(ctx->opad)); // wipe key + return HASH_final(&ctx->hash); +} diff --git a/hw/ip/hmac/dv copy/cryptoc_dpi/hmac.h b/hw/ip/hmac/dv copy/cryptoc_dpi/hmac.h new file mode 100644 index 0000000000000..6f968373d8d20 --- /dev/null +++ b/hw/ip/hmac/dv copy/cryptoc_dpi/hmac.h @@ -0,0 +1,51 @@ +// Copyright 2016 Google Inc. +// +// 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 +// +// http://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. +#ifndef OPENTITAN_HW_IP_HMAC_DV_CRYPTOC_DPI_HMAC_H_ +#define OPENTITAN_HW_IP_HMAC_DV_CRYPTOC_DPI_HMAC_H_ + +#include + +#include "hash-internal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct LITE_HMAC_CTX { + HASH_CTX hash; + uint8_t opad[64]; +} LITE_HMAC_CTX; + +typedef struct HMAC_CTX { + HASH_CTX hash; + uint8_t opad[128]; +} HMAC_CTX; + +void HMAC_MD5_init(LITE_HMAC_CTX *ctx, const void *key, unsigned int len); +void HMAC_SHA_init(LITE_HMAC_CTX *ctx, const void *key, unsigned int len); +void HMAC_SHA256_init(LITE_HMAC_CTX *ctx, const void *key, unsigned int len); +void HMAC_SHA384_init(HMAC_CTX *ctx, const void *key, unsigned int len); +void HMAC_SHA512_init(HMAC_CTX *ctx, const void *key, unsigned int len); + +const uint8_t *HMAC_final_LITE(LITE_HMAC_CTX *ctx); +const uint8_t *HMAC_final(HMAC_CTX *ctx); + +#define HMAC_update(ctx, data, len) HASH_update(&(ctx)->hash, data, len) +#define HMAC_size(ctx) HASH_size(&(ctx)->hash) + +#ifdef __cplusplus +} +#endif + +#endif // OPENTITAN_HW_IP_HMAC_DV_CRYPTOC_DPI_HMAC_H_ diff --git a/hw/ip/hmac/dv copy/cryptoc_dpi/hmac_wrap.c b/hw/ip/hmac/dv copy/cryptoc_dpi/hmac_wrap.c new file mode 100644 index 0000000000000..b9d358c5e7c3a --- /dev/null +++ b/hw/ip/hmac/dv copy/cryptoc_dpi/hmac_wrap.c @@ -0,0 +1,52 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#include +#include + +#include "hmac.h" +#include "sha.h" +#include "sha256.h" +#include "sha384.h" +#include "sha512.h" + +const uint8_t *HMAC_SHA(const void *key, size_t key_len, const void *msg, + size_t msg_len, uint8_t *hmac) { + LITE_HMAC_CTX ctx; + HMAC_SHA_init(&ctx, key, key_len); + // H(msg) + HMAC_update(&ctx, msg, msg_len); + memcpy(hmac, HMAC_final(&ctx), SHA_DIGEST_SIZE); + return hmac; +} + +const uint8_t *HMAC_SHA256(const void *key, size_t key_len, const void *msg, + size_t msg_len, uint8_t *hmac) { + LITE_HMAC_CTX ctx; + HMAC_SHA256_init(&ctx, key, key_len); + // H(msg) + HMAC_update(&ctx, msg, msg_len); + memcpy(hmac, HMAC_final_LITE(&ctx), SHA256_DIGEST_SIZE); + return hmac; +} + +const uint8_t *HMAC_SHA384(const void *key, size_t key_len, const void *msg, + size_t msg_len, uint8_t *hmac) { + HMAC_CTX ctx; + HMAC_SHA384_init(&ctx, key, key_len); + // H(msg) + HMAC_update(&ctx, msg, msg_len); + memcpy(hmac, HMAC_final(&ctx), SHA384_DIGEST_SIZE); + return hmac; +} + +const uint8_t *HMAC_SHA512(const void *key, size_t key_len, const void *msg, + size_t msg_len, uint8_t *hmac) { + HMAC_CTX ctx; + HMAC_SHA512_init(&ctx, key, key_len); + // H(msg) + HMAC_update(&ctx, msg, msg_len); + memcpy(hmac, HMAC_final(&ctx), SHA512_DIGEST_SIZE); + return hmac; +} diff --git a/hw/ip/hmac/dv copy/cryptoc_dpi/hmac_wrap.h b/hw/ip/hmac/dv copy/cryptoc_dpi/hmac_wrap.h new file mode 100644 index 0000000000000..65af75c6cba2b --- /dev/null +++ b/hw/ip/hmac/dv copy/cryptoc_dpi/hmac_wrap.h @@ -0,0 +1,36 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#ifndef OPENTITAN_HW_IP_HMAC_DV_CRYPTOC_DPI_HMAC_WRAP_H_ +#define OPENTITAN_HW_IP_HMAC_DV_CRYPTOC_DPI_HMAC_WRAP_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +// Compute HMAC using arbitrary length key and msg with SHA. Returns digest +// address. +const uint8_t *HMAC_SHA(const void *key, size_t key_len, const void *msg, + size_t msg_len, uint8_t *hmac); + +// Compute HMAC using arbitrary length key and msg with SHA256. Returns digest +// address. +const uint8_t *HMAC_SHA256(const void *key, size_t key_len, const void *msg, + size_t msg_len, uint8_t *hmac); + +// Compute HMAC using arbitrary length key and msg with SHA384. Returns digest +// address. +const uint8_t *HMAC_SHA384(const void *key, size_t key_len, const void *msg, + size_t msg_len, uint8_t *hmac); + +// Compute HMAC using arbitrary length key and msg with SHA512. Returns digest +// address. +const uint8_t *HMAC_SHA512(const void *key, size_t key_len, const void *msg, + size_t msg_len, uint8_t *hmac); + +#ifdef __cplusplus +} +#endif + +#endif // OPENTITAN_HW_IP_HMAC_DV_CRYPTOC_DPI_HMAC_WRAP_H_ diff --git a/hw/ip/hmac/dv copy/cryptoc_dpi/main.c b/hw/ip/hmac/dv copy/cryptoc_dpi/main.c new file mode 100644 index 0000000000000..c7707c627261c --- /dev/null +++ b/hw/ip/hmac/dv copy/cryptoc_dpi/main.c @@ -0,0 +1,102 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// Standalone command line utility to calculate the SHA2-256/384/512 of an +// input file, which may be compared directly against the output of the +// system utilities 'sha256sum', 'sha384sum' and 'sha512sum' for +// verification. +// +// Build with eg. +// gcc -o sha256 -Wall -Werror main.c sha256.c sha384.c sha512.c +// gcc -o sha384 -Wall -Werror main.c sha256.c sha384.c sha512.c +// gcc -o sha512 -Wall -Werror main.c sha256.c sha384.c sha512.c +// +// The utility simply consults the final character of its executable name +// to determine the algorithm to apply. + +#include +#include +#include +#include + +#include "sha256.h" +#ifdef SHA512_SUPPORT +#include "sha384.h" +#include "sha512.h" +#endif + +typedef enum { Opcode256, Opcode384, Opcode512 } opcode_t; + +int main(int argc, char *argv[]) { + if (argc < 2) { + fprintf(stderr, "Syntax: %s \n", argv[0]); + return 1; + } + + const char *infile = argv[1]; + FILE *out = stdout; + + const char *opc = argv[0] + strlen(argv[0]) - 1; + opcode_t opcode; + switch (*opc) { + case '2': + opcode = Opcode512; + break; + case '4': + opcode = Opcode384; + break; + default: + opcode = Opcode256; + break; + } + + FILE *in = fopen(infile, "rb"); + if (!in) { + fprintf(stderr, "Cannot open input file '%s'\n", infile); + return 2; + } + fseek(in, 0, SEEK_END); + long file_len = ftell(in); + rewind(in); + uint8_t *buf = malloc(file_len); + if (!buf) { + fprintf(stderr, "Not enough memory to load '%s' (%lu bytes required)\n", + infile, file_len); + fclose(in); + return 3; + } + fread(buf, file_len, 1, in); + fclose(in); + + uint8_t digest[64]; + unsigned digest_size = 64; + switch (opcode) { +#ifdef SHA512_SUPPORT + case Opcode512: + SHA512_hash(buf, file_len, digest); + break; + case Opcode384: + SHA384_hash(buf, file_len, digest); + digest_size = 48; + break; +#endif + default: + SHA256_hash(buf, file_len, digest); + digest_size = 32; + break; + } + + free(buf); + + for (unsigned idx = 0u; idx < digest_size; ++idx) { + static const char lower_xdigits[] = "0123456789abcdef"; + + fputc(lower_xdigits[digest[idx] >> 4], out); + fputc(lower_xdigits[digest[idx] & 0xf], out); + } + fputs(" ", out); + puts(infile); + + return 0; +} diff --git a/hw/ip/hmac/dv copy/cryptoc_dpi/sha.c b/hw/ip/hmac/dv copy/cryptoc_dpi/sha.c new file mode 100644 index 0000000000000..564ff9ee79a48 --- /dev/null +++ b/hw/ip/hmac/dv copy/cryptoc_dpi/sha.c @@ -0,0 +1,133 @@ +// Copyright 2016 Google Inc. +// +// 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 +// +// http://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. +#include "sha.h" + +#include +#include + +#define rol(bits, value) (((value) << (bits)) | ((value) >> (32 - (bits)))) + +static void SHA1_Transform(SHA_CTX *ctx) { + uint32_t W[80]; + uint32_t A, B, C, D, E; + uint8_t *p = ctx->buf; + int t; + + for (t = 0; t < 16; ++t) { + uint32_t tmp = *p++ << 24; + tmp |= *p++ << 16; + tmp |= *p++ << 8; + tmp |= *p++; + W[t] = tmp; + } + + for (; t < 80; t++) { + W[t] = rol(1, W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16]); + } + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + E = ctx->state[4]; + + for (t = 0; t < 80; t++) { + uint32_t tmp = rol(5, A) + E + W[t]; + + if (t < 20) { + tmp += (D ^ (B & (C ^ D))) + 0x5A827999; + } else if (t < 40) { + tmp += (B ^ C ^ D) + 0x6ED9EBA1; + } else if (t < 60) { + tmp += ((B & C) | (D & (B | C))) + 0x8F1BBCDC; + } else { + tmp += (B ^ C ^ D) + 0xCA62C1D6; + } + + E = D; + D = C; + C = rol(30, B); + B = A; + A = tmp; + } + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; + ctx->state[4] += E; +} + +static const HASH_VTAB SHA_VTAB = {SHA_init, SHA_update, SHA_final, SHA_hash, + SHA_DIGEST_SIZE}; + +void SHA_init(SHA_CTX *ctx) { + ctx->f = &SHA_VTAB; + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + ctx->state[4] = 0xC3D2E1F0; + ctx->count = 0; +} + +void SHA_update(SHA_CTX *ctx, const void *data, size_t len) { + unsigned int i = (unsigned int)(ctx->count & 63); + const uint8_t *p = (const uint8_t *)data; + + ctx->count += len; + + while (len--) { + ctx->buf[i++] = *p++; + if (i == 64) { + SHA1_Transform(ctx); + i = 0; + } + } +} + +const uint8_t *SHA_final(SHA_CTX *ctx) { + uint8_t *p = ctx->buf; + uint64_t cnt = ctx->count * 8; + int i; + + SHA_update(ctx, (uint8_t *)"\x80", 1); + while ((ctx->count & 63) != 56) { + SHA_update(ctx, (uint8_t *)"\0", 1); + } + for (i = 0; i < 8; ++i) { + uint8_t tmp = (uint8_t)(cnt >> 56); + cnt <<= 8; + SHA_update(ctx, &tmp, 1); + } + + for (i = 0; i < 5; i++) { + uint32_t tmp = ctx->state[i]; + *p++ = (uint8_t)(tmp >> 24); + *p++ = (uint8_t)(tmp >> 16); + *p++ = (uint8_t)(tmp >> 8); + *p++ = (uint8_t)(tmp >> 0); + } + + return ctx->buf; +} + +/* Convenience function */ +const uint8_t *SHA_hash(const void *data, size_t len, uint8_t *digest) { + SHA_CTX ctx; + SHA_init(&ctx); + SHA_update(&ctx, data, len); + memcpy(digest, SHA_final(&ctx), SHA_DIGEST_SIZE); + return digest; +} diff --git a/hw/ip/hmac/dv copy/cryptoc_dpi/sha.h b/hw/ip/hmac/dv copy/cryptoc_dpi/sha.h new file mode 100644 index 0000000000000..f907ec7acd7ec --- /dev/null +++ b/hw/ip/hmac/dv copy/cryptoc_dpi/sha.h @@ -0,0 +1,43 @@ +// Copyright 2016 Google Inc. +// +// 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 +// +// http://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. +#ifndef OPENTITAN_HW_IP_HMAC_DV_CRYPTOC_DPI_SHA_H_ +#define OPENTITAN_HW_IP_HMAC_DV_CRYPTOC_DPI_SHA_H_ + +#include + +#include "hash-internal.h" + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +typedef HASH_CTX SHA_CTX; + +void SHA_init(SHA_CTX *ctx); +void SHA_update(SHA_CTX *ctx, const void *data, size_t len); +const uint8_t *SHA_final(SHA_CTX *ctx); + +// Convenience method. Returns digest address. +// NOTE: *digest needs to hold SHA_DIGEST_SIZE bytes. +const uint8_t *SHA_hash(const void *data, size_t len, uint8_t *digest); + +#ifndef SHA_DIGEST_SIZE +#define SHA_DIGEST_SIZE 20 +#endif + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif // OPENTITAN_HW_IP_HMAC_DV_CRYPTOC_DPI_SHA_H_ diff --git a/hw/ip/hmac/dv copy/cryptoc_dpi/sha256.c b/hw/ip/hmac/dv copy/cryptoc_dpi/sha256.c new file mode 100644 index 0000000000000..21eb5f55533b2 --- /dev/null +++ b/hw/ip/hmac/dv copy/cryptoc_dpi/sha256.c @@ -0,0 +1,156 @@ +// Copyright 2016 Google Inc. +// +// 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 +// +// http://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. +#include "sha256.h" + +#include +#include + +#define ror(value, bits) (((value) >> (bits)) | ((value) << (32 - (bits)))) +#define shr(value, bits) ((value) >> (bits)) + +static const uint32_t K[64] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, + 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, + 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, + 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, + 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, + 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2}; + +static void SHA256_Transform(LITE_SHA256_CTX *ctx) { + uint32_t W[64]; + uint32_t A, B, C, D, E, F, G, H; + uint8_t *p = ctx->buf; + int t; + + for (t = 0; t < 16; ++t) { + uint32_t tmp = *p++ << 24; + tmp |= *p++ << 16; + tmp |= *p++ << 8; + tmp |= *p++; + W[t] = tmp; + } + + for (; t < 64; t++) { + uint32_t s0 = ror(W[t - 15], 7) ^ ror(W[t - 15], 18) ^ shr(W[t - 15], 3); + uint32_t s1 = ror(W[t - 2], 17) ^ ror(W[t - 2], 19) ^ shr(W[t - 2], 10); + W[t] = W[t - 16] + s0 + W[t - 7] + s1; + } + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + E = ctx->state[4]; + F = ctx->state[5]; + G = ctx->state[6]; + H = ctx->state[7]; + + for (t = 0; t < 64; t++) { + uint32_t s0 = ror(A, 2) ^ ror(A, 13) ^ ror(A, 22); + uint32_t maj = (A & B) ^ (A & C) ^ (B & C); + uint32_t t2 = s0 + maj; + uint32_t s1 = ror(E, 6) ^ ror(E, 11) ^ ror(E, 25); + uint32_t ch = (E & F) ^ ((~E) & G); + uint32_t t1 = H + s1 + ch + K[t] + W[t]; + + H = G; + G = F; + F = E; + E = D + t1; + D = C; + C = B; + B = A; + A = t1 + t2; + } + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; + ctx->state[4] += E; + ctx->state[5] += F; + ctx->state[6] += G; + ctx->state[7] += H; +} + +static const HASH_VTAB SHA256_VTAB = {SHA256_init, SHA256_update, SHA256_final, + SHA256_hash, SHA256_DIGEST_SIZE}; + +void SHA256_init(LITE_SHA256_CTX *ctx) { + ctx->f = &SHA256_VTAB; + ctx->state[0] = 0x6a09e667; + ctx->state[1] = 0xbb67ae85; + ctx->state[2] = 0x3c6ef372; + ctx->state[3] = 0xa54ff53a; + ctx->state[4] = 0x510e527f; + ctx->state[5] = 0x9b05688c; + ctx->state[6] = 0x1f83d9ab; + ctx->state[7] = 0x5be0cd19; + ctx->count = 0; +} + +void SHA256_update(LITE_SHA256_CTX *ctx, const void *data, size_t len) { + int i = (int)(ctx->count & 63); + const uint8_t *p = (const uint8_t *)data; + + ctx->count += len; + + while (len--) { + ctx->buf[i++] = *p++; + if (i == 64) { + SHA256_Transform(ctx); + i = 0; + } + } +} + +const uint8_t *SHA256_final(LITE_SHA256_CTX *ctx) { + uint8_t *p = ctx->buf; + uint64_t cnt = ctx->count * 8; + int i; + + SHA256_update(ctx, (uint8_t *)"\x80", 1); + while ((ctx->count & 63) != 56) { + SHA256_update(ctx, (uint8_t *)"\0", 1); + } + for (i = 0; i < 8; ++i) { + uint8_t tmp = (uint8_t)(cnt >> 56); + cnt <<= 8; + SHA256_update(ctx, &tmp, 1); + } + + for (i = 0; i < 8; i++) { + uint32_t tmp = ctx->state[i]; + *p++ = (uint8_t)(tmp >> 24); + *p++ = (uint8_t)(tmp >> 16); + *p++ = (uint8_t)(tmp >> 8); + *p++ = (uint8_t)(tmp >> 0); + } + + return ctx->buf; +} + +/* Convenience function */ +const uint8_t *SHA256_hash(const void *data, size_t len, uint8_t *digest) { + LITE_SHA256_CTX ctx; + SHA256_init(&ctx); + SHA256_update(&ctx, data, len); + memcpy(digest, SHA256_final(&ctx), SHA256_DIGEST_SIZE); + return digest; +} diff --git a/hw/ip/hmac/dv copy/cryptoc_dpi/sha256.h b/hw/ip/hmac/dv copy/cryptoc_dpi/sha256.h new file mode 100644 index 0000000000000..30c886522bae5 --- /dev/null +++ b/hw/ip/hmac/dv copy/cryptoc_dpi/sha256.h @@ -0,0 +1,41 @@ +// Copyright 2016 Google Inc. +// +// 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 +// +// http://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. +#ifndef OPENTITAN_HW_IP_HMAC_DV_CRYPTOC_DPI_SHA256_H_ +#define OPENTITAN_HW_IP_HMAC_DV_CRYPTOC_DPI_SHA256_H_ + +#include +#include + +#include "hash-internal.h" + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +typedef HASH_CTX LITE_SHA256_CTX; + +void SHA256_init(LITE_SHA256_CTX *ctx); +void SHA256_update(LITE_SHA256_CTX *ctx, const void *data, size_t len); +const uint8_t *SHA256_final(LITE_SHA256_CTX *ctx); + +// Convenience method. Returns digest address. +const uint8_t *SHA256_hash(const void *data, size_t len, uint8_t *digest); + +#define SHA256_DIGEST_SIZE 32 + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif // OPENTITAN_HW_IP_HMAC_DV_CRYPTOC_DPI_SHA256_H_ diff --git a/hw/ip/hmac/dv copy/cryptoc_dpi/sha384.c b/hw/ip/hmac/dv copy/cryptoc_dpi/sha384.c new file mode 100644 index 0000000000000..f0aabf70b54ac --- /dev/null +++ b/hw/ip/hmac/dv copy/cryptoc_dpi/sha384.c @@ -0,0 +1,53 @@ +// Copyright 2016 Google Inc. +// +// 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 +// +// http://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. +#include "sha384.h" + +#include +#include + +#include "sha512.h" + +#ifndef SHA512_SUPPORT +#error "-DSHA512_SUPPORT must be specified to enable SHA-384/512" +#endif + +static const HASH_VTAB SHA384_VTAB = {SHA384_init, SHA512_update, SHA512_final, + SHA384_hash, SHA384_DIGEST_SIZE}; + +void SHA384_init(LITE_SHA384_CTX *ctx) { + ctx->f = &SHA384_VTAB; + ctx->state[0] = 0xcbbb9d5dc1059ed8ll; + ctx->state[1] = 0x629a292a367cd507ll; + ctx->state[2] = 0x9159015a3070dd17ll; + ctx->state[3] = 0x152fecd8f70e5939ll; + ctx->state[4] = 0x67332667ffc00b31ll; + ctx->state[5] = 0x8eb44a8768581511ll; + ctx->state[6] = 0xdb0c2e0d64f98fa7ll; + ctx->state[7] = 0x47b5481dbefa4fa4ll; + ctx->count = 0; +} + +void SHA384_update(LITE_SHA384_CTX *ctx, const void *data, size_t len) { + SHA512_update(ctx, data, len); +} + +const uint8_t *SHA384_final(LITE_SHA384_CTX *ctx) { return SHA512_final(ctx); } + +const uint8_t *SHA384_hash(const void *data, size_t len, uint8_t *digest) { + LITE_SHA384_CTX ctx; + SHA384_init(&ctx); + SHA384_update(&ctx, data, len); + memcpy(digest, SHA384_final(&ctx), SHA384_DIGEST_SIZE); + return digest; +} diff --git a/hw/ip/hmac/dv copy/cryptoc_dpi/sha384.h b/hw/ip/hmac/dv copy/cryptoc_dpi/sha384.h new file mode 100644 index 0000000000000..1d3b5f50ae62e --- /dev/null +++ b/hw/ip/hmac/dv copy/cryptoc_dpi/sha384.h @@ -0,0 +1,41 @@ +// Copyright 2016 Google Inc. +// +// 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 +// +// http://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. +#ifndef OPENTITAN_HW_IP_HMAC_DV_CRYPTOC_DPI_SHA384_H_ +#define OPENTITAN_HW_IP_HMAC_DV_CRYPTOC_DPI_SHA384_H_ + +#include +#include + +#include "hash-internal.h" + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +typedef HASH_CTX LITE_SHA384_CTX; + +void SHA384_init(LITE_SHA384_CTX *ctx); +void SHA384_update(LITE_SHA384_CTX *ctx, const void *data, size_t len); +const uint8_t *SHA384_final(LITE_SHA384_CTX *ctx); + +// Convenience method. Returns digest address. +const uint8_t *SHA384_hash(const void *data, size_t len, uint8_t *digest); + +#define SHA384_DIGEST_SIZE 48 + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif // OPENTITAN_HW_IP_HMAC_DV_CRYPTOC_DPI_SHA384_H_ diff --git a/hw/ip/hmac/dv copy/cryptoc_dpi/sha512.c b/hw/ip/hmac/dv copy/cryptoc_dpi/sha512.c new file mode 100644 index 0000000000000..e1ef3c60d7146 --- /dev/null +++ b/hw/ip/hmac/dv copy/cryptoc_dpi/sha512.c @@ -0,0 +1,193 @@ +// Copyright 2016 Google Inc. +// +// 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 +// +// http://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. +#include "sha512.h" + +#include +#include + +#ifndef SHA512_SUPPORT +#error "-DSHA512_SUPPORT must be specified to enable SHA-384/512" +#endif + +#define ror(value, bits) (((value) >> (bits)) | ((value) << (64 - (bits)))) +#define shr(value, bits) ((value) >> (bits)) + +static const uint64_t K[80] = { + 0x428A2F98D728AE22ll, 0x7137449123EF65CDll, 0xB5C0FBCFEC4D3B2Fll, + 0xE9B5DBA58189DBBCll, 0x3956C25BF348B538ll, 0x59F111F1B605D019ll, + 0x923F82A4AF194F9Bll, 0xAB1C5ED5DA6D8118ll, 0xD807AA98A3030242ll, + 0x12835B0145706FBEll, 0x243185BE4EE4B28Cll, 0x550C7DC3D5FFB4E2ll, + 0x72BE5D74F27B896Fll, 0x80DEB1FE3B1696B1ll, 0x9BDC06A725C71235ll, + 0xC19BF174CF692694ll, 0xE49B69C19EF14AD2ll, 0xEFBE4786384F25E3ll, + 0x0FC19DC68B8CD5B5ll, 0x240CA1CC77AC9C65ll, 0x2DE92C6F592B0275ll, + 0x4A7484AA6EA6E483ll, 0x5CB0A9DCBD41FBD4ll, 0x76F988DA831153B5ll, + 0x983E5152EE66DFABll, 0xA831C66D2DB43210ll, 0xB00327C898FB213Fll, + 0xBF597FC7BEEF0EE4ll, 0xC6E00BF33DA88FC2ll, 0xD5A79147930AA725ll, + 0x06CA6351E003826Fll, 0x142929670A0E6E70ll, 0x27B70A8546D22FFCll, + 0x2E1B21385C26C926ll, 0x4D2C6DFC5AC42AEDll, 0x53380D139D95B3DFll, + 0x650A73548BAF63DEll, 0x766A0ABB3C77B2A8ll, 0x81C2C92E47EDAEE6ll, + 0x92722C851482353Bll, 0xA2BFE8A14CF10364ll, 0xA81A664BBC423001ll, + 0xC24B8B70D0F89791ll, 0xC76C51A30654BE30ll, 0xD192E819D6EF5218ll, + 0xD69906245565A910ll, 0xF40E35855771202All, 0x106AA07032BBD1B8ll, + 0x19A4C116B8D2D0C8ll, 0x1E376C085141AB53ll, 0x2748774CDF8EEB99ll, + 0x34B0BCB5E19B48A8ll, 0x391C0CB3C5C95A63ll, 0x4ED8AA4AE3418ACBll, + 0x5B9CCA4F7763E373ll, 0x682E6FF3D6B2B8A3ll, 0x748F82EE5DEFB2FCll, + 0x78A5636F43172F60ll, 0x84C87814A1F0AB72ll, 0x8CC702081A6439ECll, + 0x90BEFFFA23631E28ll, 0xA4506CEBDE82BDE9ll, 0xBEF9A3F7B2C67915ll, + 0xC67178F2E372532Bll, 0xCA273ECEEA26619Cll, 0xD186B8C721C0C207ll, + 0xEADA7DD6CDE0EB1Ell, 0xF57D4F7FEE6ED178ll, 0x06F067AA72176FBAll, + 0x0A637DC5A2C898A6ll, 0x113F9804BEF90DAEll, 0x1B710B35131C471Bll, + 0x28DB77F523047D84ll, 0x32CAAB7B40C72493ll, 0x3C9EBE0A15C9BEBCll, + 0x431D67C49C100D4Cll, 0x4CC5D4BECB3E42B6ll, 0x597F299CFC657E2All, + 0x5FCB6FAB3AD6FAECll, 0x6C44198C4A475817ll}; + +static void SHA512_Transform(LITE_SHA512_CTX *ctx) { + uint64_t W[80]; + uint64_t A, B, C, D, E, F, G, H; + uint8_t *p = ctx->buf; + int t; + + for (t = 0; t < 16; t++) { + uint64_t tmp = (uint64_t)(*p++) << 56; + tmp |= (uint64_t)(*p++) << 48; + tmp |= (uint64_t)(*p++) << 40; + tmp |= (uint64_t)(*p++) << 32; + tmp |= (uint64_t)(*p++) << 24; + tmp |= (uint64_t)(*p++) << 16; + tmp |= (uint64_t)(*p++) << 8; + tmp |= (uint64_t)(*p++); + W[t] = tmp; + } + + for (; t < 80; t++) { + uint64_t Wt2 = W[t - 2]; + uint64_t Wt7 = W[t - 7]; + uint64_t Wt15 = W[t - 15]; + uint64_t Wt16 = W[t - 16]; + + uint64_t s0 = ror(Wt15, 1) ^ ror(Wt15, 8) ^ shr(Wt15, 7); + uint64_t s1 = ror(Wt2, 19) ^ ror(Wt2, 61) ^ shr(Wt2, 6); + + W[t] = s1 + Wt7 + s0 + Wt16; + } + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + E = ctx->state[4]; + F = ctx->state[5]; + G = ctx->state[6]; + H = ctx->state[7]; + + for (t = 0; t < 80; t++) { + uint64_t s0 = ror(A, 28) ^ ror(A, 34) ^ ror(A, 39); + uint64_t maj = (A & B) ^ (A & C) ^ (B & C); + uint64_t t2 = s0 + maj; + uint64_t s1 = ror(E, 14) ^ ror(E, 18) ^ ror(E, 41); + uint64_t ch = (E & F) ^ ((~E) & G); + uint64_t t1 = H + s1 + ch + K[t] + W[t]; + + H = G; + G = F; + F = E; + E = D + t1; + D = C; + C = B; + B = A; + A = t1 + t2; + } + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; + ctx->state[4] += E; + ctx->state[5] += F; + ctx->state[6] += G; + ctx->state[7] += H; +} + +static const HASH_VTAB SHA512_VTAB = {SHA512_init, SHA512_update, SHA512_final, + SHA512_hash, SHA512_DIGEST_SIZE}; + +void SHA512_init(LITE_SHA512_CTX *ctx) { + ctx->f = &SHA512_VTAB; + ctx->state[0] = 0x6a09e667f3bcc908ll; + ctx->state[1] = 0xbb67ae8584caa73bll; + ctx->state[2] = 0x3c6ef372fe94f82bll; + ctx->state[3] = 0xa54ff53a5f1d36f1ll; + ctx->state[4] = 0x510e527fade682d1ll; + ctx->state[5] = 0x9b05688c2b3e6c1fll; + ctx->state[6] = 0x1f83d9abfb41bd6bll; + ctx->state[7] = 0x5be0cd19137e2179ll; + ctx->count = 0; +} + +void SHA512_update(LITE_SHA512_CTX *ctx, const void *data, size_t len) { + int i = (int)(ctx->count & 127); + const uint8_t *p = (const uint8_t *)data; + + ctx->count += len; + + while (len--) { + ctx->buf[i++] = *p++; + if (i == 128) { + SHA512_Transform(ctx); + i = 0; + } + } +} + +const uint8_t *SHA512_final(LITE_SHA512_CTX *ctx) { + uint8_t *p = ctx->buf; + uint64_t cnt = ctx->count * 8; + int i; + + SHA512_update(ctx, (uint8_t *)"\x80", 1); + while ((ctx->count & 127) != 112) { + SHA512_update(ctx, (uint8_t *)"\0", 1); + } + for (i = 0; i < 8; ++i) { + SHA512_update(ctx, (uint8_t *)"\0", 1); + } + for (i = 0; i < 8; ++i) { + uint8_t tmp = (uint8_t)(cnt >> 56); + cnt <<= 8; + SHA512_update(ctx, &tmp, 1); + } + + for (i = 0; i < 8; i++) { + uint64_t tmp = ctx->state[i]; + *p++ = (uint8_t)(tmp >> 56); + *p++ = (uint8_t)(tmp >> 48); + *p++ = (uint8_t)(tmp >> 40); + *p++ = (uint8_t)(tmp >> 32); + *p++ = (uint8_t)(tmp >> 24); + *p++ = (uint8_t)(tmp >> 16); + *p++ = (uint8_t)(tmp >> 8); + *p++ = (uint8_t)(tmp >> 0); + } + + return ctx->buf; +} + +/* Convenience function */ +const uint8_t *SHA512_hash(const void *data, size_t len, uint8_t *digest) { + LITE_SHA512_CTX ctx; + SHA512_init(&ctx); + SHA512_update(&ctx, data, len); + memcpy(digest, SHA512_final(&ctx), SHA512_DIGEST_SIZE); + return digest; +} diff --git a/hw/ip/hmac/dv copy/cryptoc_dpi/sha512.h b/hw/ip/hmac/dv copy/cryptoc_dpi/sha512.h new file mode 100644 index 0000000000000..b0a7216df0e4d --- /dev/null +++ b/hw/ip/hmac/dv copy/cryptoc_dpi/sha512.h @@ -0,0 +1,41 @@ +// Copyright 2016 Google Inc. +// +// 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 +// +// http://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. +#ifndef OPENTITAN_HW_IP_HMAC_DV_CRYPTOC_DPI_SHA512_H_ +#define OPENTITAN_HW_IP_HMAC_DV_CRYPTOC_DPI_SHA512_H_ + +#include +#include + +#include "hash-internal.h" + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +typedef HASH_CTX LITE_SHA512_CTX; + +void SHA512_init(LITE_SHA512_CTX *ctx); +void SHA512_update(LITE_SHA512_CTX *ctx, const void *data, size_t len); +const uint8_t *SHA512_final(LITE_SHA512_CTX *ctx); + +// Convenience method. Returns digest address. +const uint8_t *SHA512_hash(const void *data, size_t len, uint8_t *digest); + +#define SHA512_DIGEST_SIZE 64 + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif // OPENTITAN_HW_IP_HMAC_DV_CRYPTOC_DPI_SHA512_H_ diff --git a/hw/ip/hmac/dv copy/cryptoc_dpi/util.c b/hw/ip/hmac/dv copy/cryptoc_dpi/util.c new file mode 100644 index 0000000000000..64d719355ef2f --- /dev/null +++ b/hw/ip/hmac/dv copy/cryptoc_dpi/util.c @@ -0,0 +1,25 @@ +// Copyright 2016 Google Inc. +// +// 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 +// +// http://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. +#include "util.h" + +static void always_memset_impl(volatile char *s, int c, size_t n) { + while (n--) { + *s++ = c; + } +} + +void *always_memset(void *s, int c, size_t n) { + always_memset_impl(s, c, n); + return s; +} diff --git a/hw/ip/hmac/dv copy/cryptoc_dpi/util.h b/hw/ip/hmac/dv copy/cryptoc_dpi/util.h new file mode 100644 index 0000000000000..1dc783840b97a --- /dev/null +++ b/hw/ip/hmac/dv copy/cryptoc_dpi/util.h @@ -0,0 +1,23 @@ +// Copyright 2016 Google Inc. +// +// 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 +// +// http://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. +#ifndef OPENTITAN_HW_IP_HMAC_DV_CRYPTOC_DPI_UTIL_H_ +#define OPENTITAN_HW_IP_HMAC_DV_CRYPTOC_DPI_UTIL_H_ + +#include + +/* An implementation of memset that ought not to be optimized away; + * useful for scrubbing security sensitive buffers. */ +void *always_memset(void *s, int c, size_t n); + +#endif // OPENTITAN_HW_IP_HMAC_DV_CRYPTOC_DPI_UTIL_H_ diff --git a/hw/ip/hmac/dv copy/doc/tb.svg b/hw/ip/hmac/dv copy/doc/tb.svg new file mode 100644 index 0000000000000..213a51b3dac03 --- /dev/null +++ b/hw/ip/hmac/dv copy/doc/tb.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/hw/ip/hmac/dv copy/env/hmac_env.core b/hw/ip/hmac/dv copy/env/hmac_env.core new file mode 100644 index 0000000000000..3b145cc37c054 --- /dev/null +++ b/hw/ip/hmac/dv copy/env/hmac_env.core @@ -0,0 +1,51 @@ +CAPI=2: +# Copyright lowRISC contributors (OpenTitan project). +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: "lowrisc:dv:hmac_env:0.1" +description: "HMAC DV UVM environmnt" +filesets: + files_rtl: + depend: + - lowrisc:ip:hmac + files_dv: + depend: + - lowrisc:dv:ralgen + - lowrisc:dv:cip_lib + - lowrisc:dv:cryptoc_dpi:0.1 + - lowrisc:dv:test_vectors + files: + - hmac_env_pkg.sv + - hmac_if.sv + - hmac_env_cfg.sv: {is_include_file: true} + - hmac_env_cov.sv: {is_include_file: true} + - hmac_scoreboard.sv: {is_include_file: true} + - hmac_env.sv: {is_include_file: true} + - seq_lib/hmac_vseq_list.sv: {is_include_file: true} + - seq_lib/hmac_base_vseq.sv: {is_include_file: true} + - seq_lib/hmac_common_vseq.sv: {is_include_file: true} + - seq_lib/hmac_smoke_vseq.sv: {is_include_file: true} + - seq_lib/hmac_back_pressure_vseq.sv: {is_include_file: true} + - seq_lib/hmac_datapath_stress_vseq.sv: {is_include_file: true} + - seq_lib/hmac_test_vectors_hmac_vseq.sv: {is_include_file: true} + - seq_lib/hmac_long_msg_vseq.sv: {is_include_file: true} + - seq_lib/hmac_test_vectors_sha_vseq.sv: {is_include_file: true} + - seq_lib/hmac_burst_wr_vseq.sv: {is_include_file: true} + - seq_lib/hmac_error_vseq.sv: {is_include_file: true} + - seq_lib/hmac_wipe_secret_vseq.sv: {is_include_file: true} + - seq_lib/hmac_stress_all_vseq.sv: {is_include_file: true} + file_type: systemVerilogSource + +generate: + ral: + generator: ralgen + parameters: + name: hmac + ip_hjson: ../../data/hmac.hjson + +targets: + default: + filesets: + - files_dv + generate: + - ral diff --git a/hw/ip/hmac/dv copy/env/hmac_env.sv b/hw/ip/hmac/dv copy/env/hmac_env.sv new file mode 100644 index 0000000000000..3c627f2ab85f0 --- /dev/null +++ b/hw/ip/hmac/dv copy/env/hmac_env.sv @@ -0,0 +1,37 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +class hmac_env extends cip_base_env #(.CFG_T (hmac_env_cfg), + .COV_T (hmac_env_cov), + .VIRTUAL_SEQUENCER_T (hmac_virtual_sequencer), + .SCOREBOARD_T (hmac_scoreboard)); + `uvm_component_utils(hmac_env) + + // Standard SV/UVM methods + extern function new(string name="", uvm_component parent=null); + extern function void build_phase(uvm_phase phase); + extern function void end_of_elaboration_phase(uvm_phase phase); +endclass : hmac_env + + +function hmac_env::new(string name="", uvm_component parent=null); + super.new(name, parent); +endfunction : new + +function void hmac_env::build_phase(uvm_phase phase); + super.build_phase(phase); + + // config hmac virtual interface + if (!uvm_config_db#(hmac_vif)::get(this, "", "hmac_vif", cfg.hmac_vif)) begin + `uvm_fatal(`gfn, "failed to get hmac_vif from uvm_config_db") + end +endfunction : build_phase + +function void hmac_env::end_of_elaboration_phase(uvm_phase phase); + dv_base_mem mem; + super.end_of_elaboration_phase(phase); + // hmac mem supports partial write, set it after ral model is locked + `downcast(mem, get_mem_by_addr(cfg.ral, cfg.ral.get_addr_from_offset(HMAC_MSG_FIFO_BASE))) + mem.set_mem_partial_write_support(1); +endfunction : end_of_elaboration_phase diff --git a/hw/ip/hmac/dv copy/env/hmac_env_cfg.sv b/hw/ip/hmac/dv copy/env/hmac_env_cfg.sv new file mode 100644 index 0000000000000..5ee5543afffad --- /dev/null +++ b/hw/ip/hmac/dv copy/env/hmac_env_cfg.sv @@ -0,0 +1,47 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +class hmac_env_cfg extends cip_base_env_cfg #(.RAL_T(hmac_reg_block)); + `uvm_object_utils(hmac_env_cfg) + + // A flag to nofity scoreboard if digest is corrupted by wipe_secret command. + bit wipe_secret_triggered; + + // Flag to notify stress_all_with_rand_reset task that hash_process command is triggered. + // This would help trying to issue reset at specific timing during hmac hashing. + bit hash_process_triggered; + + // Randomization knob that controls how often an opportunity for save and restore is taken. 'Save + // and restore' means that on a complete block, we stop hashing, read the digest and message + // length via CSRs, disable SHA, write digest and message length back via CSRs, re-enable SHA and + // continue hashing. + int save_and_restore_pct; + + // TODO (#23562): will be removed when tackling this issue + // Flag to notify the scoreboard to skip the current message writes and don't flush its variables + bit sar_skip_ctxt = 0; + + hmac_vif hmac_vif; + + // Standard SV/UVM methods + extern function new(string name=""); + + // Class specific methods + extern function void initialize(bit [TL_AW-1:0] csr_base_addr = '1); +endclass : hmac_env_cfg + + +function hmac_env_cfg::new(string name=""); + super.new(name); +endfunction : new + +function void hmac_env_cfg::initialize(bit [TL_AW-1:0] csr_base_addr = '1); + list_of_alerts = hmac_env_pkg::LIST_OF_ALERTS; + super.initialize(csr_base_addr); + // set num_interrupts & num_alerts which will be used to create coverage and more + num_interrupts = ral.intr_state.get_n_used_bits(); + + // only support 1 outstanding TL items in tlul_adapter + m_tl_agent_cfg.max_outstanding_req = 1; +endfunction : initialize diff --git a/hw/ip/hmac/dv copy/env/hmac_env_cov.sv b/hw/ip/hmac/dv copy/env/hmac_env_cov.sv new file mode 100644 index 0000000000000..1ec87fbb46d0e --- /dev/null +++ b/hw/ip/hmac/dv copy/env/hmac_env_cov.sv @@ -0,0 +1,164 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +class hmac_env_cov extends cip_base_env_cov #(.CFG_T(hmac_env_cfg)); + `uvm_component_utils(hmac_env_cov) + + covergroup cfg_cg with function sample (bit [TL_DW-1:0] cfg); + hmac_en: coverpoint cfg[HmacEn] { + bins disabled = {1'b0}; + bins enabled = {1'b1}; + } + sha_en: coverpoint cfg[ShaEn] { + bins disabled = {1'b0}; + bins enabled = {1'b1}; + } + endian_swap : coverpoint cfg[EndianSwap]; + digest_swap : coverpoint cfg[DigestSwap]; + key_swap : coverpoint cfg[KeySwap]; + digest_size : coverpoint cfg[DigestSizeMsb:DigestSizeLsb] { + bins sha2_256 = {4'h1}; + bins sha2_384 = {4'h2}; + bins sha2_512 = {4'h4}; + bins sha2_none = {4'h8}; + bins sha2_invalid = digest_size with (!$onehot0(item)); + } + key_length: coverpoint cfg[KeyLengthMsb:KeyLengthLsb] { + bins key_128 = {6'h01}; + bins key_256 = {6'h02}; + bins key_384 = {6'h04}; + bins key_512 = {6'h08}; + bins key_1024 = {6'h10}; + bins key_none = {6'h20}; + bins key_invalid = key_length with (!$onehot0(item)); + } + cfg_cross: cross hmac_en, endian_swap, digest_swap, key_swap; + hmac_dis_x_sha_en: cross hmac_en, sha_en { + bins b0 = binsof(hmac_en.disabled) && binsof(sha_en.enabled); + } + key_x_digest_mismatch: cross key_length, digest_size { + bins b0 = binsof(key_length.key_1024) && binsof(digest_size.sha2_256); + } + key_length_x_digest_size: cross key_length, digest_size; + endgroup : cfg_cg + + covergroup status_cg with function sample (bit [TL_DW-1:0] sta, bit [TL_DW-1:0] cfg); + hmac_en : coverpoint cfg[HmacEn]; + endian_swap : coverpoint cfg[EndianSwap]; + digest_swap : coverpoint cfg[DigestSwap]; + key_swap : coverpoint cfg[KeySwap]; + sta_fifo_empty : coverpoint sta[HmacStaMsgFifoEmpty]; + sta_fifo_full : coverpoint sta[HmacStaMsgFifoFull]; + sta_fifo_depth : coverpoint sta[HmacStaMsgFifoDepthMsb:HmacStaMsgFifoDepthLsb] { + bins fifo_depth[] = {[0:2^(HmacStaMsgFifoDepthMsb+1-HmacStaMsgFifoDepthLsb)-1]}; + } + fifo_empty_cross: cross sta_fifo_empty, hmac_en, endian_swap, digest_swap, key_swap; + fifo_full_cross : cross sta_fifo_full, hmac_en, endian_swap, digest_swap, key_swap; + fifo_depth_cross: cross sta_fifo_depth, hmac_en, endian_swap, digest_swap, key_swap; + endgroup : status_cg + + covergroup err_code_cg with function sample (bit [TL_DW-1:0] err_code); + hmac_errors: coverpoint err_code { + bins no_error = {NoError}; + // This error code is not used in this version. PR #13854. + // bins push_msg_when_sha_disabled = {SwPushMsgWhenShaDisabled}; + bins hash_start_when_sha_disabled = {SwHashStartWhenShaDisabled}; + bins update_secret_key_in_process = {SwUpdateSecretKeyInProcess}; + bins hash_start_when_active = {SwHashStartWhenActive}; + bins push_msg_when_disallowed = {SwPushMsgWhenDisallowed}; + bins invalid_config = {SwInvalidConfig}; + illegal_bins illegalvalue = default; + } + endgroup : err_code_cg + + covergroup msg_len_cg with function sample (logic [TL_DW-1:0] msg_len_lower, + logic [TL_DW-1:0] msg_len_upper, + logic [TL_DW-1:0] cfg ); + hmac_en: coverpoint cfg[HmacEn]; + // Message length is byte granularity + msg_len_lower_cp: coverpoint (msg_len_lower) { + bins len_0 = {0}; // Empty message + bins len_8 = {8}; // One byte message + bins len_504 = {504}; // One block in SHA-2 256, -1 byte + bins len_512 = {512}; // One block in SHA-2 256 + bins len_520 = {520}; // One block in SHA-2 256, +1 byte + bins len_1016 = {1016}; // One block in SHA-2 384/512 or two in SHA-2 256, -1 byte + bins len_1024 = {1024}; // One block in SHA-2 384/512 or two in SHA-2 256 + bins len_1032 = {1032}; // One block in SHA-2 384/512 or two in SHA-2 256, +1 byte + bins len_2040 = {2040}; // Two blocks in SHA-2 384/512, -1 byte + bins len_2048 = {2048}; // Two blocks in SHA-2 384/512 + bins len_2056 = {2056}; // Two blocks in SHA-2 384/512, +1 byte + // Any others than the one defined above + bins len_2_510 = {[16:496]}; + bins len_514_1022 = {[528:1008]}; + bins len_1026_2046 = {[1040:2032]}; + bins len_2050_plus = {[2064:$]}; + } + // Ensure that message length upper register has been used once at least + msg_len_upper_cp: coverpoint (msg_len_upper) { + bins len_upper = {[1:$]}; + } + msg_len_lower_cross: cross hmac_en, msg_len_lower_cp; + msg_len_upper_cross: cross hmac_en, msg_len_upper_cp; + endgroup : msg_len_cg + + covergroup wr_config_during_hash_cg with function sample (logic wr_config_during_hash); + cp: coverpoint wr_config_during_hash {bins true = {1'b1};} + endgroup : wr_config_during_hash_cg + + covergroup wr_key_during_hash_cg with function sample (logic wr_key_during_hash); + cp: coverpoint wr_key_during_hash {bins true = {1'b1};} + endgroup : wr_key_during_hash_cg + + covergroup wr_key_during_sha_only_cg with function sample (logic wr_key_during_sha_only); + cp: coverpoint wr_key_during_sha_only {bins true = {1'b1};} + endgroup : wr_key_during_sha_only_cg + + covergroup wr_msg_during_hash_cg with function sample (logic wr_msg_during_hash); + cp: coverpoint wr_msg_during_hash {bins true = {1'b1};} + endgroup : wr_msg_during_hash_cg + + covergroup trig_rst_during_hash_cg with function sample (logic trig_rst_during_hash); + cp: coverpoint trig_rst_during_hash {bins true = {1'b1};} + endgroup : trig_rst_during_hash_cg + + covergroup rd_digest_during_hmac_en_cg with function sample (logic rd_digest_during_hmac_en); + cp: coverpoint rd_digest_during_hmac_en {bins true = {1'b1};} + endgroup : rd_digest_during_hmac_en_cg + + covergroup save_and_restore_cg with function sample (save_and_restore_e sar_ctxt, + bit [TL_DW-1:0] cfg); + save_and_restore_cp : coverpoint sar_ctxt { + bins same_context = {SameContext}; + bins different_context = {DifferentContext}; + bins stop_and_continue = {StopAndContinue}; + } + digest_size_cp : coverpoint cfg[DigestSizeMsb:DigestSizeLsb] { + bins sha2_256 = {4'h1}; + bins sha2_384 = {4'h2}; + bins sha2_512 = {4'h4}; + // sha2_none and sha2_invalid are not valid here + } + sar_type_x_digest_size : cross save_and_restore_cp, digest_size_cp; + endgroup : save_and_restore_cg + + // Standard SV/UVM methods + extern function new(string name, uvm_component parent); +endclass : hmac_env_cov + + +function hmac_env_cov::new(string name, uvm_component parent); + super.new(name, parent); + cfg_cg = new(); + status_cg = new(); + msg_len_cg = new(); + err_code_cg = new(); + wr_config_during_hash_cg = new(); + wr_key_during_hash_cg = new(); + wr_key_during_sha_only_cg = new(); + wr_msg_during_hash_cg = new(); + trig_rst_during_hash_cg = new(); + rd_digest_during_hmac_en_cg = new(); + save_and_restore_cg = new(); +endfunction : new diff --git a/hw/ip/hmac/dv copy/env/hmac_env_pkg.sv b/hw/ip/hmac/dv copy/env/hmac_env_pkg.sv new file mode 100644 index 0000000000000..7978f870da7b3 --- /dev/null +++ b/hw/ip/hmac/dv copy/env/hmac_env_pkg.sv @@ -0,0 +1,222 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +package hmac_env_pkg; + // dep packages + import uvm_pkg::*; + import top_pkg::*; + import dv_utils_pkg::*; + import csr_utils_pkg::*; + import tl_agent_pkg::*; + import cryptoc_dpi_pkg::*; + import dv_base_reg_pkg::*; + import cip_base_pkg::*; + import test_vectors_pkg::*; + import hmac_ral_pkg::*; + import prim_sha2_pkg::*; + + // macro includes + `include "uvm_macros.svh" + `include "dv_macros.svh" + + // local parameters and types + parameter uint32 HMAC_MSG_FIFO_DEPTH_WR = 32; + // SHA-2 256 block size = 16 32-bit words, so FIFO reading depth is up to 16 words + parameter uint32 HMAC_MSG_FIFO_DEPTH_RD_256 = 16; + // SHA-2 385/512 block size = 16 64-bit words, so FIFO reading depth is up to 32 words + parameter uint32 HMAC_MSG_FIFO_DEPTH_RD_512 = 32; + parameter uint32 HMAC_MSG_FIFO_DEPTH_BYTES = HMAC_MSG_FIFO_DEPTH_WR * 4; + parameter uint32 HMAC_MSG_FIFO_SIZE = 2048; + parameter uint32 HMAC_MSG_FIFO_BASE = 32'h1000; + parameter uint32 HMAC_MSG_FIFO_LAST_ADDR = HMAC_MSG_FIFO_BASE + HMAC_MSG_FIFO_SIZE - 1; + parameter uint32 HMAC_BLK_SIZE_SHA2_256 = 512/8; // Nb bytes + parameter uint32 HMAC_BLK_SIZE_SHA2_384_512 = 1024/8; // Nb bytes + + // 48 cycles of hashing, 16 cycles to rd next 16 words, 1 cycle to update digest + parameter uint32 HMAC_MSG_PROCESS_CYCLES_256 = 65; + parameter uint32 HMAC_MSG_PROCESS_CYCLES_512 = 81; + // 80 (64+16) cycles for hmac key padding for SHA-2 256 + parameter uint32 HMAC_KEY_PROCESS_CYCLES_256 = 80; + // 112 (80+32) cycles for hmac key padding for SHA-2 384/512 + parameter uint32 HMAC_KEY_PROCESS_CYCLES_512 = 112; + // 1 cycles to write a msg word to hmac_msg_fifo + parameter uint32 HMAC_WR_WORD_CYCLE = 1; + + parameter uint NUM_DIGESTS = 16; + parameter uint NUM_KEYS = 32; + + // alerts + parameter uint NUM_ALERTS = 1; + parameter string LIST_OF_ALERTS[] = {"fatal_fault"}; + + // HMAC interrupt register indices + typedef enum int { + HmacDone = 0, + HmacMsgFifoEmpty = 1, + HmacErr = 2 + } hmac_intr_e; + + // HMAC status register indices + typedef enum int { + HmacStaIdle = 0, + HmacStaMsgFifoEmpty = 1, + HmacStaMsgFifoFull = 2, + HmacStaMsgFifoDepthLsb = 4, + HmacStaMsgFifoDepthMsb = 9 + } hmac_sta_e; + + // HMAC cfg register indices + typedef enum int { + HmacEn = 0, + ShaEn = 1, + EndianSwap = 2, + DigestSwap = 3, + KeySwap = 4, + DigestSizeLsb = 5, + DigestSizeMsb = 8, + KeyLengthLsb = 9, + KeyLengthMsb = 14 + } hmac_cfg_e; + + // HMAC cmd register indices + typedef enum int { + HashStart = 0, + HashProcess = 1, + HashStop = 2, + HashContinue = 3 + } hmac_cmd_e; + + typedef enum int { + NoError = 0, + SwPushMsgWhenShaDisabled = 1, + SwHashStartWhenShaDisabled = 2, + SwUpdateSecretKeyInProcess = 3, + SwHashStartWhenActive = 4, + SwPushMsgWhenDisallowed = 5, + SwInvalidConfig = 6 + } err_code_e; + + // Enum for the timing when issue wipe_secret CSR. + typedef enum bit [2:0] { + NoWipeSecret, + WipeSecretBeforeKey, + WipeSecretBeforeStart, + WipeSecretBeforeProcess, + WipeSecretBeforeDone + } wipe_secret_req_e; + + typedef enum int { + SameContext = 0, + DifferentContext = 1, + StopAndContinue = 2 + } save_and_restore_e; + + typedef class hmac_env_cfg; + typedef class hmac_env_cov; + typedef cip_base_virtual_sequencer #(hmac_env_cfg, hmac_env_cov) hmac_virtual_sequencer; + typedef virtual pins_if #(1) d2h_a_ready_vif; + typedef uvm_object_string_pool #(uvm_event) uvm_event_sar_pool; + + // functions + function automatic int get_digest_index(string csr_name); + case (csr_name) + "digest_0": return 0; + "digest_1": return 1; + "digest_2": return 2; + "digest_3": return 3; + "digest_4": return 4; + "digest_5": return 5; + "digest_6": return 6; + "digest_7": return 7; + "digest_8": return 8; + "digest_9": return 9; + "digest_10": return 10; + "digest_11": return 11; + "digest_12": return 12; + "digest_13": return 13; + "digest_14": return 14; + "digest_15": return 15; + default: `uvm_fatal("get_digest_index", $sformatf("invalid digest csr name: %0s", csr_name)) + endcase + endfunction + + function automatic int get_key_index(string csr_name); + case (csr_name) + "key_0": return 0; + "key_1": return 1; + "key_2": return 2; + "key_3": return 3; + "key_4": return 4; + "key_5": return 5; + "key_6": return 6; + "key_7": return 7; + "key_8": return 8; + "key_9": return 9; + "key_10": return 10; + "key_11": return 11; + "key_12": return 12; + "key_13": return 13; + "key_14": return 14; + "key_15": return 15; + "key_16": return 16; + "key_17": return 17; + "key_18": return 18; + "key_19": return 19; + "key_20": return 20; + "key_21": return 21; + "key_22": return 22; + "key_23": return 23; + "key_24": return 24; + "key_25": return 25; + "key_26": return 26; + "key_27": return 27; + "key_28": return 28; + "key_29": return 29; + "key_30": return 30; + "key_31": return 31; + default: `uvm_fatal("get_key_index", $sformatf("invalid key csr name: %0s", csr_name)) + endcase + endfunction + + function automatic int get_key_length(int key_length_reg); + case (key_length_reg) + 'h01: return 128; // 128-bit secret key + 'h02: return 256; // 256-bit secret key + 'h04: return 384; // 384-bit secret key + 'h08: return 512; // 512-bit secret key + 'h10: return 1024; // 1024-bit secret key + default: return 0; // Unsupported/invalid/all-zero values are mapped to Key_None + endcase + endfunction : get_key_length + + function automatic string get_digest_size(int digest_size_reg); + case (digest_size_reg) + 'h01: return "SHA2_256"; // SHA-2 256 digest + 'h02: return "SHA2_384"; // SHA-2 384 digest + 'h04: return "SHA2_512"; // SHA-2 512 digest + 'h08: return "SHA2_None"; // Unsupported/invalid values and all-zero values + default: return "SHA2_None"; + endcase + endfunction : get_digest_size + + // Return block size in bits according to the digest size + function automatic int get_block_size(int digest_size_reg); + case (digest_size_reg) + 'h01: return HMAC_BLK_SIZE_SHA2_256*8; // SHA-2 256: 512-bit block + 'h02: return HMAC_BLK_SIZE_SHA2_384_512*8; // SHA-2 384: 1024-bit block + 'h04: return HMAC_BLK_SIZE_SHA2_384_512*8; // SHA-2 512: 1024-bit block + 'h08: return 0; // Unsupported/invalid and all-zero values + default: return 0; + endcase + endfunction : get_block_size + + typedef virtual hmac_if hmac_vif; + + // package sources + `include "hmac_env_cfg.sv" + `include "hmac_env_cov.sv" + `include "hmac_scoreboard.sv" + `include "hmac_env.sv" + `include "hmac_vseq_list.sv" +endpackage diff --git a/hw/ip/hmac/dv copy/env/hmac_if.sv b/hw/ip/hmac/dv copy/env/hmac_if.sv new file mode 100644 index 0000000000000..e82e0871bb03b --- /dev/null +++ b/hw/ip/hmac/dv copy/env/hmac_if.sv @@ -0,0 +1,13 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// A lightweight interface to sample idle signal. +interface hmac_if(input clk_i, input rst_ni); + prim_mubi_pkg::mubi4_t idle; + + function automatic bit is_idle(); + return (idle == prim_mubi_pkg::MuBi4True); + endfunction + +endinterface diff --git a/hw/ip/hmac/dv copy/env/hmac_scoreboard.sv b/hw/ip/hmac/dv copy/env/hmac_scoreboard.sv new file mode 100644 index 0000000000000..e4f8e216e6f95 --- /dev/null +++ b/hw/ip/hmac/dv copy/env/hmac_scoreboard.sv @@ -0,0 +1,945 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +class hmac_scoreboard extends cip_base_scoreboard #(.CFG_T (hmac_env_cfg), + .RAL_T (hmac_reg_block), + .COV_T (hmac_env_cov)); + `uvm_component_utils(hmac_scoreboard) + + bit sha_en, hmac_idle; + bit [7:0] msg_q[$]; + bit [7:0] msg_part_q[$]; // Queue containing piece of the message if HASH is interrupted + bit hmac_start, hmac_process, hmac_stopped, hmac_continue; + int hmac_wr_cnt, hmac_rd_cnt; + int fifo_rd_depth; + int block_process_cycles; + int key_process_cycles; + bit [TL_DW-1:0] key[NUM_KEYS]; + bit [TL_DW-1:0] exp_digest[NUM_DIGESTS]; + bit [3:0] previous_digest_size, expected_digest_size; + bit invalid_cfg; + bit [TL_DW-1:0] hmac_status_data; + bit [5:0] hmac_fifo_depth; + bit hmac_fifo_full; + bit fifo_full_detected; + bit hmac_fifo_empty; + bit fifo_empty_intr; + bit hmac_process_last; + bit hmac_stopped_last; + bit hmac_start_last; + bit hmac_continue_last; + bit [TL_DW-1:0] intr_test; + bit [TL_DW-1:0] intr_state_exp; + + // Standard SV/UVM methods + extern function new(string name="", uvm_component parent=null); + extern function void build_phase(uvm_phase phase); + extern task run_phase(uvm_phase phase); + extern function void check_phase(uvm_phase phase); + + // Class specific methods + // Update predicted digest to RAL mirrored value + extern virtual task process_tl_access(tl_seq_item item, tl_channels_e channel, string ral_name); + // Reset some variables in case of a reset is happening + extern virtual function void reset(string kind = "HARD"); + // Clear some variables after hmac_done/invalid_config + extern virtual function void flush(); + // Model of the message FIFO when is written + extern virtual task hmac_process_fifo_wr(); + // Model of the message FIFO when is read + extern virtual task hmac_process_fifo_rd(); + // Model the status of the message FIFO + extern virtual task hmac_process_fifo_status(); + // Spawn process to check interrupt pins in test mode + extern virtual task hmac_intr_test(); + // Check interrupt pins in test mode + extern virtual task hmac_intr_test_pin(int intr_i); + // Query SHA/HMAC to the C model to get expected digest + extern virtual function void predict_digest(bit [7:0] msg_i[], bit use_gmv = 1, bit sha_en = 0, + bit hmac_en = 0, bit [3:0] digest_size = 0, bit [5:0] key_length = 0); + // Update the write message length + extern virtual function void update_wr_msg_length(int size_bytes); + // Model the interrupt code error + extern virtual task update_err_intr_code(err_code_e err_code_val); + // Check idle output pin and update status register predicted value + extern virtual function void check_idle(bit val); + // Trigger coverage sampling + extern virtual task monitor_cov(); +endclass : hmac_scoreboard + + +function hmac_scoreboard::new(string name="", uvm_component parent=null); + super.new(name, parent); +endfunction : new + +function void hmac_scoreboard::build_phase(uvm_phase phase); + super.build_phase(phase); +endfunction : build_phase + +task hmac_scoreboard::run_phase(uvm_phase phase); + super.run_phase(phase); + wait(cfg.under_reset); + forever begin + wait(!cfg.under_reset); + // This isolation fork is needed to ensure that "disable fork" call won't kill any other + // processes at the same level from the base classes + fork begin : isolation_fork + fork + begin : main_thread + fork + hmac_process_fifo_status(); + hmac_process_fifo_wr(); + hmac_process_fifo_rd(); + hmac_intr_test(); + monitor_cov(); + join + wait fork; // To ensure it will be killed only when the reset will occur + end + begin : reset_thread + wait(cfg.under_reset); + end + join_any + disable fork; // Terminates all descendants and sub-descendants of isolation_fork + end join + end +endtask : run_phase + +task hmac_scoreboard::process_tl_access(tl_seq_item item, tl_channels_e channel, string ral_name); + uvm_reg csr; + string csr_name; + bit do_read_check = 1'b1; + bit do_cycle_accurate_check = 1'b1; + bit write = item.is_write(); + bit [TL_AW-1:0] addr_mask = ral.get_addr_mask(); + uvm_reg_addr_t csr_addr = cfg.ral_models[ral_name].get_word_aligned_addr(item.a_addr); + + // if access was to a valid csr, get the csr handle + if (csr_addr inside {cfg.ral_models[ral_name].csr_addrs}) begin + csr = cfg.ral_models[ral_name].default_map.get_reg_by_offset(csr_addr); + `DV_CHECK_NE_FATAL(csr, null) + csr_name = csr.get_name(); + // if addr inside msg fifo, no ral model + end else if (!((item.a_addr & addr_mask) inside {[HMAC_MSG_FIFO_BASE : + HMAC_MSG_FIFO_LAST_ADDR]})) begin + `uvm_fatal(`gfn, $sformatf("Access unexpected addr 0x%0h", csr_addr)) + end + + // if incoming access is a write to a valid csr or mem, then update right away on addr channel + if (write && channel == AddrChannel) begin + // push the msg into msg_fifo + if ((item.a_addr & addr_mask) inside {[HMAC_MSG_FIFO_BASE : HMAC_MSG_FIFO_LAST_ADDR]}) begin + // Only push message into the FIFO when intended, as in case of S&R triggered with another + // context, we don't want to process the message of this other context. + if (!cfg.sar_skip_ctxt) begin + if ((!sha_en) || (!hmac_start && !hmac_continue)) begin + update_err_intr_code(SwPushMsgWhenDisallowed); + end else if (!cfg.under_reset) begin + bit [7:0] bytes[4]; + bit [7:0] msg[$]; + // Register coverage for the fact that a write occurs to the message FIFO during + // a compression round + if (cfg.en_cov) cov.wr_msg_during_hash_cg.sample(1); + {< msg_q.size()) begin + msg_slice_length = msg_q.size(); + end + + // Push partial message into a new queue to be processed by the digest predictor + for (int i=0; i= (hmac_wr_cnt + 1) * 4 || (hmac_process && msg_q.size() > 0)); + // Ensure that current context has to be taken into account or skipped + if (cfg.sar_skip_ctxt) begin + wait(!cfg.sar_skip_ctxt); + end + // if hmac process is issued and there are still unprocessed word (can hold up to at + // most one word), then the hmac_wr_cnt will increment + // if all the written msgs have been process, will skip the counter incrementation + if (hmac_process) begin + if (msg_q.size() <= hmac_wr_cnt * 4) begin + has_unprocessed_msg = 0; + end + msg_q.delete(); + msg_part_q.delete(); + end + if (sha_en && has_unprocessed_msg) begin + // if fifo full, tlul will not write next data until fifo has space again + if ((hmac_wr_cnt - hmac_rd_cnt) == HMAC_MSG_FIFO_DEPTH_WR) begin + wait((hmac_wr_cnt - hmac_rd_cnt) < HMAC_MSG_FIFO_DEPTH_WR); + end + @(negedge cfg.clk_rst_vif.clk); + if (!hmac_stopped) begin + hmac_wr_cnt++; + `uvm_info(`gfn, $sformatf("increase wr cnt %0d", hmac_wr_cnt), UVM_HIGH) + cfg.clk_rst_vif.wait_clks(HMAC_WR_WORD_CYCLE); + end + end + end +endtask : hmac_process_fifo_wr + +task hmac_scoreboard::hmac_process_fifo_status(); + bit pre_fifo_empty_intr; + forever @(hmac_wr_cnt, hmac_rd_cnt, hmac_process, hmac_start, hmac_stopped, hmac_continue) begin + // Store hmac_process and hmac_start to be able to detect when it goes up, as it could remain + // up for a while + bit hmac_process_posedge = hmac_process & ~hmac_process_last; + bit hmac_start_posedge = hmac_start & ~hmac_start_last; + bit hmac_stopped_posedge = hmac_stopped & ~hmac_stopped_last; + bit hmac_continue_posedge = hmac_continue & ~hmac_continue_last; + + // Store last value to be able to detect signal change + hmac_process_last = hmac_process; + hmac_stopped_last = hmac_stopped; + hmac_start_last = hmac_start; + hmac_continue_last = hmac_continue; + + // when hmac_wr_cnt and hmac_rd_cnt update at the same time, wait the clock rising edge + // to guarantee get both update and at the same time as the DUT + cfg.clk_rst_vif.wait_clks(1); + + // Compute FIFO level flags + hmac_fifo_depth = hmac_wr_cnt - hmac_rd_cnt; + hmac_fifo_full = hmac_fifo_depth == HMAC_MSG_FIFO_DEPTH_WR; + hmac_fifo_empty = hmac_fifo_depth == 0; + + // The FIFO empty interrupt is raised only if the message FIFO is actually writable by + // software, i.e., if all of the following conditions are met: + // 1- The HMAC block is not running in HMAC mode and performing the second round of + // computing the final hash of the outer key as well as the result of the first round + // using the inner key. + // 2- Software has not yet written the Process or Stop command to finish the hashing + // operation. + // 3- The message FIFO must also have been full previously. Otherwise, the hardware empties + // the FIFO faster than software can fill it and there is no point in interrupting the + // software to inform it about the message FIFO being empty. + if (fifo_full_detected && hmac_fifo_empty) begin + pre_fifo_empty_intr = 1; + end else begin + pre_fifo_empty_intr = 0; + end + + // Delay FIFO empty signal to be aligned with the DUT behavior + fork + begin + cfg.clk_rst_vif.wait_clks(1); + fifo_empty_intr = pre_fifo_empty_intr; + end + join_none + + // Check whether FIFO full has been detected for the ongoing message but the retrictions cases + // have the priority in case full is set at the same moment + if (hmac_fifo_empty || hmac_start_posedge || hmac_process_posedge || + hmac_stopped_posedge || hmac_continue_posedge) begin + fifo_full_detected = 0; + end else if (hmac_fifo_full) begin + fifo_full_detected = 1; + end + end +endtask : hmac_process_fifo_status + +// Spawn process to check interrupt pins in test mode +task hmac_scoreboard::hmac_intr_test(); + foreach (intr_test[intr_i]) begin + fork begin + hmac_intr_test_pin(intr_i); + end join_none + end +endtask : hmac_intr_test + +// Check interrupt pins in test mode +task hmac_scoreboard::hmac_intr_test_pin(int intr_i); + bit [TL_DW-1:0] intr_en; + hmac_intr_e intr = hmac_intr_e'(intr_i); + forever @(intr_test[intr_i]) begin + intr_en = `gmv(ral.intr_enable); + if (intr_test[intr_i]) begin + // Check interrupt state pins only if enabled + if (intr_en[intr_i]) begin + fork: intr_pins + begin + wait(cfg.intr_vif.pins[intr_i]); + `uvm_info(`gfn, $sformatf("Detected interrupt on pin %s", intr.name()), UVM_HIGH) + end + begin + cfg.clk_rst_vif.wait_clks(100); // 100 clk cycles timeout + `uvm_error(`gfn, $sformatf("Wait pin interrupt timeout for %s", intr.name())) + end + join_any + disable fork; + end + end + end +endtask : hmac_intr_test_pin + +// internal msg_fifo model to check fifo status and interrupt. +// monitor rd_cnt and wr_cnt on the negedge of the clk +// rd_cnt followed by wr_cnt with a clk cycle delay, except: +// 1). hmac process key: DUT will process the key first +// 2). read cnt reaches FIFO_MAX: DUT will process msg in the FIFO +task hmac_scoreboard::hmac_process_fifo_rd(); + bit key_processed = 0; + fork + begin : process_hmac_key_pad + forever begin + cfg.clk_rst_vif.wait_clks(1); + // Key padding + wait(hmac_start && sha_en); + if (`gmv(ral.cfg.hmac_en) && hmac_rd_cnt == 0 && !invalid_cfg) begin + if (`gmv(ral.cfg.digest_size) == SHA2_256) begin + key_process_cycles = HMAC_KEY_PROCESS_CYCLES_256; + end else begin + key_process_cycles = HMAC_KEY_PROCESS_CYCLES_512; + end + // key_process_cycles for hmac key padding + 1 cycle for hash_start reg to reset + cfg.clk_rst_vif.wait_clks(key_process_cycles + 1); + @(negedge cfg.clk_rst_vif.clk); + key_processed = 1; + end + while (1) begin + // TODO: check if we need the error checking here - might not be necessary + // break if hmac is done or if invalid config error is triggered or if SHA is + // being disabled as HMAC enable configuration could be changed and thus + // key_process_cycles might need to be updated + if (`gmv(ral.intr_state.hmac_done) || + (`gmv(ral.intr_state.hmac_err) && `gmv(ral.err_code) == SwInvalidConfig) || + !sha_en) begin + break; + end + cfg.clk_rst_vif.wait_clks(1); + end + key_processed = 0; + end + end + + begin : process_internal_fifo_rd + forever begin + // Ensure that current context has to be taken into account or skipped + if (cfg.sar_skip_ctxt) begin + wait(!cfg.sar_skip_ctxt); + end + wait((hmac_wr_cnt > hmac_rd_cnt) && (sha_en)); + if (`gmv(ral.cfg.hmac_en) && hmac_rd_cnt == 0) begin + `uvm_info(`gfn, $sformatf("waiting on key processing to complete"), UVM_HIGH) + wait(key_processed); + `uvm_info(`gfn, $sformatf("key processing has completed"), UVM_HIGH) + end + #1ps; // delay 1 ps to make sure did not sample right at negedge clk + cfg.clk_rst_vif.wait_n_clks(1); + hmac_rd_cnt++; + `uvm_info(`gfn, $sformatf("increase rd cnt %0d", hmac_rd_cnt), UVM_HIGH) + // select correct FIFO read depth and message processing cycles + if (`gmv(ral.cfg.digest_size) == SHA2_256) begin + fifo_rd_depth = HMAC_MSG_FIFO_DEPTH_RD_256; + block_process_cycles = HMAC_MSG_PROCESS_CYCLES_256; + end else begin + fifo_rd_depth = HMAC_MSG_FIFO_DEPTH_RD_512; + block_process_cycles = HMAC_MSG_PROCESS_CYCLES_512; + end + if (hmac_rd_cnt % fifo_rd_depth == 0) begin + `uvm_info(`gfn, $sformatf("start waiting on message processing now"), UVM_HIGH) + cfg.clk_rst_vif.wait_n_clks(block_process_cycles); + `uvm_info(`gfn, $sformatf("message processing has completed"), UVM_HIGH) + end + end + end + join_none +endtask : hmac_process_fifo_rd + +function void hmac_scoreboard::check_phase(uvm_phase phase); + super.check_phase(phase); + `DV_CHECK_EQ(cfg.intr_vif.pins[HmacMsgFifoEmpty], 1'b0) + `DV_CHECK_EQ(cfg.intr_vif.pins[HmacDone], 1'b0) + `DV_CHECK_EQ(cfg.intr_vif.pins[HmacErr], 1'b0) +endfunction : check_phase + +// query the sha / hmac c model to get expected digest +// update predicted digest to ral mirrored value +function void hmac_scoreboard::predict_digest( + bit [7:0] msg_i[], + bit use_gmv = 1, + bit sha_en = 0, + bit hmac_en = 0, + bit [3:0] digest_size = 0, + bit [5:0] key_length = 0); + + bit [7:0] msg_tmp[]; + bit [TL_DW-1:0] big_endian_key[NUM_KEYS]; + + // Use mirrored values, otherwise take values from the arguments + if (use_gmv) begin + sha_en = `gmv(ral.cfg.sha_en); + hmac_en = `gmv(ral.cfg.hmac_en); + digest_size = `gmv(ral.cfg.digest_size); + key_length = `gmv(ral.cfg.key_length); + end + + exp_digest = '{default:0}; // clear previous expected digest + + // Swap the key when required according to the dedicated register field CFG.key_swap + if (`gmv(ral.cfg.key_swap)) begin + `uvm_info(`gfn, "Swap the key from little-endian to big-endian", UVM_HIGH) + foreach (big_endian_key[key_i]) begin + big_endian_key[key_i] = {<<8{key[key_i]}}; + end + end else begin + `uvm_info(`gfn, "Keep the key in big-endian", UVM_HIGH) + big_endian_key = key; + end + + `uvm_info(`gfn, $sformatf("Computing digest prediction"), UVM_LOW) + + // TODO: predict even if sha_en == 0? + case ({hmac_en, sha_en}) + 2'b11: begin + if (digest_size == SHA2_256) begin + if (key_length == Key_128) begin + cryptoc_dpi_pkg::sv_dpi_get_hmac_sha256(big_endian_key[0:3], msg_i, exp_digest[0:7]); + end else if (key_length == Key_256) begin + cryptoc_dpi_pkg::sv_dpi_get_hmac_sha256(big_endian_key[0:7], msg_i, exp_digest[0:7]); + end else if (key_length == Key_384) begin + cryptoc_dpi_pkg::sv_dpi_get_hmac_sha256(big_endian_key[0:11], msg_i, exp_digest[0:7]); + end else if (key_length == Key_512) begin + cryptoc_dpi_pkg::sv_dpi_get_hmac_sha256(big_endian_key[0:15], msg_i, exp_digest[0:7]); + end else if (key_length == Key_1024) begin + // model how the HW will limit key length to max of block size + cryptoc_dpi_pkg::sv_dpi_get_hmac_sha256(big_endian_key[0:15], msg_i, exp_digest[0:7]); + end + end else if (digest_size == SHA2_384) begin + if (key_length == Key_128) cryptoc_dpi_pkg::sv_dpi_get_hmac_sha384( + big_endian_key[0:3], msg_i, exp_digest[0:11]); + if (key_length == Key_256) cryptoc_dpi_pkg::sv_dpi_get_hmac_sha384( + big_endian_key[0:7], msg_i, exp_digest[0:11]); + if (key_length == Key_384) cryptoc_dpi_pkg::sv_dpi_get_hmac_sha384( + big_endian_key[0:11], msg_i, exp_digest[0:11]); + if (key_length == Key_512) cryptoc_dpi_pkg::sv_dpi_get_hmac_sha384( + big_endian_key[0:15], msg_i, exp_digest[0:11]); + if (key_length == Key_1024) cryptoc_dpi_pkg::sv_dpi_get_hmac_sha384( + big_endian_key[0:31], msg_i, exp_digest[0:11]); + end else if (digest_size == SHA2_512) begin + if (key_length == Key_128) cryptoc_dpi_pkg::sv_dpi_get_hmac_sha512( + big_endian_key[0:3], msg_i, exp_digest); + if (key_length == Key_256) cryptoc_dpi_pkg::sv_dpi_get_hmac_sha512( + big_endian_key[0:7], msg_i, exp_digest); + if (key_length == Key_384) cryptoc_dpi_pkg::sv_dpi_get_hmac_sha512( + big_endian_key[0:11], msg_i, exp_digest); + if (key_length == Key_512) cryptoc_dpi_pkg::sv_dpi_get_hmac_sha512( + big_endian_key[0:15], msg_i, exp_digest); + if (key_length == Key_1024) cryptoc_dpi_pkg::sv_dpi_get_hmac_sha512( + big_endian_key[0:31], msg_i, exp_digest); + end + `uvm_info(`gfn, $sformatf("HMAC of key=%p (key_swap=%1b), msg_i=%p: %p", + key, `gmv(ral.cfg.key_swap), msg_i, exp_digest), UVM_LOW) + end + 2'b01: begin + if (digest_size == SHA2_256) begin + cryptoc_dpi_pkg::sv_dpi_get_sha256_digest(msg_i, exp_digest[0:7]); + end else if (digest_size == SHA2_384) begin + cryptoc_dpi_pkg::sv_dpi_get_sha384_digest(msg_i, exp_digest[0:11]); + end else if (digest_size == SHA2_512) begin + cryptoc_dpi_pkg::sv_dpi_get_sha512_digest(msg_i, exp_digest); + end + `uvm_info(`gfn, $sformatf("SHA-2 digest of msg_i=%p: %p", msg_i, exp_digest), UVM_LOW) + end + default: begin + // disgest is cleared if sha_en = 0 + exp_digest = '{default:0}; + end + endcase +endfunction : predict_digest + +function void hmac_scoreboard::update_wr_msg_length(int size_bytes); + uint64 size_bits = size_bytes * 8; + void'(ral.msg_length_upper.predict(size_bits[TL_DW*2-1:TL_DW])); + void'(ral.msg_length_lower.predict(size_bits[TL_DW-1:0])); +endfunction : update_wr_msg_length + +task hmac_scoreboard::update_err_intr_code(err_code_e err_code_val); + if (!`gmv(ral.intr_state.hmac_err)) begin + while (ral.intr_state.is_busy()) begin + // using cfg.clk_rst_vif.wait_clks(1) instead was still resulting in race conditions with + // the incrementing of hmac_rd_cnt and hmac_wr_cnt and a desynchronization + #1ps; + end + void'(ral.intr_state.hmac_err.predict(.value(1), .kind(UVM_PREDICT_DIRECT))); + + while (ral.err_code.is_busy()) begin + // using cfg.clk_rst_vif.wait_clks(1) instead was still resulting in race conditions with + // the incrementing of hmac_rd_cnt and hmac_wr_cnt and a desynchronization + #1ps; + end + void'(ral.err_code.predict(.value(err_code_val), .kind(UVM_PREDICT_DIRECT))); + end +endtask : update_err_intr_code + +// Check idle output pin and update status register predicted value +function void hmac_scoreboard::check_idle(bit val); + if (cfg.under_reset == 0) begin + `DV_CHECK_EQ(cfg.hmac_vif.is_idle(), val) + end + hmac_idle = val; + void'(ral.status.hmac_idle.predict(.value(hmac_idle), .kind(UVM_PREDICT_READ))); +endfunction : check_idle + +task hmac_scoreboard::monitor_cov(); + save_and_restore_e sar_ctxt; + uvm_event sar_same_ctxt_ev; + uvm_event sar_different_ctxt_ev; + uvm_event sar_stop_continue_ev; + sar_same_ctxt_ev = uvm_event_sar_pool::get_global("sar_same_context_event"); + sar_different_ctxt_ev = uvm_event_sar_pool::get_global("sar_different_context_event"); + sar_stop_continue_ev = uvm_event_sar_pool::get_global("sar_stop_and_continue_event"); + + fork + // Save and Restore with same context + begin + forever begin + sar_same_ctxt_ev.wait_trigger(); + if (cfg.en_cov) cov.save_and_restore_cg.sample(.sar_ctxt(SameContext), + .cfg(`gmv(ral.cfg))); + end + end + // Save and Restore with different contexts + begin + forever begin + sar_different_ctxt_ev.wait_trigger(); + if (cfg.en_cov) cov.save_and_restore_cg.sample(.sar_ctxt(DifferentContext), + .cfg(`gmv(ral.cfg))); + end + end + // Stop and Continue without Saving and Restoring + begin + forever begin + sar_stop_continue_ev.wait_trigger(); + if (cfg.en_cov) cov.save_and_restore_cg.sample(.sar_ctxt(StopAndContinue), + .cfg(`gmv(ral.cfg))); + end + end + join_none +endtask : monitor_cov diff --git a/hw/ip/hmac/dv copy/env/seq_lib/hmac_back_pressure_vseq.sv b/hw/ip/hmac/dv copy/env/seq_lib/hmac_back_pressure_vseq.sv new file mode 100644 index 0000000000000..06c5e2910654d --- /dev/null +++ b/hw/ip/hmac/dv copy/env/seq_lib/hmac_back_pressure_vseq.sv @@ -0,0 +1,43 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// This sequence generates back-pressure seq +// The sequence disabled all the rand delay and optional reg checkings + +class hmac_back_pressure_vseq extends hmac_smoke_vseq; + `uvm_object_utils(hmac_back_pressure_vseq) + + // Constraints + extern constraint msg_c; + extern constraint wr_mask_c; + + // Standard SV/UVM methods + extern function new(string name=""); + extern task pre_start(); +endclass : hmac_back_pressure_vseq + + +constraint hmac_back_pressure_vseq::msg_c { + msg.size() dist { + [129 :999] :/ 1, // larger than input FIFO depth + [1000 :3000] :/ 8, // 1KB - 2KB according to SW immediate usage + [3001 :10_000] :/ 1 // temp set to 10KB as max length, spec max size is 2^64 bits + }; +} + +constraint hmac_back_pressure_vseq::wr_mask_c { + $countones(wr_mask) dist { + TL_DBW :/ 9, + [1:TL_DBW-1] :/ 1 + }; +} + +function hmac_back_pressure_vseq::new(string name=""); + super.new(name); +endfunction : new + +task hmac_back_pressure_vseq::pre_start(); + do_back_pressure = 1'b1; + super.pre_start(); +endtask : pre_start diff --git a/hw/ip/hmac/dv copy/env/seq_lib/hmac_base_vseq.sv b/hw/ip/hmac/dv copy/env/seq_lib/hmac_base_vseq.sv new file mode 100644 index 0000000000000..800e9b6cc2793 --- /dev/null +++ b/hw/ip/hmac/dv copy/env/seq_lib/hmac_base_vseq.sv @@ -0,0 +1,819 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +class hmac_base_vseq extends cip_base_vseq #(.CFG_T (hmac_env_cfg), + .RAL_T (hmac_reg_block), + .COV_T (hmac_env_cov), + .VIRTUAL_SEQUENCER_T (hmac_virtual_sequencer)); + `uvm_object_utils(hmac_base_vseq) + + // Control knobs + bit do_hmac_init = 1'b1; + bit do_back_pressure = 1'b0; + bit do_burst_wr = 1'b0; + + bit invalid_cfg; + bit [5:0] cast_key_length; + bit [3:0] cast_digest_size; + + rand bit [TL_AW-1:0] wr_addr; + rand bit [TL_DBW-1:0] wr_mask; + rand bit wr_config_during_hash; + rand bit wr_key_during_hash; + rand bit hmac_en; + rand bit [3:0] digest_size; + rand bit [31:0] key[NUM_KEYS]; + rand bit [5:0] key_length; + rand bit endian_swap; + rand bit digest_swap; + rand bit key_swap; + + // Local variables + // Keep context configuration while testing Save and Restore feature + local bit endian_swap_bak; + local bit digest_swap_bak; + local bit key_swap_bak; + local bit [3:0] digest_size_bak; + local bit [5:0] key_length_bak; + local bit [TL_DW-1:0] key_bak[]; + local uvm_event sar_window = new(); + local uvm_event hash_continue = new(); + local bit save_ctx_ongoing; + local bit sar_ongoing; + + // Constraints + extern constraint wr_addr_c; + extern constraint wr_mask_c; + extern constraint key_length_c; + extern constraint digest_size_c; + extern constraint wr_mask_contiguous_c; + + // Standard SV/UVM methods + extern function new(string name=""); + + // Class specific methods + extern task dut_init(string reset_kind = "HARD"); + extern task apply_reset(string kind = "HARD"); + extern task hmac_init(bit sha_en = 1'b1, bit hmac_en = 1'b1, bit endian_swap = 1'b1, + bit digest_swap = 1'b1, bit key_swap = 1'b0, bit [3:0] digest_size = 4'b0001, + bit [5:0] key_length = 6'b00_0010, bit intr_fifo_empty_en = 1'b1, bit intr_hmac_done_en = 1'b1, + bit intr_hmac_err_en = 1'b1); + extern task write_discard_config_and_key(bit do_wr_config, bit do_wr_key); + extern task sha_enable(); + extern task write_discard_config(); + extern task write_discard_key(); + extern task trigger_hash(); + extern task trigger_hash_continue(); + extern task trigger_hash_stop(); + extern task trigger_process(); + extern task trigger_hash_when_active(); + extern task rd_digest(); + extern function void clear_wipe_secret(); + extern task csr_rd_digest(output bit [TL_DW-1:0] digest[16]); + extern task csr_wr_digest(bit [TL_DW-1:0] digest[16]); + extern task csr_rd_digest_size(output bit [3:0] read_digest_size); + extern task csr_rd_key_length(output bit [5:0] read_key_length); + // Write 1024-bit hashed key + extern task wr_key(bit [TL_DW-1:0] key[]); + extern task wipe_secrets(); + // Write into DUT's message FIFO + extern task wr_msg(bit [7:0] msg[], bit no_sar=0); + // Burst write a chunk of words into DUT's message FIFO + extern task burst_wr_msg(bit [7:0] msg[], int burst_wr_length); + // Read the message length from the DUT reg (but discard it) + extern task rd_msg_length(); + // Read the message length from the DUT reg + extern task csr_rd_msg_length(output bit [2*TL_DW-1:0] msg_length); + // Write message length to the DUT reg + extern task csr_wr_msg_length(bit [2*TL_DW-1:0] msg_length); + // Read status and interrupt state and clear the interrupt state + extern task read_status_intr_clr(); + // Check intr_pin, intr_state, and error_code registers + extern task check_error_code(bit check_err = 1); + extern task compare_digest(bit [7:0] exp_digest[], int tag_len_byte, bit [3:0] digest_size_i); + extern task save_and_restore(); + extern task sar_stop_and_continue(); + extern task sar_same_context(); + extern task sar_different_context(); + extern task save_and_restore_cfg(bit save_current_cfg, bit restore_previous_cfg); + extern function int wait_cycles_with_no_outstanding_accesses(); +endclass : hmac_base_vseq + + +constraint hmac_base_vseq::wr_addr_c { + wr_addr inside {[HMAC_MSG_FIFO_BASE : HMAC_MSG_FIFO_LAST_ADDR]}; +} + +constraint hmac_base_vseq::wr_mask_c { + $countones(wr_mask) dist { + TL_DBW :/ 1, + [1:TL_DBW-1] :/ 1 + }; +} + +constraint hmac_base_vseq::key_length_c { + $countones(key_length) == 1 dist { + 1 :/ 4, // Key_128/Key_256/Key_384/Key_512/Key_1024/Key_None + 0 :/ 1 // Illegal -> should get casted to Key_None in HW + }; +} + +constraint hmac_base_vseq::digest_size_c { + $countones(digest_size) == 1 dist { + 1 :/ 4, // SHA2_256/SHA2_384/SHA2_512/SHA2_None + 0 :/ 1 // Illegal -> should get casted to SHA2_None in HW + }; +} + +constraint hmac_base_vseq::wr_mask_contiguous_c { + $countones(wr_mask ^ {wr_mask[TL_DBW-2:0], 1'b0}) <= 2; // mask must have contiguous ones +} + +function hmac_base_vseq::new(string name=""); + super.new(name); +endfunction : new + +task hmac_base_vseq::dut_init(string reset_kind = "HARD"); + super.dut_init(reset_kind); + if (do_hmac_init) begin + hmac_init(); + end + `DV_CHECK_EQ(cfg.hmac_vif.is_idle(), 1'b1) +endtask : dut_init + +task hmac_base_vseq::apply_reset(string kind = "HARD"); + super.apply_reset(kind); + cfg.hash_process_triggered = 0; +endtask : apply_reset + +task hmac_base_vseq::hmac_init( bit sha_en = 1'b1, + bit hmac_en = 1'b1, + bit endian_swap = 1'b1, + bit digest_swap = 1'b1, + bit key_swap = 1'b0, + bit [3:0] digest_size = 4'b0001, // SHA-256 + bit [5:0] key_length = 6'b00_0010, // 256-bit key + bit intr_fifo_empty_en = 1'b1, + bit intr_hmac_done_en = 1'b1, + bit intr_hmac_err_en = 1'b1); + bit [TL_DW-1:0] interrupts; + // enable sha, hmac data paths with digest size SHA-2 256 + // and 512-bit key and writing to msg_fifo + ral.cfg.sha_en.set(sha_en); + ral.cfg.hmac_en.set(hmac_en); + ral.cfg.endian_swap.set(endian_swap); + ral.cfg.digest_swap.set(digest_swap); + ral.cfg.key_swap.set(key_swap); + ral.cfg.digest_size.set(digest_size); + ral.cfg.key_length.set(key_length); + csr_update(.csr(ral.cfg)); + + // read digest size and key length after casting from CSRs and update mirrored values + csr_rd_digest_size(cast_digest_size); + csr_rd_key_length(cast_key_length); + + // indicate if config is invalid and would block triggering the hash to start + if ((cast_digest_size == SHA2_None) || + ((cast_key_length == Key_None) && hmac_en) || + ((cast_digest_size == SHA2_256) && (cast_key_length == Key_1024) && hmac_en)) begin + invalid_cfg = 1; + end else begin + invalid_cfg = 0; + end + + `uvm_info(`gfn, $sformatf("invalid config: %1b", invalid_cfg), UVM_LOW) + + // enable interrupts + interrupts = (intr_hmac_err_en << HmacErr) | (intr_hmac_done_en << HmacDone) | + (intr_fifo_empty_en << HmacMsgFifoEmpty); + cfg_interrupts(.interrupts(interrupts), .enable(1'b1)); +endtask : hmac_init + +task hmac_base_vseq::write_discard_config_and_key(bit do_wr_config, bit do_wr_key); + if (do_wr_config) begin + write_discard_config(); + end + if (do_wr_key) begin + write_discard_key(); + check_error_code(0); + end +endtask : write_discard_config_and_key + +// Keep all the config values, but enable sha_en +task hmac_base_vseq::sha_enable(); + ral.cfg.sha_en.set(1'b1); + csr_update(.csr(ral.cfg)); +endtask : sha_enable + +// Attempt to change config reg during msg write, design will ignore the change +task hmac_base_vseq::write_discard_config(); + bit [TL_DW-1:0] rand_config_value = $urandom(); + csr_wr(ral.cfg, rand_config_value); +endtask : write_discard_config + +task hmac_base_vseq::write_discard_key(); + bit [TL_DW-1:0] rand_key_value = $urandom(); + int key_idx = $urandom_range(0, 31); + csr_wr(ral.key[key_idx], rand_key_value); +endtask : write_discard_key + +// Start hash computations +task hmac_base_vseq::trigger_hash(); + `uvm_info(`gfn, "triggering hash to start", UVM_LOW) + csr_wr(.ptr(ral.cmd), .value(1'b1 << HashStart)); + // If incorrectly configured or SHA is not enabled, check that an error is signaled. + if (invalid_cfg || !`gmv(ral.cfg.sha_en)) begin + check_error_code(); + end +endtask : trigger_hash + +// Continue hash computations +task hmac_base_vseq::trigger_hash_continue(); + `uvm_info(`gfn, "triggering hash to continue", UVM_LOW) + csr_wr(.ptr(ral.cmd), .value(1'b1 << HashContinue)); + // If SHA is not enabled, check that an error is signaled. + if (!`gmv(ral.cfg.sha_en)) begin + check_error_code(); + end + // Should be triggered while B context to freeze wr_msg/burst_wr_msg as continue will + // be triggered to check a fictive B context with a large msg_length + if (!cfg.sar_skip_ctxt) begin + hash_continue.trigger(); + end +endtask : trigger_hash_continue + +// Stop hash computations +task hmac_base_vseq::trigger_hash_stop(); + `uvm_info(`gfn, "triggering hash to stop", UVM_LOW) + csr_wr(.ptr(ral.cmd), .value(1'b1 << HashStop)); +endtask : trigger_hash_stop + +// Trigger calculation of digest at the end of a message only when Save and Restore hasn't been +// triggered before +task hmac_base_vseq::trigger_process(); + if (!save_ctx_ongoing) begin + `uvm_info(`gfn, "triggering hash to process", UVM_LOW) + csr_wr(.ptr(ral.cmd), .value(1'b1 << HashProcess)); + cfg.hash_process_triggered = 1; + end +endtask : trigger_process + +task hmac_base_vseq::trigger_hash_when_active(); + `uvm_info(`gfn, "triggering hash when active", UVM_LOW) + repeat ($urandom_range(1, 10)) trigger_hash(); + check_error_code(0); +endtask : trigger_hash_when_active + +// Read digest value +task hmac_base_vseq::rd_digest(); + bit [TL_DW-1:0] digest[16]; + csr_rd_digest(digest); +endtask : rd_digest + +function void hmac_base_vseq::clear_wipe_secret(); + `uvm_info(`gfn, "wiping secret untriggered", UVM_LOW) + cfg.wipe_secret_triggered = 0; +endfunction : clear_wipe_secret + +// Read digest value and output read value +task hmac_base_vseq::csr_rd_digest(output bit [TL_DW-1:0] digest[16]); + foreach (digest[i]) begin + csr_rd(.ptr(ral.digest[i]), .value(digest[i])); + `uvm_info(`gfn, $sformatf("digest[%0d]=32'h%08x", i, digest[i]), UVM_MEDIUM) + end +endtask : csr_rd_digest + +// Write digest value +task hmac_base_vseq::csr_wr_digest(bit [TL_DW-1:0] digest[16]); + foreach (digest[i]) csr_wr(.ptr(ral.digest[i]), .value(digest[i])); +endtask : csr_wr_digest + +// Read digest size and update mirrored value +task hmac_base_vseq::csr_rd_digest_size(output bit [3:0] read_digest_size); + csr_rd(.ptr(ral.cfg.digest_size), .value(read_digest_size)); + `uvm_info(`gfn, $sformatf("reading digest size: %04b", read_digest_size), UVM_MEDIUM) +endtask : csr_rd_digest_size + +// Read key length and update mirrored value +task hmac_base_vseq::csr_rd_key_length(output bit [5:0] read_key_length); + csr_rd(.ptr(ral.cfg.key_length), .value(read_key_length)); + `uvm_info(`gfn, $sformatf("reading key length: %06b", read_key_length), UVM_MEDIUM) +endtask : csr_rd_key_length + +// Can safely assume that the input array will always have 32 elements +// key_length determines how much of the key array is relevant for the HMAC operation +task hmac_base_vseq::wr_key(bit [TL_DW-1:0] key[]); + foreach (key[i]) begin + ral.key[i].set(key[i]); + csr_update(.csr(ral.key[i])); + `uvm_info(`gfn, $sformatf("key[%0d] = 0x%0h", i, key[i]), UVM_HIGH) + end +endtask : wr_key + +task hmac_base_vseq::wipe_secrets(); + bit [TL_DW-1:0] secret_val; + `DV_CHECK_STD_RANDOMIZE_FATAL(secret_val) + csr_wr(.ptr(ral.wipe_secret), .value(secret_val)); + cfg.wipe_secret_triggered = 1; + `uvm_info(`gfn, $sformatf("wiping secret triggered"), UVM_LOW) +endtask : wipe_secrets + +// Write msg to DUT, read status FIFO FULL and check intr FIFO FULL +// Spawn a Save and Restore thread only when needed (as burst_wr_msg might call this task also +// while the sar_thread is already ongoing) +task hmac_base_vseq::wr_msg(bit [7:0] msg[], bit no_sar=0); + int bits_written = 0; + bit [7:0] msg_q[$] = msg; + + // Spawn save and restore task only on some occasions + fork : sar_simple_thread + begin + if (!invalid_cfg && !no_sar && !sar_ongoing && (sar_window.get_num_waiters() == 0) && + (cfg.save_and_restore_pct > $urandom_range(0, 99)) && (msg_q.size() > 0)) begin + save_and_restore(); + end + end + begin + // randomly pick the size of bytes to write + // unless msg size is smaller than randomized size + while (msg_q.size() > 0) begin + bit [7:0] word_unpack[4]; + bit [TL_DW-1:0] word; + `DV_CHECK_FATAL(randomize(wr_addr, wr_mask) with {$countones(wr_mask) <= msg_q.size();}) + + foreach (wr_mask[i]) begin + // wr_mask is a packed array, word_unpacked is unpack, has different index + if (wr_mask[i]) begin + word_unpack[3 - i] = msg_q.pop_front(); + end else begin + word_unpack[3 - i] = $urandom(); + end + end + word = {>>byte{word_unpack}}; + `uvm_info(`gfn, $sformatf("wr_addr = %0h, wr_mask = %04b, words = 0x%0h", + wr_addr, wr_mask, word), UVM_LOW) + tl_access(.addr(cfg.ral.get_addr_from_offset(wr_addr)), + .write(1'b1), .data(word), .mask(wr_mask), .blocking(1)); + bits_written += $countones(wr_mask) * 8; + + `uvm_info(`gfn, $sformatf("bits written: %0d", bits_written), UVM_HIGH) + + // Block size has to be not zero to avoid to divide by zero + if (get_block_size(digest_size) != 0) begin + // Multiple of block size reached => opportunity to trigger a save and restore sequence + // Only when message is not completely yet transmitted, as it doesn't make sense + if ((bits_written % get_block_size(digest_size) == 0) && (msg_q.size() > 0)) begin + // Trigger the event only if someone is waiting for it, this is to prevent infinite + // wait in case of a S&R is triggered 2 times for a same message + if (sar_window.get_num_waiters() > 0) begin + sar_window.trigger(); + hash_continue.wait_trigger(); + end + end + end + + if (`gmv(ral.cfg.sha_en)) begin + if (!do_back_pressure) begin + if ($urandom_range(0, 1)) begin + read_status_intr_clr(); + end + end + // randomly change key, config regs during msg wr, should trigger error or be discarded + write_discard_config_and_key(wr_config_during_hash, wr_key_during_hash); + // Randomly trigger error code read also when no error is supposed to happen + if ($urandom_range(0, 1)) begin + check_error_code(0); + end + end else begin + check_error_code(1); + end + end + // Keep it alive only if needed + if (!sar_ongoing) begin + disable sar_simple_thread; + sar_window.reset(); + end + end + join + sar_window.reset(); + // ensure all msg fifo are written before trigger hmac_process + if ($urandom_range(0, 1)) begin + rd_msg_length(); + end + read_status_intr_clr(); +endtask : wr_msg + +// Read fifo_depth reg and burst write a chunk of words +task hmac_base_vseq::burst_wr_msg(bit [7:0] msg[], int burst_wr_length); + bit [7:0] msg_q[$] = msg; + bit [7:0] word_unpack[4]; + bit [TL_DW-1:0] word; + int bits_written = 0; + + // Spawn save and restore task only on some occasions + fork : sar_burst_thread + begin + if (!invalid_cfg && !sar_ongoing && (sar_window.get_num_waiters() == 0) && + (cfg.save_and_restore_pct > $urandom_range(0, 99)) && (msg_q.size() > 0)) begin + save_and_restore(); + end + end + begin + while (msg_q.size() > 0) begin + // wait until HMAC has enough space to burst write + csr_spinwait(.ptr(ral.status.fifo_depth), + .exp_data(HMAC_MSG_FIFO_DEPTH_WR - burst_wr_length), + .compare_op(CompareOpLe)); + if (msg_q.size() >= burst_wr_length * 4) begin + repeat (burst_wr_length) begin + for (int i = 0; i < 4; i++) word_unpack[i] = msg_q.pop_front(); + word = {>>byte{word_unpack}}; + `uvm_info(`gfn, $sformatf("wr_addr = %0h, wr_mask = %0h, words = 0x%0h", + wr_addr, wr_mask, word), UVM_HIGH) + `DV_CHECK_FATAL(randomize(wr_addr, wr_mask) with {wr_mask == '1;}) + tl_access(.addr(cfg.ral.get_addr_from_offset(wr_addr)), + .write(1'b1), .data(word), .mask(wr_mask), .blocking(1)); + bits_written += $countones(wr_mask) * 8; + + `uvm_info(`gfn, $sformatf("bits written: %0d", bits_written), UVM_HIGH) + + // Block size has to be not zero to avoid to divide by zero + if (get_block_size(digest_size) != 0) begin + // Multiple of block size reached => opportunity to trigger a S&R sequence + // Only when message is not completely yet transmitted, as it doesn't make sense + if ((bits_written % get_block_size(digest_size) == 0) && (msg_q.size() > 0)) begin + // Trigger the event only if someone is waiting for it, this is to prevent + // infinite wait in case of a S&R is triggered 2 times for a same message + if (sar_window.get_num_waiters() > 0) begin + sar_window.trigger(); + hash_continue.wait_trigger(); + end + end + end + end + // Expected error as we may not push message into the FIFO while SHA is disabled + if (!`gmv(ral.cfg.sha_en)) begin + check_error_code(); + end + // remaining msg is smaller than the burst_wr_length + end else begin + wr_msg(msg_q, 1); // Do not S&R on the last piece as message boundary could be wrong + msg_q.delete(); // Flush the queue to avoid infinite loop + end + if ($urandom_range(0, 1)) begin + rd_msg_length(); + end + read_status_intr_clr(); + end + // Keep it alive only if needed + if (!sar_ongoing) begin + disable sar_burst_thread; + sar_window.reset(); + end + end + join + sar_window.reset(); +endtask : burst_wr_msg + +task hmac_base_vseq::rd_msg_length(); + bit [2*TL_DW-1:0] unused; + csr_rd_msg_length(unused); +endtask : rd_msg_length + +task hmac_base_vseq::csr_rd_msg_length(output bit [2*TL_DW-1:0] msg_length); + csr_rd(ral.msg_length_upper, msg_length[2*TL_DW-1:TL_DW]); + csr_rd(ral.msg_length_lower, msg_length[TL_DW-1:0]); +endtask : csr_rd_msg_length + +task hmac_base_vseq::csr_wr_msg_length(bit [2*TL_DW-1:0] msg_length); + csr_wr(.ptr(ral.msg_length_upper), .value(msg_length[2*TL_DW-1:TL_DW])); + csr_wr(.ptr(ral.msg_length_lower), .value(msg_length[TL_DW-1:0])); +endtask : csr_wr_msg_length + +task hmac_base_vseq::read_status_intr_clr(); + bit [TL_DW-1:0] rdata; + csr_rd(ral.status, rdata); + csr_rd(ral.intr_state, rdata); + csr_wr(.ptr(ral.intr_state), .value(rdata)); +endtask : read_status_intr_clr +// This task is called when sha_en=0 and sequence set hash_start, or streamed in msg. +// It will check intr_pin, intr_state, and error_code registers. +// Default check_err is 1, if set to 0, means user is not sure if it is error case or not, +// will leave the checking to scoreboard +task hmac_base_vseq::check_error_code(bit check_err = 1); + bit [TL_DW-1:0] error_code; + if (check_err) begin + if (`gmv(ral.intr_enable.hmac_err)) begin + check_interrupts(.interrupts((1 << HmacErr)), .check_set(1'b1)); + end else begin + csr_rd_check(.ptr(ral.intr_state), .compare_value(1 << HmacErr)); + csr_wr(.ptr(ral.intr_state), .value(1 << HmacErr)); + end + end else begin + csr_rd(.ptr(ral.intr_state), .value(error_code)); + csr_wr(.ptr(ral.intr_state), .value(error_code)); + end + csr_rd(ral.err_code, error_code); + `uvm_info(`gfn, $sformatf("Error code: 0x%0h", error_code), UVM_HIGH) +endtask : check_error_code + +// TODO (#23288): remove this check from the seq +task hmac_base_vseq::compare_digest(bit [7:0] exp_digest[], int tag_len_byte, bit [3:0] digest_size_i); + bit [TL_DW-1:0] act_digest[16]; + bit [TL_DW-1:0] packed_exp_digest[16]; + csr_rd_digest(act_digest); + // `exp_digest` is guaranteed to always contain 16 words (64 bytes) of data + // since HMAC digest size is max 512 bits. + packed_exp_digest = {>>byte{exp_digest}}; + if (cfg.clk_rst_vif.rst_n) begin + foreach (act_digest[i]) begin + // for HMAC test vectors: + // -only compare up to expected tag length (parsed in for each test vector) + // -which is always divisble by 4 (word-aligned) --> (tag_len_byte/4) + // for SHA-2 (!hmac_en) test vectors: + // -compare up to the correct digest index depending on the digest size + if ((hmac_en && (i < (tag_len_byte/4))) || + (!hmac_en && + ((i < 8) || + ((i >= 8 && i < 12) && (digest_size_i == SHA2_384 || digest_size_i == SHA2_512)) || + ((i >= 12) && (digest_size_i == SHA2_512))))) begin + + `uvm_info(`gfn, $sformatf("Actual digest[%0d]: 0x%0h", i, act_digest[i]), UVM_HIGH) + `uvm_info(`gfn, $sformatf("Expected digest[%0d]: 0x%0h", i, + packed_exp_digest[i]), UVM_HIGH) + `DV_CHECK_EQ(act_digest[i], packed_exp_digest[i], $sformatf("for index %0d", i)) + end + end + end else begin + `uvm_info(`gfn, "skipped comparison due to reset", UVM_LOW) + end +endtask : compare_digest + +// Stop hash, save current context, do something/nothing and restore context +// - Test with context A saved and restored +// - Test with context A and B, alternatively saved and restored. Ensure to randomize again: +// key length, digest size, digest swap, endian swap and secret key +task hmac_base_vseq::save_and_restore(); + // Wait until message transmission is on a block boundary (multiple of 512 bits in SHA-2 256 + // or 1024 bits SHA-2 384/512) + sar_window.wait_trigger(); + randcase + 1: sar_stop_and_continue(); + 1: sar_same_context(); + 1: sar_different_context(); + endcase +endtask : save_and_restore + +task hmac_base_vseq::sar_stop_and_continue(); + uvm_event sar_stop_continue_ev; + + sar_stop_continue_ev = uvm_event_sar_pool::get_global("sar_stop_and_continue_event"); + `uvm_info(`gfn, $sformatf("Stop and trigger continue only"), UVM_LOW) + sar_ongoing = 1; + // Stop hash operations. + trigger_hash_stop(); + // Expose ongoing Save and Restore triggered to avoid to request a new hash process + save_ctx_ongoing = 1; + // Wait for hash to be done so the digest is updated. + csr_spinwait(.ptr(ral.intr_state.hmac_done), .exp_data(1'b1)); + // Clear the interrupt. + csr_wr(.ptr(ral.intr_state.hmac_done), .value(1'b1)); + save_ctx_ongoing = 0; + trigger_hash_continue(); + sar_stop_continue_ev.trigger(); + sar_ongoing = 0; +endtask : sar_stop_and_continue; + +task hmac_base_vseq::sar_same_context(); + bit [TL_DW-1:0] digest_a[16]; + bit [2*TL_DW-1:0] msg_length_a; + uvm_event sar_same_ctxt_ev; + + sar_same_ctxt_ev = uvm_event_sar_pool::get_global("sar_same_context_event"); + `uvm_info(`gfn, $sformatf("Saving and restoring with the same context"), UVM_LOW) + sar_ongoing = 1; + // Stop hash operations. + trigger_hash_stop(); + // Expose ongoing Save and Restore triggered to avoid to request a new hash process + save_ctx_ongoing = 1; + // Wait for hash to be done so the digest is updated. + csr_spinwait(.ptr(ral.intr_state.hmac_done), .exp_data(1'b1)); + // Clear the interrupt. + csr_wr(.ptr(ral.intr_state.hmac_done), .value(1'b1)); + // Read the digest and save it. + csr_rd_digest(digest_a); + // Read message length and save it. + csr_rd_msg_length(msg_length_a); + save_ctx_ongoing = 0; + // Disable SHA so we can write digest and message length. + csr_wr(.ptr(ral.cfg.sha_en), .value(1'b0)); + // Clearing the message length is not strictly necessary but currently done to ensure the + // previous value does not persist. + csr_wr_msg_length('0); // + // Reload the digest by writing it back. + csr_wr_digest(digest_a); + // Reload the message length by writing it back. + csr_wr_msg_length(msg_length_a); + // Re-enable SHA and continue hashing. + csr_wr(.ptr(ral.cfg.sha_en), .value(1'b1)); + trigger_hash_continue(); + sar_same_ctxt_ev.trigger(); + sar_ongoing = 0; +endtask : sar_same_context; + +// Different context: +// All those parameters could be changed: key length, digest size, digest swap, endian swap +// and secret key, update all those registers and restart. Operations: +// 1- config registers for A, run A hash, stop A hash +// 2- save A context +// 3- config registers for B, run hash process/continue, wait B hash completion +// 4- run B hash, stop B hash +// 5- restore A context, resume A hash until the end +// Note: here we are taking the advantage of SAR feature to test the msg_length_upper register +task hmac_base_vseq::sar_different_context(); + bit [TL_DW-1:0] digest_a[16]; + bit [2*TL_DW-1:0] msg_length_a; + bit [7:0] msg_b[]; + bit [2*TL_DW-1:0] msg_length_rd, msg_length_rand; + uvm_event sar_different_ctxt_ev; + + sar_different_ctxt_ev = uvm_event_sar_pool::get_global("sar_different_context_event"); + // ----- 1- config registers for A, run A hash, stop A hash + `uvm_info(`gfn, $sformatf("Saving and restoring with different contexts"), UVM_LOW) + sar_ongoing = 1; + // Stop hash operations. + trigger_hash_stop(); + // Expose ongoing Save and Restore triggered to avoid to request a new hash process + save_ctx_ongoing = 1; + // Wait for hash to be done so the digest is updated. + csr_spinwait(.ptr(ral.intr_state.hmac_done), .exp_data(1'b1)); + // Clear the interrupt. + csr_wr(.ptr(ral.intr_state.hmac_done), .value(1'b1)); + + // ----- 2- save A context + // Read the digest and save it. + csr_rd_digest(digest_a); + // Read message length and save it. + csr_rd_msg_length(msg_length_a); + save_ctx_ongoing = 0; + + // ----- 3- config registers for B, run hash process/continue, wait B hash completion + // Disable SHA so we can write digest and message length. + csr_wr(.ptr(ral.cfg.sha_en), .value(1'b0)); + // Generate random message for B context + msg_b = new[$urandom_range(0, 400)]; + foreach (msg_b[i]) msg_b[i] = $urandom(); + `uvm_info(`gfn, $sformatf("SAR context B - message size %0d bits", msg_b.size()*8), UVM_LOW) + `uvm_info(`gfn, $sformatf("SAR context B - msg_b=%p", msg_b), UVM_LOW) + // Set this flag to tell the SCB to skip ongoing things + cfg.sar_skip_ctxt = 1; + // Save config A, generate config B and config DUT + save_and_restore_cfg(1, 0); + // In 50% of the case run a new context from the beginning, or restore a hypothetical context + // with a huge message length to test the upper part of the register msg_length_upper + randcase + 1: begin + // Re-enable SHA and continue hashing. + csr_wr(.ptr(ral.cfg.sha_en), .value(1'b1)); + // Start processing message stream + trigger_hash(); + // Write complete message for B context + wr_msg(msg_b, 1); + // Start hash + trigger_process(); + // Wait for hash to be done so the digest is updated. + csr_spinwait(.ptr(ral.intr_state.hmac_done), .exp_data(1'b1)); + end + 1: begin + // Override the msg_length value to be able to verify the upper part of the register. + // We need to cover the 32 MSBs of this register. Be careful, the programmed value + // has to be a multiple of 512/1024 otherwise the DUT won't support it! + randcase + 1: msg_length_rand = 'h0000_0000_FFFF_FC00; // Toggle LSB upper part reg transition + 1: msg_length_rand = 'hFFFF_FFFF_FFFF_A800; // Toggle MSB, without overflowing + endcase + csr_wr_msg_length(msg_length_rand); + // Re-enable SHA and continue hashing. + csr_wr(.ptr(ral.cfg.sha_en), .value(1'b1)); + // Trigger hash to continue + trigger_hash_continue(); + // Write complete message for B context + wr_msg(msg_b, 1); + // Start hash + trigger_process(); + // Wait for hash to be done so the digest is updated. + csr_spinwait(.ptr(ral.intr_state.hmac_done), .exp_data(1'b1)); + // Check message length -> TODO (#23562) move to the SCB when removing sar_skip_ctxt + csr_rd_msg_length(msg_length_rd); + `DV_CHECK_EQ(msg_length_rd, msg_length_rand+msg_b.size()*8) + end + endcase + // Clear the interrupt. + csr_wr(.ptr(ral.intr_state.hmac_done), .value(1'b1)); + // Clear this flag to tell the SCB to proceed with the prediction and checks + cfg.sar_skip_ctxt = 0; + save_ctx_ongoing = 0; + + // ----- 4- restore A context, resume A hash until the end + // Disable SHA so we can write digest and message length. + csr_wr(.ptr(ral.cfg.sha_en), .value(1'b0)); + // Restore config A without saving config B as not required + save_and_restore_cfg(0, 1); + // Reload the digest by writing it back. + csr_wr_digest(digest_a); + // Reload the message length by writing it back. + csr_wr_msg_length(msg_length_a); + // Re-enable SHA and continue hashing. + csr_wr(.ptr(ral.cfg.sha_en), .value(1'b1)); + trigger_hash_continue(); + sar_different_ctxt_ev.trigger(); + sar_ongoing = 0; +endtask : sar_different_context; + +// Save the current config for some registers, and restore the previous saved config or genrate +// a new random one +task hmac_base_vseq::save_and_restore_cfg(bit save_current_cfg, bit restore_previous_cfg); + hmac_base_vseq rand_cfg; // Only here to randomize variables + bit endian_swap_tmp; + bit digest_swap_tmp; + bit key_swap_tmp; + bit [3:0] digest_size_tmp; + bit [5:0] key_length_tmp; + bit [TL_DW-1:0] key_tmp[]; + string secret_key_path = {`DUT_HIER_STR, ".secret_key"}; + logic [NUM_KEYS*TL_DW-1:0] secret_key_probe; + + `DV_CHECK_FATAL(uvm_hdl_read(secret_key_path, secret_key_probe), + $sformatf("Failed to access path %s", secret_key_path)) + + if (save_current_cfg) begin + endian_swap_tmp = `gmv(ral.cfg.endian_swap); + digest_swap_tmp = `gmv(ral.cfg.digest_swap); + key_swap_tmp = `gmv(ral.cfg.key_swap); + digest_size_tmp = `gmv(ral.cfg.digest_size); + key_length_tmp = `gmv(ral.cfg.key_length); + key_tmp = new[get_key_length(key_length_tmp)/TL_DW]; + for (int i=0; i (key_length != Key_None); + (local::hmac_en && digest_size == SHA2_256) -> (key_length != Key_1024); + }) + // Write into registers + ral.cfg.endian_swap.set(rand_cfg.endian_swap); + ral.cfg.digest_swap.set(rand_cfg.digest_swap); + ral.cfg.key_swap.set(rand_cfg.key_swap); + ral.cfg.digest_size.set(rand_cfg.digest_size); + ral.cfg.key_length.set(rand_cfg.key_length); + csr_update(.csr(ral.cfg)); + wr_key(rand_cfg.key); + `uvm_info(`gfn, $sformatf("SAR context B - digest size=%s, key length=%0d", + get_digest_size(rand_cfg.digest_size), + get_key_length(rand_cfg.key_length)), UVM_LOW) + `uvm_info(`gfn, $sformatf("SAR context B - endian/digest/key_swap=%b", + {rand_cfg.endian_swap, rand_cfg.digest_swap, rand_cfg.key_swap}), UVM_LOW) + `uvm_info(`gfn, $sformatf("SAR context B - key=%p", rand_cfg.key), UVM_LOW) + end + + // Copy over into the previous config variables + endian_swap_bak = endian_swap_tmp; + digest_swap_bak = digest_swap_tmp; + key_swap_bak = key_swap_tmp; + digest_size_bak = digest_size_tmp; + key_length_bak = key_length_tmp; + key_bak = key_tmp; +endtask : save_and_restore_cfg + +// Overriding timeout on outstanding accesses for the hmac_stress_test_all_with_rand_reset test +function int hmac_base_vseq::wait_cycles_with_no_outstanding_accesses(); + return 1_000_000; +endfunction : wait_cycles_with_no_outstanding_accesses diff --git a/hw/ip/hmac/dv copy/env/seq_lib/hmac_burst_wr_vseq.sv b/hw/ip/hmac/dv copy/env/seq_lib/hmac_burst_wr_vseq.sv new file mode 100644 index 0000000000000..2a1a2e93daf45 --- /dev/null +++ b/hw/ip/hmac/dv copy/env/seq_lib/hmac_burst_wr_vseq.sv @@ -0,0 +1,24 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// This sequence pre-select certain length within the msg_fifo_length (16 words) +// Wait until msg_fifo has enough depth, then burst write the pre-selected length + +class hmac_burst_wr_vseq extends hmac_long_msg_vseq; + `uvm_object_utils(hmac_burst_wr_vseq) + + // Standard SV/UVM methods + extern function new(string name=""); + extern task pre_start(); +endclass : hmac_burst_wr_vseq + + +function hmac_burst_wr_vseq::new(string name=""); + super.new(name); +endfunction : new + +task hmac_burst_wr_vseq::pre_start(); + do_burst_wr = 1'b1; + super.pre_start(); +endtask : pre_start diff --git a/hw/ip/hmac/dv copy/env/seq_lib/hmac_common_vseq.sv b/hw/ip/hmac/dv copy/env/seq_lib/hmac_common_vseq.sv new file mode 100644 index 0000000000000..570b3b5266367 --- /dev/null +++ b/hw/ip/hmac/dv copy/env/seq_lib/hmac_common_vseq.sv @@ -0,0 +1,63 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +class hmac_common_vseq extends hmac_base_vseq; + `uvm_object_utils(hmac_common_vseq) + + rand bit trig_rst_during_hash; + + // Constraints + extern constraint trig_rst_during_hash_c; + extern constraint num_trans_c; + + // Standard SV/UVM methods + extern function new(string name=""); + extern task pre_start(); + extern task body(); + + // Class specific methods + extern task wait_to_issue_reset(uint reset_delay_bound); +endclass : hmac_common_vseq + + +constraint hmac_common_vseq::trig_rst_during_hash_c { + trig_rst_during_hash dist { + 1 :/ 1, + 0 :/ 9 + }; +} + +constraint hmac_common_vseq::num_trans_c { + num_trans inside {[1:3]}; +} + +function hmac_common_vseq::new(string name=""); + super.new(name); +endfunction : new + +task hmac_common_vseq::pre_start(); + do_hmac_init = 1'b0; + super.pre_start(); +endtask : pre_start + +task hmac_common_vseq::body(); + run_common_vseq_wrapper(num_trans); +endtask : body + +task hmac_common_vseq::wait_to_issue_reset(uint reset_delay_bound); + `DV_CHECK_MEMBER_RANDOMIZE_FATAL(trig_rst_during_hash) + + if (trig_rst_during_hash) begin + // In hmac_core, the FSM `StPushToMsgFifo` only spans around 20 clock cycles in the entire + // hashing process. So to ensure hmac won't corrupt if reset is issued during + // `StPushToMsgFifo` state, this task try to issue reset (with a large possibility) during + // `StPushToMsgFifo` state. + wait (cfg.hash_process_triggered == 1); + super.wait_to_issue_reset($urandom_range(100, 150)); + #($urandom_range(0, cfg.clk_rst_vif.clk_period_ps) * 1ps); + end else begin + super.wait_to_issue_reset(reset_delay_bound); + end + cfg.hash_process_triggered = 0; +endtask : wait_to_issue_reset diff --git a/hw/ip/hmac/dv copy/env/seq_lib/hmac_datapath_stress_vseq.sv b/hw/ip/hmac/dv copy/env/seq_lib/hmac_datapath_stress_vseq.sv new file mode 100644 index 0000000000000..4572106ec378a --- /dev/null +++ b/hw/ip/hmac/dv copy/env/seq_lib/hmac_datapath_stress_vseq.sv @@ -0,0 +1,50 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// datapath_stress sequence will generate all message with size 1 and hmac_en +// thus will have 2 hashes (one for key, one for msg) with the shortest message required + +class hmac_datapath_stress_vseq extends hmac_smoke_vseq; + `uvm_object_utils(hmac_datapath_stress_vseq) + + rand int nb_blk_msg; + + // Constraints + extern constraint nb_blk_msg_c; + extern constraint msg_c; + extern constraint hmac_en_c; + extern constraint sha_en_c; + + // Standard SV/UVM methods + extern function new(string name=""); +endclass : hmac_datapath_stress_vseq + + +constraint hmac_datapath_stress_vseq::nb_blk_msg_c { + nb_blk_msg dist { + 0 :/1, + [1:156] :/1 + }; +} + +constraint hmac_datapath_stress_vseq::msg_c { + solve digest_size before msg; + if (digest_size == SHA2_256) { + msg.size() == 1 + nb_blk_msg * HMAC_BLK_SIZE_SHA2_256; + } else { + msg.size() == 1 + nb_blk_msg * HMAC_BLK_SIZE_SHA2_384_512; + } +} + +constraint hmac_datapath_stress_vseq::hmac_en_c { + hmac_en == 1; +} + +constraint hmac_datapath_stress_vseq::sha_en_c { + sha_en == 1; +} + +function hmac_datapath_stress_vseq::new(string name=""); + super.new(name); +endfunction : new diff --git a/hw/ip/hmac/dv copy/env/seq_lib/hmac_error_vseq.sv b/hw/ip/hmac/dv copy/env/seq_lib/hmac_error_vseq.sv new file mode 100644 index 0000000000000..cf30f913c9bfb --- /dev/null +++ b/hw/ip/hmac/dv copy/env/seq_lib/hmac_error_vseq.sv @@ -0,0 +1,29 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// this sequence tests error cases in HMAC and makes sure the core is not locked + +class hmac_error_vseq extends hmac_long_msg_vseq; + `uvm_object_utils(hmac_error_vseq) + + // Standard SV/UVM methods + extern function new(string name=""); + extern function void pre_randomize(); + extern task pre_body(); +endclass : hmac_error_vseq + + +function hmac_error_vseq::new(string name=""); + super.new(name); +endfunction : new + +function void hmac_error_vseq::pre_randomize(); + this.legal_seq_c.constraint_mode(0); +endfunction : pre_randomize + +task hmac_error_vseq::pre_body(); + // No need to trigger Save and Restore for this test + cfg.save_and_restore_pct = 0; + super.pre_body(); +endtask : pre_body diff --git a/hw/ip/hmac/dv copy/env/seq_lib/hmac_long_msg_vseq.sv b/hw/ip/hmac/dv copy/env/seq_lib/hmac_long_msg_vseq.sv new file mode 100644 index 0000000000000..61d193694d014 --- /dev/null +++ b/hw/ip/hmac/dv copy/env/seq_lib/hmac_long_msg_vseq.sv @@ -0,0 +1,30 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// This sequence generates a mix of short and long msgs +// Long msg has a larger size than HMAC input FIFO + +class hmac_long_msg_vseq extends hmac_smoke_vseq; + `uvm_object_utils(hmac_long_msg_vseq) + + // Constraints + extern constraint msg_c; + + // Standard SV/UVM methods + extern function new(string name=""); +endclass : hmac_long_msg_vseq + + +constraint hmac_long_msg_vseq::msg_c { + msg.size() dist { + 0 :/ 1, // Empty + [ 1 : 257] :/ 1, // Up to two 1024-bit blocks + [1000 : 3_000] :/ 5, // 1KB - 2KB according to SW immediate usage + [3001 :10_000] :/ 1 // temp set to 10KB as max length, spec max size is 2^64 bits + }; +} + +function hmac_long_msg_vseq::new(string name=""); + super.new(name); +endfunction : new diff --git a/hw/ip/hmac/dv copy/env/seq_lib/hmac_smoke_vseq.sv b/hw/ip/hmac/dv copy/env/seq_lib/hmac_smoke_vseq.sv new file mode 100644 index 0000000000000..608566bd0c3ac --- /dev/null +++ b/hw/ip/hmac/dv copy/env/seq_lib/hmac_smoke_vseq.sv @@ -0,0 +1,256 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +class hmac_smoke_vseq extends hmac_base_vseq; + `uvm_object_utils(hmac_smoke_vseq) + + rand bit sha_en; + rand bit intr_fifo_empty_en; + rand bit intr_hmac_done_en; + rand bit intr_hmac_err_en; + rand bit [7:0] msg[]; + rand int burst_wr_length; + rand bit do_hash_start_when_active; + rand bit do_hash_start; + rand bit re_enable_sha; + rand wipe_secret_req_e do_wipe_secret; + + int key_process_cycles; + + // Constraints + extern constraint num_trans_c; + extern constraint legal_seq_c; + extern constraint msg_c; + extern constraint burst_wr_c; + extern constraint intr_enable_c; + extern constraint wipe_secret_c; + + // Standard SV/UVM methods + extern function new(string name=""); + extern virtual task pre_start(); + extern task body(); +endclass: hmac_smoke_vseq + + +constraint hmac_smoke_vseq::num_trans_c { + num_trans inside {[1:50]}; +} + +constraint hmac_smoke_vseq::legal_seq_c { + do_hash_start == 1; + sha_en == 1; + do_hash_start_when_active == 0; + wr_key_during_hash == 0; + wr_config_during_hash == 0; +} + +//msg[] is a streaming msg input so can be of any size and needs its size dist-constrained +constraint hmac_smoke_vseq::msg_c { + msg.size() dist { + 0 :/ 3, // Empty + [ 1: 62] :/ 1, // Less than a SHA-2 256 block (512-bit) + [ 63: 65] :/ 3, // Around one SHA-2 256 block (512-bit) + [ 66:126] :/ 1, // Less than a SHA-2 384/512 block (1024-bit) or two 512-bit blocks + [127:129] :/ 3, // Around one SHA-2 384/512 block (1024-bit) or two 512-bit blocks + [130:254] :/ 1, // Less than two 1024-bit blocks + [255:257] :/ 3 // Around two 1024-bit blocks + }; +} + +constraint hmac_smoke_vseq::burst_wr_c { + burst_wr_length inside {[1 : HMAC_MSG_FIFO_DEPTH_WR]}; +} + +constraint hmac_smoke_vseq::intr_enable_c { + intr_fifo_empty_en dist { + 1'b1 := 8, + 1'b0 := 2 + }; + intr_hmac_done_en dist { + 1'b1 := 8, + 1'b0 := 2 + }; + intr_hmac_err_en dist { + 1'b1 := 8, + 1'b0 := 2 + }; +} + +constraint hmac_smoke_vseq::wipe_secret_c { + do_wipe_secret == NoWipeSecret; +} + +function hmac_smoke_vseq::new(string name=""); + super.new(name); +endfunction : new + +task hmac_smoke_vseq::pre_start(); + do_hmac_init = 1'b0; + super.pre_start(); +endtask : pre_start + +task hmac_smoke_vseq::body(); + for (int i = 1; i <= num_trans; i++) begin + bit [7:0] msg_q[$]; + `DV_CHECK_RANDOMIZE_FATAL(this) + `uvm_info(`gfn, $sformatf("starting seq %0d/%0d, message size %0d bits, hmac=%0d, sha=%0d", + i, num_trans, msg.size()*8, hmac_en, sha_en), UVM_LOW) + `uvm_info(`gfn, $sformatf("digest size=%s, key length=%0d", + get_digest_size(digest_size), get_key_length(key_length)), UVM_LOW) + `uvm_info(`gfn, $sformatf("intr_fifo_empty/hmac_done/hmac_err=%b, endian/digest/key_swap=%b", + {intr_fifo_empty_en, intr_hmac_done_en, intr_hmac_err_en}, + {endian_swap, digest_swap, key_swap}), UVM_LOW) + `uvm_info(`gfn, $sformatf("wipe secret condition is: %0s", do_wipe_secret.name()), UVM_LOW) + + // initialize hmac configs + hmac_init(.sha_en(sha_en), .hmac_en(hmac_en), .endian_swap(endian_swap), + .digest_swap(digest_swap), .key_swap(key_swap), .digest_size(digest_size), + .key_length(key_length), .intr_fifo_empty_en(intr_fifo_empty_en), + .intr_hmac_done_en(intr_hmac_done_en), .intr_hmac_err_en(intr_hmac_err_en)); + + // always start off the transaction by first clearing cfg.wipe_secret_triggered flag + // and update the exp digest val in scb with last digest + clear_wipe_secret(); + rd_digest(); + + if (do_wipe_secret == WipeSecretBeforeKey) begin + `uvm_info(`gfn, $sformatf("wiping before key"), UVM_HIGH) + wipe_secrets(); + // Check if digest data are corrupted by wiping secrets. + rd_digest(); + end + + // write key + wr_key(key); + + // clear the flag after writing key + clear_wipe_secret(); + + // randomly read previous digest, if the previous digest is not corrupted by wipe_secret + if (i != 1 && $urandom_range(0, 1)) begin + rd_digest(); + end + + if (do_wipe_secret == WipeSecretBeforeStart) begin + `uvm_info(`gfn, $sformatf("wiping before start"), UVM_HIGH) + wipe_secrets(); + // Here the wipe secret will only corrupt secret keys and current digests. + // If HMAC is not enabled, once we trigger start, the corruption does not affect the digest + // that will get computed. If HMAC is enabled, the key got corrupted, so the digest + // that will get computed will be corrupted, so only call clear_wipe_secret() when !hmac_en. + if (!hmac_en) begin + // read corrupted current digests then... + rd_digest(); + // clear the flag at/right before starting + clear_wipe_secret(); + end + end + + if (sha_en || $urandom_range(0, 1)) begin + bit [TL_DW-1:0] intr_state_val; + // start stream in msg + fork + begin + if (do_hash_start) begin + trigger_hash(); + end + if (do_burst_wr) begin + burst_wr_msg(msg, burst_wr_length); + end else begin + wr_msg(msg); + end + end + + begin + if (do_wipe_secret == WipeSecretBeforeProcess) begin + `uvm_info(`gfn, $sformatf("wiping before process"), UVM_HIGH) + cfg.clk_rst_vif.wait_clks($urandom_range(0, msg.size() * 10)); + wipe_secrets(); + end + end + join + + if (invalid_cfg) begin + rd_digest(); // capture the digest CSRs before moving on to next transaction + continue; // discard current transaction + end else if (!sha_en) begin + if (re_enable_sha) begin // restream in the message + sha_enable(); + if (do_hash_start) begin + trigger_hash(); + end + wr_msg(msg); + end else begin // discard current transaction + continue; + end + end + + if (do_hash_start_when_active && do_hash_start) begin + trigger_hash_when_active(); + `DV_CHECK_MEMBER_RANDOMIZE_FATAL(msg) + wr_msg(msg); + end + + // msg stream in finished, start hash + if (do_hash_start) begin + `uvm_info(`gfn, $sformatf("triggering process because msg stream is finished"), UVM_LOW) + trigger_process(); + end + + // there is one clk cycle difference between scb and design when predict fifo_empty, + // it could happen when input message length is not a multiple of 4, then in design + // the `sha2_pad.st_q` will transit from `StFifoReceive` to `StPad80`. + // If the last two fifo_rds are back-to-back, then design will have one cycle delay before + // the last fifo_rd in order to switch the state. + // If the last two fifo_rds are not back-to-back, then there won't be any delay for the + // last fifo_rd. + // the wait_clk below is implemented to avoid checking intr_state during this period of time + // for such corner cases, because it is hard to align the scb with the fifo_empty interrupt. + // Since prim_packer can hold more data, the ignored period of time is extended by * 2. + // TODO revisit this and understand why this particular delay is selected + if (`gmv(ral.cfg.digest_size) == SHA2_256) begin + key_process_cycles = HMAC_KEY_PROCESS_CYCLES_256; + end else begin + key_process_cycles = HMAC_KEY_PROCESS_CYCLES_512; + end + cfg.clk_rst_vif.wait_clks((msg.size() % 4 || !legal_seq_c.constraint_mode()) ? + key_process_cycles * 2 : + $urandom_range(0, key_process_cycles * 2)); + + if (do_hash_start) begin + fork + begin + if (!invalid_cfg) begin + // wait for interrupt to assert, check status and clear it + if (intr_hmac_done_en) begin + `DV_WAIT(cfg.intr_vif.pins[HmacDone] === 1'b1) + end else begin + csr_spinwait(.ptr(ral.intr_state.hmac_done), .exp_data(1'b1)); + end + end + end + begin + if (do_wipe_secret == WipeSecretBeforeDone) begin + `uvm_info(`gfn, $sformatf("wiping before done"), UVM_HIGH) + cfg.clk_rst_vif.wait_clks($urandom_range(0, 100)); + wipe_secrets(); + end + end + join + end + csr_rd(.ptr(ral.intr_state), .value(intr_state_val)); + csr_wr(.ptr(ral.intr_state), .value(intr_state_val)); + end + + // if disable sha, digest should be cleared + // read msg fifo length + if ($urandom_range(0, 1)) begin + rd_msg_length(); + end + + // read digest from DUT + `uvm_info(`gfn, $sformatf("reading digest"), UVM_LOW) + rd_digest(); + end +endtask : body diff --git a/hw/ip/hmac/dv copy/env/seq_lib/hmac_stress_all_vseq.sv b/hw/ip/hmac/dv copy/env/seq_lib/hmac_stress_all_vseq.sv new file mode 100644 index 0000000000000..5fbac6f8878bd --- /dev/null +++ b/hw/ip/hmac/dv copy/env/seq_lib/hmac_stress_all_vseq.sv @@ -0,0 +1,54 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// combine all hmac seqs (except below seqs) in one seq to run sequentially +// 1. csr seq, which requires scb to be disabled +class hmac_stress_all_vseq extends hmac_base_vseq; + `uvm_object_utils(hmac_stress_all_vseq) + + // Standard SV/UVM methods + extern function new(string name=""); + extern task body(); +endclass : hmac_stress_all_vseq + + +function hmac_stress_all_vseq::new(string name=""); + super.new(name); +endfunction : new + +task hmac_stress_all_vseq::body(); + string seq_names[] = {"hmac_smoke_vseq", + "hmac_back_pressure_vseq", + "hmac_burst_wr_vseq", + "hmac_common_vseq", // for intr_test + "hmac_datapath_stress_vseq", + "hmac_long_msg_vseq", + "hmac_error_vseq", + "hmac_wipe_secret_vseq"}; + for (int i = 1; i <= num_trans; i++) begin + uvm_sequence seq; + hmac_base_vseq hmac_vseq; + uint seq_idx = $urandom_range(0, seq_names.size - 1); + + seq = create_seq_by_name(seq_names[seq_idx]); + `downcast(hmac_vseq, seq) + + // dut_init (reset) can be skipped + if (do_apply_reset) begin + hmac_vseq.do_apply_reset = $urandom_range(0, 1); + end else begin + hmac_vseq.do_apply_reset = 0; + end + + hmac_vseq.set_sequencer(p_sequencer); + `DV_CHECK_RANDOMIZE_FATAL(hmac_vseq) + // common sequences only intr_test enabled scb + if (seq_names[seq_idx] == "hmac_common_vseq") begin + hmac_common_vseq common_vseq; + `downcast(common_vseq, hmac_vseq) + common_vseq.common_seq_type = "intr_test"; + end + hmac_vseq.start(p_sequencer); + end +endtask : body diff --git a/hw/ip/hmac/dv copy/env/seq_lib/hmac_test_vectors_hmac_vseq.sv b/hw/ip/hmac/dv copy/env/seq_lib/hmac_test_vectors_hmac_vseq.sv new file mode 100644 index 0000000000000..bfd250bc76b3b --- /dev/null +++ b/hw/ip/hmac/dv copy/env/seq_lib/hmac_test_vectors_hmac_vseq.sv @@ -0,0 +1,34 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// This vseq will read IETF HMAC test vectors (used for the RFC4868 spec) and +// compare computed results with the expected values. + +class hmac_test_vectors_hmac_vseq extends hmac_test_vectors_sha_vseq; + `uvm_object_utils(hmac_test_vectors_hmac_vseq) + + // Constraints + extern constraint hmac_enabled_c; + + // Standard SV/UVM methods + extern function new(string name=""); + extern task body(); +endclass : hmac_test_vectors_hmac_vseq + + +constraint hmac_test_vectors_hmac_vseq::hmac_enabled_c { + hmac_en == 1; +} + +function hmac_test_vectors_hmac_vseq::new(string name=""); + super.new(name); +endfunction : new + +task hmac_test_vectors_hmac_vseq::body(); + // replace with HMAC NIST test vectors + vector_list_256 = test_vectors_pkg::hmac_sha256_file_list; + vector_list_384 = test_vectors_pkg::hmac_sha384_file_list; + vector_list_512 = test_vectors_pkg::hmac_sha512_file_list; + super.body(); +endtask : body diff --git a/hw/ip/hmac/dv copy/env/seq_lib/hmac_test_vectors_sha_vseq.sv b/hw/ip/hmac/dv copy/env/seq_lib/hmac_test_vectors_sha_vseq.sv new file mode 100644 index 0000000000000..8392901746d91 --- /dev/null +++ b/hw/ip/hmac/dv copy/env/seq_lib/hmac_test_vectors_sha_vseq.sv @@ -0,0 +1,153 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// This vseq will read SHA-2 NIST vectors and compare computed results with the expected values +// https://csrc.nist.gov/projects/cryptographic-algorithm-validation-program/secure-hashing + +class hmac_test_vectors_sha_vseq extends hmac_base_vseq; + `uvm_object_utils(hmac_test_vectors_sha_vseq) + + string vector_list_256[] = test_vectors_pkg::sha2_256_file_list; + string vector_list_384[] = test_vectors_pkg::sha2_384_file_list; + string vector_list_512[] = test_vectors_pkg::sha2_512_file_list; + + string digest_size_arg; + + // Constraints + extern constraint hmac_disabled_c; + + // Standard SV/UVM methods + extern function new(string name=""); + extern task pre_start(); + extern task body(); + + // Class specific methods + extern task feed_vectors (string vector_list[], bit [3:0] digest_size); +endclass : hmac_test_vectors_sha_vseq + + +constraint hmac_test_vectors_sha_vseq::hmac_disabled_c { + soft hmac_en == 0; +} + +function hmac_test_vectors_sha_vseq::new(string name=""); + super.new(name); +endfunction : new + +task hmac_test_vectors_sha_vseq::pre_start(); + cfg.save_and_restore_pct = 0; // Should not be triggered for this test + do_hmac_init = 1'b0; + // grab SHA-2 digest size from the command-line argument + void'($value$plusargs("sha2_digest_size=%s", digest_size_arg)); + // When the command line argument is not defined then randomize the digest_size with valid data + // This is a safety but also necessary for the stress tests as extra argument cannot be passed + if (digest_size_arg == "") begin + `DV_CHECK_MEMBER_RANDOMIZE_WITH_FATAL( + digest_size, + digest_size inside {SHA2_256, SHA2_384, SHA2_512}; + ) + digest_size_arg = get_digest_size(digest_size); + end + super.pre_start(); +endtask : pre_start + +task hmac_test_vectors_sha_vseq::feed_vectors (string vector_list[], bit [3:0] digest_size); + test_vectors_pkg::test_vectors_t parsed_vectors[]; + + foreach (vector_list[i]) begin + // import function from the test_vectors_pkg to parse the sha vector file + test_vectors_pkg::get_hash_test_vectors(.test_name(vector_list[i]), + .parsed_vectors(parsed_vectors), + .reverse_key(0)); + parsed_vectors.shuffle(); + + // if in smoke_regression mode, to reduce the run time, we will randomly pick 2 vectors to + // run this sequence + if (cfg.smoke_test) begin + parsed_vectors = parsed_vectors[0:1]; + end + + foreach (parsed_vectors[j]) begin + bit [TL_DW-1:0] intr_state_val; + `uvm_info(`gfn, $sformatf("vector[%0d]: %0p", j, parsed_vectors[j]), UVM_LOW) + + case (parsed_vectors[j].sha2_key_length) + 128: key_length = Key_128; + 256: key_length = Key_256; + 384: key_length = Key_384; + 512: key_length = Key_512; + 1024: key_length = Key_1024; + default: key_length = Key_None; + endcase + + // only input HMAC test vectors with valid key length and while key length is + // not 1024-bit for SHA-2 256 to avoid invalid configuration case + if ((!hmac_en) || (hmac_en && + (key_length!= Key_None) && + !(digest_size == SHA2_256 && key_length == Key_1024))) begin + hmac_init(.hmac_en(hmac_en), .endian_swap(1'b1), .digest_swap(1'b0), .key_swap(1'b0), + .digest_size(digest_size), .key_length(key_length)); + + `uvm_info(`gtn, $sformatf("%s, starting seq %0d/%0d, message size %0d bits", + vector_list[i], j+1, parsed_vectors.size(), + parsed_vectors[j].msg_length_byte*8), + UVM_LOW) + + `uvm_info(`gfn, $sformatf("digest size=%s, key length=%0d", + get_digest_size(digest_size), get_key_length(key_length)), UVM_LOW) + + // always start off the transaction by reading previous digest to clear + // cfg.wipe_secret_triggered flag and update the exp digest val in scb with last digest + rd_digest(); + + if ($urandom_range(0, 1) && !hmac_en) begin + `DV_CHECK_RANDOMIZE_FATAL(this) // only key is randomized + wr_key(key); + end else begin + wr_key(parsed_vectors[j].keys); + end + + trigger_hash(); + + // wr_msg is non_blocking to ensure the order of input msg + wr_msg(parsed_vectors[j].msg); + + trigger_process(); + + wait(cfg.intr_vif.pins[HmacDone] === 1'b1); + csr_rd(.ptr(ral.intr_state), .value(intr_state_val)); + csr_wr(.ptr(ral.intr_state), .value(intr_state_val)); + compare_digest(parsed_vectors[j].exp_digest, + parsed_vectors[j].digest_length_byte, + digest_size); + end else begin + `uvm_info(`gtn, $sformatf("Discarding HMAC seq with invalid key length"), UVM_LOW) + continue; + end + end + end +endtask : feed_vectors + +task hmac_test_vectors_sha_vseq::body(); + string vector_list[]; + if (digest_size_arg == "SHA2_256") begin + digest_size = SHA2_256; + vector_list = vector_list_256; + end else if (digest_size_arg == "SHA2_384") begin + digest_size = SHA2_384; + vector_list = vector_list_384; + end else if (digest_size_arg == "SHA2_512") begin + digest_size = SHA2_512; + vector_list = vector_list_512; + // TODO (issue #22932): after merged with this PR #23771, a simple "else" could be used as + // hmac_en condition won't be there anymore + end else if (digest_size_arg != "SHA2_256" && digest_size_arg != "SHA2_384" && + digest_size_arg != "SHA2_512") begin + `uvm_fatal(`gfn, {"Digest size is not recognized, please use command-line argument as: ", + "sha2_digest_size=SHA2_256/SHA2_384/SHA2_512 or don't pass this argument"}) + end + `uvm_info(`gfn, $sformatf("Starting SHA-2/HMAC %s NIST test vectors...", + digest_size_arg), UVM_LOW) + feed_vectors (vector_list, digest_size); +endtask : body diff --git a/hw/ip/hmac/dv copy/env/seq_lib/hmac_vseq_list.sv b/hw/ip/hmac/dv copy/env/seq_lib/hmac_vseq_list.sv new file mode 100644 index 0000000000000..34b8044ed32c9 --- /dev/null +++ b/hw/ip/hmac/dv copy/env/seq_lib/hmac_vseq_list.sv @@ -0,0 +1,16 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +`include "hmac_base_vseq.sv" +`include "hmac_smoke_vseq.sv" +`include "hmac_long_msg_vseq.sv" +`include "hmac_test_vectors_sha_vseq.sv" +`include "hmac_test_vectors_hmac_vseq.sv" +`include "hmac_back_pressure_vseq.sv" +`include "hmac_burst_wr_vseq.sv" +`include "hmac_common_vseq.sv" +`include "hmac_datapath_stress_vseq.sv" +`include "hmac_error_vseq.sv" +`include "hmac_wipe_secret_vseq.sv" +`include "hmac_stress_all_vseq.sv" diff --git a/hw/ip/hmac/dv copy/env/seq_lib/hmac_wipe_secret_vseq.sv b/hw/ip/hmac/dv copy/env/seq_lib/hmac_wipe_secret_vseq.sv new file mode 100644 index 0000000000000..ce3433a11d24c --- /dev/null +++ b/hw/ip/hmac/dv copy/env/seq_lib/hmac_wipe_secret_vseq.sv @@ -0,0 +1,42 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// This sequence generates a mix of short and long msgs. +// During the transaction, this sequence randomly triggers wipe_secret and uses scb to check if +// digest value has been updated. +class hmac_wipe_secret_vseq extends hmac_smoke_vseq; + `uvm_object_utils(hmac_wipe_secret_vseq) + + // Constraints + extern constraint msg_c; + + // Standard SV/UVM methods + extern function new(string name=""); + extern function void pre_randomize(); + extern task pre_body(); +endclass : hmac_wipe_secret_vseq + + +constraint hmac_wipe_secret_vseq::msg_c { + msg.size() dist { + 0 :/ 1, + [1 :128] :/ 1, // 128 bytes is the FIFO depth + [119 :999] :/ 1, + [1000:3000] :/ 7 // 1KB - 2KB according to SW immediate usage + }; +} + +function hmac_wipe_secret_vseq::new(string name=""); + super.new(name); +endfunction : new + +function void hmac_wipe_secret_vseq::pre_randomize(); + this.wipe_secret_c.constraint_mode(0); +endfunction : pre_randomize + +task hmac_wipe_secret_vseq::pre_body(); + // No need to trigger Save and Restore for this test + cfg.save_and_restore_pct = 0; + super.pre_body(); +endtask : pre_body diff --git a/hw/ip/hmac/dv copy/hmac_sim.core b/hw/ip/hmac/dv copy/hmac_sim.core new file mode 100644 index 0000000000000..4f10b907b318c --- /dev/null +++ b/hw/ip/hmac/dv copy/hmac_sim.core @@ -0,0 +1,29 @@ +CAPI=2: +# Copyright lowRISC contributors (OpenTitan project). +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: "lowrisc:dv:hmac_sim:0.1" +description: "hmac DV sim target" +filesets: + files_rtl: + depend: + - lowrisc:ip:hmac:0.1 + + files_dv: + depend: + - lowrisc:dv:hmac_test + - lowrisc:dv:hmac_sva + files: + - tb/tb.sv + file_type: systemVerilogSource + +targets: + sim: &sim_target + toplevel: tb + filesets: + - files_rtl + - files_dv + default_tool: vcs + + lint: + <<: *sim_target diff --git a/hw/ip/hmac/dv copy/hmac_sim_cfg.hjson b/hw/ip/hmac/dv copy/hmac_sim_cfg.hjson new file mode 100644 index 0000000000000..429ac0ae66c9b --- /dev/null +++ b/hw/ip/hmac/dv copy/hmac_sim_cfg.hjson @@ -0,0 +1,169 @@ +// 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: hmac + + // Top level dut name (sv module). + dut: hmac + + // Top level testbench name (sv module). + tb: tb + + // Simulator used to sign off this block + tool: vcs + + // Fusesoc core file used for building the file list. + fusesoc_core: lowrisc:dv:hmac_sim:0.1 + + // Testplan hjson file. + testplan: "{proj_root}/hw/ip/hmac/data/hmac_testplan.hjson" + + // RAL spec - used to generate the RAL model. + ral_spec: "{proj_root}/hw/ip/hmac/data/hmac.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", + // Common CIP test lists + "{proj_root}/hw/dv/tools/dvsim/tests/csr_tests.hjson", + "{proj_root}/hw/dv/tools/dvsim/tests/alert_test.hjson", + "{proj_root}/hw/dv/tools/dvsim/tests/intr_test.hjson", + "{proj_root}/hw/dv/tools/dvsim/tests/tl_access_tests.hjson", + "{proj_root}/hw/dv/tools/dvsim/tests/sec_cm_tests.hjson", + "{proj_root}/hw/dv/tools/dvsim/tests/stress_tests.hjson"] + + // Add additional tops for simulation. + sim_tops: ["hmac_bind", "sec_cm_prim_onehot_check_bind"] + + // Default iterations for all tests - each test entry can override this. + reseed: 50 + + // Add HMAC specific exclusion files. + vcs_cov_excl_files: ["{proj_root}/hw/ip/hmac/dv/cov/hmac_unr_excl.el", + "{proj_root}/hw/ip/hmac/dv/cov/hmac_cov_excl.el"] + + // Default UVM test and seq class name. + uvm_test: hmac_base_test + uvm_test_seq: hmac_base_vseq + + // Enable cdc instrumentation. + run_opts: ["+cdc_instrumentation_enabled=1"] + + // List of test specifications. + tests: [ + { + name: hmac_smoke + uvm_test_seq: hmac_smoke_vseq + } + + { + name: hmac_long_msg + uvm_test_seq: hmac_long_msg_vseq + } + + { + name: hmac_back_pressure + uvm_test_seq: hmac_back_pressure_vseq + run_opts: ["+zero_delays=1"] + } + + { + name: hmac_datapath_stress + uvm_test_seq: hmac_datapath_stress_vseq + run_opts: ["+zero_delays=1"] + } + + { + name: hmac_burst_wr + uvm_test_seq: hmac_burst_wr_vseq + } + + { + name: hmac_error + uvm_test_seq: hmac_error_vseq + run_opts: ["+test_timeout_ns=500_000_000"] + } + + { + name: hmac_wipe_secret + uvm_test_seq: hmac_wipe_secret_vseq + } + + { + name: hmac_test_sha256_vectors + uvm_test_seq: hmac_test_vectors_sha_vseq + // Increase timeout for all test iterations to pass + run_opts: ["+test_vectors_dir={build_dir}/src/lowrisc_dv_test_vectors_0 +test_timeout_ns=1_000_000_000 +sha2_digest_size=SHA2_256"] + reseed: 5 + } + + { + name: hmac_test_sha384_vectors + uvm_test_seq: hmac_test_vectors_sha_vseq + // Increase timeout for all test iterations to pass + run_opts: ["+test_vectors_dir={build_dir}/src/lowrisc_dv_test_vectors_0 +test_timeout_ns=3_500_000_000 +sha2_digest_size=SHA2_384"] + reseed: 5 + } + + { + name: hmac_test_sha512_vectors + uvm_test_seq: hmac_test_vectors_sha_vseq + // Increase timeout for all test iterations to pass + run_opts: ["+test_vectors_dir={build_dir}/src/lowrisc_dv_test_vectors_0 +test_timeout_ns=3_500_000_000 +sha2_digest_size=SHA2_512"] + reseed: 5 + } + + { + name: hmac_test_hmac256_vectors + uvm_test_seq: hmac_test_vectors_hmac_vseq + run_opts: ["+test_vectors_dir={build_dir}/src/lowrisc_dv_test_vectors_0 +test_timeout_ns=1_000_000_000 +sha2_digest_size=SHA2_256"] + reseed: 5 + } + + { + name: hmac_test_hmac384_vectors + uvm_test_seq: hmac_test_vectors_hmac_vseq + run_opts: ["+test_vectors_dir={build_dir}/src/lowrisc_dv_test_vectors_0 +test_timeout_ns=3_000_000_000 +sha2_digest_size=SHA2_384"] + reseed: 5 + } + + { + name: hmac_test_hmac512_vectors + uvm_test_seq: hmac_test_vectors_hmac_vseq + run_opts: ["+test_vectors_dir={build_dir}/src/lowrisc_dv_test_vectors_0 +test_timeout_ns=3_000_000_000 +sha2_digest_size=SHA2_512"] + reseed: 5 + } + + { + // Append the common stress_tests.hjson entry for more run_opts. + name: hmac_stress_all + run_opts: ["+test_vectors_dir={build_dir}/src/lowrisc_dv_test_vectors_0"] + } + + { + // Append the common stress_tests.hjson entry for more run_opts. + name: hmac_stress_all_with_rand_reset + run_opts: ["+test_vectors_dir={build_dir}/src/lowrisc_dv_test_vectors_0"] + reseed: 10 + } + ] + + // List of regressions. + regressions: [ + { + name: smoke + tests: ["hmac_smoke", "hmac_test_sha256_vectors", + "hmac_test_sha384_vectors", "hmac_test_sha512_vectors"] + } + { + name: sha_test_vectors + tests: ["hmac_test_sha256_vectors", "hmac_test_sha384_vectors", "hmac_test_sha512_vectors"] + } + { + name: hmac_test_vectors + tests: ["hmac_test_hmac256_vectors", "hmac_test_hmac384_vectors", "hmac_test_hmac512_vectors"] + } + ] +} diff --git a/hw/ip/hmac/dv copy/sva/hmac_bind.sv b/hw/ip/hmac/dv copy/sva/hmac_bind.sv new file mode 100644 index 0000000000000..3cc4359918041 --- /dev/null +++ b/hw/ip/hmac/dv copy/sva/hmac_bind.sv @@ -0,0 +1,23 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +module hmac_bind; + + bind hmac tlul_assert #( + .EndpointType("Device") + ) tlul_assert_device ( + .clk_i, + .rst_ni, + .h2d (tl_i), + .d2h (tl_o) + ); + + bind hmac hmac_csr_assert_fpv hmac_csr_assert ( + .clk_i, + .rst_ni, + .h2d (tl_i), + .d2h (tl_o) + ); + +endmodule diff --git a/hw/ip/hmac/dv copy/sva/hmac_sva.core b/hw/ip/hmac/dv copy/sva/hmac_sva.core new file mode 100644 index 0000000000000..ca707d62d44f5 --- /dev/null +++ b/hw/ip/hmac/dv copy/sva/hmac_sva.core @@ -0,0 +1,38 @@ +CAPI=2: +# Copyright lowRISC contributors (OpenTitan project). +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: "lowrisc:dv:hmac_sva:0.1" +description: "HMAC assertion modules and bind file." +filesets: + files_dv: + depend: + - lowrisc:tlul:headers + - lowrisc:fpv:csr_assert_gen + files: + - hmac_bind.sv + file_type: systemVerilogSource + + files_formal: + depend: + - lowrisc:ip:hmac + +generate: + csr_assert_gen: + generator: csr_assert_gen + parameters: + spec: ../../data/hmac.hjson + +targets: + default: &default_target + filesets: + - files_dv + generate: + - csr_assert_gen + + formal: + <<: *default_target + filesets: + - files_formal + - files_dv + toplevel: hmac diff --git a/hw/ip/hmac/dv copy/tb/tb.sv b/hw/ip/hmac/dv copy/tb/tb.sv new file mode 100644 index 0000000000000..840ee4eb7a974 --- /dev/null +++ b/hw/ip/hmac/dv copy/tb/tb.sv @@ -0,0 +1,65 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +module tb; + // dep packages + import uvm_pkg::*; + import dv_utils_pkg::*; + import tl_agent_pkg::*; + import hmac_env_pkg::*; + import hmac_test_pkg::*; + + // macro includes + `include "uvm_macros.svh" + `include "dv_macros.svh" + + wire clk, rst_n; + wire [NUM_MAX_INTERRUPTS-1:0] interrupts; + + wire intr_hmac_done; + wire intr_fifo_empty; + wire intr_hmac_err; + + // interfaces + clk_rst_if clk_rst_if(.clk(clk), .rst_n(rst_n)); + pins_if #(NUM_MAX_INTERRUPTS) intr_if(.pins(interrupts)); + tl_if tl_if(.clk(clk), .rst_n(rst_n)); + hmac_if hmac_if(.clk_i(clk), .rst_ni(rst_n)); + + `DV_ALERT_IF_CONNECT() + + // dut + hmac dut ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + + .tl_i ( tl_if.h2d ), + .tl_o ( tl_if.d2h ), + + .alert_rx_i ( alert_rx ), + .alert_tx_o ( alert_tx ), + + .intr_hmac_done_o ( intr_hmac_done ), + .intr_fifo_empty_o ( intr_fifo_empty), + .intr_hmac_err_o ( intr_hmac_err ), + + .idle_o (hmac_if.idle) + ); + + assign interrupts[HmacDone] = intr_hmac_done; + assign interrupts[HmacMsgFifoEmpty] = intr_fifo_empty; + assign interrupts[HmacErr] = intr_hmac_err; + + initial begin + // drive clk and rst_n from clk_if + clk_rst_if.set_active(); + uvm_config_db#(virtual clk_rst_if)::set(null, "*.env", "clk_rst_vif", clk_rst_if); + uvm_config_db#(intr_vif)::set(null, "*.env", "intr_vif", intr_if); + uvm_config_db#(virtual tl_if)::set(null, "*.env.m_tl_agent*", "vif", tl_if); + uvm_config_db#(virtual hmac_if)::set(null, "*.env", "hmac_vif", hmac_if); + $timeformat(-12, 0, " ps", 12); + run_test(); + end + +endmodule diff --git a/hw/ip/hmac/dv copy/tests/hmac_base_test.sv b/hw/ip/hmac/dv copy/tests/hmac_base_test.sv new file mode 100644 index 0000000000000..6c2cc69633fa7 --- /dev/null +++ b/hw/ip/hmac/dv copy/tests/hmac_base_test.sv @@ -0,0 +1,23 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +class hmac_base_test extends cip_base_test #(.ENV_T(hmac_env), + .CFG_T(hmac_env_cfg)); + `uvm_component_utils(hmac_base_test) + + // Standard SV/UVM methods + extern function new(string name="", uvm_component parent=null); + extern function void build_phase(uvm_phase phase); +endclass : hmac_base_test + + +function hmac_base_test::new(string name="", uvm_component parent=null); + super.new(name, parent); +endfunction : new + +function void hmac_base_test::build_phase(uvm_phase phase); + super.build_phase(phase); + // Trigger this feature randomly and could be disabled for some tests + cfg.save_and_restore_pct = 20; // In percent chance to happen +endfunction : build_phase diff --git a/hw/ip/hmac/dv copy/tests/hmac_test.core b/hw/ip/hmac/dv copy/tests/hmac_test.core new file mode 100644 index 0000000000000..d6d75db9dd6dc --- /dev/null +++ b/hw/ip/hmac/dv copy/tests/hmac_test.core @@ -0,0 +1,19 @@ +CAPI=2: +# Copyright lowRISC contributors (OpenTitan project). +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: "lowrisc:dv:hmac_test:0.1" +description: "hmac DV UVM test" +filesets: + files_dv: + depend: + - lowrisc:dv:hmac_env + files: + - hmac_test_pkg.sv + - hmac_base_test.sv: {is_include_file: true} + file_type: systemVerilogSource + +targets: + default: + filesets: + - files_dv diff --git a/hw/ip/hmac/dv copy/tests/hmac_test_pkg.sv b/hw/ip/hmac/dv copy/tests/hmac_test_pkg.sv new file mode 100644 index 0000000000000..791f0813538a4 --- /dev/null +++ b/hw/ip/hmac/dv copy/tests/hmac_test_pkg.sv @@ -0,0 +1,21 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +package hmac_test_pkg; + // dep packages + import uvm_pkg::*; + import cip_base_pkg::*; + import hmac_env_pkg::*; + + // macro includes + `include "uvm_macros.svh" + `include "dv_macros.svh" + + // local types + + // functions + + // package sources + `include "hmac_base_test.sv" +endpackage