Skip to content

Commit

Permalink
[vendor] Update lowrisc_ip from OpenTitan
Browse files Browse the repository at this point in the history
Pull the latest version of lowrisc_ip from the current head of the
OpenTitan repository.

One handy result (the reason for re-vendoring!) is that prim_prince.sv
has been rewritten to avoid triggering errors with recent versions of
Verilator. See lowRISC/opentitan#19785 for an
explanation.
  • Loading branch information
rswarbrick committed Nov 20, 2023
1 parent bac72d9 commit 0b696c8
Show file tree
Hide file tree
Showing 36 changed files with 758 additions and 485 deletions.
2 changes: 1 addition & 1 deletion vendor/lowrisc_ip.lock.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@
upstream:
{
url: https://github.com/lowRISC/opentitan
rev: 0deeaa99e5760ee4f5c0a08e5fc1670509d22744
rev: 6124771b23f25fa7e8f116ed16ddbdd59336643f
}
}
2 changes: 1 addition & 1 deletion vendor/lowrisc_ip/dv/sv/dv_utils/dv_macros.svh
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,6 @@
// Do not leave this macro in other source files in the remote repo.
`ifndef OTDBG
`define OTDBG(x) \
$write($sformatf("%t:OTDBG:",$time));\
$write($sformatf("%t:OTDBG:%s:%d:",$time,`__FILE__, `__LINE__));\
$display($sformatf x);
`endif
138 changes: 79 additions & 59 deletions vendor/lowrisc_ip/dv/sv/mem_bkdr_util/mem_bkdr_util__sram.sv
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// Wrapper functions for SRAM's encrypted read/write operations.
// This file is included in `mem_bkdr_util.sv` as a continuation of `mem_bkdr_util` class.

// Returns the address after scrambling it using the given nonce.
function logic [bus_params_pkg::BUS_AW-1:0] get_sram_encrypt_addr (
logic [bus_params_pkg::BUS_AW-1:0] addr,
logic [SRAM_BLOCK_WIDTH-1:0] nonce,
Expand All @@ -22,27 +23,27 @@ function logic [bus_params_pkg::BUS_AW-1:0] get_sram_encrypt_addr (
addr_arr[i] = addr[addr_lsb + i];
end

// calculate scrambled address
scr_addr_arr = sram_scrambler_pkg::encrypt_sram_addr(addr_arr, full_addr_width, nonce_arr);

// convert to bus address output
// Convert to bus address output.
for (int i = 0; i < addr_lsb; i++) begin
scr_addr[i] = addr[i];
end

for (int i = 0; i < full_addr_width; i++) begin
scr_addr[addr_lsb + i] = scr_addr_arr[i];
end

return scr_addr;
endfunction : get_sram_encrypt_addr

endfunction // get_sram_encrypt_addr

// Returns the data after adding integrity bits and encrypting it with the given key and nonce.
// If flip_bits is non-zero it may introduce integrity errors, but notice there is a small chance
// after descrambling the data the errors will not be detected.
function logic [38:0] get_sram_encrypt32_intg_data (
logic [bus_params_pkg::BUS_AW-1:0] addr,
logic [31:0] data,
logic [SRAM_KEY_WIDTH-1:0] key,
logic [SRAM_BLOCK_WIDTH-1:0] nonce,
bit [38:0] flip_bits = '0,
int extra_addr_bits=0);

logic [38:0] integ_data;
Expand All @@ -61,25 +62,35 @@ function logic [38:0] get_sram_encrypt32_intg_data (
addr_arr[i] = addr[addr_lsb + i];
end

// Calculate the integrity constant
integ_data = prim_secded_pkg::prim_secded_inv_39_32_enc(data);
integ_data ^= flip_bits;

// Calculate the scrambled data
wdata_arr = {<<{integ_data}};
wdata_arr = sram_scrambler_pkg::encrypt_sram_data(
wdata_arr, 39, 39, addr_arr, full_addr_width, key_arr, nonce_arr
);
scrambled_data = {<<{wdata_arr}};

return scrambled_data;
endfunction : get_sram_encrypt32_intg_data

endfunction // get_sram_encrypt32_intg_data

// Returns the data at the given address after descrambling the address and decrypting the data.
// It simply ignores the integrity bits.
virtual function logic [38:0] sram_encrypt_read32_integ(logic [bus_params_pkg::BUS_AW-1:0] addr,
logic [SRAM_KEY_WIDTH-1:0] key,
logic [SRAM_BLOCK_WIDTH-1:0] nonce);
logic [bus_params_pkg::BUS_AW-1:0] scr_addr;
logic [38:0] rdata = '0;
logic [bus_params_pkg::BUS_AW-1:0] scr_addr = get_sram_encrypt_addr(addr, nonce);
logic [38:0] rdata39 = _sram_decrypt_read39(addr, scr_addr, key, nonce);
return rdata39[31:0];
endfunction : sram_encrypt_read32_integ

// This reads the data at a scrambled address and decrypts it. It returns the data and
// integrity bits.
local function logic [38:0] _sram_decrypt_read39(
logic [bus_params_pkg::BUS_AW-1:0] addr,
logic [bus_params_pkg::BUS_AW-1:0] scr_addr,
logic [SRAM_KEY_WIDTH-1:0] key,
logic [SRAM_BLOCK_WIDTH-1:0] nonce);
logic [38:0] rdata39 = '0;

logic rdata_arr [] = new[39];
logic addr_arr [] = new[addr_width];
Expand All @@ -92,59 +103,68 @@ virtual function logic [38:0] sram_encrypt_read32_integ(logic [bus_params_pkg::B
addr_arr[i] = addr[addr_lsb + i];
end

// Calculate the scrambled address
scr_addr = get_sram_encrypt_addr(addr, nonce);

// Read memory and return the decrypted data
rdata = read39integ(scr_addr);
`uvm_info(`gfn, $sformatf("scr data: 0x%0x", rdata), UVM_HIGH)
rdata_arr = {<<{rdata}};
rdata39 = read39integ(scr_addr);
`uvm_info(`gfn, $sformatf("scr data: 0x%0x", rdata39), UVM_HIGH)
rdata_arr = {<<{rdata39}};
rdata_arr = sram_scrambler_pkg::decrypt_sram_data(
rdata_arr, 39, 39, addr_arr, addr_width, key_arr, nonce_arr
);
rdata = {<<{rdata_arr}};
// Only return the data payload without ECC bits.
return rdata[31:0];

endfunction
rdata39 = {<<{rdata_arr}};
return rdata39;
endfunction : _sram_decrypt_read39

// Writes the data at the given address. It scrambles the address and encrypts the data after
// adding integrity bits. If flip_bits is non-zero it may introduce ecc errors.
virtual function void sram_encrypt_write32_integ(logic [bus_params_pkg::BUS_AW-1:0] addr,
logic [31:0] data,
logic [SRAM_KEY_WIDTH-1:0] key,
logic [SRAM_BLOCK_WIDTH-1:0] nonce,
bit [38:0] flip_bits = 0);
logic [bus_params_pkg::BUS_AW-1:0] scr_addr;
logic [38:0] integ_data;
logic [38:0] scrambled_data;

logic wdata_arr [] = new[39];
logic addr_arr [] = new[addr_width];
logic key_arr [] = new[SRAM_KEY_WIDTH];
logic nonce_arr [] = new[SRAM_BLOCK_WIDTH];

key_arr = {<<{key}};
nonce_arr = {<<{nonce}};

for (int i = 0; i < addr_width; i++) begin
addr_arr[i] = addr[addr_lsb + i];
end

// Calculate the scrambled address
scr_addr = get_sram_encrypt_addr(addr, nonce);

// Calculate the integrity constant
integ_data = prim_secded_pkg::prim_secded_inv_39_32_enc(data);

// flip some bits to inject integrity fault
integ_data ^= flip_bits;

// Calculate the scrambled data
wdata_arr = {<<{integ_data}};
wdata_arr = sram_scrambler_pkg::encrypt_sram_data(
wdata_arr, 39, 39, addr_arr, addr_width, key_arr, nonce_arr
);
scrambled_data = {<<{wdata_arr}};

// Write the scrambled data to memory
logic [bus_params_pkg::BUS_AW-1:0] scr_addr = get_sram_encrypt_addr(addr, nonce);
_sram_encrypt_write39(addr, scr_addr, data, key, nonce, flip_bits);
endfunction : sram_encrypt_write32_integ

// This encrypts, possibly flips some bits to inject errors, and writes the resulting data
// to a scrambled address.
local function void _sram_encrypt_write39(logic [bus_params_pkg::BUS_AW-1:0] addr,
logic [bus_params_pkg::BUS_AW-1:0] scr_addr,
logic [31:0] data,
logic [SRAM_KEY_WIDTH-1:0] key,
logic [SRAM_BLOCK_WIDTH-1:0] nonce,
bit [38:0] flip_bits);
logic [38:0] scrambled_data = get_sram_encrypt32_intg_data(addr, data, key, nonce, flip_bits);
write39integ(scr_addr, scrambled_data);
endfunction
endfunction : _sram_encrypt_write39

// This injects integrity errors in sram for an original address and the corresponding
// scrambled address. It needs to pass both addresses even though only the scrambled address
// is affected, since the original address is used to encrypt the data.
//
// This code needs to try multiple random data since it is possible after encryption the
// bit pattern will not result in a data error, as described in issue #10976
virtual function void sram_inject_integ_error(logic [bus_params_pkg::BUS_AW-1:0] addr,
logic [bus_params_pkg::BUS_AW-1:0] scr_addr,
logic [SRAM_KEY_WIDTH-1:0] key,
logic [SRAM_BLOCK_WIDTH-1:0] nonce);
int max_attempts = 40;
int attempt = 0;

while (attempt < max_attempts) begin
bit [31:0] data = $urandom();
bit [38:0] rdata_integ;
prim_secded_pkg::secded_inv_39_32_t dec;
// The specific bits to be flipped should be irrelevant.
_sram_encrypt_write39(addr, scr_addr, data, key, nonce, 39'h1001);
rdata_integ = _sram_decrypt_read39(addr, scr_addr, key, nonce);
dec = prim_secded_pkg::prim_secded_inv_39_32_dec(rdata_integ);
if (dec.err) begin
`uvm_info(`gfn, $sformatf(
"sram_inject_integ_error addr 0x%x, data 0x%x injects error %b after %0d attempts",
addr, rdata_integ, dec.err, attempt),
UVM_MEDIUM)
break;
end
++attempt;
end
`DV_CHECK_LT(attempt, max_attempts, "Too many attempts in sram_inject_ecc_error")
endfunction : sram_inject_integ_error
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ package sram_scrambler_pkg;

endfunction : encrypt_sram_addr

// Deccrypts the target SRAM address using the custom S&P network.
// Decrypts the target SRAM address using the custom S&P network.
function automatic state_t decrypt_sram_addr(logic addr[], int addr_width,
logic full_nonce[]);

Expand Down
27 changes: 27 additions & 0 deletions vendor/lowrisc_ip/dv/sv/push_pull_agent/push_pull_agent_cfg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,33 @@ class push_pull_agent_cfg #(parameter int HostDataWidth = 32,
return (d_user_data_q.size() > 0);
endfunction

// Return true if the interface is completely silent
virtual function logic is_silent();
return !((agent_type == PushAgent) ?
(vif.mon_cb.valid || vif.mon_cb.ready) :
(vif.mon_cb.req || vif.mon_cb.ack));
endfunction

// Return true if there's a stalled transaction
//
// If this is a pull agent, there is a stalled transaction when the req signal is high (so
// something is trying to read data), but the ack signal is low (there's no data available). If it
// is a push agent, there is a stalled transaction when the valid signal is high (so something is
// trying to provide data) but the ready signal is low (the data isn't being consumed).
virtual function logic is_stalled();
return ((agent_type == PushAgent) ?
(vif.mon_cb.valid && !vif.mon_cb.ready) :
(vif.mon_cb.req && !vif.mon_cb.ack));
endfunction

// Wait for any current transaction to finish
//
virtual task wait_while_running();
while (is_stalled()) @(vif.mon_cb);
// Add one last cycle to wait past the final cycle for the transaction that was stalled.
@(vif.mon_cb);
endtask

`uvm_object_param_utils_begin(push_pull_agent_cfg#(HostDataWidth, DeviceDataWidth))
`uvm_field_enum(push_pull_agent_e, agent_type, UVM_DEFAULT)
`uvm_field_enum(pull_handshake_e, pull_handshake_type, UVM_DEFAULT)
Expand Down
55 changes: 41 additions & 14 deletions vendor/lowrisc_ip/dv/tools/dvsim/sim.mk
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ ifneq (${sw_images},)
index=`echo $$sw_image | cut -d: -f 3`; \
flags=(`echo $$sw_image | cut -d: -f 4- --output-delimiter " "`); \
bazel_label="`echo $$sw_image | cut -d: -f 1-2`"; \
if [[ $${index} != 4 ]]; then \
if [[ $${index} != 4 && $${index} != 5 ]]; then \
bazel_label="$${bazel_label}_$${sw_build_device}"; \
bazel_cquery="labels(data, $${bazel_label}) union labels(srcs, $${bazel_label})"; \
else \
Expand Down Expand Up @@ -117,27 +117,54 @@ ifneq (${sw_images},)
fi; \
echo "Building with command: $${bazel_cmd} build $${bazel_opts} $${bazel_label}"; \
$${bazel_cmd} build $${bazel_airgapped_opts} $${bazel_opts} $${bazel_label}; \
for dep in $$($${bazel_cmd} cquery $${bazel_airgapped_opts} \
$${bazel_cquery} \
kind=$$($${bazel_cmd} cquery $${bazel_airgapped_opts} \
$${bazel_label} \
--ui_event_filters=-info \
--noshow_progress \
--output=starlark); do \
if [[ $$dep == //hw/ip/otp_ctrl/data* ]] || \
([[ $$dep != //hw* ]] && [[ $$dep != //util* ]] && [[ $$dep != //sw/host* ]]); then \
for artifact in $$($${bazel_cmd} cquery $${bazel_airgapped_opts} $${dep} \
--ui_event_filters=-info \
--noshow_progress \
--output=starlark \
--starlark:expr="\"\\n\".join([f.path for f in target.files.to_list()])"); do \
--output=label_kind | cut -f1 -d' '); \
if [[ $${kind} == "opentitan_test" \
|| $${bazel_label} == "//sw/device/lib/testing/test_rom:test_rom_sim_dv" \
|| $${bazel_label} == "//sw/device/silicon_creator/rom:rom_with_fake_keys_sim_dv" ]]; then \
for artifact in $$($${bazel_cmd} cquery $${bazel_airgapped_opts} \
$${bazel_label} \
--ui_event_filters=-info \
--noshow_progress \
--output=starlark \
`# An opentitan_test rule has all of its needed files in its runfiles.` \
--starlark:expr='"\n".join([f.path for f in target.data_runfiles.files.to_list()])'); do \
cp -f $${artifact} $${run_dir}/$$(basename $${artifact}); \
if [[ $$artifact == *.bin && \
-f "$$(echo $${artifact} | cut -d. -f 1).elf" ]]; then \
cp -f "$$(echo $${artifact} | cut -d. -f 1).elf" \
$${run_dir}/$$(basename -s .bin $${artifact}).elf; \
fi; \
done; \
fi; \
done; \
done; \
else \
for dep in $$($${bazel_cmd} cquery $${bazel_airgapped_opts} \
$${bazel_cquery} \
--ui_event_filters=-info \
--noshow_progress \
--output=starlark \
`# Bazel 6 cquery outputs repository targets in canonical format (@//blabla) whereas bazel 5 does not, ` \
`# so we use a custom starlark printer to remove in leading @ when needed.` \
--starlark:expr='str(target.label)[1:] if str(target.label).startswith("@//") else target.label'); do \
if [[ $$dep == //hw/ip/otp_ctrl/data* ]] || \
([[ $$dep != //hw* ]] && [[ $$dep != //util* ]] && [[ $$dep != //sw/host* ]]); then \
for artifact in $$($${bazel_cmd} cquery $${bazel_airgapped_opts} $${dep} \
--ui_event_filters=-info \
--noshow_progress \
--output=starlark \
--starlark:expr="\"\\n\".join([f.path for f in target.files.to_list()])"); do \
cp -f $${artifact} $${run_dir}/$$(basename $${artifact}); \
if [[ $$artifact == *.bin && \
-f "$$(echo $${artifact} | cut -d. -f 1).elf" ]]; then \
cp -f "$$(echo $${artifact} | cut -d. -f 1).elf" \
$${run_dir}/$$(basename -s .bin $${artifact}).elf; \
fi; \
done; \
fi; \
done; \
fi; \
fi; \
done;
endif
Expand Down
3 changes: 3 additions & 0 deletions vendor/lowrisc_ip/dv/tools/dvsim/vcs.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,9 @@
"-error=ENUMASSIGN",
// Tasks must not be enabled in functions. Other tools do not allow this.
"-error=TEIF"
// This helps avoid races in flops per Synopsys CASE 01552811.
// It causes flops to always use the sampled data value.
"-deraceclockdata"
]

run_opts: ["-licqueue",
Expand Down
30 changes: 30 additions & 0 deletions vendor/lowrisc_ip/ip/prim/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,35 @@
# lowRISC Hardware Primitives

[`prim_alert`](https://reports.opentitan.org/hw/ip/prim/dv/prim_alert/latest/report.html):
![](https://dashboards.lowrisc.org/badges/dv/prim_alert/test.svg)
![](https://dashboards.lowrisc.org/badges/dv/prim_alert/passing.svg)
![](https://dashboards.lowrisc.org/badges/dv/prim_alert/functional.svg)
![](https://dashboards.lowrisc.org/badges/dv/prim_alert/code.svg)

[`prim_esc`](https://reports.opentitan.org/hw/ip/prim/dv/prim_esc/latest/report.html):
![](https://dashboards.lowrisc.org/badges/dv/prim_esc/test.svg)
![](https://dashboards.lowrisc.org/badges/dv/prim_esc/passing.svg)
![](https://dashboards.lowrisc.org/badges/dv/prim_esc/functional.svg)
![](https://dashboards.lowrisc.org/badges/dv/prim_esc/code.svg)

[`prim_lfsr`](https://reports.opentitan.org/hw/ip/prim/dv/prim_lfsr/latest/report.html):
![](https://dashboards.lowrisc.org/badges/dv/prim_lfsr/test.svg)
![](https://dashboards.lowrisc.org/badges/dv/prim_lfsr/passing.svg)
![](https://dashboards.lowrisc.org/badges/dv/prim_lfsr/functional.svg)
![](https://dashboards.lowrisc.org/badges/dv/prim_lfsr/code.svg)

[`prim_present`](https://reports.opentitan.org/hw/ip/prim/dv/prim_lfsr/latest/report.html):
![](https://dashboards.lowrisc.org/badges/dv/prim_present/test.svg)
![](https://dashboards.lowrisc.org/badges/dv/prim_present/passing.svg)
![](https://dashboards.lowrisc.org/badges/dv/prim_present/functional.svg)
![](https://dashboards.lowrisc.org/badges/dv/prim_present/code.svg)

[`prim_prince`](https://reports.opentitan.org/hw/ip/prim/dv/prim_lfsr/latest/report.html):
![](https://dashboards.lowrisc.org/badges/dv/prim_prince/test.svg)
![](https://dashboards.lowrisc.org/badges/dv/prim_prince/passing.svg)
![](https://dashboards.lowrisc.org/badges/dv/prim_prince/functional.svg)
![](https://dashboards.lowrisc.org/badges/dv/prim_prince/code.svg)

## Concepts

This directory contains basic building blocks to create a hardware design,
Expand Down
Loading

0 comments on commit 0b696c8

Please sign in to comment.