Skip to content

Commit 807b3a5

Browse files
committed
[kmac,dv] Add smoke test for dynamic app interface
Signed-off-by: Pascal Etterli <pascal.etterli@lowrisc.org>
1 parent c50ba45 commit 807b3a5

7 files changed

Lines changed: 220 additions & 0 deletions

File tree

hw/dv/sv/kmac_app_agent/kmac_app_agent.core

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ filesets:
2626
- kmac_app_agent.sv: {is_include_file: true}
2727
- seq_lib/kmac_app_base_seq.sv: {is_include_file: true}
2828
- seq_lib/kmac_app_host_seq.sv: {is_include_file: true}
29+
- seq_lib/kmac_app_xof_host_seq.sv: {is_include_file: true}
2930
- seq_lib/kmac_app_device_seq.sv: {is_include_file: true}
3031
- seq_lib/kmac_app_seq_list.sv: {is_include_file: true}
3132
file_type: systemVerilogSource

hw/dv/sv/kmac_app_agent/seq_lib/kmac_app_seq_list.sv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@
44

55
`include "kmac_app_base_seq.sv"
66
`include "kmac_app_host_seq.sv"
7+
`include "kmac_app_xof_host_seq.sv"
78
`include "kmac_app_device_seq.sv"
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
// Copyright lowRISC contributors (OpenTitan project).
2+
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3+
// SPDX-License-Identifier: Apache-2.0
4+
5+
// Host sequence for AppDynamic (OTBN) XOF transactions.
6+
//
7+
// Transaction flow:
8+
// Phase 0, Config beat: one push_pull beat encoding mode/strength as data.
9+
// Phase 1, Message beats: drive message bytes.
10+
// Phase 2, Digest: KMAC pushes req_output_len chunks (rsp_valid pulses) without
11+
// per-chunk requests. Once all chunks are received the host
12+
// sends a single finish beat (last=1). Any further rsp_valid
13+
// pulses are discarded until rsp_finish signals session end.
14+
class kmac_app_xof_host_seq extends kmac_app_base_seq;
15+
`uvm_object_utils(kmac_app_xof_host_seq)
16+
`uvm_object_new
17+
18+
// Message to hash. Must be set before starting this sequence.
19+
byte msg_q[$];
20+
21+
// Number of 64-bit digest chunks to request.
22+
int unsigned req_output_len = 8;
23+
24+
virtual task body();
25+
cfg.m_data_push_agent_cfg.zero_delays = cfg.zero_delays;
26+
27+
// Phase 0: config beat.
28+
begin
29+
kmac_pkg::app_ses_config_t ses_cfg;
30+
ses_cfg = '{prefix_mode: '0, // dummy value
31+
en_xof: cfg.app_en_xof,
32+
mode: cfg.app_mode,
33+
kstrength: cfg.app_strength};
34+
send_one_beat(.data(KmacDataIfWidth'(ses_cfg)), .strb('1), .last(1'b0));
35+
end
36+
37+
// Phase 1: message beats.
38+
begin
39+
byte local_msg[$] = msg_q;
40+
while (1) begin
41+
bit [KmacDataIfWidth-1:0] beat_data = '0;
42+
bit [KmacDataIfWidth/8-1:0] beat_strb = '0;
43+
bit beat_last;
44+
int bytes_sent = 0;
45+
46+
for (int i = 0; i < KmacDataIfWidth / 8; i++) begin
47+
if (local_msg.size() == 0) break;
48+
beat_data[i*8 +: 8] = local_msg.pop_front();
49+
beat_strb[i] = 1;
50+
bytes_sent++;
51+
end
52+
53+
if (bytes_sent == 0) begin
54+
// Empty message: one beat with strb='1, last=1.
55+
beat_strb = '1;
56+
end
57+
58+
beat_last = (local_msg.size() == 0);
59+
send_one_beat(.data(beat_data), .strb(beat_strb), .last(beat_last));
60+
if (beat_last) break;
61+
end
62+
end
63+
64+
// Phase 2: receive digest chunks pushed by KMAC, then send finish.
65+
// Back pressure on rsp_ready is handled automatically by the push_pull device driver.
66+
for (int i = 0; i < int'(req_output_len); i++) begin
67+
wait_rsp_valid();
68+
end
69+
70+
// Signal to KMAC that enough digest data has been received.
71+
send_one_beat(.data('0), .strb('1), .last(1'b1));
72+
73+
// Drain any extra chunks in the pipeline before the finish response arrives.
74+
wait_rsp_finish();
75+
endtask
76+
77+
// Drive a single push-pull beat by adding to the push-pull host's user-data
78+
// queue and running a one-shot push_pull_host_seq.
79+
virtual task send_one_beat(
80+
input bit [KmacDataIfWidth-1:0] data,
81+
input bit [KmacDataIfWidth/8-1:0] strb,
82+
input bit last
83+
);
84+
push_pull_host_seq#(`CONNECT_DATA_WIDTH) host_seq;
85+
`uvm_create_on(host_seq, p_sequencer.m_push_pull_sequencer)
86+
`DV_CHECK_RANDOMIZE_FATAL(host_seq)
87+
cfg.m_data_push_agent_cfg.add_h_user_data({data, strb, last});
88+
`uvm_send(host_seq)
89+
endtask
90+
91+
// Wait for one rsp_valid/rsp_ready handshake transfer.
92+
virtual task wait_rsp_valid();
93+
while (!(cfg.vif.mon_cb.rsp_valid === 1 && cfg.vif.mon_cb.rsp_ready === 1))
94+
@(cfg.vif.mon_cb);
95+
@(cfg.vif.mon_cb);
96+
endtask
97+
98+
// Wait for the session-end handshake: a completed transfer with rsp_finish asserted.
99+
virtual task wait_rsp_finish();
100+
while (!(cfg.vif.mon_cb.rsp_valid === 1 && cfg.vif.mon_cb.rsp_ready === 1 &&
101+
cfg.vif.mon_cb.rsp_finish === 1))
102+
@(cfg.vif.mon_cb);
103+
@(cfg.vif.mon_cb);
104+
endtask
105+
106+
endclass

hw/ip/kmac/dv/env/kmac_env.core

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ filesets:
3838
- seq_lib/kmac_burst_write_vseq.sv: {is_include_file: true}
3939
- seq_lib/kmac_app_vseq.sv: {is_include_file: true}
4040
- seq_lib/kmac_app_with_partial_data_vseq.sv: {is_include_file: true}
41+
- seq_lib/kmac_app_xof_smoke_vseq.sv: {is_include_file: true}
4142
- seq_lib/kmac_sideload_invalid_vseq.sv: {is_include_file: true}
4243
- seq_lib/kmac_entropy_refresh_vseq.sv: {is_include_file: true}
4344
- seq_lib/kmac_mubi_vseq.sv: {is_include_file: true}
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
// Copyright lowRISC contributors (OpenTitan project).
2+
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3+
// SPDX-License-Identifier: Apache-2.0
4+
5+
// Smoke test for the AppDynamic interface.
6+
//
7+
// Sends a randomized message and verifies the digest against the DPI reference model.
8+
class kmac_app_xof_smoke_vseq extends kmac_sideload_vseq;
9+
`uvm_object_utils(kmac_app_xof_smoke_vseq)
10+
`uvm_object_new
11+
12+
// Select which app interface to test. For now fixed to OTBN app interface.
13+
// TODO: Constrain this to all apps which have type dynamic (via APP_CFG?)
14+
localparam kmac_app_e DutApp = AppOtbn;
15+
16+
constraint msg_c {
17+
msg.size() inside {[1:1000]};
18+
}
19+
20+
// AppDynamic mode and strength encoded in the config beat.
21+
rand kmac_pkg::app_mode_e dyn_mode;
22+
rand sha3_pkg::keccak_strength_e dyn_strength;
23+
24+
// Number of 64-bit digest chunks the host will request.
25+
rand int unsigned output_chunks;
26+
27+
// Valid mode/strength combinations under test.
28+
// TODO: Test cSHAKE and KMAC
29+
constraint dyn_mode_strength_c {
30+
dyn_mode inside {kmac_pkg::AppShake, kmac_pkg::AppSHA3};
31+
if (dyn_mode == kmac_pkg::AppShake) {
32+
dyn_strength inside {sha3_pkg::L128, sha3_pkg::L256};
33+
} else {
34+
dyn_strength inside {sha3_pkg::L256, sha3_pkg::L512};
35+
}
36+
}
37+
38+
// SHAKE: random length covering single-squeeze and multi-squeeze.
39+
// SHA3-256: 4 chunks = full output (sha3-256); 2 chunks = 128 bits
40+
constraint output_chunks_c {
41+
if (dyn_mode == kmac_pkg::AppShake) {
42+
output_chunks inside {[1:32]};
43+
} else {
44+
if (dyn_strength == sha3_pkg::L256) {
45+
output_chunks == 4;
46+
} else {
47+
output_chunks == 8; // 512 / 64 = 8
48+
}
49+
}
50+
}
51+
52+
// Whether XOF mode is enabled or not.
53+
rand bit en_xof;
54+
55+
// TODO: Flag must be set if requested responses is larger than the rate. For now always enable
56+
// it for SHAKE and cSHAKE to avoid implementing this restriction for now.
57+
constraint en_xof_c {
58+
if (dyn_mode inside {kmac_pkg::AppShake, kmac_pkg::AppCShake, kmac_pkg::AppKMAC}) {
59+
en_xof == 1'b1;
60+
} else {
61+
en_xof == 1'b0;
62+
}
63+
}
64+
65+
// TODO: For now do not test KMAC operations.
66+
constraint kmac_en_c { kmac_en == 0; }
67+
68+
virtual task pre_start();
69+
// TODO: remove this to test KMAC
70+
en_sideload_c.constraint_mode(0);
71+
cfg.m_kmac_app_agent_cfg[DutApp].app_type = AppDynamic; // TODO: assert this?
72+
cfg.m_kmac_app_agent_cfg[DutApp].app_mode = dyn_mode;
73+
cfg.m_kmac_app_agent_cfg[DutApp].app_strength = dyn_strength;
74+
cfg.m_kmac_app_agent_cfg[DutApp].app_en_xof = en_xof;
75+
cfg.m_kmac_app_agent_cfg[DutApp].req_output_len = output_chunks;
76+
`uvm_info(get_type_name(),
77+
$sformatf(
78+
"App config: app_type=%s app_mode=%s app_strength=%s en_xof=%s req_output_len=%0d",
79+
cfg.m_kmac_app_agent_cfg[DutApp].app_type.name(),
80+
dyn_mode.name(),
81+
dyn_strength.name(),
82+
en_xof,
83+
cfg.m_kmac_app_agent_cfg[DutApp].req_output_len),
84+
UVM_LOW)
85+
super.pre_start();
86+
endtask
87+
88+
virtual task body();
89+
kmac_app_xof_host_seq xof_seq;
90+
91+
kmac_init();
92+
// We must provide a seed for the entropy module via SW.
93+
if (cfg.enable_masking && entropy_mode == EntropyModeSw) begin
94+
`uvm_info(`gfn, "providing SW entropy", UVM_HIGH)
95+
provide_sw_entropy();
96+
end
97+
98+
`uvm_create_on(xof_seq, p_sequencer.kmac_app_sequencer_h[DutApp])
99+
foreach (msg[i]) xof_seq.msg_q.push_back(msg[i]);
100+
xof_seq.req_output_len = output_chunks;
101+
`uvm_send(xof_seq)
102+
103+
cfg.clk_rst_vif.wait_clks(100);
104+
endtask
105+
106+
endclass

hw/ip/kmac/dv/env/seq_lib/kmac_vseq_list.sv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
`include "kmac_burst_write_vseq.sv"
1616
`include "kmac_app_vseq.sv"
1717
`include "kmac_app_with_partial_data_vseq.sv"
18+
`include "kmac_app_xof_smoke_vseq.sv"
1819
`include "kmac_sideload_invalid_vseq.sv"
1920
`include "kmac_mubi_vseq.sv"
2021
`include "kmac_entropy_refresh_vseq.sv"

hw/ip/kmac/dv/kmac_base_sim_cfg.hjson

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@
9191
name: "{name}_smoke"
9292
uvm_test_seq: kmac_smoke_vseq
9393
}
94+
{
95+
name: "{name}_app_xof_smoke"
96+
uvm_test_seq: kmac_app_xof_smoke_vseq
97+
}
9498
{
9599
name: "{name}_long_msg_and_output"
96100
uvm_test_seq: kmac_long_msg_and_output_vseq

0 commit comments

Comments
 (0)