Skip to content

Commit

Permalink
Update lowrisc_ip to lowRISC/opentitan@e0c4026501
Browse files Browse the repository at this point in the history
Update code from upstream repository
https://github.com/lowRISC/opentitan to revision
e0c40265019aa0c74e6903d3b3a144c48a3815ec

* [prim/lint] Fix long line lint error in prim_intr_hw (Alexander
  Williams)
* [csr_seq_lib] Avoid slicing a queue (Rupert Swarbrick)
* [dv] Make mem_model's compare_byte function less chatty (Rupert
  Swarbrick)
* [doc,prim] Improve comments in prim_intr_hw (Harry Callahan)
* [dvsim] Format FormalCfg code. (Miguel Osorio)
* [dvsim] Add results_server dependency to FormalCfg (Miguel Osorio)
* [prim_sha2] Add `hash_running_o` (Andreas Kurth)
* [prim_sha2] Add `hash_continue_i` (Andreas Kurth)
* [prim_sha2] Make digest writable from input while disabled (Andreas
  Kurth)
* [dv,random_reset] Enhance handling of random resets (Guillermo
  Maturana)
* [dv] Change implementation of special mubi access modes (Michael
  Schaffner)
* [dv,cov_merge] Do serial coverage merge for vcs (Guillermo Maturana)
* [dv/csr_utils] Change csr_peek to return the peeked value (Rupert
  Swarbrick)
* [dv/csr_utils] Expand a documentation comment in csr_peek (Rupert
  Swarbrick)
* [dv/csr_utils] Simplify HDL path checking in csr_peek (Rupert
  Swarbrick)
* [dv/csr_utils] Use DV_CHECK to simplify code structure in csr_peek
  (Rupert Swarbrick)
* [dv/csr_utils] Fix a seeming typo in csr_peek (Rupert Swarbrick)
* [dv/csr_utils] Change `csr_peek` to function (Andreas Kurth)
* [prim] Fix lint error in shadow register subreg primitive (Pirmin
  Vogel)
* [otp_ctrl] Add second HW_CFG partition (Michael Schaffner)
* [primgen] Fix parameters in a primgen template (Rupert Swarbrick)
* [prim] Avoid unnecessary Impl parameter in prim_onehot_check (Rupert
  Swarbrick)
* [hw,prim,sha2] Fix syntax error in waiver file (Robert Schilling)
* [prim_sha2,rtl] prim_sha2 minor RTL and styling fixes (Ghada
  Dessouky)
* [prim_sha2,rtl] Add RTL implementation + update core + lint waivers
  (Ghada Dessouky)
* [otp_ctrl] Remove entropy_src chicken switches (Michael Schaffner)
* [dv] Correct direct prediction of regwen (Michael Schaffner)
* [clkmgr] Restructure division clock feedback (Michael Schaffner)
* Revert "[edn] Move prim_edn_req out of prim" (Rupert Swarbrick)
* [rtl, prim] Add 'commit' functionality to prim_count (Greg Chadwick)
* [prim] Fix up 1r1w cores (Alexander Williams)
* [prim] Add two-port memory ECC wrappers (Michael Schaffner)
* [prim] Add two-port memory implementation (Michael Schaffner)
* [prim] Make copies of dual port memory files (Michael Schaffner)
* [otp_ctrl] Add support for multiple HW_CFG partitions (Michael
  Schaffner)
* [otp_ctrl] Add option to disable integrity on a partition (Michael
  Schaffner)
* [dv] Enhance RAL model with clearable mubi types (Michael Schaffner)

Signed-off-by: Greg Chadwick <gac@lowrisc.org>
  • Loading branch information
GregAC authored and marnovandermaas committed Mar 1, 2024
1 parent 5a8a1a9 commit 71683aa
Show file tree
Hide file tree
Showing 45 changed files with 2,686 additions and 156 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: 4cf2479b8e6c9b68b9fe1adba202443d3dbe3ff3
rev: e0c40265019aa0c74e6903d3b3a144c48a3815ec
}
}
9 changes: 5 additions & 4 deletions vendor/lowrisc_ip/dv/sv/csr_utils/csr_seq_lib.sv
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,13 @@ class csr_base_seq extends uvm_reg_sequence #(uvm_sequence #(uvm_reg_item));
end_idx = test_csr_chunk * chunk_size;
if (end_idx >= all_csrs.size()) end_idx = all_csrs.size() - 1;

test_csrs = all_csrs[start_idx:end_idx];
`uvm_info(`gtn, $sformatf("Testing %0d csrs [%0d - %0d] in all supplied models.",
test_csrs.size(), start_idx, end_idx), UVM_MEDIUM)
foreach (test_csrs[i]) begin
`uvm_info(`gtn, $sformatf("Testing CSR %0s, reset: 0x%0x.", test_csrs[i].get_full_name(),
test_csrs[i].get_mirrored_value()), UVM_HIGH)
test_csrs.delete();
for (int i = start_idx; i <= end_idx; i++) begin
test_csrs.push_back(all_csrs[i]);
`uvm_info(`gtn, $sformatf("Testing CSR %0s, reset: 0x%0x.", all_csrs[i].get_full_name(),
all_csrs[i].get_mirrored_value()), UVM_HIGH)
end
test_csrs.shuffle();
endfunction
Expand Down
59 changes: 32 additions & 27 deletions vendor/lowrisc_ip/dv/sv/csr_utils/csr_utils_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ package csr_utils_pkg;
input uvm_reg_map map = null,
input uvm_reg_frontdoor user_ftdr = default_user_frontdoor);
if (backdoor) begin
csr_peek(ptr, value, check);
value = csr_peek(ptr, check);
status = UVM_IS_OK;
return;
end
Expand Down Expand Up @@ -383,35 +383,40 @@ package csr_utils_pkg;

// backdoor read csr
// uvm_reg::peek() returns a 2-state value, directly get data from hdl path
task automatic csr_peek(input uvm_object ptr,
output uvm_reg_data_t value,
input uvm_check_e check = default_csr_check,
input bkdr_reg_path_e kind = BkdrRegPathRtl);
string msg_id = {csr_utils_pkg::msg_id, "::csr_peek"};
csr_field_t csr_or_fld = decode_csr_or_field(ptr);
uvm_reg csr = csr_or_fld.csr;

if (csr.has_hdl_path(kind.name)) begin
uvm_hdl_path_concat paths[$];

csr.get_full_hdl_path(paths, kind.name);
foreach (paths[0].slices[i]) begin
uvm_reg_data_t field_val;
if (uvm_hdl_read(paths[0].slices[i].path, field_val)) begin
if (check == UVM_CHECK) `DV_CHECK_EQ($isunknown(value), 0, "", error, msg_id)
value |= field_val << paths[0].slices[i].offset;
end else begin
`uvm_fatal(msg_id, $sformatf("uvm_hdl_read failed for %0s", csr.get_full_name()))
end
end
end else begin
`uvm_fatal(msg_id, $sformatf("No backdoor defined for %0s path's %0s",
csr.get_full_name(), kind.name))
function automatic uvm_reg_data_t csr_peek(uvm_object ptr,
uvm_check_e check = default_csr_check,
bkdr_reg_path_e kind = BkdrRegPathRtl);
string msg_id = {csr_utils_pkg::msg_id, "::csr_peek"};
csr_field_t csr_or_fld = decode_csr_or_field(ptr);
uvm_reg csr = csr_or_fld.csr;
uvm_reg_data_t value = 0;

uvm_hdl_path_concat paths[$];
csr.get_full_hdl_path(paths, kind.name);

`DV_CHECK_FATAL(paths.size() > 0,
$sformatf("No backdoor defined for %0s path's %0s",
csr.get_full_name(), kind.name),
msg_id)

foreach (paths[0].slices[i]) begin
uvm_reg_data_t field_val;
`DV_CHECK_FATAL(uvm_hdl_read(paths[0].slices[i].path, field_val),
$sformatf("Failed to read %s, slice %d, at path %s",
csr.get_full_name(), i, paths[0].slices[i].path),
msg_id)
if (check == UVM_CHECK) `DV_CHECK_EQ($isunknown(field_val), 0, "", error, msg_id)

value |= field_val << paths[0].slices[i].offset;
end

// if it's field, only return field value
// We now have the contents of the field or register in value. If ptr was a sub-field of some
// register, it will be laid out in the same way as the field is laid out in the register.
// That's no problem: we can just extract the relevant field from the laid-out value here.
if (csr_or_fld.field != null) value = get_field_val(csr_or_fld.field, value);
endtask

return value;
endfunction

task automatic csr_rd_check(input uvm_object ptr,
input uvm_check_e check = default_csr_check,
Expand Down
17 changes: 14 additions & 3 deletions vendor/lowrisc_ip/dv/sv/dv_base_reg/dv_base_reg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -305,14 +305,15 @@ class dv_base_reg extends uvm_reg;
end
do_update_shadow_vals = 0;
end
lock_lockable_flds(rw.value[0]);
lock_lockable_flds(rw.value[0], kind);
endfunction

// This function is used for wen_reg to lock its lockable flds by changing the lockable flds'
// access policy. For register write via csr_wr(), this function is included in post_write().
// For register write via tl_access(), user will need to call this function manually.
virtual function void lock_lockable_flds(uvm_reg_data_t val);
virtual function void lock_lockable_flds(uvm_reg_data_t val, uvm_predict_e kind);
if (is_wen_reg()) begin
`uvm_info(`gfn, $sformatf("lock_lockable_flds %d val", val), UVM_LOW);
foreach (m_fields[i]) begin
dv_base_reg_field fld;
`downcast(fld, m_fields[i])
Expand All @@ -322,7 +323,17 @@ class dv_base_reg extends uvm_reg;
case (field_access)
// discussed in issue #1922: enable register is standarized to W0C or RO (if HW has
// write access).
"W0C": if (field_val == 1'b0) fld.set_lockable_flds_access(1);
"W0C": begin
// This is the regular behavior with W0C access policy enabled (i.e., only
// clearing is possible).
if (kind == UVM_PREDICT_WRITE && field_val == 1'b0) begin
fld.set_lockable_flds_access(1);
// In this case we are using direct prediction where the access policy is not
// applied. I.e., a regwen bit that has been set to 0 can be set to 1 again.
end else if (kind == UVM_PREDICT_DIRECT) begin
fld.set_lockable_flds_access((~field_val) & fld.get_field_mask());
end
end
"RO": ; // if RO, it's updated by design, need to predict in scb
default:`uvm_fatal(`gfn, $sformatf("lock register invalid access %s", field_access))
endcase
Expand Down
72 changes: 70 additions & 2 deletions vendor/lowrisc_ip/dv/sv/dv_base_reg/dv_base_reg_field.sv
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ class dv_base_reg_field extends uvm_reg_field;
// This is used for get_field_by_name
string alias_name = "";

// If this field encodes a mubi, this field encodes special access modes such as W1C that cannot
// be captured with the regular access configuration, since UVM does not model such access modes
// correctly for mubis.
string mubi_access = "";

// Default mubi_width = 0 indicates this register field is not a mubi type.
protected int mubi_width;

Expand Down Expand Up @@ -58,6 +63,7 @@ class dv_base_reg_field extends uvm_reg_field;
int unsigned size,
int unsigned lsb_pos,
string access,
string mubi_access,
bit volatile,
uvm_reg_data_t reset,
bit has_reset,
Expand All @@ -73,7 +79,7 @@ class dv_base_reg_field extends uvm_reg_field;
.is_rand (is_rand),
.individually_accessible(individually_accessible));
value.rand_mode(is_rand);

this.mubi_access = mubi_access;
is_intr_test_fld = !(uvm_re_match("intr_test*", get_parent().get_name()));
shadowed_val = ~committed_val;
endfunction
Expand All @@ -83,10 +89,53 @@ class dv_base_reg_field extends uvm_reg_field;
`downcast(get_dv_base_reg_parent, csr)
endfunction

// Local helper function to reduce code in do_predict further below.
function uvm_reg_data_t mubi_or_hi (uvm_reg_data_t a, uvm_reg_data_t b);
import prim_mubi_pkg::*;
uvm_reg_data_t out;
case (mubi_width)
4: out = uvm_reg_data_t'(mubi4_or_hi(mubi4_t'(a), mubi4_t'(b)));
8: out = uvm_reg_data_t'(mubi8_or_hi(mubi8_t'(a), mubi8_t'(b)));
12: out = uvm_reg_data_t'(mubi12_or_hi(mubi12_t'(a), mubi12_t'(b)));
16: out = uvm_reg_data_t'(mubi16_or_hi(mubi16_t'(a), mubi16_t'(b)));
default: $error("Unsupported mubi width %d.", mubi_width);
endcase
return out;
endfunction: mubi_or_hi

// Local helper function to reduce code in do_predict further below.
function uvm_reg_data_t mubi_and_hi (uvm_reg_data_t a, uvm_reg_data_t b);
import prim_mubi_pkg::*;
uvm_reg_data_t out;
case (mubi_width)
4: out = uvm_reg_data_t'(mubi4_and_hi(mubi4_t'(a), mubi4_t'(b)));
8: out = uvm_reg_data_t'(mubi8_and_hi(mubi8_t'(a), mubi8_t'(b)));
12: out = uvm_reg_data_t'(mubi12_and_hi(mubi12_t'(a), mubi12_t'(b)));
16: out = uvm_reg_data_t'(mubi16_and_hi(mubi16_t'(a), mubi16_t'(b)));
default: $error("Unsupported mubi width: %d.", mubi_width);
endcase
return out;
endfunction: mubi_and_hi

// Local helper function to reduce code in do_predict further below.
function uvm_reg_data_t mubi_false ();
import prim_mubi_pkg::*;
uvm_reg_data_t out;
case (mubi_width)
4: out = uvm_reg_data_t'(MuBi4False);
8: out = uvm_reg_data_t'(MuBi8False);
12: out = uvm_reg_data_t'(MuBi12False);
16: out = uvm_reg_data_t'(MuBi16False);
default: $error("Unsupported mubi width: %d.", mubi_width);
endcase
return out;
endfunction: mubi_false

virtual function void do_predict (uvm_reg_item rw,
uvm_predict_e kind = UVM_PREDICT_DIRECT,
uvm_reg_byte_en_t be = -1);
uvm_reg_data_t field_val = rw.value[0] & ((1 << get_n_bits())-1);
string access = get_access();

// update intr_state mirrored value if this is an intr_test reg
// if kind is UVM_PREDICT_DIRECT or UVM_PREDICT_READ, super.do_predict can handle
Expand All @@ -101,8 +150,27 @@ class dv_base_reg_field extends uvm_reg_field;
end
// use UVM_PREDICT_READ to avoid uvm_warning due to UVM_PREDICT_DIRECT
void'(intr_state_fld.predict(predict_val, .kind(UVM_PREDICT_READ)));
end

end else if (kind == UVM_PREDICT_WRITE && mubi_access inside {"W1S", "W1C", "W0C"})
begin
// Some smoke checking of the byte enables. RTL does not latch anything if not all affected
// bytes of the field are enabled. Note that we still use UVM_PREDICT_WRITE further below
// since the underlying access is set to RW in the RAL model.
if (mubi_width <= 8 && be[0] || mubi_width > 8 && mubi_width <= 16 && &be[1:0]) begin
// In case this is a clearable MUBI field, we have to interpret the write value correctly.
// ICEBOX(#9273): Note that this just uses bitwise functions to update the value and does
// not rectify incorrect mubi values. At a later point, we should discuss if and how to
// tighten this up, as discussed on the linked issue.
case (mubi_access)
"W1S": rw.value[0] = this.mubi_or_hi(rw.value[0], `gmv(this));
"W1C": rw.value[0] = this.mubi_and_hi(~rw.value[0], `gmv(this));
"W0C": rw.value[0] = this.mubi_and_hi(rw.value[0], `gmv(this));
default: ; // unreachable
endcase
end
end else if (kind == UVM_PREDICT_READ && mubi_access == "RC") begin
rw.value[0] = this.mubi_false();
end
super.do_predict(rw, kind, be);
endfunction

Expand Down
15 changes: 15 additions & 0 deletions vendor/lowrisc_ip/dv/sv/dv_lib/dv_base_env_cfg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class dv_base_env_cfg #(type RAL_T = dv_base_reg_block) extends uvm_object;
bit en_cov = 0; // Enable via plusarg, only if coverage collection is turned on.
bit en_dv_cdc = 0; // Enable via plusarg.

local bit will_reset = 0;
bit under_reset = 0;
bit is_initialized; // Indicates that the initialize() method has been called.

Expand Down Expand Up @@ -107,8 +108,22 @@ class dv_base_env_cfg #(type RAL_T = dv_base_reg_block) extends uvm_object;
protected virtual function void post_build_ral_settings(dv_base_reg_block ral);
endfunction

// This can be used to stop transaction generators either upon reset or in preparation to
// issue a random reset.
virtual function bit stop_transaction_generators();
return this.will_reset || this.under_reset;
endfunction

// This can be used to announce the intention to generate a random reset soon, to allow
// transaction generators to stop, and fire a reset with no outstanding transactions.
virtual function void set_intention_to_reset();
`uvm_info(`gfn, "Setting intention to reset", UVM_MEDIUM)
this.will_reset = 1'b1;
endfunction

virtual function void reset_asserted();
this.under_reset = 1;
this.will_reset = 0;
csr_utils_pkg::reset_asserted();
endfunction

Expand Down
42 changes: 25 additions & 17 deletions vendor/lowrisc_ip/dv/sv/mem_bkdr_util/mem_bkdr_util__otp.sv
Original file line number Diff line number Diff line change
Expand Up @@ -123,30 +123,38 @@ virtual function void otp_write_secret2_partition(bit [RmaTokenSize*8-1:0] rma_u
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,
bit [EnCsrngSwAppReadSize*8-1:0] en_csrng_sw_app_read,
bit [EnEntropySrcFwReadSize*8-1:0] en_entropy_src_fw_read,
bit [EnEntropySrcFwOverSize*8-1:0] en_entropy_src_fw_over);
bit [HwCfgDigestSize*8-1:0] digest;
virtual function void otp_write_hw_cfg0_partition(
bit [DeviceIdSize*8-1:0] device_id, bit [ManufStateSize*8-1:0] manuf_state);
bit [HwCfg0DigestSize*8-1:0] digest;

bit [bus_params_pkg::BUS_DW-1:0] hw_cfg_data[$];
bit [bus_params_pkg::BUS_DW-1:0] hw_cfg0_data[$];

for (int i = 0; i < DeviceIdSize; i += 4) begin
write32(i + DeviceIdOffset, device_id[i*8+:32]);
end
for (int i = 0; i < ManufStateSize; i += 4) begin
write32(i + ManufStateOffset, manuf_state[i*8+:32]);
end
write32(EnSramIfetchOffset,
{en_entropy_src_fw_over, en_entropy_src_fw_read, en_csrng_sw_app_read, en_sram_ifetch});

hw_cfg_data = {<<32 {32'h0, en_entropy_src_fw_over, en_entropy_src_fw_read,
en_csrng_sw_app_read, en_sram_ifetch, manuf_state, device_id}};
digest = cal_digest(HwCfgIdx, hw_cfg_data);
hw_cfg0_data = {<<32 {32'h0, manuf_state, device_id}};
digest = cal_digest(HwCfg0Idx, hw_cfg0_data);

write64(HwCfg0DigestOffset, digest);
endfunction

virtual function void otp_write_hw_cfg1_partition(
bit [EnCsrngSwAppReadSize*8-1:0] en_csrng_sw_app_read,
bit [EnSramIfetchSize*8-1:0] en_sram_ifetch);
bit [HwCfg1DigestSize*8-1:0] digest;

bit [bus_params_pkg::BUS_DW-1:0] hw_cfg1_data[$];

write32(EnSramIfetchOffset, {en_csrng_sw_app_read, en_sram_ifetch});

hw_cfg1_data = {<<32 {32'h0, en_csrng_sw_app_read, en_sram_ifetch}};
digest = cal_digest(HwCfg1Idx, hw_cfg1_data);

write64(HwCfgDigestOffset, digest);
write64(HwCfg1DigestOffset, digest);
endfunction

// Functions that clear the provisioning state of the buffered partitions.
Expand All @@ -169,8 +177,8 @@ virtual function void otp_clear_secret2_partition();
end
endfunction

virtual function void otp_clear_hw_cfg_partition();
for (int i = 0; i < HwCfgSize; i += 4) begin
write32(i + HwCfgOffset, 32'h0);
virtual function void otp_clear_hw_cfg0_partition();
for (int i = 0; i < HwCfg0Size; i += 4) begin
write32(i + HwCfg0Offset, 32'h0);
end
endfunction
2 changes: 1 addition & 1 deletion vendor/lowrisc_ip/dv/sv/mem_model/mem_model.sv
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class mem_model #(int AddrWidth = bus_params_pkg::BUS_AW,

function void compare_byte(mem_addr_t addr, logic [7:0] act_data);
`uvm_info(`gfn, $sformatf("Compare Mem : Addr[0x%0h], Act Data[0x%0h], Exp Data[0x%0h]",
addr, act_data, system_memory[addr]), UVM_MEDIUM)
addr, act_data, system_memory[addr]), UVM_HIGH)
`DV_CHECK_CASE_EQ(act_data, system_memory[addr],
$sformatf("addr 0x%0h read out mismatch", addr))
endfunction
Expand Down
10 changes: 7 additions & 3 deletions vendor/lowrisc_ip/dv/tools/dvsim/vcs.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -147,10 +147,14 @@
"-full64",
// No need of generating report when merging coverage.
"-noreport",
// Parallel merge is slower than serial merge for most
// small blocks, and the corresponding flags are commented
// out. If this becomes problematic and you have a powerful
// machine available, uncomment the three flags below.
// Merge results from tests in parallel.
"-parallel",
"-parallel_split 20",
"-parallel_temproot {cov_merge_dir}",
// "-parallel",
// "-parallel_split 20",
// "-parallel_temproot {cov_merge_dir}",
"+urg+lic+wait",
// Merge same assert instances found in different VDBs.
"-merge_across_libs",
Expand Down
8 changes: 8 additions & 0 deletions vendor/lowrisc_ip/ip/prim/lint/prim_ram_1r1w.waiver
Original file line number Diff line number Diff line change
@@ -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_ram_1r1w

waive -rules {STAR_PORT_CONN_USE} -location {prim_ram_1r1w.sv} -regexp {.*wild card port connection encountered on instance.*} \
-comment "Generated prims may have wildcard connections."
9 changes: 9 additions & 0 deletions vendor/lowrisc_ip/ip/prim/lint/prim_sha2.vbl
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# 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_sha2 pre_dv Verilator testbenches

# waive long line violations in test vectors feeding
waive --rule=line-length --location="prim_sha_multimode32_tb.sv"
waive --rule=line-length --location="prim_sha_tb.sv"
Loading

0 comments on commit 71683aa

Please sign in to comment.