Update code from upstream repository
https://github.com/lowRISC/opentitan to revision
1740ccd1ad19f83bf2cec120c87b807b9af2ca1b

* [prim_onehot_check] Add address-based check (Michael Schaffner)
* [flash_ctrl] convert flash config to mubi (Timothy Chen)
* [sw,tests] Enter RMA LC_STATE and check flash access and wipe (Dave
  Williams)
* [prim_onehot_check] Add lint waivers (Michael Schaffner)
* [prim] Stub out guts of prim_cdc_rand_delay for Verilator (Rupert
  Swarbrick)
* [prim] Add missing waiver (Timothy Chen)
* [prim_onehot_check] Add prim_onehot_check (Michael Schaffner)
* [dv] Add TL error case - write with instr_type = True (Weicai Yang)
* [cdc-rand] Enable CDC random delay injection (Srikrishna Iyer)
* [fpv/pinmux] Add tl integrity error check (Cindy Chen)
* [prim_assert] Add static assertion macro for checks in pkgs (Michael
  Schaffner)
* [prim] Add prim_blanker (Greg Chadwick)
* [prim, rtl] Add new onehot primitives (Greg Chadwick)
* [dvsim] Fix looping through old result directories (Cindy Chen)
* [chip dv] Fixes for tests failing in nightly (Srikrishna Iyer)
* [present] Rewrite TB to avoid non-freely licensed code (Rupert
  Swarbrick)
* [secded_gen] Fix a bug in inverted Hamming codes (Michael Schaffner)
* [prim,rtl] Fix RW collision bug in prim_1p_ram_scr (Greg Chadwick)
* [dvsim,xcelium] Fix sed commands to generate plusargs (Rupert
  Swarbrick)
* [dvsim,xcelium] Split two plusarg strings (Rupert Swarbrick)
* [dvsim] Add a missing newline to error message (Rupert Swarbrick)

Signed-off-by: Michael Schaffner <msf@google.com>
This commit is contained in:
Michael Schaffner 2022-04-13 14:02:39 -07:00
parent d819fa6296
commit 91745a076c
60 changed files with 1464 additions and 1408 deletions

View file

@ -9,6 +9,6 @@
upstream:
{
url: https://github.com/lowRISC/opentitan
rev: 3a33c4df2ed31b0d7a8936531a4ae9a275177f1b
rev: 1740ccd1ad19f83bf2cec120c87b807b9af2ca1b
}
}

View file

@ -69,6 +69,7 @@ class csr_base_seq extends uvm_reg_sequence #(uvm_sequence #(uvm_reg_item));
models[i].get_registers(all_csrs);
end
void'($value$plusargs("num_test_csrs=%0d", num_test_csrs));
if (num_test_csrs != 0) begin
num_csr_chunks = all_csrs.size / num_test_csrs + 1;
`DV_CHECK_STD_RANDOMIZE_WITH_FATAL(test_csr_chunk,

View file

@ -541,3 +541,11 @@
`ifndef BUILD_SEED
`define BUILD_SEED 1
`endif
// Max value out of 2 given expressions.
//
// Duplicate of dv_utils_pkg::max2() function, but this is better because
// it can consume different data types directly without the need for casting.
`ifndef DV_MAX2
`define DV_MAX2(a, b) ((a) > (b) ? (a) : (b))
`endif

View file

@ -53,6 +53,37 @@ virtual function void otp_write_secret0_partition(
write64(Secret0DigestOffset, digest);
endfunction
virtual function void otp_write_secret2_partition(bit [RmaTokenSize*8-1:0] rma_unlock_token,
bit [CreatorRootKeyShare0Size*8-1:0] creator_root_key0,
bit [CreatorRootKeyShare1Size*8-1:0] creator_root_key1
);
bit [Secret2DigestSize*8-1:0] digest;
bit [RmaTokenSize*8-1:0] scrambled_unlock_token;
bit [CreatorRootKeyShare0Size*8-1:0] scrambled_root_key0;
bit [CreatorRootKeyShare1Size*8-1:0] scrambled_root_key1;
bit [bus_params_pkg::BUS_DW-1:0] secret_data[$];
for (int i = 0; i < RmaTokenSize; i+=8) begin
scrambled_unlock_token[i*8+:64] = scramble_data(rma_unlock_token[i*8+:64], Secret2Idx);
write64(i + RmaTokenOffset, scrambled_unlock_token[i*8+:64]);
end
for (int i = 0; i < CreatorRootKeyShare0Size; i+=8) begin
scrambled_root_key0[i*8+:64] = scramble_data(creator_root_key0[i*8+:64], Secret2Idx);
write64(i + CreatorRootKeyShare0Offset, scrambled_root_key0[i*8+:64]);
end
for (int i = 0; i < CreatorRootKeyShare1Size; i+=8) begin
scrambled_root_key1[i*8+:64] = scramble_data(creator_root_key1[i*8+:64], Secret2Idx);
write64(i + CreatorRootKeyShare1Offset, scrambled_root_key1[i*8+:64]);
end
secret_data = {<<32 {scrambled_root_key1, scrambled_root_key0, scrambled_unlock_token}};
digest = cal_digest(Secret2Idx, secret_data);
write64(Secret2DigestOffset, digest);
endfunction
virtual function void otp_write_hw_cfg_partition(
bit [DeviceIdSize*8-1:0] device_id, bit [ManufStateSize*8-1:0] manuf_state,
bit [EnSramIfetchSize*8-1:0] en_sram_ifetch,

View file

@ -27,12 +27,11 @@ package otp_scrambler_pkg;
);
int secret_idx = part_idx - Secret0Idx;
bit [NUM_ROUND-1:0][SCRAMBLE_DATA_SIZE-1:0] output_data;
crypto_dpi_present_pkg::sv_dpi_present_encrypt(input_data,
RndCnstKey[secret_idx],
SCRAMBLE_KEY_SIZE == 80,
output_data);
scramble_data = output_data[NUM_ROUND-1];
SCRAMBLE_KEY_SIZE,
NUM_ROUND,
scramble_data);
endfunction
// When secret data read out of otp_array, it will be descrambled.
@ -42,25 +41,20 @@ package otp_scrambler_pkg;
);
int secret_idx = part_idx - Secret0Idx;
bit [NUM_ROUND-1:0][SCRAMBLE_DATA_SIZE-1:0] output_data;
bit [NUM_ROUND-1:0][SCRAMBLE_DATA_SIZE-1:0] padded_input;
padded_input[NUM_ROUND-1] = input_data;
crypto_dpi_present_pkg::sv_dpi_present_decrypt(padded_input,
crypto_dpi_present_pkg::sv_dpi_present_decrypt(input_data,
RndCnstKey[secret_idx],
SCRAMBLE_KEY_SIZE == 80,
output_data);
descramble_data = output_data[NUM_ROUND-1];
if (input_data != 0) begin
end
SCRAMBLE_KEY_SIZE,
NUM_ROUND,
descramble_data);
endfunction
function automatic bit [SCRAMBLE_DATA_SIZE-1:0] cal_digest(int part_idx,
ref bit [BUS_DW-1:0] mem_q[$]);
int array_size = mem_q.size();
real key_factor = SCRAMBLE_KEY_SIZE / BUS_DW;
bit [NUM_ROUND-1:0] [SCRAMBLE_DATA_SIZE-1:0] enc_array;
bit [SCRAMBLE_DATA_SIZE-1:0] init_vec = RndCnstDigestIV[0];
bit [SCRAMBLE_DATA_SIZE-1:0] enc_data;
bit [SCRAMBLE_DATA_SIZE-1:0] digest;
for (int i = 0; i < $ceil(array_size / key_factor); i++) begin
@ -76,19 +70,19 @@ package otp_scrambler_pkg;
end
// Trigger 32 round of PRESENT encrypt.
crypto_dpi_present_pkg::sv_dpi_present_encrypt(input_data, key, SCRAMBLE_KEY_SIZE == 80,
enc_array);
crypto_dpi_present_pkg::sv_dpi_present_encrypt(input_data, key, SCRAMBLE_KEY_SIZE,
NUM_ROUND, enc_data);
// XOR the previous state into the digest result according to the Davies-Meyer scheme.
digest = enc_array[NUM_ROUND-1] ^ input_data;
digest = enc_data ^ input_data;
end
// Last 32 round of digest is calculated with a digest constant.
crypto_dpi_present_pkg::sv_dpi_present_encrypt(digest,
RndCnstDigestConst[0],
SCRAMBLE_KEY_SIZE == 80,
enc_array);
SCRAMBLE_KEY_SIZE, NUM_ROUND,
enc_data);
// XOR the previous state into the digest result according to the Davies-Meyer scheme.
digest ^= enc_array[NUM_ROUND-1];
digest ^= enc_data;
return digest;
endfunction

View file

@ -70,7 +70,9 @@
"+define+DUT_HIER={dut_instance}"]
run_opts: ["+UVM_NO_RELNOTES",
"+UVM_VERBOSITY={expand_uvm_verbosity_{verbosity}}"]
"+UVM_VERBOSITY={expand_uvm_verbosity_{verbosity}}",
// TODO: remove once smoke regr passes:
"+prim_cdc_rand_delay_mode=disable"]
// Default list of things to export to shell
exports: [
@ -116,22 +118,27 @@
name: smoke
tests: []
reseed: 1
// Knob used to configure an existing test / vseq to have a shorter runtime.
run_opts: ["+smoke_test=1"]
run_opts: [// Knob used to configure an existing test / vseq to have a shorter runtime.
"+smoke_test=1",
// Enable CDC random delay once, at the start of the sim.
// TODO: uncomment once smoke regr passes:
// "+prim_cdc_rand_delay_mode=once"
]
}
{
name: all
}
{
name: all_once
reseed: 1
}
{
name: nightly
en_sim_modes: ["cov"]
run_opts: [// Enable CDC random delay changes every 10 source data changes.
// TODO: Uncomment once nightly regr passes:
// "+prim_cdc_rand_delay_mode=interval", "+prim_cdc_rand_delay_interval=10"
]
}
]

View file

@ -28,7 +28,8 @@
- 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
- read a WO (write-only) memory
- write a RO (read-only) memory'''
- write a RO (read-only) memory
- write with `instr_type = True`'''
milestone: V2
tests: ["{name}_tl_errors"]
}

View file

@ -49,8 +49,8 @@
// Xcelium generates an error (*E,OPTP2ND) if you pass an empty plusarg. To avoid doing so, these
// two variables expand to e.g. "+UVM_TESTNAME=foo" if we have a test and the empty string if
// not.
uvm_testname_plusarg: "{eval_cmd} echo {uvm_test} | sed 's/\\(.+\\)/+UVM_TESTNAME=\\1/'"
uvm_testseq_plusarg: "{eval_cmd} echo {uvm_test_seq} | sed 's/\\(.+\\)/+UVM_TEST_SEQ=\\1/'"
uvm_testname_plusarg: "{eval_cmd} echo {uvm_test} | sed -E 's/(.+)/+UVM_TESTNAME=\\1/'"
uvm_testseq_plusarg: "{eval_cmd} echo {uvm_test_seq} | sed -E 's/(.+)/+UVM_TEST_SEQ=\\1/'"
run_opts: ["-input {run_script}",
"-licqueue",
@ -58,7 +58,8 @@
// Use the same snapshot name set during the build step.
"-r {tb}",
"+SVSEED={seed}",
"{uvm_testname_plusarg} {uvm_testseq_plusarg}",
"{uvm_testname_plusarg}",
"{uvm_testseq_plusarg}",
// Ignore "IEEE 1800-2009 SystemVerilog simulation semantics" warning
"-nowarn DSEM2009",
]

View file

@ -1,27 +0,0 @@
/*
* S-Boxes and P-Boxes for
* Implementation of PRESENT in C
* v2.1, 10/13/2008
*
* Implementation is located at http://www.lightweightcrypto.org/implementations.php,
* under the title "Testvectors for PRESENT".
*
* Thomas Siebert, thomas.siebert@rub.de
*/
const uint8_t Sbox[16] = {12, 5, 6, 11, 9, 0, 10, 13, 3, 14, 15, 8, 4, 7, 1, 2};
const uint8_t SboxInv[16] = {5, 14, 15, 8, 12, 1, 2, 13,
11, 4, 6, 3, 0, 7, 9, 10};
const uint8_t PboxInv[64] = {0, 16, 32, 48, 1, 17, 33, 49, 2, 18, 34, 50, 3,
19, 35, 51, 4, 20, 36, 52, 5, 21, 37, 53, 6, 22,
38, 54, 7, 23, 39, 55, 8, 24, 40, 56, 9, 25, 41,
57, 10, 26, 42, 58, 11, 27, 43, 59, 12, 28, 44, 60,
13, 29, 45, 61, 14, 30, 46, 62, 15, 31, 47, 63};
const uint8_t Pbox[64] = {0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48,
52, 56, 60, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37,
41, 45, 49, 53, 57, 61, 2, 6, 10, 14, 18, 22, 26,
30, 34, 38, 42, 46, 50, 54, 58, 62, 3, 7, 11, 15,
19, 23, 27, 31, 35, 39, 43, 47, 51, 55, 59, 63};

View file

@ -1,196 +0,0 @@
/*
* Commandline-Option-Fetcher for
* Implementation of PRESENT in C
* v2.1, 10/13/2008
*
* Implementation is located at http://www.lightweightcrypto.org/implementations.php,
* under the title "Testvectors for PRESENT".
*
* Thomas Siebert, thomas.siebert@rub.de
*/
#include <string.h>
#include <getopt.h>
//----------------------------------
// Function prototype
//----------------------------------
// void comline_fetch_options( struct Options * , int , char ** );
//----------------------------------
// Struct declaration
//----------------------------------
struct Options {
_Bool Error;
_Bool Mode;
_Bool KeySize80;
uint8_t Verbose;
uint64_t KeyHigh;
uint64_t KeyLow;
uint64_t Text;
uint16_t Rounds;
};
#define Encrypt_Mode 1
#define Decrypt_Mode 0
//----------------------------------
// Functions
//----------------------------------
void comline_fetch_options(struct Options *sOpt, int argc, char **const argv) {
int c;
_Bool Opt_Decrypt = 0, Opt_Encrypt = 0, Opt_File = 0, Opt_Verbose = 0;
char *Opt_Text = NULL, *Opt_Key = NULL, *Opt_Rounds = NULL;
FILE *KeyFile = NULL, *TextFile = NULL;
int keyres;
sOpt->Error = 0;
sOpt->Verbose = 1;
while ((c = getopt(argc, argv, "defv:r:k:t:")) !=
-1) // Cycle through Options
{
switch (c) // set flags
{
case 'd':
if (Opt_Encrypt || Opt_Decrypt)
sOpt->Error = 1;
else
Opt_Decrypt = 1;
break;
case 'e':
if (Opt_Encrypt || Opt_Decrypt)
sOpt->Error = 1;
else
Opt_Encrypt = 1;
break;
case 'f':
if (Opt_File)
sOpt->Error = 1;
else
Opt_File = 1;
break;
case 'v':
if (Opt_Verbose)
sOpt->Error = 1;
else if (optarg != NULL) {
if (strcmp(optarg, "0") == 0)
sOpt->Verbose = 0;
else if (strcmp(optarg, "1") == 0)
sOpt->Verbose = 1;
else if (strcmp(optarg, "2") == 0)
sOpt->Verbose = 2;
else
sOpt->Error = 1;
} else
sOpt->Error = 1;
Opt_Verbose = 1;
break;
case 'k':
if (Opt_Key != NULL)
sOpt->Error = 1;
else
Opt_Key = optarg;
break;
case 'r':
if (Opt_Rounds)
sOpt->Error = 1;
else
Opt_Rounds = optarg;
break;
case 't':
if (Opt_Text != NULL)
sOpt->Error = 1;
else
Opt_Text = optarg;
break;
case '?':
sOpt->Error = 1;
break;
}
} // End Option-Cycle
// Set Error if Parameters missing
if (Opt_Key == NULL || Opt_Text == NULL || (!(Opt_Decrypt || Opt_Encrypt))) {
sOpt->Error = 1;
}
else {
// Handle Rounds Parameter
if (Opt_Rounds != NULL) // if Round Param there...
{
if (strlen(Opt_Rounds) < 6) // check length
{
uint32_t Rounds;
sscanf(Opt_Rounds, "%5" SCNu32 "", &Rounds); // get round no.
if ((Rounds > 65534) || Rounds == 0)
sOpt->Error = 1; // check 0<Rounds<65535
else
sOpt->Rounds = Rounds; // override roundno.
} else
sOpt->Error = 1;
} else
sOpt->Rounds = 32; //...else use standard
// Check if decrypt or encrypt mode
if (Opt_Encrypt)
sOpt->Mode = Encrypt_Mode;
else
sOpt->Mode = Decrypt_Mode;
// Read key and text (file mode)
if (Opt_File) {
KeyFile = fopen(Opt_Key, "r");
TextFile = fopen(Opt_Text, "r");
if (!((KeyFile == NULL) || (TextFile) == NULL)) {
fseek(KeyFile, 0, SEEK_END);
if ((ftell(KeyFile)) >= 32) {
fseek(KeyFile, 0, SEEK_SET);
if (fscanf(KeyFile, "%016" SCNx64 "", &sOpt->KeyHigh) == 0)
sOpt->Error = 1;
if (fscanf(KeyFile, "%016" SCNx64 "", &sOpt->KeyLow) == 0)
sOpt->Error = 1;
sOpt->KeySize80 = 0;
} else if ((ftell(KeyFile)) >= 20) {
fseek(KeyFile, 0, SEEK_SET);
if (fscanf(KeyFile, "%016" SCNx64 "", &sOpt->KeyHigh) == 0)
sOpt->Error = 1;
if (fscanf(KeyFile, "%04" SCNx16 "", &sOpt->KeyLow) == 0)
sOpt->Error = 1;
sOpt->KeySize80 = 1;
} else
sOpt->Error = 1;
if (fscanf(TextFile, "%016" SCNx64 "", &sOpt->Text) == EOF)
sOpt->Error = 1;
} else
sOpt->Error = 1;
if (!(KeyFile == NULL))
fclose(KeyFile);
if (!(TextFile == NULL))
fclose(TextFile);
}
// Read key and text (commandline mode)
else {
if (((strlen(Opt_Key) != 32) && (strlen(Opt_Key) != 20)) ||
(strlen(Opt_Text) != 16)) { // if wrong length...
sOpt->Error = 1; // set error
}
if (!(sOpt->Error)) // if no error...
{
sscanf(Opt_Key, "%016" SCNx64 "", &sOpt->KeyHigh); // get values
if (strlen(Opt_Key) == 20) // set key + size
{
sOpt->KeySize80 = 1;
sscanf(Opt_Key + 16, "%016" SCNx16 "", &sOpt->KeyLow);
} else {
sOpt->KeySize80 = 0;
sscanf(Opt_Key + 16, "%016" SCNx64 "", &sOpt->KeyLow);
}
sscanf(Opt_Text, "%016" SCNx64 "", &sOpt->Text);
}
}
}
}

View file

@ -1,64 +0,0 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
#include "present.inc"
#include "svdpi.h"
typedef unsigned long long int ull_t;
// Helper function used only by this C file.
// Returns the key schedule corresponding to the input key.
uint64_t *get_key_schedule(uint64_t key_high, uint64_t key_low,
uint8_t num_rounds, uint8_t key_size_80) {
return key_schedule(key_high, key_low, num_rounds, (_Bool)key_size_80, 0);
}
extern void c_dpi_key_schedule(uint64_t key_high, uint64_t key_low,
uint8_t num_rounds, uint8_t key_size_80,
svBitVecVal *key_array) {
uint64_t *key_schedule = (uint64_t *)malloc(num_rounds * sizeof(uint64_t));
uint64_t key;
svBitVecVal key_hi;
svBitVecVal key_lo;
// get the key schedule from the C model
key_schedule = get_key_schedule(key_high, key_low, num_rounds, key_size_80);
// write the key schedule to simulation
int i;
for (i = 0; i < num_rounds; i++) {
key = key_schedule[i];
key_hi = (svBitVecVal)(key >> 32);
key_lo = (svBitVecVal)(key & 0xFFFFFFFF);
key_array[i * 2] = key_lo;
key_array[i * 2 + 1] = key_hi;
}
// free allocated memory
free(key_schedule);
}
extern uint64_t c_dpi_encrypt(uint64_t plaintext, uint64_t key_high,
uint64_t key_low, uint8_t num_rounds,
uint8_t key_size_80) {
uint64_t encrypt_result;
uint64_t *key_schedule = (uint64_t *)malloc(num_rounds * sizeof(uint64_t));
key_schedule = get_key_schedule(key_high, key_low, num_rounds, key_size_80);
encrypt_result = (uint64_t)encrypt(plaintext, key_schedule, num_rounds, 0);
free(key_schedule);
return encrypt_result;
}
extern uint64_t c_dpi_decrypt(uint64_t ciphertext, uint64_t key_high,
uint64_t key_low, uint8_t num_rounds,
uint8_t key_size_80) {
uint64_t decrypt_result;
uint64_t *key_schedule = (uint64_t *)malloc(sizeof(uint64_t));
key_schedule = get_key_schedule(key_high, key_low, num_rounds, key_size_80);
decrypt_result = (uint64_t)decrypt(ciphertext, key_schedule, num_rounds, 0);
free(key_schedule);
return decrypt_result;
}

View file

@ -0,0 +1,257 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
// Simple unhardened reference implementation of the PRESENT cipher, following
// the description in
//
// [1] Bognadov et al, PRESENT: An Ultra-Lightweight Block Cipher. LNCS 4727:
// 450466. doi:10.1007/978-3-540-74735-2_31.
#include <cassert>
#include <cstdint>
#include <svdpi.h>
#include <vector>
static const uint8_t sbox4[16] = {0xc, 0x5, 0x6, 0xb, 0x9, 0x0, 0xa, 0xd,
0x3, 0xe, 0xf, 0x8, 0x4, 0x7, 0x1, 0x2};
static const uint8_t sbox4_inv[16] = {0x5, 0xe, 0xf, 0x8, 0xc, 0x1, 0x2, 0xd,
0xb, 0x4, 0x6, 0x3, 0x0, 0x7, 0x9, 0xa};
static const uint8_t bit_perm[64] = {
0, 16, 32, 48, 1, 17, 33, 49, 2, 18, 34, 50, 3, 19, 35, 51,
4, 20, 36, 52, 5, 21, 37, 53, 6, 22, 38, 54, 7, 23, 39, 55,
8, 24, 40, 56, 9, 25, 41, 57, 10, 26, 42, 58, 11, 27, 43, 59,
12, 28, 44, 60, 13, 29, 45, 61, 14, 30, 46, 62, 15, 31, 47, 63};
static const uint8_t bit_perm_inv[64] = {
0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60,
1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61,
2, 6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46, 50, 54, 58, 62,
3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47, 51, 55, 59, 63};
static uint64_t mask64(int bits) { return ((uint64_t)1 << bits) - 1; }
namespace {
struct key128_t {
uint64_t hi, lo;
};
class PresentState {
public:
PresentState(unsigned key_size, key128_t key);
// This is the body of the for loop in Fig. 1 of the paper ([1], above). If
// is_last_round, then it also includes the call to addRoundKey that follows.
uint64_t enc_round(uint64_t input, unsigned round, bool is_last_round) const;
// The inverse of enc_round. Note that a decryption should start with a high
// round and with is_last_round set, then count down.
uint64_t dec_round(uint64_t input, unsigned round, bool is_last_round) const;
private:
static key128_t next_round_key(const key128_t &k, unsigned key_size,
unsigned round_count);
static uint64_t add_round_key(uint64_t data, const key128_t &k,
unsigned key_size);
static uint64_t sbox_layer(bool inverse, uint64_t data);
static uint64_t perm_layer(bool inverse, uint64_t data);
unsigned key_size;
std::vector<key128_t> key_schedule;
};
} // namespace
PresentState::PresentState(unsigned key_size, key128_t key)
: key_size(key_size) {
assert(key_size == 80 || key_size == 128);
key_schedule.reserve(32);
key_schedule.push_back(key);
for (int i = 1; i <= 31; ++i) {
key = next_round_key(key, key_size, i);
key_schedule.push_back(key);
}
}
uint64_t PresentState::enc_round(uint64_t input, unsigned round,
bool is_last_round) const {
assert(1 <= round && round < key_schedule.size());
const key128_t &key = key_schedule[round - 1];
// addRoundKey
uint64_t w1 = add_round_key(input, key, key_size);
// sBoxLayer
uint64_t w2 = sbox_layer(false, w1);
// pLayer
uint64_t w3 = perm_layer(false, w2);
// On the final round, call addRoundKey with the following key.
uint64_t w4 =
is_last_round ? add_round_key(w3, key_schedule[round], key_size) : w3;
return w4;
}
uint64_t PresentState::dec_round(uint64_t input, unsigned round,
bool is_last_round) const {
assert(1 <= round && round < key_schedule.size());
const key128_t &key = key_schedule[round - 1];
// If we're undoing the last round, start by calling addRoundKey with the
// following key.
uint64_t w1 = is_last_round
? add_round_key(input, key_schedule[round], key_size)
: input;
// pLayer^{-1}
uint64_t w2 = perm_layer(true, w1);
// sBoxLayer^{-1}
uint64_t w3 = sbox_layer(true, w2);
// addRoundKey
uint64_t w4 = add_round_key(w3, key, key_size);
return w4;
}
key128_t PresentState::next_round_key(const key128_t &k, unsigned key_size,
unsigned round_count) {
assert((round_count >> 5) == 0);
assert(key_size == 80 || key_size == 128);
if (key_size == 80) {
assert((k.hi >> 16) == 0);
// Rotate the key left by 61 bits
//
// The top word (bits 79:64) will come from bits (18:3). The
// bottom word (bits 63:0) will have bits 2:0 at the top, then
// bits 79:64 (from the top word) and finally bits 63:19.
uint64_t rot_hi = (k.lo >> 3) & mask64(16);
uint64_t rot_lo =
((((k.lo >> 0) & mask64(3)) << 61) | (((k.hi >> 0)) << 45) |
(((k.lo >> 19) & mask64(45)) << 0));
assert((rot_hi >> 16) == 0);
// Pass the top 4 bits through sbox4
uint64_t subst_hi =
(((uint64_t)sbox4[rot_hi >> 12] << 12) | (rot_hi & mask64(12)));
uint64_t subst_lo = rot_lo;
// XOR bits 19:15 with the round counter
uint64_t xored_hi = subst_hi;
uint64_t xored_lo =
((subst_lo & ~mask64(20)) |
((((subst_lo >> 15) & mask64(5)) ^ round_count) << 15) |
(subst_lo >> 0 & mask64(15)));
key128_t next = {.hi = xored_hi, .lo = xored_lo};
return next;
} else {
// Rotate the key left by 61 bits
//
// The top word (bits 127:64) will come from bits 66:64 (from the
// top word) and then bits 63:3 (from the bottom word). The bottom
// word (bits 63:0) will have bits 2:0 at the top and then bits
// 127:67.
uint64_t rot_hi = (((k.hi & mask64(3)) << 61) | (k.lo >> 3));
uint64_t rot_lo = (((k.lo & mask64(3)) << 61) | (k.hi >> 3));
// Pass top 8 bits through a pair of sbox4's
uint64_t rot_nib124 = (rot_hi >> 60) & mask64(4);
uint64_t rot_nib120 = (rot_hi >> 56) & mask64(4);
uint64_t subst_hi =
(((uint64_t)sbox4[rot_nib124] << 60) |
((uint64_t)sbox4[rot_nib120] << 56) | (rot_hi & mask64(56)));
uint64_t subst_lo = rot_lo;
// XOR bits 66:62
uint64_t xored_hi = subst_hi ^ ((uint64_t)round_count >> 2);
uint64_t xored_lo = subst_lo ^ ((uint64_t)round_count << 62);
key128_t next = {.hi = xored_hi, .lo = xored_lo};
return next;
}
}
uint64_t PresentState::add_round_key(uint64_t data, const key128_t &k,
unsigned key_size) {
assert(key_size == 80 || key_size == 128);
uint64_t k64 = (key_size == 80) ? ((k.hi << 48) | (k.lo >> 16)) : k.hi;
return data ^ k64;
}
uint64_t PresentState::sbox_layer(bool inverse, uint64_t data) {
uint64_t ret = 0;
for (int i = 0; i < 64 / 4; ++i) {
unsigned nibble = (data >> (4 * i)) & 0xf;
uint64_t subst = inverse ? sbox4_inv[nibble] : sbox4[nibble];
ret |= subst << (4 * i);
}
return ret;
}
uint64_t PresentState::perm_layer(bool inverse, uint64_t data) {
uint64_t ret = 0;
for (int i = 0; i < 64; ++i) {
uint64_t bit = (data >> i) & 1;
ret |= bit << (inverse ? bit_perm_inv[i] : bit_perm[i]);
}
return ret;
}
extern "C" {
PresentState *c_dpi_present_mk(unsigned key_size, const svBitVecVal *key) {
assert(key_size == 80 || key_size == 128);
// Each element of key represents 32 bits. Unpack into a key128_t, zeroing
// the top bits if key size was 80.
uint32_t w32s[4];
for (int i = 0; i < 4; ++i) {
unsigned lsb = 32 * i;
unsigned bits_left = (lsb < key_size) ? key_size - lsb : 0;
unsigned mask =
(bits_left < 32) ? ((uint32_t)1 << bits_left) - 1 : ~(uint32_t)0;
w32s[i] = key[i] & mask;
}
key128_t k128 = {.hi = ((uint64_t)w32s[3] << 32) | w32s[2],
.lo = ((uint64_t)w32s[1] << 32) | w32s[0]};
return new PresentState(key_size, k128);
}
void c_dpi_present_free(PresentState *ps) { delete ps; }
void c_dpi_present_enc_round(const PresentState *ps, unsigned round,
unsigned char is_last_round,
const svBitVecVal *src, svBitVecVal *dst) {
assert(ps);
assert(is_last_round == 0 || is_last_round == 1);
uint64_t in64 = ((uint64_t)src[1] << 32) | src[0];
uint64_t out64 = ps->enc_round(in64, round, is_last_round != 0);
dst[1] = out64 >> 32;
dst[0] = (uint32_t)out64;
}
void c_dpi_present_dec_round(const PresentState *ps, unsigned round,
unsigned char is_last_round,
const svBitVecVal *src, svBitVecVal *dst) {
assert(ps);
assert(is_last_round == 0 || is_last_round == 1);
uint64_t in64 = ((uint64_t)src[1] << 32) | src[0];
uint64_t out64 = ps->dec_round(in64, round, is_last_round != 0);
dst[1] = out64 >> 32;
dst[0] = (uint32_t)out64;
}
}

View file

@ -7,11 +7,7 @@ description: "PRESENT block cipher reference implementation in C from Ruhr-Unive
filesets:
files_dv:
files:
- boxes.inc: {file_type: cSource, is_include_file: true}
- comline.inc: {file_type: cSource, is_include_file: true}
- verbose.inc: {file_type: cSource, is_include_file: true}
- present.inc: {file_type: cSource, is_include_file: true}
- crypto_dpi_present.c: {file_type: cSource}
- crypto_dpi_present.cc: {file_type: cppSource}
- crypto_dpi_present_pkg.sv: {file_type: systemVerilogSource}
file_type: cSource

View file

@ -3,117 +3,76 @@
// SPDX-License-Identifier: Apache-2.0
package crypto_dpi_present_pkg;
// dep packages
import uvm_pkg::*;
// parameters
// This is defined here so we can size all arrays properly.
parameter int unsigned NumRounds = 31;
// PRESENT expects up to 31 rounds in total
localparam int unsigned MaxRounds = 31;
localparam int unsigned MaxKeyWidth = 128;
localparam int unsigned DataWidth = 64;
// DPI-C imports
import "DPI-C" context function void c_dpi_key_schedule(
input longint unsigned key_high,
input longint unsigned key_low,
input int unsigned num_rounds,
input int unsigned key_size_80,
output bit [NumRounds:0][63:0] key_schedule
);
import "DPI-C" function chandle c_dpi_present_mk(int unsigned key_size,
bit [MaxKeyWidth-1:0] key);
import "DPI-C" function void c_dpi_present_free(chandle h);
import "DPI-C" context function longint c_dpi_encrypt(
input longint unsigned plaintext,
input longint unsigned key_high,
input longint unsigned key_low,
input int unsigned num_rounds,
input int unsigned key_size_80
);
import "DPI-C" function void c_dpi_present_enc_round(chandle h,
int unsigned round,
bit is_last_round,
bit [DataWidth-1:0] in,
output bit [DataWidth-1:0] out);
import "DPI-C" function void c_dpi_present_dec_round(chandle h,
int unsigned round,
bit is_last_round,
bit [DataWidth-1:0] in,
output bit [DataWidth-1:0] out);
import "DPI-C" context function longint c_dpi_decrypt(
input longint unsigned ciphertext,
input longint unsigned key_high,
input longint unsigned key_low,
input int unsigned num_rounds,
input int unsigned key_size_80
);
// Helper Functions
function automatic void get_keys(input bit [127:0] key,
input bit key_size_80,
output bit [63:0] key_high,
output bit [63:0] key_low);
key_high = (key_size_80) ? key[79:16] : key[127:64];
key_low = (key_size_80) ? key[15:0] : key[63:0];
endfunction
//////////////////////////////////////////////////////
// SV wrapper functions to be used by the testbench //
//////////////////////////////////////////////////////
// This function takes in a 128 bit key by default, it determines how to
// split this key for the DPI calls based on the value of key_size_80.
// This function encrypts the input plaintext with the PRESENT encryption algorithm.
//
// This returns the list of round keys used during the course of the algorithm.
function automatic void sv_dpi_present_get_key_schedule(
input bit [127:0] key,
input bit key_size_80,
output bit [NumRounds:0][63:0] key_schedule
);
bit [63:0] key_high, key_low;
bit [(NumRounds*2)+1:0][31:0] compressed_key_schedule;
get_keys(key, key_size_80, key_high, key_low);
c_dpi_key_schedule(key_high, key_low, NumRounds+1, key_size_80, compressed_key_schedule);
for (int i = 0; i < NumRounds+1; i++) begin
key_schedule[i][31:0] = compressed_key_schedule[i*2];
key_schedule[i][63:32] = compressed_key_schedule[i*2+1];
end
endfunction
// This function encrypts the input plaintext with the PRESENT encryption
// algorithm using the specified number of rounds.
//
// This produces a list of all intermediate values produced after each round
// of the algorithm, including the final encrypted ciphertext value.
// This produces a list of all intermediate values produced after each round of the algorithm,
// including the final encrypted ciphertext value.
function automatic void sv_dpi_present_encrypt(
input bit [63:0] plaintext,
input bit [127:0] key,
input bit key_size_80,
output bit [NumRounds-1:0][63:0] encrypted_values
input bit [DataWidth-1:0] plaintext,
input bit [MaxKeyWidth-1:0] key,
input int unsigned key_size,
input int unsigned num_rounds,
output bit [DataWidth-1:0] ciphertext
);
bit [63:0] key_high, key_low;
bit [DataWidth-1:0] round_in, round_out;
chandle h = c_dpi_present_mk(key_size, key);
get_keys(key, key_size_80, key_high, key_low);
for (int i = 1; i <= NumRounds; i++) begin
encrypted_values[i-1] = c_dpi_encrypt(plaintext, key_high, key_low, i+1, key_size_80);
round_out = plaintext;
for (int i = 1; i <= num_rounds; i++) begin
round_in = round_out;
c_dpi_present_enc_round(h, i, i == num_rounds, round_in, round_out);
end
ciphertext = round_out;
c_dpi_present_free(h);
endfunction
// This function decrypts the input ciphertext with the PRESENT decryption
// algorithm using the specified number of rounds.
// This function decrypts the input ciphertext with the PRESENT decryption algorithm.
//
// This produces a list of all intermediate values produced after each round
// of the algorithm, including the final decrypted plaintext value.
// This produces a list of all intermediate values produced after each round of the algorithm,
// including the final decrypted plaintext value.
function automatic void sv_dpi_present_decrypt(
input bit [NumRounds-1:0][63:0] ciphertext,
input bit [127:0] key,
input bit key_size_80,
output bit [NumRounds-1:0][63:0] decrypted_values
input bit [DataWidth-1:0] ciphertext,
input bit [MaxKeyWidth-1:0] key,
input int unsigned key_size,
input int unsigned num_rounds,
output bit [DataWidth-1:0] plaintext
);
bit [63:0] key_high, key_low;
bit [DataWidth-1:0] round_in, round_out;
chandle h = c_dpi_present_mk(key_size, key);
get_keys(key, key_size_80, key_high, key_low);
for (int i = 1; i <= NumRounds; i++) begin
decrypted_values[i-1] = c_dpi_decrypt(ciphertext[i-1], key_high, key_low, i+1, key_size_80);
round_in = ciphertext;
for (int i = num_rounds; i > 0; i--) begin
c_dpi_present_dec_round(h, i, i == num_rounds, round_in, round_out);
round_in = round_out;
end
plaintext = round_out;
c_dpi_present_free(h);
endfunction

View file

@ -1,396 +0,0 @@
/*
* Implementation of PRESENT in C
* v2.1, 10/13/2008
*
* Implementation is located at http://www.lightweightcrypto.org/implementations.php,
* under the title "Testvectors for PRESENT".
*
* Thomas Siebert, thomas.siebert@rub.de
*
*
* Your Compiler currently should support
* the ANSI-C99-standard.
*
* Tested with gcc (with Option -std=c99)
*/
//----------------------------------
// Includes
//----------------------------------
#include "verbose.inc" //For verbose output
#include "comline.inc" //Command Line
#include "boxes.inc" //S-Boxes and P-Boxes
#include <stdlib.h>
//----------------------------------
// Macros for bit manipulation
//----------------------------------
//returns...
#define high45_64(h45in) ((uint64_t)h45in >> 9) // 45 msb as lsb
#define high61_64(h4in) ((uint64_t)h4in >> 3) // 61 msb as lsb
#define high4_64(h4in) ((uint64_t)h4in >> 60) // 4 msb as lsb
#define high8to4_64(h8in) (((uint64_t)h8in >> 56) & 0x0F) // 4 msb as 2. lsb
#define high16_64(h16in) ((uint64_t)h16in >> 48) // 16 msb as lsb
#define high1_64(h1in) ((uint64_t)h1in >> 63) // msb as lsb
#define low4_64(l4in) ((uint64_t)l4in << 60) // 4 lsb as msb
#define low8to4_64(l4in) ((uint64_t)l4in << 56) // 4 lsb as 2. msb
#define low16_64(l4in) ((uint64_t)l4in << 48) // 4 lsb as msb
#define rotate1l_64(r1lin) \
(high1_64(r1lin) | (r1lin << 1)) // input rotated left (1x)
#define rotate1r_64(r1rin) \
(high1_64(r1rin) | (r1rin >> 1)) // input rotated right (1x)
#define rotate4l_64(r4lin) \
(high4_64(r4lin) | (r4lin << 4)) // input rotated left (4x)
#define rotate4r_64(r4rin) \
(high4_64(r4rin) | (r4rin >> 4)) // input rotated right (4x)
//----------------------------------
// Function prototypes
//----------------------------------
uint64_t encrypt(uint64_t, uint64_t *, uint16_t, _Bool);
uint64_t decrypt(uint64_t, uint64_t *, uint16_t, _Bool);
uint64_t *key_schedule(uint64_t, uint64_t, uint16_t, _Bool, _Bool);
// We have commented out the main(...) function of the C model as the testbench is directly
// calling encrypt(), decrypt(), and key_schedule() functions.
// It also contains unnecessary command line parsing functionality that is not needed for
// the testbench.
//
//----------------------------------
// Start of code
//----------------------------------
// int main( int argc, char ** const argv )
//{
// // Initialize variables
// uint64_t result;
// struct Options Opt;
//
// // Get Commandline Options
// comline_fetch_options( &Opt, argc, argv );
//
// // Banner
// if ( Opt.Verbose != 0 )
// {
// printf( "---------------------------------------\n" );
// printf( "PRESENT Commandline Tool v2.1\n" );
// printf( "Thomas Siebert, thomas.siebert@rub.de\n" );
// printf( "---------------------------------------\n\n" );
// }
//
// if ( !Opt.Error )
// {
// uint64_t *subkey;
//
// if ( Opt.Mode == Encrypt_Mode )
// {
// // Put out Values
// if ( Opt.Verbose != 0 )
// {
// printf( "Starting values\n" );
// printf( "Plaintext: %016"PRIx64" \n", Opt.Text);
// if (Opt.KeySize80) printf( "Given Key (80bit):
//%016"PRIx64" %04"PRIx64"\n\n", Opt.KeyHigh, (Opt.KeyLow&0xFFFF) ); else
//printf( "Given Key (128bit): %016"PRIx64" %016"PRIx64"\n\n", Opt.KeyHigh,
//Opt.KeyLow );
// }
//
// // Generate Subkeys
// subkey=key_schedule( Opt.KeyHigh, Opt.KeyLow, Opt.Rounds,
//Opt.KeySize80, (Opt.Verbose>1) );
//
// // Start Encryption
// if ( Opt.Verbose != 0 ) printf( "Starting
//encryption...\n" ); result=encrypt(Opt.Text, subkey, Opt.Rounds,
//(Opt.Verbose>1) ); if ( Opt.Verbose != 0 ) printf( "Resulting Cipher:
//%016"PRIx64" \n\n", result); else printf( "%016"PRIx64"\n", result);
// }
//
// else if ( Opt.Mode == Decrypt_Mode )
// {
// // Put out Values
// if ( Opt.Verbose != 0 )
// {
// printf( "Starting values\n" );
// printf( "Ciphertext: %016"PRIx64" \n",
//Opt.Text); if (Opt.KeySize80) printf( "Given Key (80bit): %016"PRIx64"
//%04"PRIx64"\n\n", Opt.KeyHigh, (Opt.KeyLow&0xFFFF) ); else printf( "Given Key
//(128bit): %016"PRIx64" %016"PRIx64"\n\n", Opt.KeyHigh, Opt.KeyLow );
// }
//
// // Generate Subkeys
// subkey=key_schedule( Opt.KeyHigh, Opt.KeyLow, Opt.Rounds,
//Opt.KeySize80, (Opt.Verbose>1) );
//
// // Start Decryption
// if ( Opt.Verbose != 0 ) printf( "Starting
//decryption...\n" ); result=decrypt(Opt.Text, subkey, Opt.Rounds,
//(Opt.Verbose>1) ); if ( Opt.Verbose != 0 ) printf( "Resulting Plaintext:
//%016"PRIx64" \n", result); else printf( "%016"PRIx64"\n", result);
// }
//
// free(subkey);
//
// }
//
// else
// {
// // Put out Syntax
// printf( "Syntax:\n");
// printf( "PRESENT -d|e [-f] [-r rounds] [-v level] -k key -t
//text\n\n"); printf( "Choose -d to decrypt, or -e to encrypt one block\n\n");
// printf( "-f (optional): File input, see below\n");
// printf( "-r rounds (optional): Change number of rounds (up
//to 65534, standard is 32)\n"); printf( "-v level (optional): Specify verbose
//level:\n"); printf( " 0 for result-output only\n"); printf( " 1 for output
//of mode, input, result (standard)\n"); printf( " 2 for roundwise
//output\n\n"); printf( "-k key: Key in hexadecimal (length: *EXACTLY* 20
//chars(80bit)/32 chars(128bit))\n"); printf( "-t text: Text in hexadecimal
//(length: *EXACTLY* 16 chars)\n"); printf( "If -f is set, key and text
//represent files containing the values,\n"); printf( "otherwise they must be
//passed directly via commandline.\n\n"); printf( "Returned Errorlevel: 0 if
//successful, 1 if non-successful\n");
// }
// return Opt.Error;
//}
//----------------------------------
// Key Scheduling
//----------------------------------
uint64_t *key_schedule(uint64_t key_high, uint64_t key_low, uint16_t Rounds,
_Bool KeySize80, _Bool Output) {
uint64_t temp64;
uint64_t i;
uint64_t *subkey = (uint64_t *)malloc(Rounds * sizeof(uint64_t));
if (subkey != NULL) {
if (Output)
v_key_start();
if (KeySize80) {
key_low &= 0xFFFF;
if (Output)
v_k80_init(key_high, key_low);
for (i = 0; i < Rounds; i++) {
subkey[i] = key_high;
//----------------------------------
// Shift
//----------------------------------
temp64 = key_high;
key_high <<= 61;
key_high |= (key_low << 45);
key_high |= (temp64 >> 19);
key_low = (temp64 >> 3) & 0xFFFF;
if (Output && (i + 2 <= Rounds))
v_k80_shift(key_high, key_low);
//----------------------------------
// S-Box
//----------------------------------
temp64 = high4_64(key_high); // get highest nibble
key_high &= 0x0FFFFFFFFFFFFFFF; // kill highest nibble
temp64 = Sbox[temp64];
key_high |= low4_64(temp64); // put new value to highest nibble (sbox)
if (Output && (i + 2 <= Rounds))
v_k80_sbox(key_high, key_low);
//----------------------------------
// Round Salt
//----------------------------------
key_low ^= (((i + 1) & 0x01) << 15);
key_high ^= ((i + 1) >> 1);
if (Output && (i + 2 <= Rounds))
v_k80_round(key_high, key_low, i);
}
} else // 128 Bit
{
if (Output)
v_k128_init(key_high, key_low);
for (i = 0; i < Rounds; i++) {
subkey[i] = key_high;
//----------------------------------
// Shift
//----------------------------------
temp64 = high61_64(key_high);
key_high <<= 61;
key_high |= high61_64(key_low);
key_low <<= 61;
key_low |= temp64;
if (Output && (i + 2 <= Rounds))
v_k128_shift(key_high, key_low);
//----------------------------------
// S-Box
//----------------------------------
temp64 = high4_64(key_high); // get highest nibble
key_high &= 0x0FFFFFFFFFFFFFFF; // kill highest nibble
temp64 = Sbox[temp64];
key_high |= low4_64(temp64); // put new value to highest nibble (sbox)
temp64 = high8to4_64(key_high); // get 2. highest nibble
key_high &= 0xF0FFFFFFFFFFFFFF; // kill 2. highest nibble
temp64 = Sbox[temp64];
key_high |=
low8to4_64(temp64); // put new value to 2. highest nibble (sbox)
if (Output && (i + 2 <= Rounds))
v_k128_sbox(key_high, key_low);
//----------------------------------
// Round Salt
//----------------------------------
key_low ^= (((i + 1) & 0x03) << 62); // add counter to lower key part
key_high ^= ((i + 1) >> 2); // add counter to higher key part
if (Output && (i + 2 <= Rounds))
v_k128_round(key_high, key_low, i);
}
}
if (Output)
v_final();
} else {
printf("RAM problem!\n");
exit(0);
}
return subkey;
}
//----------------------------------
// Encryption
//----------------------------------
uint64_t encrypt(uint64_t in, uint64_t *subkey, uint16_t Rounds,
_Bool Roundwise) { // Start encryption
#define out in
uint16_t RoundNr;
uint64_t text;
if (Roundwise)
v_enc_start(in);
for (RoundNr = 1; RoundNr < Rounds; RoundNr++) { // Start "for"
uint16_t temp;
#define SboxNr temp
#define PBit temp
if (Roundwise)
v_roundstart(RoundNr, subkey[RoundNr - 1]);
//----------------------------------
// Xor with roundkey
//----------------------------------
text = in ^ subkey[RoundNr - 1];
if (Roundwise)
v_after_xor(text);
//----------------------------------
// S-Boxes
//----------------------------------
for (SboxNr = 0; SboxNr < 16; SboxNr++) {
uint16_t SboxVal;
SboxVal = text & 0x0F; // get lowest nibble
text &= 0xFFFFFFFFFFFFFFF0; // kill lowest nibble
text |= Sbox[SboxVal]; // put new value to lowest nibble (sbox)
text = rotate4l_64(text); // next(rotate by one nibble)
}
if (Roundwise)
v_after_s(text);
//----------------------------------
// P-Box
//----------------------------------
for (PBit = 0, out = 0; PBit < 64; PBit++) {
out = rotate1l_64(out); // next(rotate by one bit)
out |= ((text >> 63 - Pbox[PBit]) &
1); // put new value to lowest bit (pbox)
}
if (Roundwise)
v_after_p(in);
} // End "for"
text = in ^ subkey[RoundNr - 1];
if (Roundwise)
v_enc_final(text, subkey[RoundNr - 1]);
return text;
} // End encryption
//----------------------------------
// Decryption
//----------------------------------
uint64_t decrypt(uint64_t in, uint64_t *subkey, uint16_t Rounds,
_Bool Roundwise) { // Start decryption
#define out in
uint16_t RoundNr;
uint64_t text;
if (Roundwise)
v_dec_start(in);
for (RoundNr = 1; RoundNr <= Rounds; RoundNr++) { // Start "for"
uint64_t key_temp;
uint16_t temp;
#define SboxNr temp
#define PBit temp
if (Roundwise)
v_roundstart(RoundNr, subkey[Rounds - RoundNr]);
//----------------------------------
// Xor with roundkey
//----------------------------------
text = in ^ subkey[Rounds - RoundNr];
if (Roundwise)
v_after_xor(text);
//----------------------------------
// P-Box
//----------------------------------
for (PBit = 0, out = 0; PBit < 64; PBit++) {
out = rotate1l_64(out); // next(rotate by one bit)
out |= ((text >> 63 - PboxInv[PBit]) &
1); // put new value to lowest bit (pbox)
}
if (Roundwise)
v_after_p(out);
//----------------------------------
// S-Boxes
//----------------------------------
for (SboxNr = 0; SboxNr < 16; SboxNr++) {
uint16_t SboxVal;
SboxVal = out & 0x0F;
out &= 0xFFFFFFFFFFFFFFF0;
out |= SboxInv[SboxVal];
out = rotate4l_64(out);
}
if (Roundwise)
v_after_s(out);
} // End "for"
if (Roundwise)
v_final();
return text;
} // End decryption

View file

@ -1,125 +0,0 @@
/*
* Verbose-Functions for
* Implementation of PRESENT in C
* v2.1, 10/13/2008
*
* Implementation is located at http://www.lightweightcrypto.org/implementations.php,
* under the title "Testvectors for PRESENT".
*
* Thomas Siebert, thomas.siebert@rub.de
*/
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
//----------------------------------
// Function prototypes
//----------------------------------
void v_enc_start(uint64_t);
void v_enc_final(uint64_t, uint64_t);
void v_dec_start(uint64_t);
void v_roundstart(uint16_t, uint64_t);
void v_after_xor(uint64_t);
void v_after_s(uint64_t);
void v_after_p(uint64_t);
void v_final(void);
void v_k80_init(uint64_t, uint64_t);
void v_k80_shift(uint64_t, uint64_t);
void v_k80_sbox(uint64_t, uint64_t);
void v_k80_round(uint64_t, uint64_t, uint16_t);
void v_k128_init(uint64_t, uint64_t);
void v_k128_shift(uint64_t, uint64_t);
void v_k128_sbox(uint64_t, uint64_t);
void v_k128_round(uint64_t, uint64_t, uint16_t);
void v_key_start(void);
//----------------------------------
// Functions
//----------------------------------
void v_enc_start(uint64_t v_plain) {
printf("************************************\n");
printf("Verbose output of PRESENT-encryption\n");
printf("************************************\n\n");
printf("Given Plaintext: %016" PRIx64 " \n\n", v_plain);
}
void v_dec_start(uint64_t v_plain) {
printf("************************************\n");
printf("Verbose output of PRESENT-decryption\n");
printf("************************************\n\n");
printf("Given Ciphertext: %016" PRIx64 " \n", v_plain);
}
void v_roundstart(uint16_t v_round, uint64_t v_key) {
printf("--------------------------------------\n");
printf("Round %" PRIu16 "\n", v_round);
printf("Subkey: %016" PRIx64 "\n\n", v_key);
printf("Text after...\n");
}
void v_enc_final(uint64_t v_final_text, uint64_t v_key) {
printf("--------------------------------------\n");
printf("Final Round\n\n");
printf("Subkey: %016" PRIx64 "\n", v_key);
printf("Text: %016" PRIx64 " \n\n", v_final_text);
v_final();
}
void v_final(void) {
printf("************************************\n");
printf("End of verbose output\n");
printf("************************************\n");
}
void v_after_xor(uint64_t v_xor) {
printf("...Key-Xor: %016" PRIx64 " \n", v_xor);
}
void v_after_s(uint64_t v_s) { printf(".....S-Box: %016" PRIx64 " \n", v_s); }
void v_after_p(uint64_t v_p) { printf(".....P-Box: %016" PRIx64 " \n", v_p); }
void v_k128_init(uint64_t key_high, uint64_t key_low) {
printf("Input: %016" PRIx64 " %016" PRIx64 "\n\n", key_high, key_low);
printf("Subkey Round 1: >>%016" PRIx64 "<<\n\n", key_high);
}
void v_k128_shift(uint64_t key_high, uint64_t key_low) {
printf("...after Shift: %016" PRIx64 " %016" PRIx64 "\n", key_high, key_low);
}
void v_k128_sbox(uint64_t key_high, uint64_t key_low) {
printf("...after S-Box: %016" PRIx64 " %016" PRIx64 "\n", key_high, key_low);
}
void v_k128_round(uint64_t key_high, uint64_t key_low, uint16_t i) {
printf("Subkey Round %" PRIu16 " (after Salt): >>%016" PRIx64 "<< %016" PRIx64
"\n\n",
i + 2, key_high, key_low);
}
void v_k80_init(uint64_t key_high, uint64_t key_low) {
printf("Input: %016" PRIx64 " %04" PRIx64 "\n\n", key_high,
(key_low & 0xFFFF));
printf("Subkey Round 1: >>%016" PRIx64 "<<\n\n", key_high);
}
void v_k80_shift(uint64_t key_high, uint64_t key_low) {
printf("...after Shift: %016" PRIx64 " %04" PRIx64 "\n", key_high, key_low);
}
void v_k80_sbox(uint64_t key_high, uint64_t key_low) {
printf("...after S-Box: %016" PRIx64 " %04" PRIx64 "\n", key_high, key_low);
}
void v_k80_round(uint64_t key_high, uint64_t key_low, uint16_t i) {
printf("Subkey Round %" PRIu16 " (after Salt): >>%016" PRIx64 "<< %04" PRIx64
"\n\n",
i + 2, key_high, key_low);
}
void v_key_start(void) {
printf("**************************************\n");
printf("Verbose output of PRESENT-Key-Schedule\n");
printf("**************************************\n\n");
}

View file

@ -13,19 +13,15 @@
module prim_present_tb;
`include "dv_macros.svh"
import crypto_dpi_present_pkg::MaxRounds;
import crypto_dpi_present_pkg::MaxKeyWidth;
import crypto_dpi_present_pkg::DataWidth;
//////////////////////////////////////////////////////
// config
//////////////////////////////////////////////////////
// Default to {data_width:64, key_width:128} configuration.
// Data width and key width can be overriden from command-line if desired.
`ifdef DATA_WIDTH
localparam int unsigned DataWidth = `DATA_WIDTH;
`else
localparam int unsigned DataWidth = 64;
`endif
// Key width can be set with a define, but must be 80 or 128
`ifdef KEY_WIDTH
localparam int unsigned KeyWidth = `KEY_WIDTH;
`else
@ -34,17 +30,10 @@ module prim_present_tb;
localparam string MSG_ID = $sformatf("%m");
// Max number of rounds according to spec.
// We redefine this parameter here to avoid clutter from the long package identifier.
localparam int unsigned NumRounds = crypto_dpi_present_pkg::NumRounds;
// used to index the data arrays
localparam bit Encrypt = 1'b0;
localparam bit Decrypt = 1'b1;
// this parameter is required for the DPI model.
localparam bit KeySize80 = (KeyWidth == 80);
// This bit can be set from the command line to indicate that we are running a smoke regression,
// and to run just a single iteration of the test.
// This helps drastically reduce runtimes in the CI flows.
@ -56,15 +45,15 @@ module prim_present_tb;
// data_in[0]: encryption, data_in[1]: decryption.
// Same scheme used for key_in, data_out, key_out.
logic [1:0][NumRounds-1:0][DataWidth-1:0] data_in;
logic [1:0][NumRounds-1:0][KeyWidth-1 :0] key_in;
logic [1:0][NumRounds-1:0][4:0] idx_in;
logic [1:0][NumRounds-1:0][DataWidth-1:0] data_out;
logic [1:0][NumRounds-1:0][KeyWidth-1 :0] key_out;
logic [1:0][NumRounds-1:0][4:0] idx_out;
logic [1:0][MaxRounds-1:0][DataWidth-1:0] data_in;
logic [1:0][MaxRounds-1:0][KeyWidth-1 :0] key_in;
logic [1:0][MaxRounds-1:0][4:0] idx_in;
logic [1:0][MaxRounds-1:0][DataWidth-1:0] data_out;
logic [1:0][MaxRounds-1:0][KeyWidth-1 :0] key_out;
logic [1:0][MaxRounds-1:0][4:0] idx_out;
for (genvar j = 0; j < 2; j++) begin : gen_encrypt_decrypt
for (genvar k = 0; k < NumRounds; k++) begin : gen_duts
for (genvar k = 0; k < MaxRounds; k++) begin : gen_duts
if (j == 0) begin : gen_encrypt
assign idx_in[j][k] = 5'd1;
end else begin : gen_decrypt
@ -96,15 +85,10 @@ module prim_present_tb;
task automatic test_present(bit [DataWidth-1:0] plaintext,
bit [KeyWidth-1:0] key);
bit [NumRounds:0][63:0] key_schedule;
bit [NumRounds-1:0][DataWidth-1:0] encrypted_text;
crypto_dpi_present_pkg::sv_dpi_present_get_key_schedule(key, KeySize80, key_schedule);
check_encryption(plaintext, key, key_schedule, encrypted_text);
bit [MaxRounds-1:0][DataWidth-1:0] encrypted_text;
check_encryption(plaintext, key, encrypted_text);
check_decryption(encrypted_text, key, key_out[Encrypt]);
endtask
@ -112,11 +96,10 @@ module prim_present_tb;
// Calls a subroutine to perform checks on the outputs (once they are available).
task automatic check_encryption(input bit [DataWidth-1:0] plaintext,
input bit [KeyWidth-1:0] key,
input bit [NumRounds:0][63:0] key_schedule,
output bit [NumRounds-1:0][DataWidth-1:0] expected_ciphertext);
output bit [MaxRounds-1:0][DataWidth-1:0] expected_ciphertext);
// Drive input into encryption instances.
for (int unsigned i = 0; i < NumRounds; i++) begin
for (int unsigned i = 0; i < MaxRounds; i++) begin
data_in[Encrypt][i] = plaintext;
key_in[Encrypt][i] = key;
end
@ -124,30 +107,22 @@ module prim_present_tb;
// Wait a bit for the DUTs to finish calculations.
#100ns;
// query DPI model for expected encrypted output.
crypto_dpi_present_pkg::sv_dpi_present_encrypt(plaintext, key,
KeySize80, expected_ciphertext);
for (int unsigned i = 0; i < MaxRounds; i++) begin
crypto_dpi_present_pkg::sv_dpi_present_encrypt(plaintext, MaxKeyWidth'(key),
KeyWidth, i + 1, expected_ciphertext[i]);
check_output(key_schedule[NumRounds:1], expected_ciphertext,
key_out[Encrypt], data_out[Encrypt], "Encryption");
check_output(data_out[Encrypt][i],
expected_ciphertext[i],
$sformatf("Encryption; %0d rounds, key width %0d", i + 1, KeyWidth));
end
endtask
// Helper task to drive ciphertext and key into each decryption instance.
// Calls a subroutine to perform checks on the outputs (once they are available).
task automatic check_decryption(input bit [NumRounds-1:0][DataWidth-1:0] ciphertext,
task automatic check_decryption(input bit [MaxRounds-1:0][DataWidth-1:0] ciphertext,
input bit [KeyWidth-1:0] key,
input bit [NumRounds-1:0][KeyWidth-1:0] decryption_keys);
// the expected plaintext after decryption will be provided by the C model.
bit [NumRounds-1:0][DataWidth-1:0] expected_plaintext;
// the expected key after decryption will simply be the original key.
// the C model only provides a key schedule, which is not useful here.
bit [NumRounds-1:0][63:0] expected_key;
for (int i = 0; i < NumRounds; i++) begin
expected_key[i] = key[KeyWidth-1:KeyWidth-64];
end
input bit [MaxRounds-1:0][KeyWidth-1:0] decryption_keys);
// Drive input into decryption instances.
data_in[Decrypt] = ciphertext;
@ -157,49 +132,29 @@ module prim_present_tb;
#100ns;
// query DPI model for expected decrypted output.
crypto_dpi_present_pkg::sv_dpi_present_decrypt(ciphertext, key, KeySize80, expected_plaintext);
check_output(expected_key, expected_plaintext,
key_out[Decrypt], data_out[Decrypt], "Decryption");
for (int unsigned i = 0; i < MaxRounds; i++) begin
bit [DataWidth-1:0] expected_plaintext;
crypto_dpi_present_pkg::sv_dpi_present_decrypt(ciphertext[i],
key, KeyWidth,
i + 1,
expected_plaintext);
check_output(data_out[Decrypt][i],
expected_plaintext,
$sformatf("Decryption; %0d rounds, key width %0d", i + 1, KeyWidth));
end
endtask
// Helper subroutine to compare key and data output values from
// the C-reference model and the DUTs.
//
// For each instance of PRESENT (whether encryption or decryption),
// we need to perform two checks:
// 1) Check that the output key matches the corresponding key in the schedule.
// 2) Check that the output data matches the output of the reference model.
//
// If any comparison error is seen, this task short-circuits immediately,
// printing out some debug information and the correct failure signature.
task automatic check_output(input bit [NumRounds-1:0][63:0] expected_key,
input bit [NumRounds-1:0][DataWidth-1:0] expected_text,
input bit [NumRounds-1:0][KeyWidth-1:0] actual_key,
input bit [NumRounds-1:0][DataWidth-1:0] actual_data,
input string msg);
bit error = 1'b0;
for (int unsigned i = 0; i < NumRounds; i++) begin
// compare the output key to the corresponding key in the schedule.
if (expected_key[i] != actual_key[i][KeyWidth-1:KeyWidth-64]) begin
error = 1'b1;
$error("%s output key mismatch at round %0d! Expected[0x%0x] - Actual[0x%0x]",
msg, i, expected_key[i], actual_key[i][KeyWidth-1:KeyWidth-64]);
break;
end
// compare encrypted output text to reference model
if (expected_text[i] != actual_data[i]) begin
error = 1'b1;
$error("%s output text mismatch at round %0d! Expected[0x%0x] - Actual[0x%0x]",
msg, i, expected_text[i], actual_data[i]);
break;
end
function automatic void check_output(bit [DataWidth-1:0] dut_value,
bit [DataWidth-1:0] exp_value,
string desc);
if (dut_value != exp_value) begin
$error("%s: MISMATCH. Expected[0x%0x] - Actual[0x%0x]", desc, exp_value, dut_value);
dv_test_status_pkg::dv_test_status(.passed(1'b0));
end
if (error) dv_test_status_pkg::dv_test_status(.passed(1'b0));
endtask
endfunction
//////////////////////////////////////////////////////

View file

@ -0,0 +1,10 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
`verilator_config
// When running this prim through Verilator, we stub out all of its contents.
// This, in turn, generates UNUSED warnings which we can waive here. No need to
// be fine-grained: this is DV code anyway.
lint_off -rule UNUSED -file "*/rtl/prim_cdc_rand_delay.sv" -match "*"

View file

@ -0,0 +1,19 @@
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
#
# waiver file for prim_cdc_rand_delay
waive -rules {IFDEF_CODE} -location {prim_cdc_rand_delay.sv} -regexp {.*contained within \`else block.*} \
-comment "Ifdefs are required for prim_rand_cdc_delay since it is turned on only for simulation."
waive -rules {HIER_BRANCH_NOT_READ} -location {prim_cdc_rand_delay.sv} -regexp {.*dst_clk.*} \
-comment "Destination clock is only used when attempting to simulate random delays."
waive -rules {INPUT_NOT_READ} -location {prim_cdc_rand_delay.sv} -regexp {dst_clk|src_clk} \
-comment "Source/Destination clock is only used when attempting to simulate random delays."
waive -rules {PARAM_NOT_USED} -location {prim_cdc_rand_delay.sv} -regexp {UseSourceClock|LatencyPs|JitterPs} \
-comment "Randomization parameters are only used when attempting to simulate random delays."

View file

@ -0,0 +1,18 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
`verilator_config
// Tell the Verilator scheduler to split up these variables into
// separate pieces when it's figuring out process scheduling. This
// avoids spurious UNOPTFLAT warnings caused by the fact that the
// arrays feed into themselves (with different bits for different
// positions in the tree).
split_var -module "prim_onehot_check" -var "or_tree"
split_var -module "prim_onehot_check" -var "and_tree"
split_var -module "prim_onehot_check" -var "err_tree"
// The clock and reset are only used for assertions in this module.
lint_off -rule UNUSED -file "*/rtl/prim_onehot_check.sv" -match "Signal is not used: 'clk_i'"
lint_off -rule UNUSED -file "*/rtl/prim_onehot_check.sv" -match "Signal is not used: 'rst_ni'"

View file

@ -0,0 +1,8 @@
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
#
# waiver file for prim_onehot_check
waive -rules {HIER_BRANCH_NOT_READ INPUT_NOT_READ} -location {prim_onehot_check.sv} -regexp {.*'(clk_i|rst_ni)' is not read from in module 'prim_onehot_check'.*} \
-comment "clk_ and rst_ni are only used for assertions in this module."

View file

@ -0,0 +1,31 @@
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:prim_flop_2sync_sim:0.1"
description: "prim_flop_2sync_sim sim target"
filesets:
files_rtl:
depend:
- lowrisc:prim:flop_2sync
files_dv:
depend:
- lowrisc:dv:common_ifs
- lowrisc:dv:dv_macros
- lowrisc:dv:dv_utils
- lowrisc:dv:dv_test_status
files:
- tb.sv
file_type: systemVerilogSource
targets:
sim: &sim_target
toplevel: tb
filesets:
- files_rtl
- files_dv
default_tool: vcs
lint:
<<: *sim_target

View file

@ -0,0 +1,41 @@
// Copyright lowRISC contributors.
// 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: prim_flop_2sync
// Top level dut name (sv module).
dut: prim_flop_2sync
// 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:prim_flop_2sync_sim:0.1
// Import additional common sim cfg files.
import_cfgs: [// Project wide common sim cfg file
"{proj_root}/hw/dv/tools/dvsim/common_sim_cfg.hjson"]
// Default iterations for all tests - each test entry can override this.
reseed: 5
// List of test specifications.
tests: [
{
name: unit_test
}
]
// List of regressions.
regressions: [
{
name: smoke
tests: ["unit_test"]
}
]
}

View file

@ -0,0 +1,85 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
// Basic testbench for prim_flop_2sync with CDC random delay enabled.
module tb;
`include "dv_macros.svh"
localparam string MsgId = $sformatf("%m");
logic [31:0] src_d, src_q;
wire clk, rst_n;
clk_rst_if clk_rst_if(.clk, .rst_n);
prim_flop_2sync #(.Width(32)) dut (
// source clock domain
.d_i (src_d),
// destination clock domain
.clk_i (clk),
.rst_ni (rst_n),
.q_o (src_q)
);
initial begin
clk_rst_if.set_active();
clk_rst_if.apply_reset(.reset_width_clks(10));
$display("Using prim_cdc_rand_delay_mode slow");
dut.u_prim_cdc_rand_delay.set_prim_cdc_rand_delay_mode(1);
repeat (100) begin
src_d <= $urandom();
clk_rst_if.wait_clks($urandom_range(1, 20));
end
clk_rst_if.wait_clks(200);
$display("Using prim_cdc_rand_delay_mode once");
dut.u_prim_cdc_rand_delay.set_prim_cdc_rand_delay_mode(2);
repeat (100) begin
src_d <= $urandom();
clk_rst_if.wait_clks($urandom_range(1, 20));
end
clk_rst_if.wait_clks(200);
$display("Using prim_cdc_rand_delay_mode interval = 10");
dut.u_prim_cdc_rand_delay.set_prim_cdc_rand_delay_mode(3);
dut.u_prim_cdc_rand_delay.set_prim_cdc_rand_delay_interval(10);
repeat (100) begin
src_d <= $urandom();
clk_rst_if.wait_clks($urandom_range(1, 20));
end
clk_rst_if.wait_clks(200);
$display("Using prim_cdc_rand_delay_mode interval = 1");
dut.u_prim_cdc_rand_delay.set_prim_cdc_rand_delay_interval(1);
repeat (100) begin
src_d <= $urandom();
clk_rst_if.wait_clks($urandom_range(1, 20));
end
clk_rst_if.wait_clks(200);
$display("Using prim_cdc_rand_delay_mode interval = 0");
dut.u_prim_cdc_rand_delay.set_prim_cdc_rand_delay_interval(0);
repeat (100) begin
src_d <= $urandom();
clk_rst_if.wait_clks($urandom_range(1, 20));
end
clk_rst_if.wait_clks(200);
// TODO: Add more checks.
dv_test_status_pkg::dv_test_status(.passed(1));
`DV_CHECK(!src_d_q.size(), , , MsgId)
$finish;
end
// Verify src_d to src_q consistency.
logic [31:0] src_d_q[$];
initial begin
fork
forever @src_d if (rst_n) src_d_q.push_back(src_d);
forever @src_q `DV_CHECK_EQ(src_q, src_d_q.pop_front(), , , MsgId)
join_none
end
endmodule

View file

@ -0,0 +1,42 @@
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:blanker"
description: "Primitive for blanking signals"
filesets:
files_rtl:
depend:
- lowrisc:prim:and2
files:
- rtl/prim_blanker.sv
file_type: systemVerilogSource
files_verilator_waiver:
depend:
# common waivers
- lowrisc:lint:common
files:
file_type: vlt
files_ascentlint_waiver:
depend:
# common waivers
- lowrisc:lint:common
files:
- lint/prim_and2.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

View file

@ -18,6 +18,7 @@ filesets:
# common waivers
- lowrisc:lint:common
files:
- lint/prim_cdc_rand_delay.vlt
file_type: vlt
files_ascentlint_waiver:
@ -25,7 +26,7 @@ filesets:
# common waivers
- lowrisc:lint:common
files:
- lint/prim_cdc_rand_delay.waiver
#- lint/prim_cdc_rand_delay.waiver
file_type: waiver
files_veriblelint_waiver:
@ -35,6 +36,10 @@ filesets:
targets:
default:
tools:
verilator:
verilator_options:
- '-DDISABLE_PRIM_CDC_RAND_DELAY'
filesets:
- files_rtl
- tool_verilator ? (files_verilator_waiver)

View file

@ -12,6 +12,7 @@ filesets:
# Needed because the generic prim_flop_2sync has a
# dependency on prim:flop.
- lowrisc:prim:flop
- lowrisc:prim:cdc_rand_delay
files:
- rtl/prim_flop_2sync.sv
file_type: systemVerilogSource

View 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:onehot"
description: "Utilities for working with one-hot encoding"
filesets:
files_rtl:
depend:
- lowrisc:prim:util
files:
- rtl/prim_onehot_enc.sv
- rtl/prim_onehot_mux.sv
file_type: systemVerilogSource
files_verilator_waiver:
depend:
# common waivers
- lowrisc:lint:common
#files:
# - lint/prim_onehot.vlt
file_type: vlt
files_ascentlint_waiver:
depend:
# common waivers
- lowrisc:lint:common
#files:
# - lint/prim_onehot.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

View file

@ -0,0 +1,49 @@
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:onehot_check"
description: "One-hot encoding checker"
filesets:
files_rtl:
depend:
- lowrisc:prim:util
- lowrisc:prim:assert
files:
- rtl/prim_onehot_check.sv
file_type: systemVerilogSource
files_verilator_waiver:
depend:
# common waivers
- lowrisc:lint:common
files:
- lint/prim_onehot_check.vlt
file_type: vlt
files_ascentlint_waiver:
depend:
# common waivers
- lowrisc:lint:common
files:
- lint/prim_onehot_check.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
formal:
filesets:
- files_rtl
toplevel: prim_onehot_check

View file

@ -304,12 +304,16 @@ module prim_alert_sender
sequence AckSigInt_S;
alert_rx_i.ping_p == alert_rx_i.ping_n [*2];
endsequence
`ifndef FPV_ALERT_NO_SIGINT_ERR
// check propagation of sigint issues to output within three cycles
// shift sequence to the right to avoid reset effects.
`ASSERT(SigIntPing_A, ##1 PingSigInt_S |->
##3 alert_tx_o.alert_p == alert_tx_o.alert_n)
`ASSERT(SigIntAck_A, ##1 AckSigInt_S |->
##3 alert_tx_o.alert_p == alert_tx_o.alert_n)
`endif
// Test in-band FSM reset request (via signal integrity error)
`ASSERT(InBandInitFsm_A, PingSigInt_S or AckSigInt_S |-> ##3 state_q == Idle)
`ASSERT(InBandInitPing_A, PingSigInt_S or AckSigInt_S |-> ##3 !ping_set_q)
@ -332,11 +336,15 @@ module prim_alert_sender
sequence AckSigInt_S;
alert_rx_i.ping_p == alert_rx_i.ping_n;
endsequence
`ifndef FPV_ALERT_NO_SIGINT_ERR
// check propagation of sigint issues to output within one cycle
`ASSERT(SigIntPing_A, PingSigInt_S |=>
alert_tx_o.alert_p == alert_tx_o.alert_n)
`ASSERT(SigIntAck_A, AckSigInt_S |=>
alert_tx_o.alert_p == alert_tx_o.alert_n)
`endif
// Test in-band FSM reset request (via signal integrity error)
`ASSERT(InBandInitFsm_A, PingSigInt_S or AckSigInt_S |=> state_q == Idle)
`ASSERT(InBandInitPing_A, PingSigInt_S or AckSigInt_S |=> !ping_set_q)
@ -374,7 +382,7 @@ module prim_alert_sender
clk_i, !rst_ni || (alert_tx_o.alert_p == alert_tx_o.alert_n))
`endif
`ifdef FPV_SEC_CM_ON
`ifdef FPV_ALERT_NO_SIGINT_ERR
// Assumptions for FPV security countermeasures to ensure the alert protocol functions collectly.
`ASSUME_FPV(AckPFollowsAlertP_S, alert_rx_i.ack_p == $past(alert_tx_o.alert_p))
`ASSUME_FPV(AckNFollowsAlertN_S, alert_rx_i.ack_n == $past(alert_tx_o.alert_n))

View file

@ -43,6 +43,15 @@
unused_assert_static_lint_error = __name'(1'b1); \
end
// Static assertions for checks inside SV packages. If the conditions is not true, this will
// trigger an error during elaboration.
`define ASSERT_STATIC_IN_PACKAGE(__name, __prop) \
function automatic bit assert_static_in_package_``__name(); \
bit unused_bit [((__prop) ? 1 : -1)]; \
unused_bit = '{default: 1'b0}; \
return unused_bit[0]; \
endfunction
// The basic helper macros are actually defined in "implementation headers". The macros should do
// the same thing in each case (except for the dummy flavour), but in a way that the respective
// tools support.

View file

@ -0,0 +1,20 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
// Convenience module for wrapping prim_and2 for use in blanking.
// When en_i == 1 the input is fed through to the output.
// When en_i == 0 the output is 0.
module prim_blanker #(
parameter int Width = 1
) (
input logic [Width-1:0] in_i,
input logic en_i,
output logic [Width-1:0] out_o
);
prim_and2 #(.Width(Width)) u_blank_and (
.in0_i(in_i),
.in1_i({Width{en_i}}),
.out_o
);
endmodule

View file

@ -17,26 +17,22 @@
// This is meant to model skew between synchronizer bits and wire delay between the src and dst
// flops.
//
// Five (5) different random delay modes are available:
// Four different random delay modes are available:
//
// - PrimCdcRandDelayDisable: If this delay mode is picked, this module acts as a simple
// passthrough.
// - RandDelayDisable: If this delay mode is picked, this module acts as a passthrough.
//
// - PrimCdcRandDelaySlow: If this delay mode is picked, the output to the dst domain is
// continuously driven to `src_data_delayed`.
// - RandDelaySlow: If this delay mode is picked, the output to the dst domain is
// continuously driven to `src_data_delayed`.
//
// - PrimCdcRandDelayOnce: If this delay mode is picked, the mask `out_data_mask` used to combine
// `src_data_with_latency` and `src_data_delayed` is fully randomized
// once at the beginning of the simulation.
// - RandDelayOnce: If this delay mode is picked, the mask `out_data_mask` used to combine
// `src_data_with_latency` and `src_data_delayed` is randomized once at the
// start of the simulation.
//
// - PrimCdcRandDelayInterval: If this delay mode is picked, the mask `out_data_mask` used to
// combine `src_data_with_latency` and `src_data_delayed` is fully
// randomized every `prim_cdc_num_src_data_changes` times that
// `src_data_with_latency` changes.
//
// - PrimCdcRandDelayFull: If this delay mode is picked, the mask `out_data_mask` used to combine
// `src_data_with_latency` and `src_data_delayed` is fully randomized
// any time `src_data_with_latency` changes.
// - RandDelayInterval: If this delay mode is picked, the mask `out_data_mask` used to
// combine `src_data_with_latency` and `src_data_delayed` is fully
// randomized every `prim_cdc_rand_delay_interval` times the src_data
// value changes. If the `prim_cdc_rand_delay_interval` is set to 0,
// then out_data_mask is randomized on every src_data change.
//
// DV has control of the weights corresponding to each random delay mode when the delay mode is
// randomized, but can also directly override the delay mode as desired.
@ -47,8 +43,8 @@
module prim_cdc_rand_delay #(
parameter int DataWidth = 1,
parameter bit UseSourceClock = 1,
parameter int LatencyPs = 500,
parameter int JitterPs = 500
parameter int LatencyPs = 1000,
parameter int JitterPs = 1000
) (
input logic src_clk,
input logic [DataWidth-1:0] src_data,
@ -57,148 +53,181 @@ module prim_cdc_rand_delay #(
output logic [DataWidth-1:0] dst_data
);
`ASSERT_INIT(LegalWidth_A, DataWidth > 0)
`ASSERT_INIT(LegalDataWidth_A, DataWidth > 0)
`ASSERT_INIT(LegalLatencyPs_A, LatencyPs >= 0)
`ASSERT_INIT(LegalJitterPs_A, JitterPs >= 0)
int prim_cdc_latency_ps = LatencyPs;
int prim_cdc_jitter_ps = JitterPs;
`ifdef SIMULATION
`ifndef DISABLE_PRIM_CDC_RAND_DELAY
// Only applies with using CdcRandDelayInterval randomization mode.
//
// This is the number of times that `src_data_with_latency` is allowed to change before
// we re-randomize `out_data_mask`.
int prim_cdc_num_src_data_changes = 10;
int counter = 0;
typedef enum bit [1:0] {
RandDelayModeDisable,
RandDelayModeSlow,
RandDelayModeOnce,
RandDelayModeInterval
} rand_delay_mode_e;
task automatic set_prim_cdc_latency_ps(int val);
prim_cdc_latency_ps = val;
`ASSERT_I(LegalLatency_A, prim_cdc_latency_ps > 0)
endtask
rand_delay_mode_e prim_cdc_rand_delay_mode;
int unsigned prim_cdc_rand_delay_interval = 10;
int unsigned prim_cdc_rand_delay_disable_weight = 1;
int unsigned prim_cdc_rand_delay_slow_weight = 2;
int unsigned prim_cdc_rand_delay_once_weight = 4;
int unsigned prim_cdc_rand_delay_interval_weight = 3;
bit [3:0] mode; // onehot encoded version of prim_cdc_rand_delay_mode.
task automatic set_prim_cdc_jitter_ps(int val);
prim_cdc_jitter_ps = val;
`ASSERT_I(LegalJitter_A, prim_cdc_jitter_ps > 0)
endtask
task automatic set_prim_cdc_num_src_data_changes(int val);
prim_cdc_num_src_data_changes = val;
endtask
typedef enum bit [2:0] {
PrimCdcRandDelayDisable,
PrimCdcRandDelaySlow,
PrimCdcRandDelayOnce,
PrimCdcRandDelayInterval,
PrimCdcRandDelayFull
} prim_cdc_rand_delay_mode_e;
prim_cdc_rand_delay_mode_e prim_cdc_rand_mode;
int unsigned prim_cdc_jitter_ps = JitterPs;
int unsigned prim_cdc_latency_ps = LatencyPs;
logic [DataWidth-1:0] out_data_mask;
bit en_passthru = 1'b0;
bit out_randomize_en = 1'b0;
bit en_rand_interval_mask = 1'b0;
logic [DataWidth-1:0] src_data_with_latency;
logic [DataWidth-1:0] src_data_delayed;
int unsigned prim_cdc_rand_disable_weight = 0;
int unsigned prim_cdc_rand_slow_weight = 20;
int unsigned prim_cdc_rand_once_weight = 50;
int unsigned prim_cdc_rand_interval_weight = 20;
int unsigned prim_cdc_rand_full_weight = 10;
function automatic void set_prim_cdc_rand_delay_mode(int val);
prim_cdc_rand_delay_mode = rand_delay_mode_e'(val);
update_settings();
endfunction
function automatic void set_prim_cdc_rand_delay_interval(int unsigned val);
prim_cdc_rand_delay_interval = val;
endfunction
function automatic void set_prim_cdc_jitter_ps(int val);
`ASSERT_I(LegalJitter_A, prim_cdc_jitter_ps >= 0)
prim_cdc_jitter_ps = val;
endfunction
function automatic void set_prim_cdc_latency_ps(int val);
`ASSERT_I(LegalLatencyPs_A, val >= 0)
prim_cdc_latency_ps = val;
endfunction
// Internal method called after prim_cdc_rand_delay_mode is set.
function automatic void update_settings();
mode = '0;
mode[prim_cdc_rand_delay_mode] = 1'b1;
if (prim_cdc_rand_delay_mode == RandDelayModeSlow) out_data_mask = '1;
if (prim_cdc_rand_delay_mode == RandDelayModeOnce) fast_randomize(out_data_mask);
endfunction
// A slightly more performant version of std::randomize(), using $urandom.
//
// Empirically, using std::randomize() has been found to be slower than $urandom, since the latter
// operates on a fixed data width of 32-bits. There may be an incredibly large number of instances
// of this module in the DUT, causing this preformance hit to be noticeable. This method
// randomizes the data piece-wise, 32-bits at a time using $urandom instead.
function automatic void fast_randomize(output logic [DataWidth-1:0] data);
for (int i = 0; i < DataWidth; i += 32) data = (data << 32) | $urandom();
endfunction
// Retrieves settings via plusargs.
//
// prefix is a string prefix to retrieve the plusarg.
// Returns 1 if prim_cdc_rand_delay_mode was set, else 0.
function automatic bit get_plusargs(string prefix = "");
string mode = "";
int unsigned val;
if (prefix != "") prefix = {prefix, "."};
void'($value$plusargs({prefix, "prim_cdc_rand_delay_mode=%0s"}, mode));
`ASSERT_I(ValidMode_A, mode inside {"", "disable", "slow", "once", "interval"})
void'($value$plusargs({prefix, "prim_cdc_rand_delay_interval=%0d"},
prim_cdc_rand_delay_interval));
void'($value$plusargs({prefix, "prim_cdc_rand_delay_disable_weight=%0d"},
prim_cdc_rand_delay_disable_weight));
void'($value$plusargs({prefix, "prim_cdc_rand_delay_slow_weight=%0d"},
prim_cdc_rand_delay_slow_weight));
void'($value$plusargs({prefix, "prim_cdc_rand_delay_once_weight=%0d"},
prim_cdc_rand_delay_once_weight));
void'($value$plusargs({prefix, "prim_cdc_rand_delay_interval_weight=%0d"},
prim_cdc_rand_delay_interval_weight));
void'($value$plusargs({prefix, "prim_cdc_jitter_ps=%0d"}, prim_cdc_jitter_ps));
void'($value$plusargs({prefix, "prim_cdc_latency_ps=%0d"}, prim_cdc_latency_ps));
case (mode)
"disable": prim_cdc_rand_delay_mode = RandDelayModeDisable;
"slow": prim_cdc_rand_delay_mode = RandDelayModeSlow;
"once": prim_cdc_rand_delay_mode = RandDelayModeOnce;
"interval": prim_cdc_rand_delay_mode = RandDelayModeInterval;
default: return 0;
endcase
return 1;
endfunction
initial begin
// DV can override these from command line as desired.
void'($value$plusargs("prim_cdc_latency_ps=%0d", prim_cdc_latency_ps));
void'($value$plusargs("prim_cdc_jitter_ps=%0d", prim_cdc_jitter_ps));
void'($value$plusargs("prim_cdc_num_src_data_changes=%0d", prim_cdc_num_src_data_changes));
void'($value$plusargs("prim_cdc_rand_disable_weight=%0d", prim_cdc_rand_disable_weight));
void'($value$plusargs("prim_cdc_rand_slow_weight=%0d", prim_cdc_rand_slow_weight));
void'($value$plusargs("prim_cdc_rand_once_weight=%0d", prim_cdc_rand_once_weight));
void'($value$plusargs("prim_cdc_rand_interval_weight=%0d", prim_cdc_rand_interval_weight));
void'($value$plusargs("prim_cdc_rand_full_weight=%0d", prim_cdc_rand_full_weight));
bit res;
if (!$value$plusargs("prim_cdc_rand_mode=%0d", prim_cdc_rand_mode)) begin
// By default pick the most performant(*) random delay mode for normal test
// development/simulation.
//
// (*): Need to do some performance experiments to check that the chosen mode is actually the
// most performant.
prim_cdc_rand_mode = PrimCdcRandDelaySlow;
// Command-line override via plusargs (global, applies to ALL instances).
// Example: +prim_cdc_rand_delay_mode=once
res = get_plusargs();
// Command-line override via plusargs (instance-specific).
// Example: +tb.dut.u_foo.u_bar.u_flop_2sync.u_prim_cdc_rand_delay.prim_cdc_latency_ps=200
res |= get_plusargs($sformatf("%m"));
if (!res) begin
`DV_CHECK_STD_RANDOMIZE_WITH_FATAL(prim_cdc_rand_delay_mode,
prim_cdc_rand_delay_mode dist {
RandDelayModeDisable :/ prim_cdc_rand_delay_disable_weight,
RandDelayModeSlow :/ prim_cdc_rand_delay_slow_weight,
RandDelayModeOnce :/ prim_cdc_rand_delay_once_weight,
RandDelayModeInterval :/ prim_cdc_rand_delay_interval_weight
};,
, $sformatf("%m"))
end
unique case (prim_cdc_rand_mode)
PrimCdcRandDelayDisable: begin
// If CDC randomization disabled, behave like a passthrough
en_passthru = 1'b1;
end
PrimCdcRandDelaySlow: begin
out_data_mask = '1;
end
PrimCdcRandDelayOnce: begin
void'(std::randomize(out_data_mask));
end
PrimCdcRandDelayInterval: begin
out_randomize_en = 1'b1;
en_rand_interval_mask = 1'b1;
end
PrimCdcRandDelayFull: begin
out_randomize_en = 1'b1;
end
default: begin
$fatal("%0d is an invalid randomization mode", prim_cdc_rand_mode);
end
endcase
update_settings();
end
// TODO: Run some performance experiments using this implementation versus an implementation that
// primarily uses `forever` blocks rather than RTL constructs.
// Need to also check if this alternate implementation is still valid when
// compiling/simulating the design.
// primarily uses `forever` blocks rather than RTL constructs. Need to also check if this
// alternate implementation is still valid when compiling/simulating the design.
if (UseSourceClock) begin : gen_use_source_clock
// If relying on src_clk, insert a delay on the fastest clock
// If relying on src_clk, insert a delay on the faster clock.
always_ff @(posedge src_clk or posedge dst_clk) begin
src_data_delayed <= src_data;
end
assign src_data_with_latency = src_data;
end else begin : gen_no_use_source_clock
// If not relying on src_clk, delay by a fixed number of ps determined by the module parameters
always_comb begin
// If not relying on src_clk, delay by a fixed number of ps determined by the module parameters.
always @(src_data) begin
src_data_with_latency <= #(prim_cdc_latency_ps * 1ps) src_data;
end
always_comb begin
always @(src_data_with_latency) begin
src_data_delayed <= #(prim_cdc_jitter_ps * 1ps) src_data_with_latency;
end
end : gen_no_use_source_clock
// Randomize delayed random data selection only when input data changes
// Randomize delayed random data selection when input data changes, every
// prim_cdc_rand_delay_interval number of changes.
int counter = 0;
always @(src_data_with_latency) begin
if ((out_randomize_en && !en_rand_interval_mask) ||
(en_rand_interval_mask && counter == prim_cdc_num_src_data_changes) begin
for (int i = 0; i < DataWidth; i += 32) begin
// As of VCS 2017.12-SP2-6, it is slower to randomize for a DataWidth <= 32 with
// std::randomize() than using $urandom(), which may be more noticeable here as this module
// can potentially have a large number of instances.
//
// Whenever time permits, it will be interesting to run some perf tests with the current VCS
// version and see what updated performance looks like.
out_data_mask = (out_data_mask << 32) | $urandom();
end
end
if (en_rand_interval_mask) begin
counter <= (counter == prim_cdc_num_src_data_changes) ? 0 : counter + 1;
if (mode[RandDelayModeInterval]) begin
counter <= (counter >= prim_cdc_rand_delay_interval) ? '0 : counter + 1;
if (counter == prim_cdc_rand_delay_interval) fast_randomize(out_data_mask);
end else begin
counter <= 0;
end
end
assign dst_data = (en_passthru) ?
(src_data) :
assign dst_data = mode[RandDelayModeDisable] ? src_data :
((src_data_delayed & out_data_mask) | (src_data_with_latency & ~out_data_mask));
`else
// Direct pass through.
assign dst_data = src_data;
`endif // DISABLE_PRIM_CDC_RAND_DELAY
`else
// Direct pass through.
assign dst_data = src_data;
`endif // SIMULATION
//TODO: coverage
endmodule

View file

@ -233,6 +233,7 @@ module prim_diff_decode #(
end
end
`ifndef FPV_ALERT_NO_SIGINT_ERR
// correctly detect sigint issue (only one transition cycle of permissible due to skew)
`ASSERT(SigintCheck0_A, hlp_diff_pq == hlp_diff_nq [*2] |-> ##[0:1] sigint_o)
// the synchronizer adds 2 cycles of latency with respect to input signals.
@ -256,6 +257,8 @@ module prim_diff_decode #(
$fell(hlp_diff_nq) && $stable(hlp_diff_pq) ##1 $stable(hlp_diff_nq) && $rose(hlp_diff_pq)
|->
##1 rise_o)
`endif
// correctly detect edges
`ASSERT(RiseCheck_A, ##1 $rose(hlp_diff_pq) && (hlp_diff_pq ^ hlp_diff_nq) |->
##[1:2] rise_o, clk_i, !rst_ni || sigint_o)
@ -270,8 +273,12 @@ module prim_diff_decode #(
`endif
end else begin : gen_sync_assert
// assertions for synchronous case
`ifndef FPV_ALERT_NO_SIGINT_ERR
// correctly detect sigint issue
`ASSERT(SigintCheck_A, diff_pi == diff_ni |-> sigint_o)
`endif
// correctly detect edges
`ASSERT(RiseCheck_A, ##1 $rose(diff_pi) && (diff_pi ^ diff_ni) |-> rise_o)
`ASSERT(FallCheck_A, ##1 $fell(diff_pi) && (diff_pi ^ diff_ni) |-> fall_o)

View file

@ -8,7 +8,9 @@
module prim_flop_2sync #(
parameter int Width = 16,
parameter logic [Width-1:0] ResetValue = '0
parameter logic [Width-1:0] ResetValue = '0,
parameter int CdcLatencyPs = 1000,
parameter int CdcJitterPs = 1000
) (
input clk_i,
input rst_ni,
@ -16,7 +18,19 @@ module prim_flop_2sync #(
output logic [Width-1:0] q_o
);
// TODO(#10432): Add CDC instrumentation for simulations
logic [Width-1:0] d_o;
prim_cdc_rand_delay #(
.DataWidth(Width),
.UseSourceClock(0),
.LatencyPs(CdcLatencyPs),
.JitterPs(CdcJitterPs)
) u_prim_cdc_rand_delay (
.src_clk(),
.src_data(d_i),
.dst_clk(clk_i),
.dst_data(d_o)
);
logic [Width-1:0] intq;
@ -26,7 +40,7 @@ module prim_flop_2sync #(
) u_sync_1 (
.clk_i,
.rst_ni,
.d_i,
.d_i(d_o),
.q_o(intq)
);

View file

@ -0,0 +1,122 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
// Onehot checker.
//
// This module checks whether the input vector oh_i is onehot0 and generates an error if not.
//
// Optionally, two additional checks can be activated:
//
// 1) EnableCheck: this check performs an OR reduction of the onehot vector, and compares
// the result with en_i. If there is a mismatch, an error is generated.
// 2) AddrCheck: this checks whether the bit at a certain location is equal to en_i.
// It requires an additional address addr_i to be supplied to the module.
// This check can only be enabled if EnableCheck is enabled.
//
// All checks make use of an explicit binary tree implementation in order to minimize the delay.
//
`include "prim_assert.sv"
module prim_onehot_check #(
parameter int unsigned AddrWidth = 5,
// The onehot width can be <= 2**AddrWidth and does not have to be a power of two.
parameter int unsigned OneHotWidth = 2**AddrWidth,
// If set to 0, the addr_i input will not be used for the check and can be tied off.
parameter bit AddrCheck = 1,
// If set to 0, the en_i value will not be used for the check and can be tied off.
parameter bit EnableCheck = 1
) (
// The module is combinational - the clock and reset are only used for assertions.
input clk_i,
input rst_ni,
input logic [OneHotWidth-1:0] oh_i,
input logic [AddrWidth-1:0] addr_i,
input logic en_i,
output logic err_o
);
///////////////////////
// Binary tree logic //
///////////////////////
// This only works with 2 or more sources.
`ASSERT_INIT(NumSources_A, OneHotWidth >= 2)
`ASSERT_INIT(AddrSize_A, OneHotWidth <= 2**AddrWidth)
`ASSERT_INIT(AddrImpliesEnable_A, AddrCheck && EnableCheck || !AddrCheck)
// Align to powers of 2 for simplicity.
// A full binary tree with N levels has 2**N + 2**N-1 nodes.
localparam int NumLevels = $clog2(OneHotWidth);
logic [2**(NumLevels+1)-2:0] or_tree;
logic [2**(NumLevels+1)-2:0] and_tree; // Used for the address check
logic [2**(NumLevels+1)-2:0] err_tree; // Used for the enable check
for (genvar level = 0; level < NumLevels+1; level++) begin : gen_tree
//
// level+1 C0 C1 <- "Base1" points to the first node on "level+1",
// \ / these nodes are the children of the nodes one level below
// level Pa <- "Base0", points to the first node on "level",
// these nodes are the parents of the nodes one level above
//
// hence we have the following indices for the paPa, C0, C1 nodes:
// Pa = 2**level - 1 + offset = Base0 + offset
// C0 = 2**(level+1) - 1 + 2*offset = Base1 + 2*offset
// C1 = 2**(level+1) - 1 + 2*offset + 1 = Base1 + 2*offset + 1
//
localparam int Base0 = (2**level)-1;
localparam int Base1 = (2**(level+1))-1;
for (genvar offset = 0; offset < 2**level; offset++) begin : gen_level
localparam int Pa = Base0 + offset;
localparam int C0 = Base1 + 2*offset;
localparam int C1 = Base1 + 2*offset + 1;
// This assigns the input values, their corresponding IDs and valid signals to the tree leafs.
if (level == NumLevels) begin : gen_leafs
if (offset < OneHotWidth) begin : gen_assign
assign or_tree[Pa] = oh_i[offset];
assign and_tree[Pa] = oh_i[offset];
end else begin : gen_tie_off
assign or_tree[Pa] = 1'b0;
assign and_tree[Pa] = 1'b0;
end
assign err_tree[Pa] = 1'b0;
// This creates the node assignments.
end else begin : gen_nodes
assign or_tree[Pa] = or_tree[C0] || or_tree[C1];
assign and_tree[Pa] = (!addr_i[AddrWidth-1-level] && and_tree[C0]) ||
(addr_i[AddrWidth-1-level] && and_tree[C1]);
assign err_tree[Pa] = (or_tree[C0] && or_tree[C1]) || err_tree[C0] || err_tree[C1];
end
end : gen_level
end : gen_tree
// Check whether:
// 1) more than 1 bit is set in the vector
// 2) whether en_i agrees with (|oh_i)
// 3) the bit that is set is actually in the correct position
logic enable_err, addr_err, oh0_err;
assign oh0_err = err_tree[0];
if (EnableCheck) begin : gen_enable_check
assign enable_err = or_tree[0] ^ en_i;
`ASSERT(EnableCheck_A, ($countones(oh_i) != en_i) |-> err_o)
if (AddrCheck) begin : gen_addr_check
assign addr_err = and_tree[0] ^ en_i;
`ASSERT(AddrCheck_A, oh_i[addr_i] != en_i |-> err_o)
end else begin : gen_no_addr_check
assign addr_err = 1'b0;
end
end else begin : gen_no_enable_check
assign enable_err = 1'b0;
assign addr_err = 1'b0;
end
assign err_o = oh0_err || enable_err || addr_err;
`ASSERT(Onehot0Check_A, !$onehot0(oh_i) |-> err_o)
endmodule : prim_onehot_check

View file

@ -0,0 +1,21 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
// One-hot encoder
// Outputs a one-hot encoded version of an integer input.
module prim_onehot_enc #(
parameter int unsigned OneHotWidth = 32,
localparam int unsigned InputWidth = $clog2(OneHotWidth)
) (
input logic [InputWidth-1:0] in_i,
input logic en_i, // out_o == '0 when en_i == 0
output logic [OneHotWidth-1:0] out_o
);
for (genvar i = 0; i < OneHotWidth; ++i) begin : g_out
assign out_o[i] = (in_i == i) & en_i;
end
endmodule

View file

@ -0,0 +1,48 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
// One-hot mux
// A AND/OR mux with a one-hot select input.
`include "prim_assert.sv"
module prim_onehot_mux #(
parameter int Width = 32,
parameter int Inputs = 8
) (
// Clock and reset only for assertions
input clk_i,
input rst_ni,
input logic [Width-1:0] in_i [Inputs],
input logic [Inputs-1:0] sel_i, // Must be one-hot or zero
output logic [Width-1:0] out_o
);
logic [Inputs-1:0] in_mux [Width];
for (genvar b = 0; b < Width; ++b) begin : g_in_mux_outer
logic [Inputs-1:0] out_mux_bits;
for (genvar i = 0; i < Inputs; ++i) begin : g_in_mux_inner
assign in_mux[b][i] = in_i[i][b];
end
prim_and2 #(.Width(Inputs)) u_mux_bit_and(
.in0_i(in_mux[b]),
.in1_i(sel_i),
.out_o(out_mux_bits)
);
assign out_o[b] = |out_mux_bits;
end
logic unused_clk;
logic unused_rst_n;
// clock and reset only needed for assertion
assign unused_clk = clk_i;
assign unused_rst_n = rst_ni;
`ASSERT(SelIsOnehot_A, $onehot0(sel_i))
endmodule

View file

@ -320,6 +320,8 @@ module prim_ram_1p_scr import prim_ram_1p_pkg::*; #(
for (int k = 0; k < Width; k++) begin
if (wmask_q[k]) begin
rdata_o[k] = wdata_q[k];
end else begin
rdata_o[k] = rdata[k];
end
end
// regular reads. note that we just return zero in case

View file

@ -11,12 +11,12 @@ module prim_secded_22_16_enc (
always_comb begin : p_encode
data_o = 22'(data_i);
data_o[16] = 1'b0 ^ ^(data_o & 22'h00496E);
data_o[17] = 1'b0 ^ ^(data_o & 22'h00F20B);
data_o[18] = 1'b0 ^ ^(data_o & 22'h008ED8);
data_o[19] = 1'b0 ^ ^(data_o & 22'h007714);
data_o[20] = 1'b0 ^ ^(data_o & 22'h00ACA5);
data_o[21] = 1'b0 ^ ^(data_o & 22'h0011F3);
data_o[16] = ^(data_o & 22'h00496E);
data_o[17] = ^(data_o & 22'h00F20B);
data_o[18] = ^(data_o & 22'h008ED8);
data_o[19] = ^(data_o & 22'h007714);
data_o[20] = ^(data_o & 22'h00ACA5);
data_o[21] = ^(data_o & 22'h0011F3);
end
endmodule : prim_secded_22_16_enc

View file

@ -11,12 +11,12 @@ module prim_secded_28_22_enc (
always_comb begin : p_encode
data_o = 28'(data_i);
data_o[22] = 1'b0 ^ ^(data_o & 28'h03003FF);
data_o[23] = 1'b0 ^ ^(data_o & 28'h010FC0F);
data_o[24] = 1'b0 ^ ^(data_o & 28'h0271C71);
data_o[25] = 1'b0 ^ ^(data_o & 28'h03B6592);
data_o[26] = 1'b0 ^ ^(data_o & 28'h03DAAA4);
data_o[27] = 1'b0 ^ ^(data_o & 28'h03ED348);
data_o[22] = ^(data_o & 28'h03003FF);
data_o[23] = ^(data_o & 28'h010FC0F);
data_o[24] = ^(data_o & 28'h0271C71);
data_o[25] = ^(data_o & 28'h03B6592);
data_o[26] = ^(data_o & 28'h03DAAA4);
data_o[27] = ^(data_o & 28'h03ED348);
end
endmodule : prim_secded_28_22_enc

View file

@ -11,13 +11,13 @@ module prim_secded_39_32_enc (
always_comb begin : p_encode
data_o = 39'(data_i);
data_o[32] = 1'b0 ^ ^(data_o & 39'h002606BD25);
data_o[33] = 1'b0 ^ ^(data_o & 39'h00DEBA8050);
data_o[34] = 1'b0 ^ ^(data_o & 39'h00413D89AA);
data_o[35] = 1'b0 ^ ^(data_o & 39'h0031234ED1);
data_o[36] = 1'b0 ^ ^(data_o & 39'h00C2C1323B);
data_o[37] = 1'b0 ^ ^(data_o & 39'h002DCC624C);
data_o[38] = 1'b0 ^ ^(data_o & 39'h0098505586);
data_o[32] = ^(data_o & 39'h002606BD25);
data_o[33] = ^(data_o & 39'h00DEBA8050);
data_o[34] = ^(data_o & 39'h00413D89AA);
data_o[35] = ^(data_o & 39'h0031234ED1);
data_o[36] = ^(data_o & 39'h00C2C1323B);
data_o[37] = ^(data_o & 39'h002DCC624C);
data_o[38] = ^(data_o & 39'h0098505586);
end
endmodule : prim_secded_39_32_enc

View file

@ -11,13 +11,13 @@ module prim_secded_64_57_enc (
always_comb begin : p_encode
data_o = 64'(data_i);
data_o[57] = 1'b0 ^ ^(data_o & 64'h0103FFF800007FFF);
data_o[58] = 1'b0 ^ ^(data_o & 64'h017C1FF801FF801F);
data_o[59] = 1'b0 ^ ^(data_o & 64'h01BDE1F87E0781E1);
data_o[60] = 1'b0 ^ ^(data_o & 64'h01DEEE3B8E388E22);
data_o[61] = 1'b0 ^ ^(data_o & 64'h01EF76CDB2C93244);
data_o[62] = 1'b0 ^ ^(data_o & 64'h01F7BB56D5525488);
data_o[63] = 1'b0 ^ ^(data_o & 64'h01FBDDA769A46910);
data_o[57] = ^(data_o & 64'h0103FFF800007FFF);
data_o[58] = ^(data_o & 64'h017C1FF801FF801F);
data_o[59] = ^(data_o & 64'h01BDE1F87E0781E1);
data_o[60] = ^(data_o & 64'h01DEEE3B8E388E22);
data_o[61] = ^(data_o & 64'h01EF76CDB2C93244);
data_o[62] = ^(data_o & 64'h01F7BB56D5525488);
data_o[63] = ^(data_o & 64'h01FBDDA769A46910);
end
endmodule : prim_secded_64_57_enc

View file

@ -11,14 +11,14 @@ module prim_secded_72_64_enc (
always_comb begin : p_encode
data_o = 72'(data_i);
data_o[64] = 1'b0 ^ ^(data_o & 72'h00B9000000001FFFFF);
data_o[65] = 1'b0 ^ ^(data_o & 72'h005E00000FFFE0003F);
data_o[66] = 1'b0 ^ ^(data_o & 72'h0067003FF003E007C1);
data_o[67] = 1'b0 ^ ^(data_o & 72'h00CD0FC0F03C207842);
data_o[68] = 1'b0 ^ ^(data_o & 72'h00B671C711C4438884);
data_o[69] = 1'b0 ^ ^(data_o & 72'h00B5B65926488C9108);
data_o[70] = 1'b0 ^ ^(data_o & 72'h00CBDAAA4A91152210);
data_o[71] = 1'b0 ^ ^(data_o & 72'h007AED348D221A4420);
data_o[64] = ^(data_o & 72'h00B9000000001FFFFF);
data_o[65] = ^(data_o & 72'h005E00000FFFE0003F);
data_o[66] = ^(data_o & 72'h0067003FF003E007C1);
data_o[67] = ^(data_o & 72'h00CD0FC0F03C207842);
data_o[68] = ^(data_o & 72'h00B671C711C4438884);
data_o[69] = ^(data_o & 72'h00B5B65926488C9108);
data_o[70] = ^(data_o & 72'h00CBDAAA4A91152210);
data_o[71] = ^(data_o & 72'h007AED348D221A4420);
end
endmodule : prim_secded_72_64_enc

View file

@ -11,12 +11,12 @@ module prim_secded_hamming_22_16_enc (
always_comb begin : p_encode
data_o = 22'(data_i);
data_o[16] = 1'b0 ^ ^(data_o & 22'h00AD5B);
data_o[17] = 1'b0 ^ ^(data_o & 22'h00366D);
data_o[18] = 1'b0 ^ ^(data_o & 22'h00C78E);
data_o[19] = 1'b0 ^ ^(data_o & 22'h0007F0);
data_o[20] = 1'b0 ^ ^(data_o & 22'h00F800);
data_o[21] = 1'b0 ^ ^(data_o & 22'h1FFFFF);
data_o[16] = ^(data_o & 22'h00AD5B);
data_o[17] = ^(data_o & 22'h00366D);
data_o[18] = ^(data_o & 22'h00C78E);
data_o[19] = ^(data_o & 22'h0007F0);
data_o[20] = ^(data_o & 22'h00F800);
data_o[21] = ^(data_o & 22'h1FFFFF);
end
endmodule : prim_secded_hamming_22_16_enc

View file

@ -11,13 +11,13 @@ module prim_secded_hamming_39_32_enc (
always_comb begin : p_encode
data_o = 39'(data_i);
data_o[32] = 1'b0 ^ ^(data_o & 39'h0056AAAD5B);
data_o[33] = 1'b0 ^ ^(data_o & 39'h009B33366D);
data_o[34] = 1'b0 ^ ^(data_o & 39'h00E3C3C78E);
data_o[35] = 1'b0 ^ ^(data_o & 39'h0003FC07F0);
data_o[36] = 1'b0 ^ ^(data_o & 39'h0003FFF800);
data_o[37] = 1'b0 ^ ^(data_o & 39'h00FC000000);
data_o[38] = 1'b0 ^ ^(data_o & 39'h3FFFFFFFFF);
data_o[32] = ^(data_o & 39'h0056AAAD5B);
data_o[33] = ^(data_o & 39'h009B33366D);
data_o[34] = ^(data_o & 39'h00E3C3C78E);
data_o[35] = ^(data_o & 39'h0003FC07F0);
data_o[36] = ^(data_o & 39'h0003FFF800);
data_o[37] = ^(data_o & 39'h00FC000000);
data_o[38] = ^(data_o & 39'h3FFFFFFFFF);
end
endmodule : prim_secded_hamming_39_32_enc

View file

@ -11,14 +11,14 @@ module prim_secded_hamming_72_64_enc (
always_comb begin : p_encode
data_o = 72'(data_i);
data_o[64] = 1'b0 ^ ^(data_o & 72'h00AB55555556AAAD5B);
data_o[65] = 1'b0 ^ ^(data_o & 72'h00CD9999999B33366D);
data_o[66] = 1'b0 ^ ^(data_o & 72'h00F1E1E1E1E3C3C78E);
data_o[67] = 1'b0 ^ ^(data_o & 72'h0001FE01FE03FC07F0);
data_o[68] = 1'b0 ^ ^(data_o & 72'h0001FFFE0003FFF800);
data_o[69] = 1'b0 ^ ^(data_o & 72'h0001FFFFFFFC000000);
data_o[70] = 1'b0 ^ ^(data_o & 72'h00FE00000000000000);
data_o[71] = 1'b0 ^ ^(data_o & 72'h7FFFFFFFFFFFFFFFFF);
data_o[64] = ^(data_o & 72'h00AB55555556AAAD5B);
data_o[65] = ^(data_o & 72'h00CD9999999B33366D);
data_o[66] = ^(data_o & 72'h00F1E1E1E1E3C3C78E);
data_o[67] = ^(data_o & 72'h0001FE01FE03FC07F0);
data_o[68] = ^(data_o & 72'h0001FFFE0003FFF800);
data_o[69] = ^(data_o & 72'h0001FFFFFFFC000000);
data_o[70] = ^(data_o & 72'h00FE00000000000000);
data_o[71] = ^(data_o & 72'h7FFFFFFFFFFFFFFFFF);
end
endmodule : prim_secded_hamming_72_64_enc

View file

@ -11,14 +11,14 @@ module prim_secded_hamming_76_68_enc (
always_comb begin : p_encode
data_o = 76'(data_i);
data_o[68] = 1'b0 ^ ^(data_o & 76'h00AAB55555556AAAD5B);
data_o[69] = 1'b0 ^ ^(data_o & 76'h00CCD9999999B33366D);
data_o[70] = 1'b0 ^ ^(data_o & 76'h000F1E1E1E1E3C3C78E);
data_o[71] = 1'b0 ^ ^(data_o & 76'h00F01FE01FE03FC07F0);
data_o[72] = 1'b0 ^ ^(data_o & 76'h00001FFFE0003FFF800);
data_o[73] = 1'b0 ^ ^(data_o & 76'h00001FFFFFFFC000000);
data_o[74] = 1'b0 ^ ^(data_o & 76'h00FFE00000000000000);
data_o[75] = 1'b0 ^ ^(data_o & 76'h7FFFFFFFFFFFFFFFFFF);
data_o[68] = ^(data_o & 76'h00AAB55555556AAAD5B);
data_o[69] = ^(data_o & 76'h00CCD9999999B33366D);
data_o[70] = ^(data_o & 76'h000F1E1E1E1E3C3C78E);
data_o[71] = ^(data_o & 76'h00F01FE01FE03FC07F0);
data_o[72] = ^(data_o & 76'h00001FFFE0003FFF800);
data_o[73] = ^(data_o & 76'h00001FFFFFFFC000000);
data_o[74] = ^(data_o & 76'h00FFE00000000000000);
data_o[75] = ^(data_o & 76'h7FFFFFFFFFFFFFFFFFF);
end
endmodule : prim_secded_hamming_76_68_enc

View file

@ -11,12 +11,13 @@ module prim_secded_inv_22_16_enc (
always_comb begin : p_encode
data_o = 22'(data_i);
data_o[16] = 1'b0 ^ ^(data_o & 22'h00496E);
data_o[17] = 1'b1 ^ ^(data_o & 22'h00F20B);
data_o[18] = 1'b0 ^ ^(data_o & 22'h008ED8);
data_o[19] = 1'b1 ^ ^(data_o & 22'h007714);
data_o[20] = 1'b0 ^ ^(data_o & 22'h00ACA5);
data_o[21] = 1'b1 ^ ^(data_o & 22'h0011F3);
data_o[16] = ^(data_o & 22'h00496E);
data_o[17] = ^(data_o & 22'h00F20B);
data_o[18] = ^(data_o & 22'h008ED8);
data_o[19] = ^(data_o & 22'h007714);
data_o[20] = ^(data_o & 22'h00ACA5);
data_o[21] = ^(data_o & 22'h0011F3);
data_o ^= 22'h2A0000;
end
endmodule : prim_secded_inv_22_16_enc

View file

@ -11,12 +11,13 @@ module prim_secded_inv_28_22_enc (
always_comb begin : p_encode
data_o = 28'(data_i);
data_o[22] = 1'b0 ^ ^(data_o & 28'h03003FF);
data_o[23] = 1'b1 ^ ^(data_o & 28'h010FC0F);
data_o[24] = 1'b0 ^ ^(data_o & 28'h0271C71);
data_o[25] = 1'b1 ^ ^(data_o & 28'h03B6592);
data_o[26] = 1'b0 ^ ^(data_o & 28'h03DAAA4);
data_o[27] = 1'b1 ^ ^(data_o & 28'h03ED348);
data_o[22] = ^(data_o & 28'h03003FF);
data_o[23] = ^(data_o & 28'h010FC0F);
data_o[24] = ^(data_o & 28'h0271C71);
data_o[25] = ^(data_o & 28'h03B6592);
data_o[26] = ^(data_o & 28'h03DAAA4);
data_o[27] = ^(data_o & 28'h03ED348);
data_o ^= 28'hA800000;
end
endmodule : prim_secded_inv_28_22_enc

View file

@ -11,13 +11,14 @@ module prim_secded_inv_39_32_enc (
always_comb begin : p_encode
data_o = 39'(data_i);
data_o[32] = 1'b0 ^ ^(data_o & 39'h002606BD25);
data_o[33] = 1'b1 ^ ^(data_o & 39'h00DEBA8050);
data_o[34] = 1'b0 ^ ^(data_o & 39'h00413D89AA);
data_o[35] = 1'b1 ^ ^(data_o & 39'h0031234ED1);
data_o[36] = 1'b0 ^ ^(data_o & 39'h00C2C1323B);
data_o[37] = 1'b1 ^ ^(data_o & 39'h002DCC624C);
data_o[38] = 1'b0 ^ ^(data_o & 39'h0098505586);
data_o[32] = ^(data_o & 39'h002606BD25);
data_o[33] = ^(data_o & 39'h00DEBA8050);
data_o[34] = ^(data_o & 39'h00413D89AA);
data_o[35] = ^(data_o & 39'h0031234ED1);
data_o[36] = ^(data_o & 39'h00C2C1323B);
data_o[37] = ^(data_o & 39'h002DCC624C);
data_o[38] = ^(data_o & 39'h0098505586);
data_o ^= 39'h2A00000000;
end
endmodule : prim_secded_inv_39_32_enc

View file

@ -11,13 +11,14 @@ module prim_secded_inv_64_57_enc (
always_comb begin : p_encode
data_o = 64'(data_i);
data_o[57] = 1'b0 ^ ^(data_o & 64'h0103FFF800007FFF);
data_o[58] = 1'b1 ^ ^(data_o & 64'h017C1FF801FF801F);
data_o[59] = 1'b0 ^ ^(data_o & 64'h01BDE1F87E0781E1);
data_o[60] = 1'b1 ^ ^(data_o & 64'h01DEEE3B8E388E22);
data_o[61] = 1'b0 ^ ^(data_o & 64'h01EF76CDB2C93244);
data_o[62] = 1'b1 ^ ^(data_o & 64'h01F7BB56D5525488);
data_o[63] = 1'b0 ^ ^(data_o & 64'h01FBDDA769A46910);
data_o[57] = ^(data_o & 64'h0103FFF800007FFF);
data_o[58] = ^(data_o & 64'h017C1FF801FF801F);
data_o[59] = ^(data_o & 64'h01BDE1F87E0781E1);
data_o[60] = ^(data_o & 64'h01DEEE3B8E388E22);
data_o[61] = ^(data_o & 64'h01EF76CDB2C93244);
data_o[62] = ^(data_o & 64'h01F7BB56D5525488);
data_o[63] = ^(data_o & 64'h01FBDDA769A46910);
data_o ^= 64'h5400000000000000;
end
endmodule : prim_secded_inv_64_57_enc

View file

@ -11,14 +11,15 @@ module prim_secded_inv_72_64_enc (
always_comb begin : p_encode
data_o = 72'(data_i);
data_o[64] = 1'b0 ^ ^(data_o & 72'h00B9000000001FFFFF);
data_o[65] = 1'b1 ^ ^(data_o & 72'h005E00000FFFE0003F);
data_o[66] = 1'b0 ^ ^(data_o & 72'h0067003FF003E007C1);
data_o[67] = 1'b1 ^ ^(data_o & 72'h00CD0FC0F03C207842);
data_o[68] = 1'b0 ^ ^(data_o & 72'h00B671C711C4438884);
data_o[69] = 1'b1 ^ ^(data_o & 72'h00B5B65926488C9108);
data_o[70] = 1'b0 ^ ^(data_o & 72'h00CBDAAA4A91152210);
data_o[71] = 1'b1 ^ ^(data_o & 72'h007AED348D221A4420);
data_o[64] = ^(data_o & 72'h00B9000000001FFFFF);
data_o[65] = ^(data_o & 72'h005E00000FFFE0003F);
data_o[66] = ^(data_o & 72'h0067003FF003E007C1);
data_o[67] = ^(data_o & 72'h00CD0FC0F03C207842);
data_o[68] = ^(data_o & 72'h00B671C711C4438884);
data_o[69] = ^(data_o & 72'h00B5B65926488C9108);
data_o[70] = ^(data_o & 72'h00CBDAAA4A91152210);
data_o[71] = ^(data_o & 72'h007AED348D221A4420);
data_o ^= 72'hAA0000000000000000;
end
endmodule : prim_secded_inv_72_64_enc

View file

@ -11,12 +11,13 @@ module prim_secded_inv_hamming_22_16_enc (
always_comb begin : p_encode
data_o = 22'(data_i);
data_o[16] = 1'b0 ^ ^(data_o & 22'h00AD5B);
data_o[17] = 1'b1 ^ ^(data_o & 22'h00366D);
data_o[18] = 1'b0 ^ ^(data_o & 22'h00C78E);
data_o[19] = 1'b1 ^ ^(data_o & 22'h0007F0);
data_o[20] = 1'b0 ^ ^(data_o & 22'h00F800);
data_o[21] = 1'b1 ^ ^(data_o & 22'h1FFFFF);
data_o[16] = ^(data_o & 22'h00AD5B);
data_o[17] = ^(data_o & 22'h00366D);
data_o[18] = ^(data_o & 22'h00C78E);
data_o[19] = ^(data_o & 22'h0007F0);
data_o[20] = ^(data_o & 22'h00F800);
data_o[21] = ^(data_o & 22'h1FFFFF);
data_o ^= 22'h2A0000;
end
endmodule : prim_secded_inv_hamming_22_16_enc

View file

@ -11,13 +11,14 @@ module prim_secded_inv_hamming_39_32_enc (
always_comb begin : p_encode
data_o = 39'(data_i);
data_o[32] = 1'b0 ^ ^(data_o & 39'h0056AAAD5B);
data_o[33] = 1'b1 ^ ^(data_o & 39'h009B33366D);
data_o[34] = 1'b0 ^ ^(data_o & 39'h00E3C3C78E);
data_o[35] = 1'b1 ^ ^(data_o & 39'h0003FC07F0);
data_o[36] = 1'b0 ^ ^(data_o & 39'h0003FFF800);
data_o[37] = 1'b1 ^ ^(data_o & 39'h00FC000000);
data_o[38] = 1'b0 ^ ^(data_o & 39'h3FFFFFFFFF);
data_o[32] = ^(data_o & 39'h0056AAAD5B);
data_o[33] = ^(data_o & 39'h009B33366D);
data_o[34] = ^(data_o & 39'h00E3C3C78E);
data_o[35] = ^(data_o & 39'h0003FC07F0);
data_o[36] = ^(data_o & 39'h0003FFF800);
data_o[37] = ^(data_o & 39'h00FC000000);
data_o[38] = ^(data_o & 39'h3FFFFFFFFF);
data_o ^= 39'h2A00000000;
end
endmodule : prim_secded_inv_hamming_39_32_enc

View file

@ -11,14 +11,15 @@ module prim_secded_inv_hamming_72_64_enc (
always_comb begin : p_encode
data_o = 72'(data_i);
data_o[64] = 1'b0 ^ ^(data_o & 72'h00AB55555556AAAD5B);
data_o[65] = 1'b1 ^ ^(data_o & 72'h00CD9999999B33366D);
data_o[66] = 1'b0 ^ ^(data_o & 72'h00F1E1E1E1E3C3C78E);
data_o[67] = 1'b1 ^ ^(data_o & 72'h0001FE01FE03FC07F0);
data_o[68] = 1'b0 ^ ^(data_o & 72'h0001FFFE0003FFF800);
data_o[69] = 1'b1 ^ ^(data_o & 72'h0001FFFFFFFC000000);
data_o[70] = 1'b0 ^ ^(data_o & 72'h00FE00000000000000);
data_o[71] = 1'b1 ^ ^(data_o & 72'h7FFFFFFFFFFFFFFFFF);
data_o[64] = ^(data_o & 72'h00AB55555556AAAD5B);
data_o[65] = ^(data_o & 72'h00CD9999999B33366D);
data_o[66] = ^(data_o & 72'h00F1E1E1E1E3C3C78E);
data_o[67] = ^(data_o & 72'h0001FE01FE03FC07F0);
data_o[68] = ^(data_o & 72'h0001FFFE0003FFF800);
data_o[69] = ^(data_o & 72'h0001FFFFFFFC000000);
data_o[70] = ^(data_o & 72'h00FE00000000000000);
data_o[71] = ^(data_o & 72'h7FFFFFFFFFFFFFFFFF);
data_o ^= 72'hAA0000000000000000;
end
endmodule : prim_secded_inv_hamming_72_64_enc

View file

@ -11,14 +11,15 @@ module prim_secded_inv_hamming_76_68_enc (
always_comb begin : p_encode
data_o = 76'(data_i);
data_o[68] = 1'b0 ^ ^(data_o & 76'h00AAB55555556AAAD5B);
data_o[69] = 1'b1 ^ ^(data_o & 76'h00CCD9999999B33366D);
data_o[70] = 1'b0 ^ ^(data_o & 76'h000F1E1E1E1E3C3C78E);
data_o[71] = 1'b1 ^ ^(data_o & 76'h00F01FE01FE03FC07F0);
data_o[72] = 1'b0 ^ ^(data_o & 76'h00001FFFE0003FFF800);
data_o[73] = 1'b1 ^ ^(data_o & 76'h00001FFFFFFFC000000);
data_o[74] = 1'b0 ^ ^(data_o & 76'h00FFE00000000000000);
data_o[75] = 1'b1 ^ ^(data_o & 76'h7FFFFFFFFFFFFFFFFFF);
data_o[68] = ^(data_o & 76'h00AAB55555556AAAD5B);
data_o[69] = ^(data_o & 76'h00CCD9999999B33366D);
data_o[70] = ^(data_o & 76'h000F1E1E1E1E3C3C78E);
data_o[71] = ^(data_o & 76'h00F01FE01FE03FC07F0);
data_o[72] = ^(data_o & 76'h00001FFFE0003FFF800);
data_o[73] = ^(data_o & 76'h00001FFFFFFFC000000);
data_o[74] = ^(data_o & 76'h00FFE00000000000000);
data_o[75] = ^(data_o & 76'h7FFFFFFFFFFFFFFFFFF);
data_o ^= 76'hAA00000000000000000;
end
endmodule : prim_secded_inv_hamming_76_68_enc

View file

@ -244,12 +244,12 @@ package prim_secded_pkg;
prim_secded_22_16_enc (logic [15:0] data_i);
logic [21:0] data_o;
data_o = 22'(data_i);
data_o[16] = 1'b0 ^ ^(data_o & 22'h00496E);
data_o[17] = 1'b0 ^ ^(data_o & 22'h00F20B);
data_o[18] = 1'b0 ^ ^(data_o & 22'h008ED8);
data_o[19] = 1'b0 ^ ^(data_o & 22'h007714);
data_o[20] = 1'b0 ^ ^(data_o & 22'h00ACA5);
data_o[21] = 1'b0 ^ ^(data_o & 22'h0011F3);
data_o[16] = ^(data_o & 22'h00496E);
data_o[17] = ^(data_o & 22'h00F20B);
data_o[18] = ^(data_o & 22'h008ED8);
data_o[19] = ^(data_o & 22'h007714);
data_o[20] = ^(data_o & 22'h00ACA5);
data_o[21] = ^(data_o & 22'h0011F3);
return data_o;
endfunction
@ -302,12 +302,12 @@ package prim_secded_pkg;
prim_secded_28_22_enc (logic [21:0] data_i);
logic [27:0] data_o;
data_o = 28'(data_i);
data_o[22] = 1'b0 ^ ^(data_o & 28'h03003FF);
data_o[23] = 1'b0 ^ ^(data_o & 28'h010FC0F);
data_o[24] = 1'b0 ^ ^(data_o & 28'h0271C71);
data_o[25] = 1'b0 ^ ^(data_o & 28'h03B6592);
data_o[26] = 1'b0 ^ ^(data_o & 28'h03DAAA4);
data_o[27] = 1'b0 ^ ^(data_o & 28'h03ED348);
data_o[22] = ^(data_o & 28'h03003FF);
data_o[23] = ^(data_o & 28'h010FC0F);
data_o[24] = ^(data_o & 28'h0271C71);
data_o[25] = ^(data_o & 28'h03B6592);
data_o[26] = ^(data_o & 28'h03DAAA4);
data_o[27] = ^(data_o & 28'h03ED348);
return data_o;
endfunction
@ -366,13 +366,13 @@ package prim_secded_pkg;
prim_secded_39_32_enc (logic [31:0] data_i);
logic [38:0] data_o;
data_o = 39'(data_i);
data_o[32] = 1'b0 ^ ^(data_o & 39'h002606BD25);
data_o[33] = 1'b0 ^ ^(data_o & 39'h00DEBA8050);
data_o[34] = 1'b0 ^ ^(data_o & 39'h00413D89AA);
data_o[35] = 1'b0 ^ ^(data_o & 39'h0031234ED1);
data_o[36] = 1'b0 ^ ^(data_o & 39'h00C2C1323B);
data_o[37] = 1'b0 ^ ^(data_o & 39'h002DCC624C);
data_o[38] = 1'b0 ^ ^(data_o & 39'h0098505586);
data_o[32] = ^(data_o & 39'h002606BD25);
data_o[33] = ^(data_o & 39'h00DEBA8050);
data_o[34] = ^(data_o & 39'h00413D89AA);
data_o[35] = ^(data_o & 39'h0031234ED1);
data_o[36] = ^(data_o & 39'h00C2C1323B);
data_o[37] = ^(data_o & 39'h002DCC624C);
data_o[38] = ^(data_o & 39'h0098505586);
return data_o;
endfunction
@ -442,13 +442,13 @@ package prim_secded_pkg;
prim_secded_64_57_enc (logic [56:0] data_i);
logic [63:0] data_o;
data_o = 64'(data_i);
data_o[57] = 1'b0 ^ ^(data_o & 64'h0103FFF800007FFF);
data_o[58] = 1'b0 ^ ^(data_o & 64'h017C1FF801FF801F);
data_o[59] = 1'b0 ^ ^(data_o & 64'h01BDE1F87E0781E1);
data_o[60] = 1'b0 ^ ^(data_o & 64'h01DEEE3B8E388E22);
data_o[61] = 1'b0 ^ ^(data_o & 64'h01EF76CDB2C93244);
data_o[62] = 1'b0 ^ ^(data_o & 64'h01F7BB56D5525488);
data_o[63] = 1'b0 ^ ^(data_o & 64'h01FBDDA769A46910);
data_o[57] = ^(data_o & 64'h0103FFF800007FFF);
data_o[58] = ^(data_o & 64'h017C1FF801FF801F);
data_o[59] = ^(data_o & 64'h01BDE1F87E0781E1);
data_o[60] = ^(data_o & 64'h01DEEE3B8E388E22);
data_o[61] = ^(data_o & 64'h01EF76CDB2C93244);
data_o[62] = ^(data_o & 64'h01F7BB56D5525488);
data_o[63] = ^(data_o & 64'h01FBDDA769A46910);
return data_o;
endfunction
@ -543,14 +543,14 @@ package prim_secded_pkg;
prim_secded_72_64_enc (logic [63:0] data_i);
logic [71:0] data_o;
data_o = 72'(data_i);
data_o[64] = 1'b0 ^ ^(data_o & 72'h00B9000000001FFFFF);
data_o[65] = 1'b0 ^ ^(data_o & 72'h005E00000FFFE0003F);
data_o[66] = 1'b0 ^ ^(data_o & 72'h0067003FF003E007C1);
data_o[67] = 1'b0 ^ ^(data_o & 72'h00CD0FC0F03C207842);
data_o[68] = 1'b0 ^ ^(data_o & 72'h00B671C711C4438884);
data_o[69] = 1'b0 ^ ^(data_o & 72'h00B5B65926488C9108);
data_o[70] = 1'b0 ^ ^(data_o & 72'h00CBDAAA4A91152210);
data_o[71] = 1'b0 ^ ^(data_o & 72'h007AED348D221A4420);
data_o[64] = ^(data_o & 72'h00B9000000001FFFFF);
data_o[65] = ^(data_o & 72'h005E00000FFFE0003F);
data_o[66] = ^(data_o & 72'h0067003FF003E007C1);
data_o[67] = ^(data_o & 72'h00CD0FC0F03C207842);
data_o[68] = ^(data_o & 72'h00B671C711C4438884);
data_o[69] = ^(data_o & 72'h00B5B65926488C9108);
data_o[70] = ^(data_o & 72'h00CBDAAA4A91152210);
data_o[71] = ^(data_o & 72'h007AED348D221A4420);
return data_o;
endfunction
@ -653,12 +653,12 @@ package prim_secded_pkg;
prim_secded_hamming_22_16_enc (logic [15:0] data_i);
logic [21:0] data_o;
data_o = 22'(data_i);
data_o[16] = 1'b0 ^ ^(data_o & 22'h00AD5B);
data_o[17] = 1'b0 ^ ^(data_o & 22'h00366D);
data_o[18] = 1'b0 ^ ^(data_o & 22'h00C78E);
data_o[19] = 1'b0 ^ ^(data_o & 22'h0007F0);
data_o[20] = 1'b0 ^ ^(data_o & 22'h00F800);
data_o[21] = 1'b0 ^ ^(data_o & 22'h1FFFFF);
data_o[16] = ^(data_o & 22'h00AD5B);
data_o[17] = ^(data_o & 22'h00366D);
data_o[18] = ^(data_o & 22'h00C78E);
data_o[19] = ^(data_o & 22'h0007F0);
data_o[20] = ^(data_o & 22'h00F800);
data_o[21] = ^(data_o & 22'h1FFFFF);
return data_o;
endfunction
@ -711,13 +711,13 @@ package prim_secded_pkg;
prim_secded_hamming_39_32_enc (logic [31:0] data_i);
logic [38:0] data_o;
data_o = 39'(data_i);
data_o[32] = 1'b0 ^ ^(data_o & 39'h0056AAAD5B);
data_o[33] = 1'b0 ^ ^(data_o & 39'h009B33366D);
data_o[34] = 1'b0 ^ ^(data_o & 39'h00E3C3C78E);
data_o[35] = 1'b0 ^ ^(data_o & 39'h0003FC07F0);
data_o[36] = 1'b0 ^ ^(data_o & 39'h0003FFF800);
data_o[37] = 1'b0 ^ ^(data_o & 39'h00FC000000);
data_o[38] = 1'b0 ^ ^(data_o & 39'h3FFFFFFFFF);
data_o[32] = ^(data_o & 39'h0056AAAD5B);
data_o[33] = ^(data_o & 39'h009B33366D);
data_o[34] = ^(data_o & 39'h00E3C3C78E);
data_o[35] = ^(data_o & 39'h0003FC07F0);
data_o[36] = ^(data_o & 39'h0003FFF800);
data_o[37] = ^(data_o & 39'h00FC000000);
data_o[38] = ^(data_o & 39'h3FFFFFFFFF);
return data_o;
endfunction
@ -787,14 +787,14 @@ package prim_secded_pkg;
prim_secded_hamming_72_64_enc (logic [63:0] data_i);
logic [71:0] data_o;
data_o = 72'(data_i);
data_o[64] = 1'b0 ^ ^(data_o & 72'h00AB55555556AAAD5B);
data_o[65] = 1'b0 ^ ^(data_o & 72'h00CD9999999B33366D);
data_o[66] = 1'b0 ^ ^(data_o & 72'h00F1E1E1E1E3C3C78E);
data_o[67] = 1'b0 ^ ^(data_o & 72'h0001FE01FE03FC07F0);
data_o[68] = 1'b0 ^ ^(data_o & 72'h0001FFFE0003FFF800);
data_o[69] = 1'b0 ^ ^(data_o & 72'h0001FFFFFFFC000000);
data_o[70] = 1'b0 ^ ^(data_o & 72'h00FE00000000000000);
data_o[71] = 1'b0 ^ ^(data_o & 72'h7FFFFFFFFFFFFFFFFF);
data_o[64] = ^(data_o & 72'h00AB55555556AAAD5B);
data_o[65] = ^(data_o & 72'h00CD9999999B33366D);
data_o[66] = ^(data_o & 72'h00F1E1E1E1E3C3C78E);
data_o[67] = ^(data_o & 72'h0001FE01FE03FC07F0);
data_o[68] = ^(data_o & 72'h0001FFFE0003FFF800);
data_o[69] = ^(data_o & 72'h0001FFFFFFFC000000);
data_o[70] = ^(data_o & 72'h00FE00000000000000);
data_o[71] = ^(data_o & 72'h7FFFFFFFFFFFFFFFFF);
return data_o;
endfunction
@ -897,14 +897,14 @@ package prim_secded_pkg;
prim_secded_hamming_76_68_enc (logic [67:0] data_i);
logic [75:0] data_o;
data_o = 76'(data_i);
data_o[68] = 1'b0 ^ ^(data_o & 76'h00AAB55555556AAAD5B);
data_o[69] = 1'b0 ^ ^(data_o & 76'h00CCD9999999B33366D);
data_o[70] = 1'b0 ^ ^(data_o & 76'h000F1E1E1E1E3C3C78E);
data_o[71] = 1'b0 ^ ^(data_o & 76'h00F01FE01FE03FC07F0);
data_o[72] = 1'b0 ^ ^(data_o & 76'h00001FFFE0003FFF800);
data_o[73] = 1'b0 ^ ^(data_o & 76'h00001FFFFFFFC000000);
data_o[74] = 1'b0 ^ ^(data_o & 76'h00FFE00000000000000);
data_o[75] = 1'b0 ^ ^(data_o & 76'h7FFFFFFFFFFFFFFFFFF);
data_o[68] = ^(data_o & 76'h00AAB55555556AAAD5B);
data_o[69] = ^(data_o & 76'h00CCD9999999B33366D);
data_o[70] = ^(data_o & 76'h000F1E1E1E1E3C3C78E);
data_o[71] = ^(data_o & 76'h00F01FE01FE03FC07F0);
data_o[72] = ^(data_o & 76'h00001FFFE0003FFF800);
data_o[73] = ^(data_o & 76'h00001FFFFFFFC000000);
data_o[74] = ^(data_o & 76'h00FFE00000000000000);
data_o[75] = ^(data_o & 76'h7FFFFFFFFFFFFFFFFFF);
return data_o;
endfunction
@ -1011,12 +1011,13 @@ package prim_secded_pkg;
prim_secded_inv_22_16_enc (logic [15:0] data_i);
logic [21:0] data_o;
data_o = 22'(data_i);
data_o[16] = 1'b0 ^ ^(data_o & 22'h00496E);
data_o[17] = 1'b1 ^ ^(data_o & 22'h00F20B);
data_o[18] = 1'b0 ^ ^(data_o & 22'h008ED8);
data_o[19] = 1'b1 ^ ^(data_o & 22'h007714);
data_o[20] = 1'b0 ^ ^(data_o & 22'h00ACA5);
data_o[21] = 1'b1 ^ ^(data_o & 22'h0011F3);
data_o[16] = ^(data_o & 22'h00496E);
data_o[17] = ^(data_o & 22'h00F20B);
data_o[18] = ^(data_o & 22'h008ED8);
data_o[19] = ^(data_o & 22'h007714);
data_o[20] = ^(data_o & 22'h00ACA5);
data_o[21] = ^(data_o & 22'h0011F3);
data_o ^= 22'h2A0000;
return data_o;
endfunction
@ -1069,12 +1070,13 @@ package prim_secded_pkg;
prim_secded_inv_28_22_enc (logic [21:0] data_i);
logic [27:0] data_o;
data_o = 28'(data_i);
data_o[22] = 1'b0 ^ ^(data_o & 28'h03003FF);
data_o[23] = 1'b1 ^ ^(data_o & 28'h010FC0F);
data_o[24] = 1'b0 ^ ^(data_o & 28'h0271C71);
data_o[25] = 1'b1 ^ ^(data_o & 28'h03B6592);
data_o[26] = 1'b0 ^ ^(data_o & 28'h03DAAA4);
data_o[27] = 1'b1 ^ ^(data_o & 28'h03ED348);
data_o[22] = ^(data_o & 28'h03003FF);
data_o[23] = ^(data_o & 28'h010FC0F);
data_o[24] = ^(data_o & 28'h0271C71);
data_o[25] = ^(data_o & 28'h03B6592);
data_o[26] = ^(data_o & 28'h03DAAA4);
data_o[27] = ^(data_o & 28'h03ED348);
data_o ^= 28'hA800000;
return data_o;
endfunction
@ -1133,13 +1135,14 @@ package prim_secded_pkg;
prim_secded_inv_39_32_enc (logic [31:0] data_i);
logic [38:0] data_o;
data_o = 39'(data_i);
data_o[32] = 1'b0 ^ ^(data_o & 39'h002606BD25);
data_o[33] = 1'b1 ^ ^(data_o & 39'h00DEBA8050);
data_o[34] = 1'b0 ^ ^(data_o & 39'h00413D89AA);
data_o[35] = 1'b1 ^ ^(data_o & 39'h0031234ED1);
data_o[36] = 1'b0 ^ ^(data_o & 39'h00C2C1323B);
data_o[37] = 1'b1 ^ ^(data_o & 39'h002DCC624C);
data_o[38] = 1'b0 ^ ^(data_o & 39'h0098505586);
data_o[32] = ^(data_o & 39'h002606BD25);
data_o[33] = ^(data_o & 39'h00DEBA8050);
data_o[34] = ^(data_o & 39'h00413D89AA);
data_o[35] = ^(data_o & 39'h0031234ED1);
data_o[36] = ^(data_o & 39'h00C2C1323B);
data_o[37] = ^(data_o & 39'h002DCC624C);
data_o[38] = ^(data_o & 39'h0098505586);
data_o ^= 39'h2A00000000;
return data_o;
endfunction
@ -1209,13 +1212,14 @@ package prim_secded_pkg;
prim_secded_inv_64_57_enc (logic [56:0] data_i);
logic [63:0] data_o;
data_o = 64'(data_i);
data_o[57] = 1'b0 ^ ^(data_o & 64'h0103FFF800007FFF);
data_o[58] = 1'b1 ^ ^(data_o & 64'h017C1FF801FF801F);
data_o[59] = 1'b0 ^ ^(data_o & 64'h01BDE1F87E0781E1);
data_o[60] = 1'b1 ^ ^(data_o & 64'h01DEEE3B8E388E22);
data_o[61] = 1'b0 ^ ^(data_o & 64'h01EF76CDB2C93244);
data_o[62] = 1'b1 ^ ^(data_o & 64'h01F7BB56D5525488);
data_o[63] = 1'b0 ^ ^(data_o & 64'h01FBDDA769A46910);
data_o[57] = ^(data_o & 64'h0103FFF800007FFF);
data_o[58] = ^(data_o & 64'h017C1FF801FF801F);
data_o[59] = ^(data_o & 64'h01BDE1F87E0781E1);
data_o[60] = ^(data_o & 64'h01DEEE3B8E388E22);
data_o[61] = ^(data_o & 64'h01EF76CDB2C93244);
data_o[62] = ^(data_o & 64'h01F7BB56D5525488);
data_o[63] = ^(data_o & 64'h01FBDDA769A46910);
data_o ^= 64'h5400000000000000;
return data_o;
endfunction
@ -1310,14 +1314,15 @@ package prim_secded_pkg;
prim_secded_inv_72_64_enc (logic [63:0] data_i);
logic [71:0] data_o;
data_o = 72'(data_i);
data_o[64] = 1'b0 ^ ^(data_o & 72'h00B9000000001FFFFF);
data_o[65] = 1'b1 ^ ^(data_o & 72'h005E00000FFFE0003F);
data_o[66] = 1'b0 ^ ^(data_o & 72'h0067003FF003E007C1);
data_o[67] = 1'b1 ^ ^(data_o & 72'h00CD0FC0F03C207842);
data_o[68] = 1'b0 ^ ^(data_o & 72'h00B671C711C4438884);
data_o[69] = 1'b1 ^ ^(data_o & 72'h00B5B65926488C9108);
data_o[70] = 1'b0 ^ ^(data_o & 72'h00CBDAAA4A91152210);
data_o[71] = 1'b1 ^ ^(data_o & 72'h007AED348D221A4420);
data_o[64] = ^(data_o & 72'h00B9000000001FFFFF);
data_o[65] = ^(data_o & 72'h005E00000FFFE0003F);
data_o[66] = ^(data_o & 72'h0067003FF003E007C1);
data_o[67] = ^(data_o & 72'h00CD0FC0F03C207842);
data_o[68] = ^(data_o & 72'h00B671C711C4438884);
data_o[69] = ^(data_o & 72'h00B5B65926488C9108);
data_o[70] = ^(data_o & 72'h00CBDAAA4A91152210);
data_o[71] = ^(data_o & 72'h007AED348D221A4420);
data_o ^= 72'hAA0000000000000000;
return data_o;
endfunction
@ -1420,12 +1425,13 @@ package prim_secded_pkg;
prim_secded_inv_hamming_22_16_enc (logic [15:0] data_i);
logic [21:0] data_o;
data_o = 22'(data_i);
data_o[16] = 1'b0 ^ ^(data_o & 22'h00AD5B);
data_o[17] = 1'b1 ^ ^(data_o & 22'h00366D);
data_o[18] = 1'b0 ^ ^(data_o & 22'h00C78E);
data_o[19] = 1'b1 ^ ^(data_o & 22'h0007F0);
data_o[20] = 1'b0 ^ ^(data_o & 22'h00F800);
data_o[21] = 1'b1 ^ ^(data_o & 22'h1FFFFF);
data_o[16] = ^(data_o & 22'h00AD5B);
data_o[17] = ^(data_o & 22'h00366D);
data_o[18] = ^(data_o & 22'h00C78E);
data_o[19] = ^(data_o & 22'h0007F0);
data_o[20] = ^(data_o & 22'h00F800);
data_o[21] = ^(data_o & 22'h1FFFFF);
data_o ^= 22'h2A0000;
return data_o;
endfunction
@ -1478,13 +1484,14 @@ package prim_secded_pkg;
prim_secded_inv_hamming_39_32_enc (logic [31:0] data_i);
logic [38:0] data_o;
data_o = 39'(data_i);
data_o[32] = 1'b0 ^ ^(data_o & 39'h0056AAAD5B);
data_o[33] = 1'b1 ^ ^(data_o & 39'h009B33366D);
data_o[34] = 1'b0 ^ ^(data_o & 39'h00E3C3C78E);
data_o[35] = 1'b1 ^ ^(data_o & 39'h0003FC07F0);
data_o[36] = 1'b0 ^ ^(data_o & 39'h0003FFF800);
data_o[37] = 1'b1 ^ ^(data_o & 39'h00FC000000);
data_o[38] = 1'b0 ^ ^(data_o & 39'h3FFFFFFFFF);
data_o[32] = ^(data_o & 39'h0056AAAD5B);
data_o[33] = ^(data_o & 39'h009B33366D);
data_o[34] = ^(data_o & 39'h00E3C3C78E);
data_o[35] = ^(data_o & 39'h0003FC07F0);
data_o[36] = ^(data_o & 39'h0003FFF800);
data_o[37] = ^(data_o & 39'h00FC000000);
data_o[38] = ^(data_o & 39'h3FFFFFFFFF);
data_o ^= 39'h2A00000000;
return data_o;
endfunction
@ -1554,14 +1561,15 @@ package prim_secded_pkg;
prim_secded_inv_hamming_72_64_enc (logic [63:0] data_i);
logic [71:0] data_o;
data_o = 72'(data_i);
data_o[64] = 1'b0 ^ ^(data_o & 72'h00AB55555556AAAD5B);
data_o[65] = 1'b1 ^ ^(data_o & 72'h00CD9999999B33366D);
data_o[66] = 1'b0 ^ ^(data_o & 72'h00F1E1E1E1E3C3C78E);
data_o[67] = 1'b1 ^ ^(data_o & 72'h0001FE01FE03FC07F0);
data_o[68] = 1'b0 ^ ^(data_o & 72'h0001FFFE0003FFF800);
data_o[69] = 1'b1 ^ ^(data_o & 72'h0001FFFFFFFC000000);
data_o[70] = 1'b0 ^ ^(data_o & 72'h00FE00000000000000);
data_o[71] = 1'b1 ^ ^(data_o & 72'h7FFFFFFFFFFFFFFFFF);
data_o[64] = ^(data_o & 72'h00AB55555556AAAD5B);
data_o[65] = ^(data_o & 72'h00CD9999999B33366D);
data_o[66] = ^(data_o & 72'h00F1E1E1E1E3C3C78E);
data_o[67] = ^(data_o & 72'h0001FE01FE03FC07F0);
data_o[68] = ^(data_o & 72'h0001FFFE0003FFF800);
data_o[69] = ^(data_o & 72'h0001FFFFFFFC000000);
data_o[70] = ^(data_o & 72'h00FE00000000000000);
data_o[71] = ^(data_o & 72'h7FFFFFFFFFFFFFFFFF);
data_o ^= 72'hAA0000000000000000;
return data_o;
endfunction
@ -1664,14 +1672,15 @@ package prim_secded_pkg;
prim_secded_inv_hamming_76_68_enc (logic [67:0] data_i);
logic [75:0] data_o;
data_o = 76'(data_i);
data_o[68] = 1'b0 ^ ^(data_o & 76'h00AAB55555556AAAD5B);
data_o[69] = 1'b1 ^ ^(data_o & 76'h00CCD9999999B33366D);
data_o[70] = 1'b0 ^ ^(data_o & 76'h000F1E1E1E1E3C3C78E);
data_o[71] = 1'b1 ^ ^(data_o & 76'h00F01FE01FE03FC07F0);
data_o[72] = 1'b0 ^ ^(data_o & 76'h00001FFFE0003FFF800);
data_o[73] = 1'b1 ^ ^(data_o & 76'h00001FFFFFFFC000000);
data_o[74] = 1'b0 ^ ^(data_o & 76'h00FFE00000000000000);
data_o[75] = 1'b1 ^ ^(data_o & 76'h7FFFFFFFFFFFFFFFFFF);
data_o[68] = ^(data_o & 76'h00AAB55555556AAAD5B);
data_o[69] = ^(data_o & 76'h00CCD9999999B33366D);
data_o[70] = ^(data_o & 76'h000F1E1E1E1E3C3C78E);
data_o[71] = ^(data_o & 76'h00F01FE01FE03FC07F0);
data_o[72] = ^(data_o & 76'h00001FFFE0003FFF800);
data_o[73] = ^(data_o & 76'h00001FFFFFFFC000000);
data_o[74] = ^(data_o & 76'h00FFE00000000000000);
data_o[75] = ^(data_o & 76'h7FFFFFFFFFFFFFFFFFF);
data_o ^= 76'hAA00000000000000000;
return data_o;
endfunction

View file

@ -6,6 +6,7 @@ import datetime
import logging as log
import os
import pprint
import re
import subprocess
import sys
from shutil import which
@ -558,7 +559,9 @@ class FlowCfg():
for rdir in results_dirs:
dirname = rdir.replace(self.results_server_path, '')
dirname = dirname.replace('/', '')
if dirname == "latest":
# Only track history directories with format
# "year.month.date_hour.min.sec".
if not bool(re.match('[\d*.]*_[\d*.]*', dirname)):
continue
rdirs.append(dirname)
rdirs.sort(reverse=True)

View file

@ -36,7 +36,7 @@ TS_FORMAT_LONG = "%A %B %d %Y %H:%M:%S UTC"
def run_cmd(cmd):
(status, output) = subprocess.getstatusoutput(cmd)
if status:
sys.stderr.write("cmd " + cmd + " returned with status " + str(status))
print(f'cmd {cmd} returned with status {status}', file=sys.stderr)
sys.exit(status)
return output