mirror of
https://github.com/lowRISC/ibex.git
synced 2025-04-20 11:57:12 -04:00
Update lowrisc_ip to lowRISC/opentitan@4cf2479b8e
Update code from upstream repository https://github.com/lowRISC/opentitan to revision 4cf2479b8e6c9b68b9fe1adba202443d3dbe3ff3 * [prim_trivium] Allow dynamically disabling the lockup protection (Pirmin Vogel) * [scrambling] Add reference to RFC issue (Michael Schaffner) * [edn] Move prim_edn_req out of prim (Rupert Swarbrick) * [reggen] Remove the devmode input (Michael Schaffner) * [prim, rom_ctrl] Remove S&P layer from data scrambling (Michael Schaffner) * [prim] Fix typo in Trivium/Bivium stream cipher primitives (Pirmin Vogel) * [prim] Add scratch Verilator testbench for Trivium/Bivium primitives (Pirmin Vogel) * [prim] Add Trivium/Bivium stream cipher primitives (Pirmin Vogel) * [chip,dv] update makefile for real_key rom test (Jaedon Kim) * [dvsim] cast self.seed to 'int' (Jaedon Kim) * [dvsim] Change systemverilog seed to 32 bits (Hakim Filali) * [dv] Specialize dv_spinwait_* documentation comments (Rupert Swarbrick) Signed-off-by: Michael Schaffner <msf@opentitan.org>
This commit is contained in:
parent
123d46b4d6
commit
94a7446277
31 changed files with 1250 additions and 365 deletions
2
vendor/lowrisc_ip.lock.hjson
vendored
2
vendor/lowrisc_ip.lock.hjson
vendored
|
@ -9,6 +9,6 @@
|
|||
upstream:
|
||||
{
|
||||
url: https://github.com/lowRISC/opentitan
|
||||
rev: e6a0e9a1363d33789283ea6ba3c4d94d41f2dee5
|
||||
rev: 4cf2479b8e6c9b68b9fe1adba202443d3dbe3ff3
|
||||
}
|
||||
}
|
||||
|
|
17
vendor/lowrisc_ip/dv/sv/dv_utils/dv_macros.svh
vendored
17
vendor/lowrisc_ip/dv/sv/dv_utils/dv_macros.svh
vendored
|
@ -360,14 +360,13 @@
|
|||
`define GET_PARITY(val, odd=0) (^val ^ odd)
|
||||
`endif
|
||||
|
||||
// Wait a task or statement with exit condition
|
||||
// Kill the thread when either the wait statement is completed or exit condition occurs
|
||||
// input WAIT_ need to be a statement. Here are some examples
|
||||
// `DV_SPINWAIT(wait(...);, "Wait for ...")
|
||||
// `DV_SPINWAIT(
|
||||
// while (1) begin
|
||||
// ...
|
||||
// end)
|
||||
// Wait for a statement but stop early if the EXIT statement completes.
|
||||
//
|
||||
// Example usage:
|
||||
//
|
||||
// `DV_SPINWAIT_EXIT(do_something_time_consuming();,
|
||||
// wait(stop_now_flag);,
|
||||
// "The stop flag was set when we were working")
|
||||
`ifndef DV_SPINWAIT_EXIT
|
||||
`define DV_SPINWAIT_EXIT(WAIT_, EXIT_, MSG_ = "exit condition occurred!", ID_ =`gfn) \
|
||||
begin \
|
||||
|
@ -398,7 +397,7 @@
|
|||
end
|
||||
`endif
|
||||
|
||||
// wait a task or statement with timer watchdog
|
||||
// Wait for a statement, but exit early after a timeout
|
||||
`ifndef DV_SPINWAIT
|
||||
`define DV_SPINWAIT(WAIT_, MSG_ = "timeout occurred!", TIMEOUT_NS_ = default_spinwait_timeout_ns, ID_ =`gfn) \
|
||||
`DV_SPINWAIT_EXIT(WAIT_, `DV_WAIT_TIMEOUT(TIMEOUT_NS_, ID_, MSG_);, "", ID_)
|
||||
|
|
|
@ -36,7 +36,6 @@ package dv_utils_pkg;
|
|||
|
||||
// typedef parameterized pins_if for ease of implementation for interrupts and alerts
|
||||
typedef virtual pins_if #(NUM_MAX_INTERRUPTS) intr_vif;
|
||||
typedef virtual pins_if #(1) devmode_vif;
|
||||
|
||||
// interface direction / mode - Host or Device
|
||||
typedef enum bit {
|
||||
|
|
|
@ -59,7 +59,6 @@ virtual function bit [38:0] rom_encrypt_read32(bit [bus_params_pkg::BUS_AW-1:0]
|
|||
zero_key[i] = '0;
|
||||
end
|
||||
|
||||
data_arr = sram_scrambler_pkg::sp_decrypt(data_arr, 39, zero_key);
|
||||
for (int i = 0; i < 39; i++) begin
|
||||
data[i] = data_arr[i] ^ keystream[i];
|
||||
end
|
||||
|
|
|
@ -237,10 +237,10 @@ package sram_scrambler_pkg;
|
|||
// SRAM data encryption is more involved, we need to run 2 rounds of PRINCE on the nonce and key
|
||||
// and then XOR the result with the data.
|
||||
//
|
||||
// After that, the XORed data neeeds to them be passed through the S&P network one byte at a time.
|
||||
// Optionally, the XORed data can be passed through the S&P network.
|
||||
function automatic state_t encrypt_sram_data(logic data[], int data_width, int sp_width,
|
||||
logic addr[], int addr_width,
|
||||
logic key[], logic nonce[]);
|
||||
logic key[], logic nonce[], bit use_sp_layer = 0);
|
||||
logic keystream[] = new[SRAM_BLOCK_WIDTH];
|
||||
logic data_enc[] = new[data_width];
|
||||
logic byte_to_enc[] = new[8];
|
||||
|
@ -262,31 +262,33 @@ package sram_scrambler_pkg;
|
|||
data_enc[i] = data[i] ^ keystream[i % ks_width];
|
||||
end
|
||||
|
||||
if (data_width == sp_width) begin
|
||||
// pass the entire word through the subst/perm network at once (the next cases would give the
|
||||
// same results too, but this should be a bit more efficient)
|
||||
data_enc = sp_encrypt(data_enc, data_width, zero_key);
|
||||
end else if (sp_width == 8) begin
|
||||
// pass each byte of the encoded result through the subst/perm network (special case of the
|
||||
// general code below)
|
||||
for (int i = 0; i < data_width / 8; i++) begin
|
||||
byte_to_enc = data_enc[i*8 +: 8];
|
||||
enc_byte = sp_encrypt(byte_to_enc, 8, zero_key);
|
||||
data_enc[i*8 +: 8] = enc_byte;
|
||||
end
|
||||
end else begin
|
||||
// divide the word into sp_width chunks to pass it through the subst/perm network
|
||||
for (int chunk_lsb = 0; chunk_lsb < data_width; chunk_lsb += sp_width) begin
|
||||
int bits_remaining = data_width - chunk_lsb;
|
||||
int chunk_width = (bits_remaining < sp_width) ? bits_remaining : sp_width;
|
||||
logic chunk[] = new[chunk_width];
|
||||
|
||||
for (int j = 0; j < chunk_width; j++) begin
|
||||
chunk[j] = data_enc[chunk_lsb + j];
|
||||
if (use_sp_layer) begin
|
||||
if (data_width == sp_width) begin
|
||||
// pass the entire word through the subst/perm network at once (the next cases would give the
|
||||
// same results too, but this should be a bit more efficient)
|
||||
data_enc = sp_encrypt(data_enc, data_width, zero_key);
|
||||
end else if (sp_width == 8) begin
|
||||
// pass each byte of the encoded result through the subst/perm network (special case of the
|
||||
// general code below)
|
||||
for (int i = 0; i < data_width / 8; i++) begin
|
||||
byte_to_enc = data_enc[i*8 +: 8];
|
||||
enc_byte = sp_encrypt(byte_to_enc, 8, zero_key);
|
||||
data_enc[i*8 +: 8] = enc_byte;
|
||||
end
|
||||
chunk = sp_encrypt(chunk, chunk_width, zero_key);
|
||||
for (int j = 0; j < chunk_width; j++) begin
|
||||
data_enc[chunk_lsb + j] = chunk[j];
|
||||
end else begin
|
||||
// divide the word into sp_width chunks to pass it through the subst/perm network
|
||||
for (int chunk_lsb = 0; chunk_lsb < data_width; chunk_lsb += sp_width) begin
|
||||
int bits_remaining = data_width - chunk_lsb;
|
||||
int chunk_width = (bits_remaining < sp_width) ? bits_remaining : sp_width;
|
||||
logic chunk[] = new[chunk_width];
|
||||
|
||||
for (int j = 0; j < chunk_width; j++) begin
|
||||
chunk[j] = data_enc[chunk_lsb + j];
|
||||
end
|
||||
chunk = sp_encrypt(chunk, chunk_width, zero_key);
|
||||
for (int j = 0; j < chunk_width; j++) begin
|
||||
data_enc[chunk_lsb + j] = chunk[j];
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -296,7 +298,7 @@ package sram_scrambler_pkg;
|
|||
|
||||
function automatic state_t decrypt_sram_data(logic data[], int data_width, int sp_width,
|
||||
logic addr[], int addr_width,
|
||||
logic key[], logic nonce[]);
|
||||
logic key[], logic nonce[], bit use_sp_layer = 0);
|
||||
logic keystream[] = new[SRAM_BLOCK_WIDTH];
|
||||
logic data_dec[] = new[data_width];
|
||||
logic byte_to_dec[] = new[8];
|
||||
|
@ -312,40 +314,47 @@ package sram_scrambler_pkg;
|
|||
// Generate the keystream
|
||||
keystream = gen_keystream(addr, addr_width, key, nonce);
|
||||
|
||||
if (data_width == sp_width) begin
|
||||
// pass the entire word through the subst/perm network at once (the next cases would give the
|
||||
// same results too, but this should be a bit more efficient)
|
||||
data_dec = sp_decrypt(data, data_width, zero_key);
|
||||
end else if (sp_width == 8) begin
|
||||
// pass each byte of the data through the subst/perm network (special case of the general code
|
||||
// below)
|
||||
for (int i = 0; i < data_width / 8; i++) begin
|
||||
byte_to_dec = data[i*8 +: 8];
|
||||
dec_byte = sp_decrypt(byte_to_dec, 8, zero_key);
|
||||
data_dec[i*8 +: 8] = dec_byte;
|
||||
if (use_sp_layer) begin
|
||||
if (data_width == sp_width) begin
|
||||
// pass the entire word through the subst/perm network at once (the next cases would give the
|
||||
// same results too, but this should be a bit more efficient)
|
||||
data_dec = sp_decrypt(data, data_width, zero_key);
|
||||
end else if (sp_width == 8) begin
|
||||
// pass each byte of the data through the subst/perm network (special case of the general code
|
||||
// below)
|
||||
for (int i = 0; i < data_width / 8; i++) begin
|
||||
byte_to_dec = data[i*8 +: 8];
|
||||
dec_byte = sp_decrypt(byte_to_dec, 8, zero_key);
|
||||
data_dec[i*8 +: 8] = dec_byte;
|
||||
end
|
||||
end else begin
|
||||
// divide the word into sp_width chunks to pass it through the subst/perm network
|
||||
for (int chunk_lsb = 0; chunk_lsb < data_width; chunk_lsb += sp_width) begin
|
||||
int bits_remaining = data_width - chunk_lsb;
|
||||
int chunk_width = (bits_remaining < sp_width) ? bits_remaining : sp_width;
|
||||
logic chunk[] = new[chunk_width];
|
||||
|
||||
for (int j = 0; j < chunk_width; j++) begin
|
||||
chunk[j] = data[chunk_lsb + j];
|
||||
end
|
||||
chunk = sp_decrypt(chunk, chunk_width, zero_key);
|
||||
for (int j = 0; j < chunk_width; j++) begin
|
||||
data_dec[chunk_lsb + j] = chunk[j];
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// XOR result data with the keystream
|
||||
for (int i = 0; i < data_width; i++) begin
|
||||
data_dec[i] = data_dec[i] ^ keystream[i % ks_width];
|
||||
end
|
||||
end else begin
|
||||
// divide the word into sp_width chunks to pass it through the subst/perm network
|
||||
for (int chunk_lsb = 0; chunk_lsb < data_width; chunk_lsb += sp_width) begin
|
||||
int bits_remaining = data_width - chunk_lsb;
|
||||
int chunk_width = (bits_remaining < sp_width) ? bits_remaining : sp_width;
|
||||
logic chunk[] = new[chunk_width];
|
||||
|
||||
for (int j = 0; j < chunk_width; j++) begin
|
||||
chunk[j] = data[chunk_lsb + j];
|
||||
end
|
||||
chunk = sp_decrypt(chunk, chunk_width, zero_key);
|
||||
for (int j = 0; j < chunk_width; j++) begin
|
||||
data_dec[chunk_lsb + j] = chunk[j];
|
||||
end
|
||||
// XOR result data with the keystream
|
||||
for (int i = 0; i < data_width; i++) begin
|
||||
data_dec[i] = data[i] ^ keystream[i % ks_width];
|
||||
end
|
||||
end
|
||||
|
||||
// XOR result data with the keystream
|
||||
for (int i = 0; i < data_width; i++) begin
|
||||
data_dec[i] = data_dec[i] ^ keystream[i % ks_width];
|
||||
end
|
||||
|
||||
return data_dec;
|
||||
|
||||
endfunction : decrypt_sram_data
|
||||
|
|
37
vendor/lowrisc_ip/dv/tools/dvsim/sim.mk
vendored
37
vendor/lowrisc_ip/dv/tools/dvsim/sim.mk
vendored
|
@ -19,9 +19,9 @@ pre_build:
|
|||
mkdir -p ${build_dir}
|
||||
ifneq (${pre_build_cmds},)
|
||||
# pre_build_cmds are likely changing the in-tree sources. We hence use FLOCK
|
||||
# utility to prevent multiple builds that may be running in parallel from
|
||||
# stepping on each other. TODO: Enforce the list of pre_build_cmds is
|
||||
# identical across all build modes.
|
||||
# utility to prevent multiple builds that may be running in parallel from
|
||||
# stepping on each other. TODO: Enforce the list of pre_build_cmds is
|
||||
# identical across all build modes.
|
||||
${LOCK_ROOT_DIR} "cd ${build_dir} && ${pre_build_cmds}"
|
||||
endif
|
||||
|
||||
|
@ -124,6 +124,7 @@ ifneq (${sw_images},)
|
|||
--output=label_kind | cut -f1 -d' '); \
|
||||
if [[ $${kind} == "opentitan_test" \
|
||||
|| $${bazel_label} == "//sw/device/lib/testing/test_rom:test_rom_sim_dv" \
|
||||
|| $${bazel_label} == "//sw/device/silicon_creator/rom:rom_with_real_keys_sim_dv" \
|
||||
|| $${bazel_label} == "//sw/device/silicon_creator/rom:rom_with_fake_keys_sim_dv" ]]; then \
|
||||
for artifact in $$($${bazel_cmd} cquery $${bazel_airgapped_opts} \
|
||||
$${bazel_label} \
|
||||
|
@ -229,18 +230,18 @@ cov_analyze:
|
|||
${cov_analyze_cmd} ${cov_analyze_opts}
|
||||
|
||||
.PHONY: build \
|
||||
pre_build \
|
||||
gen_sv_flist \
|
||||
do_build \
|
||||
post_build \
|
||||
build_result \
|
||||
run \
|
||||
pre_run \
|
||||
sw_build \
|
||||
simulate \
|
||||
post_run \
|
||||
run_result \
|
||||
debug_waves \
|
||||
cov_merge \
|
||||
cov_analyze \
|
||||
cov_report
|
||||
pre_build \
|
||||
gen_sv_flist \
|
||||
do_build \
|
||||
post_build \
|
||||
build_result \
|
||||
run \
|
||||
pre_run \
|
||||
sw_build \
|
||||
simulate \
|
||||
post_run \
|
||||
run_result \
|
||||
debug_waves \
|
||||
cov_merge \
|
||||
cov_analyze \
|
||||
cov_report
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
- address and size aren't aligned, e.g. `a_address = 0x01`, `a_size != 0`
|
||||
- size is greater than 2
|
||||
- OpenTitan defined error cases
|
||||
- access unmapped address, expect `d_error = 1` when `devmode_i == 1`
|
||||
- access unmapped address, expect `d_error = 1`
|
||||
- write a CSR with unaligned address, e.g. `a_address[1:0] != 0`
|
||||
- write a CSR less than its width, e.g. when CSR is 2 bytes wide, only write 1 byte
|
||||
- write a memory with `a_mask != '1` when it doesn't support partial accesses
|
||||
|
|
4
vendor/lowrisc_ip/dv/tools/dvsim/vcs.hjson
vendored
4
vendor/lowrisc_ip/dv/tools/dvsim/vcs.hjson
vendored
|
@ -113,7 +113,7 @@
|
|||
|
||||
run_opts: ["-licqueue",
|
||||
"-ucli -do {run_script}",
|
||||
"+ntb_random_seed={seed}",
|
||||
"+ntb_random_seed={svseed}",
|
||||
// Disable the display of the SystemVerilog assert and cover statement summary
|
||||
// at the end of simulation. This summary is list of assertions that started but
|
||||
// did not finish because the simulation terminated, or assertions that did not
|
||||
|
@ -134,7 +134,7 @@
|
|||
|
||||
// Individual test specific coverage data - this will be deleted if the test fails
|
||||
// so that coverage from failiing tests is not included in the final report.
|
||||
cov_db_test_dir_name: "{run_dir_name}.{seed}"
|
||||
cov_db_test_dir_name: "{run_dir_name}.{svseed}"
|
||||
cov_db_test_dir: "{cov_db_dir}/snps/coverage/db/testdata/{cov_db_test_dir_name}"
|
||||
|
||||
// Merging coverage.
|
||||
|
|
|
@ -69,9 +69,7 @@
|
|||
// "--x-initial unique",
|
||||
]
|
||||
|
||||
run_opts: [// Set random seed.
|
||||
// "+verilator+seed+{seed}",
|
||||
]
|
||||
run_opts: []
|
||||
|
||||
// Supported wave dumping formats (in order of preference).
|
||||
supported_wave_formats: ["fst"]
|
||||
|
|
|
@ -68,7 +68,7 @@
|
|||
"-64bit -xmlibdirname {build_db_dir}",
|
||||
// Use the same snapshot name set during the build step.
|
||||
"-r {tb}",
|
||||
"+SVSEED={seed}",
|
||||
"+SVSEED={svseed}",
|
||||
"{uvm_testname_plusarg}",
|
||||
"{uvm_testseq_plusarg}",
|
||||
// Ignore "IEEE 1800-2009 SystemVerilog simulation semantics" warning
|
||||
|
@ -129,7 +129,7 @@
|
|||
|
||||
// Individual test specific coverage data - this will be deleted if the test fails
|
||||
// so that coverage from failiing tests is not included in the final report.
|
||||
cov_db_test_dir_name: "{run_dir_name}.{seed}"
|
||||
cov_db_test_dir_name: "{run_dir_name}.{svseed}"
|
||||
cov_db_test_dir: "{cov_db_dir}/{cov_db_test_dir_name}"
|
||||
|
||||
// Merging coverage.
|
||||
|
|
|
@ -162,9 +162,10 @@ void ScrambledEcc32MemArea::WriteBuffer(uint8_t buf[SV_MEM_WIDTH_BYTES],
|
|||
std::vector<uint8_t> ScrambledEcc32MemArea::ReadUnscrambled(
|
||||
const uint8_t buf[SV_MEM_WIDTH_BYTES], uint32_t src_word) const {
|
||||
std::vector<uint8_t> scrambled_data(buf, buf + GetPhysWidthByte());
|
||||
return scramble_decrypt_data(
|
||||
scrambled_data, GetPhysWidth(), 39, AddrIntToBytes(src_word, addr_width_),
|
||||
addr_width_, GetScrambleNonce(), GetScrambleKey(), repeat_keystream_);
|
||||
return scramble_decrypt_data(scrambled_data, GetPhysWidth(), 39,
|
||||
AddrIntToBytes(src_word, addr_width_),
|
||||
addr_width_, GetScrambleNonce(),
|
||||
GetScrambleKey(), repeat_keystream_, false);
|
||||
}
|
||||
|
||||
void ScrambledEcc32MemArea::ReadBuffer(std::vector<uint8_t> &data,
|
||||
|
@ -196,7 +197,8 @@ void ScrambledEcc32MemArea::ScrambleBuffer(uint8_t buf[SV_MEM_WIDTH_BYTES],
|
|||
// Scramble data with integrity
|
||||
scramble_buf = scramble_encrypt_data(
|
||||
scramble_buf, GetPhysWidth(), 39, AddrIntToBytes(dst_word, addr_width_),
|
||||
addr_width_, GetScrambleNonce(), GetScrambleKey(), repeat_keystream_);
|
||||
addr_width_, GetScrambleNonce(), GetScrambleKey(), repeat_keystream_,
|
||||
false);
|
||||
|
||||
// Copy scrambled data to write buffer
|
||||
std::copy(scramble_buf.begin(), scramble_buf.end(), &buf[0]);
|
||||
|
|
|
@ -322,7 +322,7 @@ std::vector<uint8_t> scramble_encrypt_data(
|
|||
const std::vector<uint8_t> &data_in, uint32_t data_width,
|
||||
uint32_t subst_perm_width, const std::vector<uint8_t> &addr,
|
||||
uint32_t addr_width, const std::vector<uint8_t> &nonce,
|
||||
const std::vector<uint8_t> &key, bool repeat_keystream) {
|
||||
const std::vector<uint8_t> &key, bool repeat_keystream, bool use_sp_layer) {
|
||||
assert(data_in.size() == ((data_width + 7) / 8));
|
||||
assert(addr.size() == ((addr_width + 7) / 8));
|
||||
|
||||
|
@ -335,28 +335,32 @@ std::vector<uint8_t> scramble_encrypt_data(
|
|||
|
||||
auto data_enc = xor_vectors(data_in, keystream);
|
||||
|
||||
return scramble_subst_perm_full_width(data_enc, data_width, subst_perm_width,
|
||||
true);
|
||||
if (use_sp_layer) {
|
||||
return scramble_subst_perm_full_width(data_enc, data_width,
|
||||
subst_perm_width, true);
|
||||
} else {
|
||||
return data_enc;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<uint8_t> scramble_decrypt_data(
|
||||
const std::vector<uint8_t> &data_in, uint32_t data_width,
|
||||
uint32_t subst_perm_width, const std::vector<uint8_t> &addr,
|
||||
uint32_t addr_width, const std::vector<uint8_t> &nonce,
|
||||
const std::vector<uint8_t> &key, bool repeat_keystream) {
|
||||
const std::vector<uint8_t> &key, bool repeat_keystream, bool use_sp_layer) {
|
||||
assert(data_in.size() == ((data_width + 7) / 8));
|
||||
assert(addr.size() == ((addr_width + 7) / 8));
|
||||
|
||||
// Data is decrypted by reversing substitution/permutation layer then XORing
|
||||
// with keystream
|
||||
auto data_sp_out = scramble_subst_perm_full_width(data_in, data_width,
|
||||
subst_perm_width, false);
|
||||
|
||||
auto keystream =
|
||||
scramble_gen_keystream(addr, addr_width, nonce, key, data_width,
|
||||
kNumPrinceHalfRounds, repeat_keystream);
|
||||
|
||||
auto data_dec = xor_vectors(data_sp_out, keystream);
|
||||
|
||||
return data_dec;
|
||||
if (use_sp_layer) {
|
||||
// Data is decrypted by reversing substitution/permutation layer then XORing
|
||||
// with keystream
|
||||
auto data_sp_out = scramble_subst_perm_full_width(data_in, data_width,
|
||||
subst_perm_width, false);
|
||||
return xor_vectors(data_sp_out, keystream);
|
||||
} else {
|
||||
return xor_vectors(data_in, keystream);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,13 +40,17 @@ std::vector<uint8_t> scramble_addr(const std::vector<uint8_t> &addr_in,
|
|||
* @param repeat_keystream Repeat the keystream of one single PRINCE instance if
|
||||
* set to true. Otherwise multiple PRINCE instances are
|
||||
* used.
|
||||
* @param use_sp_layer Use the S&P layer for data diffusion. In HW this is
|
||||
* disabled by default since it interacts adversely with
|
||||
* the end-to-end integrity scheme. See #20788 for
|
||||
* context.
|
||||
* @return Byte vector with decrypted data
|
||||
*/
|
||||
std::vector<uint8_t> scramble_decrypt_data(
|
||||
const std::vector<uint8_t> &data_in, uint32_t data_width,
|
||||
uint32_t subst_perm_width, const std::vector<uint8_t> &addr,
|
||||
uint32_t addr_width, const std::vector<uint8_t> &nonce,
|
||||
const std::vector<uint8_t> &key, bool repeat_keystream);
|
||||
const std::vector<uint8_t> &key, bool repeat_keystream, bool use_sp_layer);
|
||||
|
||||
/** Encrypt scrambled data
|
||||
* @param data_in Byte vector of data to encrypt
|
||||
|
@ -60,12 +64,16 @@ std::vector<uint8_t> scramble_decrypt_data(
|
|||
* @param repeat_keystream Repeat the keystream of one single PRINCE instance if
|
||||
* set to true. Otherwise multiple PRINCE instances are
|
||||
* used.
|
||||
* @param use_sp_layer Use the S&P layer for data diffusion. In HW this is
|
||||
* disabled by default since it interacts adversely with
|
||||
* the end-to-end integrity scheme. See #20788 for
|
||||
* context.
|
||||
* @return Byte vector with encrypted data
|
||||
*/
|
||||
std::vector<uint8_t> scramble_encrypt_data(
|
||||
const std::vector<uint8_t> &data_in, uint32_t data_width,
|
||||
uint32_t subst_perm_width, const std::vector<uint8_t> &addr,
|
||||
uint32_t addr_width, const std::vector<uint8_t> &nonce,
|
||||
const std::vector<uint8_t> &key, bool repeat_keystream);
|
||||
const std::vector<uint8_t> &key, bool repeat_keystream, bool use_sp_layer);
|
||||
|
||||
#endif // OPENTITAN_HW_IP_PRIM_DV_PRIM_RAM_SCR_CPP_SCRAMBLE_MODEL_H_
|
||||
|
|
7
vendor/lowrisc_ip/ip/prim/lint/prim_trivium.vlt
vendored
Normal file
7
vendor/lowrisc_ip/ip/prim/lint/prim_trivium.vlt
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// waiver file for Trivium/Bivium stream cipher primitives
|
||||
|
||||
`verilator_config
|
5
vendor/lowrisc_ip/ip/prim/lint/prim_trivium.waiver
vendored
Normal file
5
vendor/lowrisc_ip/ip/prim/lint/prim_trivium.waiver
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
# Copyright lowRISC contributors.
|
||||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# waiver file for Trivium/Bivium stream cipher primitives
|
35
vendor/lowrisc_ip/ip/prim/pre_dv/prim_trivium/README.md
vendored
Normal file
35
vendor/lowrisc_ip/ip/prim/pre_dv/prim_trivium/README.md
vendored
Normal file
|
@ -0,0 +1,35 @@
|
|||
Trivium/Bivium Stream Cipher Verilator Testbench
|
||||
================================================
|
||||
|
||||
This directory contains a basic, scratch Verilator testbench targeting
|
||||
functional verification of the Trivium/Bivium stream cipher primitives
|
||||
during development.
|
||||
|
||||
How to build and run the testbench
|
||||
----------------------------------
|
||||
|
||||
From the OpenTitan top level execute
|
||||
|
||||
```sh
|
||||
fusesoc --cores-root=. run --setup --build \
|
||||
lowrisc:dv_verilator:prim_trivium_tb
|
||||
```
|
||||
to build the testbench and afterwards
|
||||
|
||||
```sh
|
||||
./build/lowrisc_dv_verilator_prim_trivium_tb_0/default-verilator/Vprim_trivium_tb \
|
||||
--trace
|
||||
```
|
||||
to run it.
|
||||
|
||||
Details of the testbench
|
||||
------------------------
|
||||
|
||||
- `rtl/prim_trivium_tb.sv`: SystemVerilog testbench, instantiates and
|
||||
drives multiple, differently parameterized instances of the primitives,
|
||||
checks key streams of the Trivium instances against a known good key
|
||||
stream, signals test end and result (pass/fail) to C++ via output ports.
|
||||
Change this file to e.g. configure different output widths.
|
||||
- `cpp/prim_trivium_tb.cc`: Contains main function and instantiation of
|
||||
SimCtrl, reads output ports of the testbench and signals simulation
|
||||
termination to Verilator.
|
61
vendor/lowrisc_ip/ip/prim/pre_dv/prim_trivium/cpp/prim_trivium_tb.cc
vendored
Normal file
61
vendor/lowrisc_ip/ip/prim/pre_dv/prim_trivium/cpp/prim_trivium_tb.cc
vendored
Normal file
|
@ -0,0 +1,61 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <signal.h>
|
||||
|
||||
#include "Vprim_trivium_tb.h"
|
||||
#include "sim_ctrl_extension.h"
|
||||
#include "verilated_toplevel.h"
|
||||
#include "verilator_sim_ctrl.h"
|
||||
|
||||
class PrimTriviumTB : public SimCtrlExtension {
|
||||
using SimCtrlExtension::SimCtrlExtension;
|
||||
|
||||
public:
|
||||
PrimTriviumTB(prim_trivium_tb *top);
|
||||
|
||||
void OnClock(unsigned long sim_time);
|
||||
|
||||
private:
|
||||
prim_trivium_tb *top_;
|
||||
};
|
||||
|
||||
// Constructor:
|
||||
// - Set up top_ ptr
|
||||
PrimTriviumTB::PrimTriviumTB(prim_trivium_tb *top)
|
||||
: SimCtrlExtension{}, top_(top) {}
|
||||
|
||||
// Function called once every clock cycle from SimCtrl
|
||||
void PrimTriviumTB::OnClock(unsigned long sim_time) {
|
||||
if (top_->test_done_o) {
|
||||
VerilatorSimCtrl::GetInstance().RequestStop(top_->test_passed_o);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int ret_code;
|
||||
|
||||
// Init verilog instance
|
||||
prim_trivium_tb top;
|
||||
|
||||
// Init sim
|
||||
VerilatorSimCtrl &simctrl = VerilatorSimCtrl::GetInstance();
|
||||
simctrl.SetTop(&top, &top.clk_i, &top.rst_ni,
|
||||
VerilatorSimCtrlFlags::ResetPolarityNegative);
|
||||
|
||||
// Create and register VerilatorSimCtrl extension
|
||||
PrimTriviumTB primtriviumtb(&top);
|
||||
simctrl.RegisterExtension(&primtriviumtb);
|
||||
|
||||
std::cout << "Simulation of Trivium/Bivium PRNG primitives" << std::endl
|
||||
<< "============================================" << std::endl
|
||||
<< std::endl;
|
||||
|
||||
// Get pass / fail from Verilator
|
||||
ret_code = simctrl.Exec(argc, argv).first;
|
||||
|
||||
return ret_code;
|
||||
}
|
51
vendor/lowrisc_ip/ip/prim/pre_dv/prim_trivium/prim_trivium_tb.core
vendored
Normal file
51
vendor/lowrisc_ip/ip/prim/pre_dv/prim_trivium/prim_trivium_tb.core
vendored
Normal file
|
@ -0,0 +1,51 @@
|
|||
CAPI=2:
|
||||
# Copyright lowRISC contributors.
|
||||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
name: "lowrisc:dv_verilator:prim_trivium_tb"
|
||||
description: "Trivium/Bivium Stream Cipher Verilator TB"
|
||||
filesets:
|
||||
files_rtl:
|
||||
depend:
|
||||
- lowrisc:prim:trivium
|
||||
files:
|
||||
- rtl/prim_trivium_tb.sv
|
||||
file_type: systemVerilogSource
|
||||
|
||||
files_dv_verilator:
|
||||
depend:
|
||||
- lowrisc:dv_verilator:simutil_verilator
|
||||
|
||||
files:
|
||||
- cpp/prim_trivium_tb.cc
|
||||
file_type: cppSource
|
||||
|
||||
targets:
|
||||
default:
|
||||
default_tool: verilator
|
||||
filesets:
|
||||
- files_rtl
|
||||
- files_dv_verilator
|
||||
toplevel: prim_trivium_tb
|
||||
tools:
|
||||
verilator:
|
||||
mode: cc
|
||||
verilator_options:
|
||||
# Disabling tracing reduces compile times by multiple times, but doesn't have a
|
||||
# huge influence on runtime performance. (Based on early observations.)
|
||||
- '--trace'
|
||||
- '--trace-fst' # this requires -DVM_TRACE_FMT_FST in CFLAGS below!
|
||||
- '--trace-structs'
|
||||
- '--trace-params'
|
||||
- '--trace-max-array 1024'
|
||||
# compiler flags
|
||||
#
|
||||
# -O
|
||||
# Optimization levels have a large impact on the runtime performance of the
|
||||
# simulation model. -O2 and -O3 are pretty similar, -Os is slower than -O2/-O3
|
||||
- '-CFLAGS "-std=c++11 -Wall -DVM_TRACE_FMT_FST -DTOPLEVEL_NAME=prim_trivium_tb -g -O0"'
|
||||
- '-LDFLAGS "-pthread -lutil -lelf"'
|
||||
- "-Wall"
|
||||
# XXX: Cleanup all warnings and remove this option
|
||||
# (or make it more fine-grained at least)
|
||||
- "-Wno-fatal"
|
428
vendor/lowrisc_ip/ip/prim/pre_dv/prim_trivium/rtl/prim_trivium_tb.sv
vendored
Normal file
428
vendor/lowrisc_ip/ip/prim/pre_dv/prim_trivium/rtl/prim_trivium_tb.sv
vendored
Normal file
|
@ -0,0 +1,428 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
// Scratch verification testbench for Trivium/Bivium stream cipher primitives
|
||||
|
||||
module prim_trivium_tb (
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
|
||||
output logic test_done_o,
|
||||
output logic test_passed_o
|
||||
);
|
||||
|
||||
import prim_trivium_pkg::*;
|
||||
|
||||
// TB configuration
|
||||
localparam int unsigned OutputWidth = 128;
|
||||
localparam int unsigned PartialSeedWidth = 32;
|
||||
|
||||
localparam int unsigned TriviumLastStatePartFractional =
|
||||
TriviumStateWidth % PartialSeedWidth != 0 ? 1 : 0;
|
||||
localparam int unsigned TriviumNumStateParts =
|
||||
TriviumStateWidth / PartialSeedWidth + TriviumLastStatePartFractional;
|
||||
localparam int unsigned BiviumLastStatePartFractional =
|
||||
BiviumStateWidth % PartialSeedWidth != 0 ? 1 : 0;
|
||||
localparam int unsigned BiviumNumStateParts =
|
||||
BiviumStateWidth / PartialSeedWidth + BiviumLastStatePartFractional;
|
||||
|
||||
// Counter to control the simulation.
|
||||
localparam int unsigned CountWidth = 10;
|
||||
logic [CountWidth-1:0] count_d, count_q;
|
||||
assign count_d = count_q + 10'd1;
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin : reg_count
|
||||
if (!rst_ni) begin
|
||||
count_q <= '0;
|
||||
end else begin
|
||||
count_q <= count_d;
|
||||
end
|
||||
end
|
||||
|
||||
/////////////
|
||||
// Trivium //
|
||||
/////////////
|
||||
// Test vectors seem to be available for Trivium only. Thus only the Trivium instances are really
|
||||
// verified against a known good key stream.
|
||||
|
||||
// In case the OutputWidth is not a divisor of 1152, the key stream is offset by the remainder of
|
||||
// this division. Thus, we skip the checking of the instance seeded with key and IV.
|
||||
localparam bit SkipSeedKeyIvInstance = 1152 % OutputWidth != '0;
|
||||
localparam int unsigned TestVectorOutLen = 512;
|
||||
localparam int unsigned NumOutputsToCheck = TestVectorOutLen / OutputWidth;
|
||||
localparam int unsigned NumOutputBitsToCheck = NumOutputsToCheck * OutputWidth;
|
||||
localparam int unsigned OutCtrWidth = prim_util_pkg::vbits(NumOutputsToCheck) + 1;
|
||||
localparam int NumInstances = 3;
|
||||
|
||||
logic trivium_en, trivium_seed_en;
|
||||
logic trivium_seed_ack_seed_state_partial;
|
||||
logic trivium_seed_done_seed_key_iv;
|
||||
logic trivium_seed_done_seed_state_full;
|
||||
logic trivium_seed_done_seed_state_partial;
|
||||
logic [KeyIvWidth-1:0] seed_key, seed_iv;
|
||||
logic [TriviumStateWidth-1:0] seed_state_full;
|
||||
logic [PartialSeedWidth-1:0] trivium_seed_state_partial;
|
||||
logic [OutputWidth-1:0] key_seed_key_iv, key_seed_state_full, key_seed_state_partial;
|
||||
|
||||
// Trivium test vectors generated using
|
||||
//
|
||||
// https://asecuritysite.com/encryption/trivium
|
||||
//
|
||||
// Notes on the test vectors from the above site:
|
||||
// - key and IV are 'byte' vectors starting with Byte n (most left) and ending with Byte 0 (most
|
||||
// right). Within each byte, the LSB is the most left bit and the MSB being the
|
||||
// most right bit.
|
||||
// - The key stream is a 'byte' vector starting with Byte 0 (most left) and ending with
|
||||
// Byte n (most right). Within each byte, the LSB is the most right bit and the MSB being the
|
||||
// most left bit.
|
||||
//
|
||||
// In this testbench, we use bit vectors only with LSB being most left and the MSB being most
|
||||
// right.
|
||||
logic [TestVectorOutLen-1:0] key_stream_expected;
|
||||
|
||||
// // key = 0
|
||||
// // iv = 0
|
||||
// localparam logic [KeyIvWidth-1:0] VECTOR_0_KEY = 80'h0000_0000_0000_0000_0000;
|
||||
// localparam logic [KeyIvWidth-1:0] VECTOR_0_IV = 80'h0000_0000_0000_0000_0000;
|
||||
// localparam logic [TestVectorOutLen-1:0] VECTOR_0_KEY_STREAM =
|
||||
// {128'hF2D4_A5B5_4C1A_8003_5980_746E_9849_5528,
|
||||
// 128'h9A59_A29A_751A_4C2B_38B7_6802_0392_52F7,
|
||||
// 128'hCDE9_B2A1_0F79_A8E7_2DCF_0719_1603_3256,
|
||||
// 128'h7FC9_9F23_4E2E_7A51_1B05_5958_26BF_E0FB};
|
||||
// localparam logic [TriviumStateWidth-1:0] VECTOR_0_STATE =
|
||||
// {96'h92AC_487E_267F_5871_D3A1_896D,
|
||||
// 96'hF514_AD2F_EA84_1320_40AE_4058,
|
||||
// 96'hA21B_38EC_692A_E61D_7493_1A85};
|
||||
|
||||
// // key = 8000_0000_0000_0000_0000
|
||||
// // iv = 0
|
||||
// localparam logic [KeyIvWidth-1:0] VECTOR_1_KEY = 80'h0100_0000_0000_0000_0000;
|
||||
// localparam logic [KeyIvWidth-1:0] VECTOR_1_IV = 80'h0000_0000_0000_0000_0000;
|
||||
// localparam logic [TestVectorOutLen-1:0] VECTOR_1_KEY_STREAM =
|
||||
// {128'hF980_FC54_74EF_E87B_B962_6ACC_CC20_FF98,
|
||||
// 128'h807F_CFCE_928F_6CE0_EB21_0961_15F5_FBD2,
|
||||
// 128'h649A_F249_C241_2055_0175_C864_1465_7BBB,
|
||||
// 128'h0D54_2044_3AF1_8DAF_9C7A_0D73_FF86_EB38};
|
||||
// localparam logic [TriviumStateWidth-1:0] VECTOR_1_STATE =
|
||||
// {96'hC7D7_C89B_CC06_725B_3D94_7181,
|
||||
// 96'h06F2_A065_6422_AF1F_A457_B81F,
|
||||
// 96'h0D25_16A9_D565_893A_64C1_E50E};
|
||||
|
||||
// key = 0A5D_B003_56A9_FC4F_A2F5
|
||||
// iv = 1F86_ED54_BB22_89F0_57BE
|
||||
localparam logic [KeyIvWidth-1:0] VECTOR_2_KEY = 80'h50BA_0DC0_6A95_3FF2_45AF;
|
||||
localparam logic [KeyIvWidth-1:0] VECTOR_2_IV = 80'hF861_B72A_DD44_910F_EA7D;
|
||||
localparam logic [TestVectorOutLen-1:0] VECTOR_2_KEY_STREAM =
|
||||
{128'h7258_8CB7_89E3_8615_0DFC_DA03_BDA3_A5AE,
|
||||
128'h2F98_426C_4C75_C0F1_3BFB_6B2D_E2DD_6E54,
|
||||
128'hB8F0_AB03_51B7_F538_3C17_FAC1_E8B0_913B,
|
||||
128'h1838_E884_56D9_D2D0_ADCB_4B13_C510_94DE};
|
||||
localparam logic [TriviumStateWidth-1:0] VECTOR_2_STATE =
|
||||
{96'hE843_DB60_EB48_14D1_C198_620D,
|
||||
96'hF21B_0322_0BAD_DAD5_A15A_3958,
|
||||
96'hBC97_5171_D8C0_4C75_B395_11C4};
|
||||
|
||||
assign seed_key = VECTOR_2_KEY;
|
||||
assign seed_iv = VECTOR_2_IV;
|
||||
assign seed_state_full = VECTOR_2_STATE;
|
||||
assign key_stream_expected = VECTOR_2_KEY_STREAM;
|
||||
|
||||
// Instantiate DUTs
|
||||
prim_trivium #(
|
||||
.BiviumVariant(0),
|
||||
.OutputWidth (OutputWidth),
|
||||
.SeedType (SeedTypeKeyIv)
|
||||
) u_prim_trivium_seed_key_iv (
|
||||
.clk_i (clk_i),
|
||||
.rst_ni(rst_ni),
|
||||
|
||||
.en_i (trivium_en),
|
||||
.allow_lockup_i (1'b0),
|
||||
.seed_en_i (trivium_seed_en),
|
||||
.seed_done_o (trivium_seed_done_seed_key_iv),
|
||||
.seed_req_o (),
|
||||
.seed_ack_i (trivium_seed_en),
|
||||
.seed_key_i (seed_key),
|
||||
.seed_iv_i (seed_iv),
|
||||
.seed_state_full_i ('0), // unused
|
||||
.seed_state_partial_i('0), // unused
|
||||
|
||||
.key_o(key_seed_key_iv),
|
||||
.err_o()
|
||||
);
|
||||
|
||||
prim_trivium #(
|
||||
.BiviumVariant(0),
|
||||
.OutputWidth (OutputWidth),
|
||||
.SeedType (SeedTypeStateFull)
|
||||
) u_prim_trivium_seed_state_full (
|
||||
.clk_i (clk_i),
|
||||
.rst_ni(rst_ni),
|
||||
|
||||
.en_i (trivium_en),
|
||||
.allow_lockup_i (1'b0),
|
||||
.seed_en_i (trivium_seed_en),
|
||||
.seed_done_o (trivium_seed_done_seed_state_full),
|
||||
.seed_req_o (),
|
||||
.seed_ack_i (trivium_seed_en),
|
||||
.seed_key_i ('0), // unused
|
||||
.seed_iv_i ('0), // unused
|
||||
.seed_state_full_i (seed_state_full),
|
||||
.seed_state_partial_i('0), // unused
|
||||
|
||||
.key_o(key_seed_state_full),
|
||||
.err_o()
|
||||
);
|
||||
|
||||
prim_trivium #(
|
||||
.BiviumVariant (0),
|
||||
.OutputWidth (OutputWidth),
|
||||
.SeedType (SeedTypeStatePartial),
|
||||
.PartialSeedWidth(PartialSeedWidth)
|
||||
) u_prim_trivium_seed_state_partial (
|
||||
.clk_i (clk_i),
|
||||
.rst_ni(rst_ni),
|
||||
|
||||
.en_i (trivium_en),
|
||||
.allow_lockup_i (1'b0),
|
||||
.seed_en_i (trivium_seed_en),
|
||||
.seed_done_o (trivium_seed_done_seed_state_partial),
|
||||
.seed_req_o (),
|
||||
.seed_ack_i (trivium_seed_ack_seed_state_partial),
|
||||
.seed_key_i ('0), // unused
|
||||
.seed_iv_i ('0), // unused
|
||||
.seed_state_full_i ('0), // unused
|
||||
.seed_state_partial_i(trivium_seed_state_partial),
|
||||
|
||||
.key_o(key_seed_state_partial),
|
||||
.err_o()
|
||||
);
|
||||
|
||||
// Tracking of seed_done
|
||||
logic [NumInstances-1:0] trivium_seed_done_d, trivium_seed_done_q;
|
||||
assign trivium_seed_done_d = (trivium_seed_done_q &
|
||||
// Clear back to zero upon staring a new reseed operation.
|
||||
{NumInstances{~trivium_seed_en}}) |
|
||||
// Register finishing of reseed operation.
|
||||
{trivium_seed_done_seed_state_partial,
|
||||
trivium_seed_done_seed_state_full,
|
||||
trivium_seed_done_seed_key_iv};
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin : reg_trivium_seed_done
|
||||
if (!rst_ni) begin
|
||||
trivium_seed_done_q <= '0;
|
||||
end else begin
|
||||
trivium_seed_done_q <= trivium_seed_done_d;
|
||||
end
|
||||
end
|
||||
|
||||
// Start the reseed operation right after coming out of reset.
|
||||
assign trivium_seed_en = count_q == 10'd1;
|
||||
// Start running once all instances have finished the reseed operation.
|
||||
assign trivium_en = &trivium_seed_done_q;
|
||||
|
||||
// Provide the 9 partial seed parts.
|
||||
assign trivium_seed_ack_seed_state_partial =
|
||||
(count_q >= 10'd1) && (count_q < 10'd1 + TriviumNumStateParts[CountWidth-1:0]);
|
||||
assign trivium_seed_state_partial =
|
||||
seed_state_full[({22'h0, count_q} - 32'd1) * PartialSeedWidth +: PartialSeedWidth];
|
||||
|
||||
/////////////////////////////////
|
||||
// Record generated key streams//
|
||||
/////////////////////////////////
|
||||
logic record;
|
||||
assign record = trivium_en & (out_ctr_q < NumOutputsToCheck[OutCtrWidth-1:0]);
|
||||
|
||||
logic [OutCtrWidth-1:0] out_ctr_d, out_ctr_q;
|
||||
assign out_ctr_d = record ? out_ctr_q + 1'b1 : out_ctr_q;
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin : reg_out_ctr
|
||||
if (!rst_ni) begin
|
||||
out_ctr_q <= '0;
|
||||
end else begin
|
||||
out_ctr_q <= out_ctr_d;
|
||||
end
|
||||
end
|
||||
|
||||
logic [TestVectorOutLen-1:0] key_stream_actual_d [NumInstances];
|
||||
logic [TestVectorOutLen-1:0] key_stream_actual_q [NumInstances];
|
||||
always_comb begin
|
||||
key_stream_actual_d = key_stream_actual_q;
|
||||
if (record) begin
|
||||
key_stream_actual_d[0][out_ctr_q * OutputWidth +: OutputWidth] = key_seed_key_iv;
|
||||
key_stream_actual_d[1][out_ctr_q * OutputWidth +: OutputWidth] = key_seed_state_full;
|
||||
key_stream_actual_d[2][out_ctr_q * OutputWidth +: OutputWidth] = key_seed_state_partial;
|
||||
end
|
||||
end
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin : reg_key_stream_actual
|
||||
if (!rst_ni) begin
|
||||
key_stream_actual_q <= '{default: '0};
|
||||
end else begin
|
||||
key_stream_actual_q <= key_stream_actual_d;
|
||||
end
|
||||
end
|
||||
|
||||
///////////////////////////////////////////////
|
||||
// Check responses, signal end of simulation //
|
||||
///////////////////////////////////////////////
|
||||
logic mismatch;
|
||||
always_ff @(posedge clk_i) begin : tb_ctrl
|
||||
test_done_o <= 1'b0;
|
||||
test_passed_o <= 1'b1;
|
||||
|
||||
if (out_ctr_q == NumOutputsToCheck[OutCtrWidth-1:0]) begin
|
||||
mismatch <= 1'b0;
|
||||
for (int i = 0; i < NumInstances; i++) begin
|
||||
if (!SkipSeedKeyIvInstance || i > 0) begin
|
||||
if (key_stream_expected[NumOutputBitsToCheck-1:0]
|
||||
== key_stream_actual_q[i][NumOutputBitsToCheck-1:0]) begin
|
||||
$display("\nSUCCESS: Observed key stream of instance %1d matches expected data.", i);
|
||||
end else begin
|
||||
$display("\nERROR: Obeserved key stream of instance %1d doesn't match expected data.",
|
||||
i);
|
||||
mismatch <= 1'b1;
|
||||
end
|
||||
end
|
||||
end
|
||||
$display("Finishing simulation now.\n");
|
||||
test_passed_o <= ~mismatch;
|
||||
test_done_o <= 1'b1;
|
||||
end
|
||||
|
||||
if (count_q == 10'd1000) begin
|
||||
$display("\nDONE");
|
||||
test_done_o <= 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
////////////
|
||||
// Bivium //
|
||||
////////////
|
||||
// No test vectors seem to be available for Bivium. The 3 instances below are not checked against
|
||||
// a known good key stream. It's still useful to instantiate the 3 different Bivium variants for
|
||||
// visual inspection, for checking Verilator lint of all three variants, and for inspecting the
|
||||
// partial reseed behavior while the primitive is running.
|
||||
|
||||
logic bivium_en, bivium_seed_en;
|
||||
logic bivium_seed_done_seed_key_iv;
|
||||
logic bivium_seed_done_seed_state_full;
|
||||
logic bivium_seed_done_seed_state_partial;
|
||||
logic bivium_seed_en_seed_state_partial, bivium_seed_ack_seed_state_partial;
|
||||
logic [PartialSeedWidth-1:0] bivium_seed_state_partial;
|
||||
|
||||
// Instantiate DUTs
|
||||
prim_trivium #(
|
||||
.BiviumVariant(1),
|
||||
.OutputWidth (OutputWidth),
|
||||
.SeedType (SeedTypeKeyIv)
|
||||
) u_prim_bivium_seed_key_iv (
|
||||
.clk_i (clk_i),
|
||||
.rst_ni(rst_ni),
|
||||
|
||||
.en_i (bivium_en),
|
||||
.allow_lockup_i (1'b0),
|
||||
.seed_en_i (bivium_seed_en),
|
||||
.seed_done_o (bivium_seed_done_seed_key_iv),
|
||||
.seed_req_o (),
|
||||
.seed_ack_i (bivium_seed_en),
|
||||
.seed_key_i (seed_key),
|
||||
.seed_iv_i (seed_iv),
|
||||
.seed_state_full_i ('0), // unused
|
||||
.seed_state_partial_i('0), // unused
|
||||
|
||||
.key_o(key_seed_key_iv),
|
||||
.err_o()
|
||||
);
|
||||
|
||||
prim_trivium #(
|
||||
.BiviumVariant(1),
|
||||
.OutputWidth (OutputWidth),
|
||||
.SeedType (SeedTypeStateFull)
|
||||
) u_prim_bivium_seed_state_full (
|
||||
.clk_i (clk_i),
|
||||
.rst_ni(rst_ni),
|
||||
|
||||
.en_i (bivium_en),
|
||||
.allow_lockup_i (1'b0),
|
||||
.seed_en_i (bivium_seed_en),
|
||||
.seed_done_o (bivium_seed_done_seed_state_full),
|
||||
.seed_req_o (),
|
||||
.seed_ack_i (bivium_seed_en),
|
||||
.seed_key_i ('0), // unused
|
||||
.seed_iv_i ('0), // unused
|
||||
.seed_state_full_i (seed_state_full[BiviumStateWidth-1:0]),
|
||||
.seed_state_partial_i('0), // unused
|
||||
|
||||
.key_o(key_seed_state_full),
|
||||
.err_o()
|
||||
);
|
||||
|
||||
prim_trivium #(
|
||||
.BiviumVariant (1),
|
||||
.OutputWidth (OutputWidth),
|
||||
.StrictLockupProtection(0),
|
||||
.SeedType (SeedTypeStatePartial),
|
||||
.PartialSeedWidth (PartialSeedWidth)
|
||||
) u_prim_bivium_seed_state_partial (
|
||||
.clk_i (clk_i),
|
||||
.rst_ni(rst_ni),
|
||||
|
||||
.en_i (bivium_en),
|
||||
.allow_lockup_i (1'b1),
|
||||
.seed_en_i (bivium_seed_en_seed_state_partial),
|
||||
.seed_done_o (bivium_seed_done_seed_state_partial),
|
||||
.seed_req_o (),
|
||||
.seed_ack_i (bivium_seed_ack_seed_state_partial),
|
||||
.seed_key_i ('0), // unused
|
||||
.seed_iv_i ('0), // unused
|
||||
.seed_state_full_i ('0), // unused
|
||||
.seed_state_partial_i(bivium_seed_state_partial),
|
||||
|
||||
.key_o(),
|
||||
.err_o()
|
||||
);
|
||||
|
||||
// Tracking of seed_done
|
||||
logic [NumInstances-1:0] bivium_seed_done_d, bivium_seed_done_q;
|
||||
assign bivium_seed_done_d = (bivium_seed_done_q &
|
||||
// Clear back to zero upon staring a new reseed operation.
|
||||
{NumInstances{~bivium_seed_en}}) |
|
||||
// Register finishing of reseed operation.
|
||||
{bivium_seed_done_seed_state_partial,
|
||||
bivium_seed_done_seed_state_full,
|
||||
bivium_seed_done_seed_key_iv};
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin : reg_bivium_seed_done
|
||||
if (!rst_ni) begin
|
||||
bivium_seed_done_q <= '0;
|
||||
end else begin
|
||||
bivium_seed_done_q <= bivium_seed_done_d;
|
||||
end
|
||||
end
|
||||
|
||||
// Start the reseed operation right after coming out of reset.
|
||||
assign bivium_seed_en = count_q == 10'd1;
|
||||
// Start running once all instances have finished the reseed operation.
|
||||
assign bivium_en = &bivium_seed_done_q;
|
||||
|
||||
// The last instance is handled separately:
|
||||
// First, we put the Bivium primitive into an all-zero state. Then, a single PartialSeedWidth
|
||||
// seed is provided while the primitive is running. This allows inpsecting the diffusion pattern
|
||||
// of the primitive (depending on the OutputWidth).
|
||||
|
||||
// Register to latch counter value when initial reseed operation finishes. This depends on
|
||||
// PartialSeedWidth and OutputWidth.
|
||||
logic [CountWidth-1:0] count_seed_done_q;
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin : reg_count_seed_done
|
||||
if (!rst_ni) begin
|
||||
count_seed_done_q <= '0;
|
||||
end else if (&bivium_seed_done_q && count_seed_done_q == '0) begin
|
||||
count_seed_done_q <= count_q;
|
||||
end
|
||||
end
|
||||
|
||||
assign bivium_seed_en_seed_state_partial = bivium_seed_en ||
|
||||
((count_seed_done_q != 0) && (count_q >= count_seed_done_q + 10'd1));
|
||||
assign bivium_seed_ack_seed_state_partial =
|
||||
((count_q >= 10'd1) && (count_q < 10'd1 + BiviumNumStateParts[CountWidth-1:0])) ||
|
||||
bivium_seed_en_seed_state_partial;
|
||||
assign bivium_seed_state_partial = &bivium_seed_done_q ? '1 : '0;
|
||||
|
||||
endmodule
|
21
vendor/lowrisc_ip/ip/prim/prim_edn_req.core
vendored
21
vendor/lowrisc_ip/ip/prim/prim_edn_req.core
vendored
|
@ -1,21 +0,0 @@
|
|||
CAPI=2:
|
||||
# Copyright lowRISC contributors.
|
||||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
name: "lowrisc:prim:edn_req:0.1"
|
||||
description: "EDN synchronization and word packing IP."
|
||||
filesets:
|
||||
files_rtl:
|
||||
depend:
|
||||
- lowrisc:prim:all
|
||||
- lowrisc:prim:assert
|
||||
- lowrisc:ip:edn_pkg
|
||||
files:
|
||||
- rtl/prim_edn_req.sv
|
||||
file_type: systemVerilogSource
|
||||
|
||||
targets:
|
||||
default:
|
||||
filesets:
|
||||
- files_rtl
|
44
vendor/lowrisc_ip/ip/prim/prim_trivium.core
vendored
Normal file
44
vendor/lowrisc_ip/ip/prim/prim_trivium.core
vendored
Normal file
|
@ -0,0 +1,44 @@
|
|||
CAPI=2:
|
||||
# Copyright lowRISC contributors.
|
||||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
name: "lowrisc:prim:trivium:0.1"
|
||||
description: "Trivium/Bivium Stream Cipher Primitives"
|
||||
filesets:
|
||||
files_rtl:
|
||||
depend:
|
||||
- lowrisc:prim:assert
|
||||
- lowrisc:prim:util
|
||||
files:
|
||||
- rtl/prim_trivium_pkg.sv
|
||||
- rtl/prim_trivium.sv
|
||||
file_type: systemVerilogSource
|
||||
|
||||
files_verilator_waiver:
|
||||
depend:
|
||||
# common waivers
|
||||
- lowrisc:lint:common
|
||||
files:
|
||||
- lint/prim_trivium.vlt
|
||||
file_type: vlt
|
||||
|
||||
files_ascentlint_waiver:
|
||||
depend:
|
||||
# common waivers
|
||||
- lowrisc:lint:common
|
||||
files:
|
||||
- lint/prim_trivium.waiver
|
||||
file_type: waiver
|
||||
|
||||
files_veriblelint_waiver:
|
||||
depend:
|
||||
# common waivers
|
||||
- lowrisc:lint:common
|
||||
|
||||
targets:
|
||||
default:
|
||||
filesets:
|
||||
- tool_verilator ? (files_verilator_waiver)
|
||||
- tool_ascentlint ? (files_ascentlint_waiver)
|
||||
- tool_veriblelint ? (files_veriblelint_waiver)
|
||||
- files_rtl
|
215
vendor/lowrisc_ip/ip/prim/rtl/prim_edn_req.sv
vendored
215
vendor/lowrisc_ip/ip/prim/rtl/prim_edn_req.sv
vendored
|
@ -1,215 +0,0 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
// This module can be used as a "gadget" to adapt the native 32bit width of the EDN network
|
||||
// locally to the width needed by the consuming logic. For example, if the local consumer
|
||||
// needs 128bit, this module would request four 32 bit words from EDN and stack them accordingly.
|
||||
//
|
||||
// The module also uses a req/ack synchronizer to synchronize the EDN data over to the local
|
||||
// clock domain. Note that this assumes that the EDN data bus remains stable between subsequent
|
||||
// requests.
|
||||
//
|
||||
|
||||
`include "prim_assert.sv"
|
||||
|
||||
module prim_edn_req
|
||||
import prim_alert_pkg::*;
|
||||
#(
|
||||
parameter int OutWidth = 32,
|
||||
// Repetition check for incoming edn data
|
||||
parameter bit RepCheck = 0,
|
||||
// Disable reset-related assertion checks inside prim_sync_reqack primitives.
|
||||
parameter bit EnRstChks = 0,
|
||||
|
||||
// EDN Request latency checker
|
||||
//
|
||||
// Each consumer IP may have the maximum expected latency. MaxLatency
|
||||
// parameter describes the expected latency in terms of the consumer clock
|
||||
// cycles. If the edn request comes later than that, the assertion will be
|
||||
// fired.
|
||||
//
|
||||
// The default value is 0, which disables the assertion.
|
||||
parameter int unsigned MaxLatency = 0
|
||||
) (
|
||||
// Design side
|
||||
input clk_i,
|
||||
input rst_ni,
|
||||
input req_chk_i, // Used for gating assertions. Drive to 1 during normal
|
||||
// operation.
|
||||
input req_i,
|
||||
output logic ack_o,
|
||||
output logic [OutWidth-1:0] data_o,
|
||||
output logic fips_o,
|
||||
output logic err_o, // current data_o failed repetition check
|
||||
// EDN side
|
||||
input clk_edn_i,
|
||||
input rst_edn_ni,
|
||||
output edn_pkg::edn_req_t edn_o,
|
||||
input edn_pkg::edn_rsp_t edn_i
|
||||
);
|
||||
|
||||
// Stop requesting words from EDN once desired amount of data is available.
|
||||
logic word_req, word_ack;
|
||||
assign word_req = req_i & ~ack_o;
|
||||
|
||||
logic [edn_pkg::ENDPOINT_BUS_WIDTH-1:0] word_data;
|
||||
logic word_fips;
|
||||
localparam int SyncWidth = $bits({edn_i.edn_fips, edn_i.edn_bus});
|
||||
prim_sync_reqack_data #(
|
||||
.Width(SyncWidth),
|
||||
.EnRstChks(EnRstChks),
|
||||
.DataSrc2Dst(1'b0),
|
||||
.DataReg(1'b0)
|
||||
) u_prim_sync_reqack_data (
|
||||
.clk_src_i ( clk_i ),
|
||||
.rst_src_ni ( rst_ni ),
|
||||
.clk_dst_i ( clk_edn_i ),
|
||||
.rst_dst_ni ( rst_edn_ni ),
|
||||
.req_chk_i ( req_chk_i ),
|
||||
.src_req_i ( word_req ),
|
||||
.src_ack_o ( word_ack ),
|
||||
.dst_req_o ( edn_o.edn_req ),
|
||||
.dst_ack_i ( edn_i.edn_ack ),
|
||||
.data_i ( {edn_i.edn_fips, edn_i.edn_bus} ),
|
||||
.data_o ( {word_fips, word_data} )
|
||||
);
|
||||
|
||||
if (RepCheck) begin : gen_rep_chk
|
||||
logic [edn_pkg::ENDPOINT_BUS_WIDTH-1:0] word_data_q;
|
||||
always_ff @(posedge clk_i) begin
|
||||
if (word_ack) begin
|
||||
word_data_q <= word_data;
|
||||
end
|
||||
end
|
||||
|
||||
// do not check until we have received at least the first entry
|
||||
logic chk_rep;
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if (!rst_ni) begin
|
||||
chk_rep <= '0;
|
||||
end else if (word_ack) begin
|
||||
chk_rep <= 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
// Need to track if any of the packed words has failed the repetition check, i.e., is identical
|
||||
// to the last packed word.
|
||||
logic err_d, err_q;
|
||||
assign err_d = (req_i && ack_o) ? 1'b0 : // clear
|
||||
(chk_rep && word_ack && word_data == word_data_q) ? 1'b1 : // set
|
||||
err_q; // keep
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if (!rst_ni) begin
|
||||
err_q <= 1'b0;
|
||||
end else begin
|
||||
err_q <= err_d;
|
||||
end
|
||||
end
|
||||
assign err_o = err_q;
|
||||
|
||||
end else begin : gen_no_rep_chk // block: gen_rep_chk
|
||||
assign err_o = '0;
|
||||
end
|
||||
|
||||
prim_packer_fifo #(
|
||||
.InW(edn_pkg::ENDPOINT_BUS_WIDTH),
|
||||
.OutW(OutWidth),
|
||||
.ClearOnRead(1'b0)
|
||||
) u_prim_packer_fifo (
|
||||
.clk_i,
|
||||
.rst_ni,
|
||||
.clr_i ( 1'b0 ), // not needed
|
||||
.wvalid_i ( word_ack ),
|
||||
.wdata_i ( word_data ),
|
||||
// no need for backpressure since we're always ready to
|
||||
// sink data at this point.
|
||||
.wready_o ( ),
|
||||
.rvalid_o ( ack_o ),
|
||||
.rdata_o ( data_o ),
|
||||
// we're always ready to receive the packed output word
|
||||
// at this point.
|
||||
.rready_i ( 1'b1 ),
|
||||
.depth_o ( )
|
||||
);
|
||||
|
||||
// Need to track if any of the packed words has been generated with a pre-FIPS seed, i.e., has
|
||||
// fips == 1'b0.
|
||||
logic fips_d, fips_q;
|
||||
assign fips_d = (req_i && ack_o) ? 1'b1 : // clear
|
||||
(word_ack) ? fips_q & word_fips : // accumulate
|
||||
fips_q; // keep
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if (!rst_ni) begin
|
||||
fips_q <= 1'b1;
|
||||
end else begin
|
||||
fips_q <= fips_d;
|
||||
end
|
||||
end
|
||||
assign fips_o = fips_q;
|
||||
|
||||
////////////////
|
||||
// Assertions //
|
||||
////////////////
|
||||
|
||||
// Check EDN data is valid: Not all zeros, all ones, or not the same as previous data.
|
||||
`ifdef INC_ASSERT
|
||||
//VCS coverage off
|
||||
// pragma coverage off
|
||||
|
||||
logic [OutWidth-1:0] data_prev, data_curr;
|
||||
|
||||
always_ff @(posedge ack_o or negedge rst_ni) begin
|
||||
if (!rst_ni) begin
|
||||
data_prev <= '0;
|
||||
data_curr <= '0;
|
||||
end else if (ack_o) begin
|
||||
data_curr <= data_o;
|
||||
data_prev <= data_curr;
|
||||
end
|
||||
end
|
||||
//VCS coverage on
|
||||
// pragma coverage on
|
||||
|
||||
`ASSERT(DataOutputValid_A, ack_o |-> (data_o != 0) && (data_o != '1))
|
||||
`ASSERT(DataOutputDiffFromPrev_A, data_prev != 0 |-> data_prev != data_o)
|
||||
`endif
|
||||
|
||||
// EDN Max Latency Checker
|
||||
`ifndef SYNTHESIS
|
||||
if (MaxLatency != 0) begin: g_maxlatency_assertion
|
||||
//VCS coverage off
|
||||
// pragma coverage off
|
||||
localparam int unsigned LatencyW = $clog2(MaxLatency+1);
|
||||
logic [LatencyW-1:0] latency_counter;
|
||||
logic reset_counter;
|
||||
logic enable_counter;
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if (!rst_ni) latency_counter <= '0;
|
||||
else if (reset_counter) latency_counter <= '0;
|
||||
else if (enable_counter) latency_counter <= latency_counter + 1'b1;
|
||||
end
|
||||
|
||||
assign reset_counter = ack_o;
|
||||
assign enable_counter = req_i;
|
||||
//VCS coverage on
|
||||
// pragma coverage on
|
||||
|
||||
`ASSERT(MaxLatency_A, latency_counter <= MaxLatency)
|
||||
|
||||
// TODO: Is it worth to check req & ack pair?
|
||||
// _________________________________
|
||||
// req __/ \______
|
||||
// ____
|
||||
// ack ____________________________________/ \_
|
||||
//
|
||||
// | error
|
||||
|
||||
end // g_maxlatency_assertion
|
||||
`else // SYNTHESIS
|
||||
logic unused_param_maxlatency;
|
||||
assign unused_param_maxlatency = ^MaxLatency;
|
||||
`endif // SYNTHESIS
|
||||
|
||||
endmodule : prim_edn_req
|
|
@ -34,8 +34,11 @@ module prim_ram_1p_scr import prim_ram_1p_pkg::*; #(
|
|||
// to 2*5 + 1 effective rounds. Setting this to 2 halves this to approximately 5 effective rounds.
|
||||
// Number of PRINCE half rounds, can be [1..5]
|
||||
parameter int NumPrinceRoundsHalf = 2,
|
||||
// Number of extra diffusion rounds. Setting this to 0 to disable diffusion.
|
||||
parameter int NumDiffRounds = 2,
|
||||
// Number of extra diffusion rounds. Setting this to 0 to disables diffusion.
|
||||
// NOTE: this is zero by default, since the non-linear transformation of data bits can interact
|
||||
// adversely with end-to-end ECC integrity. Only enable this if you know what you are doing
|
||||
// (e.g. using this primitive in a different context with byte parity). See #20788 for context.
|
||||
parameter int NumDiffRounds = 0,
|
||||
// This parameter governs the block-width of additional diffusion layers.
|
||||
// For intra-byte diffusion, set this parameter to 8.
|
||||
parameter int DiffWidth = DataBitsPerMask,
|
||||
|
|
317
vendor/lowrisc_ip/ip/prim/rtl/prim_trivium.sv
vendored
Normal file
317
vendor/lowrisc_ip/ip/prim/rtl/prim_trivium.sv
vendored
Normal file
|
@ -0,0 +1,317 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Trivium and Bivium stream cipher primitives
|
||||
//
|
||||
// This module implements the Trivium [1] and its reduced variant Bivium [2] (more precisely
|
||||
// Bivium B) stream cipher primitives. Internally, they use 3 (Trivium) or 2 (Bivium) non-linear
|
||||
// feedback shift registers (NFSRs). The number of output bits produced per update can flexibly
|
||||
// be tuned using the OutputWidth parameter to match the needs of integrators. Up to an output
|
||||
// width of 64 bits, the critical path stays unchanged. For output widths above 64 bits, the
|
||||
// critical path starts to increase. The asymptotic area of the two primitives is 30 GE / output
|
||||
// bit (Trivium) and 20 GE / output bit (Bivium). For a thorough analysis of the two primitives
|
||||
// including security evaluation, as well as area and critical path figures, refer to [3].
|
||||
//
|
||||
// As thoroughly analyzed in [3], these primitives are suitable to be used as pseudo-random
|
||||
// number generators for masking countermeasures in hardware.
|
||||
//
|
||||
// This implementation supports three different reseeding interfaces which can be selected using
|
||||
// the SeedType parameter:
|
||||
// 1. SeedTypeKeyIv: 2 x 80 bits for key and IV need to be provided. Before the key stream becomes
|
||||
// usable, the primitive needs to be updated 1152 / OutputWidth (Trivium) or
|
||||
// 708 / OutputWidth (Bivium) times. These initial updates are performed automatically by the
|
||||
// primitives. Once the reseeding and the following initialization are done, this is indicated
|
||||
// with the seed_done_o output.
|
||||
// 2. SeedTypeStateFull: The full 288-bit (Trivium) or 177-bit (Bivium) state is reseeded in one
|
||||
// shot.
|
||||
// 3. SeedTypeStatePartial: PartialSeedWidth bits at a time are injected into the state. The
|
||||
// primitive latches the seed_en_i signal and keeps requesting entropy until every
|
||||
// PartialSeedWidth-wide part of the state has been overwritten once.
|
||||
// To enable updating the primitive and using the key stream during the reseed operation, the
|
||||
// number of output bits produced per update (OutputWidth) should be greater than the width of
|
||||
// the smallest NFSR in the primitve (MinNfsrWidth = 84). Thanks to the strong diffusion
|
||||
// properties of the primitives, the majority of state and key stream bits change after
|
||||
// reseeding the first state part and performing the first couple of updates if OutputWidth is
|
||||
// chosen sufficiently large. For Bivium, a quick evaluation hints that for OutputWidth equal
|
||||
// to 84, the key stream seems usable after 3 updates and most state bits seem to change after
|
||||
// 5 updates. For OutputWidth equal to 160, the key stream seems usable after only 2 updates and
|
||||
// most state bits seem to change after 3 updates.
|
||||
// If the next PartialSeedWidth bits of entropy arrive after having done at least one update
|
||||
// but the new entropy hasn't sufficiently diffused yet into the state, there is a risk that
|
||||
// previously injected entropy bits are partially or completely overwritten. It is the job of
|
||||
// the integrator to ensure sufficiently many updates are performed between reseeding state
|
||||
// parts. In practice, this should be relatively simple as there is typically a minimal latency
|
||||
// between receiving entropy bits, e.g., due to clock domain crossings in the system.
|
||||
// Independently of the chosen OutputWidth parameter, it's always safe to reseed the primitive
|
||||
// while it's completely idle.
|
||||
//
|
||||
// For details, see the following specifications and papers:
|
||||
// [1] De Canniere, "Trivium Specifications" available at
|
||||
// https://www.ecrypt.eu.org/stream/p3ciphers/trivium/trivium_p3.pdf
|
||||
// [2] Raddum "Cryptanalytic Results on Trivium" available at
|
||||
// https://www.ecrypt.eu.org/stream/papersdir/2006/039.ps
|
||||
// [3] Cassiers, "Randomness Generation for Secure Hardware Masking - Unrolled Trivium to the
|
||||
// Rescue" available at https://eprint.iacr.org/2023/1134
|
||||
|
||||
`include "prim_assert.sv"
|
||||
|
||||
module prim_trivium import prim_trivium_pkg::*;
|
||||
#(
|
||||
parameter bit BiviumVariant = 0, // 0: Trivium, 1: Bivium
|
||||
parameter int unsigned OutputWidth = 64, // Number of output bits generated per update.
|
||||
parameter bit StrictLockupProtection = 1, // Upon entering an all zero state, 1: always
|
||||
// restore to the default seed, or 0: allow
|
||||
// to keep the all zero state if requested by
|
||||
// allow_lockup_i.
|
||||
parameter seed_type_e SeedType = SeedTypeStateFull, // Reseeding inteface selection, see
|
||||
// prim_trivium_pkg.sv for possible values.
|
||||
parameter int unsigned PartialSeedWidth = PartialSeedWidthDefault,
|
||||
|
||||
// derived parameter
|
||||
localparam int unsigned StateWidth = BiviumVariant ? BiviumStateWidth : TriviumStateWidth,
|
||||
|
||||
parameter trivium_lfsr_seed_t RndCnstTriviumLfsrSeed = RndCnstTriviumLfsrSeedDefault,
|
||||
|
||||
// derived parameter
|
||||
localparam logic [StateWidth-1:0] StateSeed = RndCnstTriviumLfsrSeed[StateWidth-1:0]
|
||||
) (
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
|
||||
input logic en_i, // Update the primitive.
|
||||
input logic allow_lockup_i, // Allow locking up in all zero state.
|
||||
// Only taken into account if
|
||||
// LockupParameter = 0
|
||||
input logic seed_en_i, // Start reseeding (pulse or level).
|
||||
output logic seed_done_o, // Reseeding is done (pulse).
|
||||
output logic seed_req_o, // Seed REQ handshake signal
|
||||
input logic seed_ack_i, // Seed ACK handshake signal
|
||||
input logic [KeyIvWidth-1:0] seed_key_i, // Seed input for SeedTypeKeyIV
|
||||
input logic [KeyIvWidth-1:0] seed_iv_i, // Seed input for SeedTypeKeyIV
|
||||
input logic [StateWidth-1:0] seed_state_full_i, // Seed input for SeedTypeStateFull
|
||||
input logic [PartialSeedWidth-1:0] seed_state_partial_i, // Seed input for SeedTypeStatePartial
|
||||
|
||||
output logic [OutputWidth-1:0] key_o, // Key stream output
|
||||
output logic err_o // The primitive entered an all zero state and may have
|
||||
// locked up or entered the default state defined by
|
||||
// RndCnstTriviumLfsrSeed depending on the
|
||||
// StrictLockupProtection parameter and the allow_lockup_i
|
||||
// signal.
|
||||
);
|
||||
|
||||
localparam int unsigned LastStatePartFractional = StateWidth % PartialSeedWidth != 0 ? 1 : 0;
|
||||
localparam int unsigned NumStateParts = StateWidth / PartialSeedWidth + LastStatePartFractional;
|
||||
localparam int unsigned NumBitsLastPart = StateWidth - (NumStateParts - 1) * PartialSeedWidth;
|
||||
localparam int unsigned LastStatePart = NumStateParts - 1;
|
||||
// Width of the variable determining which state part to overwrite with the next partial seed.
|
||||
localparam int unsigned StateIdxWidth = prim_util_pkg::vbits(NumStateParts);
|
||||
|
||||
logic [StateWidth-1:0] state_d, state_q;
|
||||
logic [StateWidth-1:0] state_update, state_seed;
|
||||
logic seed_req_d, seed_req_q;
|
||||
logic unused_seed;
|
||||
logic update, update_init, wr_en_seed;
|
||||
logic [StateIdxWidth-1:0] state_idx_d, state_idx_q;
|
||||
logic last_state_part;
|
||||
logic lockup, restore;
|
||||
|
||||
assign update = en_i | update_init;
|
||||
assign wr_en_seed = seed_req_o & seed_ack_i;
|
||||
assign lockup = ~(|state_q);
|
||||
assign err_o = lockup;
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
// Regular state updating and output generation //
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
// The current key stream depends on the current state only.
|
||||
if (BiviumVariant) begin : gen_update_and_output_bivium
|
||||
always_comb begin
|
||||
state_update = state_q;
|
||||
for (int unsigned i = 0; i < OutputWidth; i++) begin
|
||||
key_o[i] = bivium_generate_key_stream(state_update);
|
||||
state_update = bivium_update_state(state_update);
|
||||
end
|
||||
end
|
||||
end else begin : gen_update_and_output_trivium
|
||||
always_comb begin
|
||||
state_update = state_q;
|
||||
for (int unsigned i = 0; i < OutputWidth; i++) begin
|
||||
key_o[i] = trivium_generate_key_stream(state_update);
|
||||
state_update = trivium_update_state(state_update);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
///////////////
|
||||
// Reseeding //
|
||||
///////////////
|
||||
|
||||
if (SeedType == SeedTypeKeyIv) begin : gen_seed_type_key_iv
|
||||
if (BiviumVariant) begin : gen_seed_type_key_iv_bivium
|
||||
assign state_seed = bivium_seed_key_iv(seed_key_i, seed_iv_i);
|
||||
end else begin : gen_seed_type_key_iv_trivium
|
||||
assign state_seed = trivium_seed_key_iv(seed_key_i, seed_iv_i);
|
||||
end
|
||||
|
||||
end else if (SeedType == SeedTypeStateFull) begin : gen_seed_type_state_full
|
||||
assign state_seed = seed_state_full_i;
|
||||
|
||||
end else begin : gen_seed_type_state_partial
|
||||
// If the primitive is idle and an update is not currently being requested (update = 1'b0), the
|
||||
// parts not currently being reseeded remain constant, i.e., the update function above doesn't
|
||||
// modify the state. This is required to put the primitive into a known state e.g. for known
|
||||
// answer testing.
|
||||
// If the primitive is busy and an update is requested, the update function always modifies
|
||||
// the state (but the part currently being reseeded is solely determined by the new seed).
|
||||
// Otherwise the primitive could potentially produce the same key stream output twice in a row.
|
||||
always_comb begin
|
||||
state_seed = !update ? state_q : state_update;
|
||||
// The last part may be shorter than PartialSeedWidth.
|
||||
if (last_state_part) begin
|
||||
state_seed[StateWidth - 1 -: NumBitsLastPart] = seed_state_partial_i[NumBitsLastPart-1:0];
|
||||
end else begin
|
||||
state_seed[state_idx_q * PartialSeedWidth +: PartialSeedWidth] = seed_state_partial_i;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
/////////////////////////////////
|
||||
// State register and updating //
|
||||
/////////////////////////////////
|
||||
|
||||
// The lockup protection can optionally be disabled at run time. This may be required to put the
|
||||
// primitive into an all zero state, e.g., to switch off masking countermeasures for analysis if
|
||||
// the primitive is used for generating masks. However, the err_o bit always signals this
|
||||
// condition to the outside.
|
||||
assign restore = lockup & (StrictLockupProtection | ~allow_lockup_i);
|
||||
assign state_d = restore ? StateSeed :
|
||||
wr_en_seed ? state_seed :
|
||||
update ? state_update : state_q;
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin : state_reg
|
||||
if (!rst_ni) begin
|
||||
state_q <= StateSeed;
|
||||
end else begin
|
||||
state_q <= state_d;
|
||||
end
|
||||
end
|
||||
|
||||
// Latch the seed enable signal and keep the request high until the last request is acknowledged.
|
||||
assign seed_req_d = (seed_en_i | seed_req_q) & (~seed_ack_i | ~last_state_part);
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin : seed_req_reg
|
||||
if (!rst_ni) begin
|
||||
seed_req_q <= 1'b0;
|
||||
end else begin
|
||||
seed_req_q <= seed_req_d;
|
||||
end
|
||||
end
|
||||
assign seed_req_o = seed_en_i | seed_req_q;
|
||||
|
||||
if (SeedType == SeedTypeKeyIv) begin : gen_key_iv_seed_handling
|
||||
// After receiving key and IV, the entire state needs to be updated 4 times before the key
|
||||
// stream becomes usable. Depending on OutputWidth, a different number of initial updates are
|
||||
// required for this. [3]
|
||||
localparam int unsigned NumInitUpdatesFractional = (StateWidth * 4) % OutputWidth != 0 ? 1 : 0;
|
||||
localparam int unsigned NumInitUpdates =
|
||||
(StateWidth * 4) / OutputWidth + NumInitUpdatesFractional;
|
||||
localparam int unsigned LastInitUpdate = NumInitUpdates - 1;
|
||||
localparam int unsigned InitUpdatesCtrWidth = prim_util_pkg::vbits(NumInitUpdates);
|
||||
|
||||
logic [InitUpdatesCtrWidth-1:0] init_update_ctr_d, init_update_ctr_q;
|
||||
logic init_update_d, init_update_q;
|
||||
logic last_init_update;
|
||||
|
||||
// Count the number of initial updates done.
|
||||
assign init_update_ctr_d = wr_en_seed ? '0 :
|
||||
init_update_q ? init_update_ctr_q + 1'b1 : init_update_ctr_q;
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin : init_update_ctr_reg
|
||||
if (!rst_ni) begin
|
||||
init_update_ctr_q <= '0;
|
||||
end else begin
|
||||
init_update_ctr_q <= init_update_ctr_d;
|
||||
end
|
||||
end
|
||||
|
||||
// Track whether we're currently doing the initial updates.
|
||||
assign last_init_update = init_update_ctr_q == LastInitUpdate[InitUpdatesCtrWidth-1:0];
|
||||
assign init_update_d = wr_en_seed ? 1'b1 :
|
||||
last_init_update ? 1'b0 : init_update_q;
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin : init_update_reg
|
||||
if (!rst_ni) begin
|
||||
init_update_q <= 1'b0;
|
||||
end else begin
|
||||
init_update_q <= init_update_d;
|
||||
end
|
||||
end
|
||||
assign update_init = init_update_q;
|
||||
|
||||
// We're done after performing the initial updates.
|
||||
assign seed_done_o = init_update_q & last_init_update;
|
||||
|
||||
// Tie off unused signals.
|
||||
assign state_idx_d = '0;
|
||||
assign state_idx_q = '0;
|
||||
assign last_state_part = 1'b0;
|
||||
assign unused_seed = ^{seed_state_full_i,
|
||||
seed_state_partial_i,
|
||||
state_idx_d,
|
||||
state_idx_q,
|
||||
last_state_part};
|
||||
|
||||
end else if (SeedType == SeedTypeStateFull) begin : gen_full_seed_handling
|
||||
|
||||
// Only one handshake is required.
|
||||
assign seed_done_o = seed_req_o & seed_ack_i;
|
||||
|
||||
// Tie off unused signals.
|
||||
assign update_init = 1'b0;
|
||||
assign state_idx_d = '0;
|
||||
assign state_idx_q = '0;
|
||||
assign last_state_part = 1'b1;
|
||||
assign unused_seed = ^{seed_key_i,
|
||||
seed_iv_i,
|
||||
seed_state_partial_i,
|
||||
state_idx_d,
|
||||
state_idx_q,
|
||||
last_state_part};
|
||||
|
||||
end else begin : gen_partial_seed_handling
|
||||
|
||||
// Seed PartialSeedWidth bits of the state at a time. Track the part idx using a counter. The
|
||||
// counter is reset when seeding the last part.
|
||||
assign last_state_part = state_idx_q == LastStatePart[StateIdxWidth-1:0];
|
||||
assign state_idx_d = wr_en_seed & last_state_part ? '0 :
|
||||
wr_en_seed & ~last_state_part ? state_idx_q + 1'b1 : state_idx_q;
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin : state_idx_reg
|
||||
if (!rst_ni) begin
|
||||
state_idx_q <= '0;
|
||||
end else begin
|
||||
state_idx_q <= state_idx_d;
|
||||
end
|
||||
end
|
||||
|
||||
// We're done upon receiving the last state part.
|
||||
assign seed_done_o = seed_req_o & seed_ack_i & last_state_part;
|
||||
|
||||
// Tie off unused signals.
|
||||
assign update_init = 1'b0;
|
||||
assign unused_seed = ^{seed_key_i,
|
||||
seed_iv_i,
|
||||
seed_state_full_i};
|
||||
end
|
||||
|
||||
/////////////////
|
||||
// Asssertions //
|
||||
/////////////////
|
||||
|
||||
// While performing a partial reseed of the state, the primitive can be updated. However, this
|
||||
// should only be done if the number of produced bits per update / shift amount per update is
|
||||
// greater than the width of the smallest NFSR (= 84) inside the primitve. Otherwise, there is a
|
||||
// risk of overwriting the previously provided partial seed which reduces the amount of fresh
|
||||
// entropy injected per full reseed operation.
|
||||
`ASSERT(PrimTriviumPartialStateSeedWhileUpdate_A,
|
||||
(SeedType == SeedTypeStatePartial) && seed_req_o && en_i |-> OutputWidth >= MinNfsrWidth)
|
||||
|
||||
endmodule
|
159
vendor/lowrisc_ip/ip/prim/rtl/prim_trivium_pkg.sv
vendored
Normal file
159
vendor/lowrisc_ip/ip/prim/rtl/prim_trivium_pkg.sv
vendored
Normal file
|
@ -0,0 +1,159 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package prim_trivium_pkg;
|
||||
|
||||
typedef enum integer {
|
||||
SeedTypeKeyIv, // 2 * 80 bits for key and IV, requires advancing the primitive
|
||||
// 1152/OutputWidth (Trivium) or 708/OutputWidth (Bivium) times
|
||||
// before the key stream becomes usable.
|
||||
SeedTypeStateFull, // Seed the full state
|
||||
SeedTypeStatePartial // Seed PartialSeedWidth bits of the state at a time.
|
||||
} seed_type_e;
|
||||
|
||||
parameter int unsigned KeyIvWidth = 80;
|
||||
parameter int unsigned PartialSeedWidthDefault = 32;
|
||||
parameter int unsigned MinNfsrWidth = 84;
|
||||
|
||||
// These LFSR parameters have been generated with
|
||||
// $ ./util/design/gen-lfsr-seed.py --width 288 --seed 31468618 --prefix "Trivium"
|
||||
parameter int TriviumLfsrWidth = 288;
|
||||
typedef logic [TriviumLfsrWidth-1:0] trivium_lfsr_seed_t;
|
||||
parameter trivium_lfsr_seed_t RndCnstTriviumLfsrSeedDefault = {
|
||||
32'h758a4420,
|
||||
256'h31e1c461_6ea343ec_153282a3_0c132b57_23c5a4cf_4743b3c7_c32d580f_74f1713a
|
||||
};
|
||||
|
||||
/////////////
|
||||
// Trivium //
|
||||
/////////////
|
||||
|
||||
parameter int unsigned TriviumMaxNfsrWidth = 111;
|
||||
parameter int TriviumStateWidth = TriviumLfsrWidth;
|
||||
|
||||
function automatic logic [TriviumStateWidth-1:0] trivium_update_state(
|
||||
logic [TriviumStateWidth-1:0] in
|
||||
);
|
||||
logic [TriviumStateWidth-1:0] out;
|
||||
logic mul_90_91, mul_174_175, mul_285_286;
|
||||
logic add_65_92, add_161_176, add_242_287;
|
||||
|
||||
// First state part intermediate results
|
||||
mul_90_91 = in[90] & in[91];
|
||||
add_65_92 = in[65] ^ in[92];
|
||||
|
||||
// Second state part intermediate results
|
||||
mul_174_175 = in[174] & in[175];
|
||||
add_161_176 = in[161] ^ in[176];
|
||||
|
||||
// Third state part intermediate results
|
||||
mul_285_286 = in[285] & in[286];
|
||||
add_242_287 = in[242] ^ in[287];
|
||||
|
||||
// Updates - feedback part
|
||||
out[0] = in[68] ^ (mul_285_286 ^ add_242_287);
|
||||
out[93] = in[170] ^ (add_65_92 ^ mul_90_91);
|
||||
out[177] = in[263] ^ (mul_174_175 ^ add_161_176);
|
||||
|
||||
// Updates - shift part
|
||||
out[92:1] = in[91:0];
|
||||
out[176:94] = in[175:93];
|
||||
out[287:178] = in[286:177];
|
||||
|
||||
return out;
|
||||
endfunction
|
||||
|
||||
function automatic logic trivium_generate_key_stream(
|
||||
logic [TriviumStateWidth-1:0] state
|
||||
);
|
||||
logic key;
|
||||
logic add_65_92, add_161_176, add_242_287;
|
||||
logic unused_state;
|
||||
|
||||
add_65_92 = state[65] ^ state[92];
|
||||
add_161_176 = state[161] ^ state[176];
|
||||
add_242_287 = state[242] ^ state[287];
|
||||
key = add_161_176 ^ add_65_92 ^ add_242_287;
|
||||
|
||||
unused_state = ^{state[286:243],
|
||||
state[241:177],
|
||||
state[175:162],
|
||||
state[160:93],
|
||||
state[91:66],
|
||||
state[64:0]};
|
||||
return key;
|
||||
endfunction
|
||||
|
||||
function automatic logic [TriviumStateWidth-1:0] trivium_seed_key_iv(
|
||||
logic [KeyIvWidth-1:0] key,
|
||||
logic [KeyIvWidth-1:0] iv
|
||||
);
|
||||
logic [TriviumStateWidth-1:0] state;
|
||||
// [287:285] [284:173] [172:93] [92:80] [79:0]
|
||||
state = {3'b111, 112'b0, iv, 13'b0, key};
|
||||
return state;
|
||||
endfunction
|
||||
|
||||
////////////
|
||||
// Bivium //
|
||||
////////////
|
||||
|
||||
parameter int unsigned BiviumMaxNfsrWidth = 93;
|
||||
parameter int BiviumStateWidth = 177;
|
||||
|
||||
function automatic logic [BiviumStateWidth-1:0] bivium_update_state(
|
||||
logic [BiviumStateWidth-1:0] in
|
||||
);
|
||||
logic [BiviumStateWidth-1:0] out;
|
||||
logic mul_90_91, mul_174_175;
|
||||
logic add_65_92, add_161_176;
|
||||
|
||||
// First state half intermediate results
|
||||
mul_90_91 = in[90] & in[91];
|
||||
add_65_92 = in[65] ^ in[92];
|
||||
|
||||
// Second state half intermediate results
|
||||
mul_174_175 = in[174] & in[175];
|
||||
add_161_176 = in[161] ^ in[176];
|
||||
|
||||
// Updates - feedback part
|
||||
out[0] = in[68] ^ (mul_174_175 ^ add_161_176);
|
||||
out[93] = in[170] ^ add_65_92 ^ mul_90_91;
|
||||
|
||||
// Updates - shift part
|
||||
out[92:1] = in[91:0];
|
||||
out[176:94] = in[175:93];
|
||||
|
||||
return out;
|
||||
endfunction
|
||||
|
||||
function automatic logic bivium_generate_key_stream(
|
||||
logic [BiviumStateWidth-1:0] state
|
||||
);
|
||||
logic key;
|
||||
logic add_65_92, add_161_176;
|
||||
logic unused_state;
|
||||
|
||||
add_65_92 = state[65] ^ state[92];
|
||||
add_161_176 = state[161] ^ state[176];
|
||||
key = add_161_176 ^ add_65_92;
|
||||
|
||||
unused_state = ^{state[175:162],
|
||||
state[160:93],
|
||||
state[91:66],
|
||||
state[64:0]};
|
||||
return key;
|
||||
endfunction
|
||||
|
||||
function automatic logic [BiviumStateWidth-1:0] bivium_seed_key_iv(
|
||||
logic [KeyIvWidth-1:0] key,
|
||||
logic [KeyIvWidth-1:0] iv
|
||||
);
|
||||
logic [BiviumStateWidth-1:0] state;
|
||||
// [176:173] [172:93] [92:80] [79:0]
|
||||
state = {4'b0, iv, 13'b0, key};
|
||||
return state;
|
||||
endfunction
|
||||
|
||||
endpackage
|
|
@ -41,13 +41,9 @@ module prim_generic_flash #(
|
|||
output tlul_pkg::tl_d2h_t tl_o,
|
||||
// Observability
|
||||
input ast_pkg::ast_obs_ctrl_t obs_ctrl_i,
|
||||
output logic [7:0] fla_obs_o,
|
||||
input devmode_i
|
||||
output logic [7:0] fla_obs_o
|
||||
);
|
||||
|
||||
logic unused_devmode;
|
||||
assign unused_devmode = devmode_i;
|
||||
|
||||
// convert this into a tlul write later
|
||||
logic init;
|
||||
assign init = 1'b1;
|
||||
|
@ -126,8 +122,7 @@ module prim_generic_flash #(
|
|||
.tl_o (tl_o),
|
||||
.reg2hw (reg2hw),
|
||||
.hw2reg (hw2reg),
|
||||
.intg_err_o(intg_err),
|
||||
.devmode_i (1'b1)
|
||||
.intg_err_o(intg_err)
|
||||
);
|
||||
|
||||
logic unused_reg_sig;
|
||||
|
|
|
@ -106,8 +106,7 @@ module prim_generic_otp
|
|||
.tl_o (test_tl_o ),
|
||||
.reg2hw (reg2hw ),
|
||||
.hw2reg (hw2reg ),
|
||||
.intg_err_o(intg_err ),
|
||||
.devmode_i (1'b1 )
|
||||
.intg_err_o(intg_err )
|
||||
);
|
||||
|
||||
logic unused_reg_sig;
|
||||
|
|
2
vendor/lowrisc_ip/util/dvsim/Deploy.py
vendored
2
vendor/lowrisc_ip/util/dvsim/Deploy.py
vendored
|
@ -473,6 +473,8 @@ class RunTest(Deploy):
|
|||
self.index = index
|
||||
self.build_seed = sim_cfg.build_seed
|
||||
self.seed = RunTest.get_seed()
|
||||
# Systemverilog accepts seeds with a maximum size of 32 bits.
|
||||
self.svseed = int(self.seed) & 0xFFFFFFFF
|
||||
self.simulated_time = JobTime()
|
||||
super().__init__(sim_cfg)
|
||||
|
||||
|
|
2
vendor/lowrisc_ip/util/dvsim/SimCfg.py
vendored
2
vendor/lowrisc_ip/util/dvsim/SimCfg.py
vendored
|
@ -42,7 +42,7 @@ class SimCfg(FlowCfg):
|
|||
|
||||
# TODO: Find a way to set these in sim cfg instead
|
||||
ignored_wildcards = [
|
||||
"build_mode", "index", "test", "seed", "uvm_test", "uvm_test_seq",
|
||||
"build_mode", "index", "test", "seed", "svseed", "uvm_test", "uvm_test_seq",
|
||||
"cov_db_dirs", "sw_images", "sw_build_device", "sw_build_cmd",
|
||||
"sw_build_opts"
|
||||
]
|
||||
|
|
1
vendor/lowrisc_ip/util/uvmdvgen/index.md.tpl
vendored
1
vendor/lowrisc_ip/util/uvmdvgen/index.md.tpl
vendored
|
@ -41,7 +41,6 @@ In addition, it instantiates the following interfaces, connects them to the DUT
|
|||
* ${name.upper()} IOs
|
||||
* Interrupts ([`pins_if`]({{< relref "hw/dv/sv/common_ifs" >}}))
|
||||
* Alerts ([`alert_esc_if`]({{< relref "hw/dv/sv/alert_esc_agent/doc" >}}))
|
||||
* Devmode ([`pins_if`]({{< relref "hw/dv/sv/common_ifs" >}}))
|
||||
|
||||
${'###'} Common DV utility components
|
||||
The following utilities provide generic helper tasks and functions to perform activities that are common across the project:
|
||||
|
|
3
vendor/lowrisc_ip/util/uvmdvgen/tb.sv.tpl
vendored
3
vendor/lowrisc_ip/util/uvmdvgen/tb.sv.tpl
vendored
|
@ -14,7 +14,6 @@ module tb;
|
|||
`include "dv_macros.svh"
|
||||
|
||||
wire clk, rst_n;
|
||||
wire devmode;
|
||||
% if is_cip:
|
||||
% if has_interrupts:
|
||||
wire [NUM_MAX_INTERRUPTS-1:0] interrupts;
|
||||
|
@ -27,7 +26,6 @@ module tb;
|
|||
% if has_interrupts:
|
||||
pins_if #(NUM_MAX_INTERRUPTS) intr_if(interrupts);
|
||||
% endif
|
||||
pins_if #(1) devmode_if(devmode);
|
||||
tl_if tl_if(.clk(clk), .rst_n(rst_n));
|
||||
% endif
|
||||
% for agent in env_agents:
|
||||
|
@ -72,7 +70,6 @@ module tb;
|
|||
% if has_interrupts:
|
||||
uvm_config_db#(intr_vif)::set(null, "*.env", "intr_vif", intr_if);
|
||||
% endif
|
||||
uvm_config_db#(devmode_vif)::set(null, "*.env", "devmode_vif", devmode_if);
|
||||
uvm_config_db#(virtual tl_if)::set(null, "*.env.m_tl_agent*", "vif", tl_if);
|
||||
% endif
|
||||
% for agent in env_agents:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue