Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lowrisc ip update #2145

Merged
merged 2 commits into from
Mar 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 12 additions & 11 deletions rtl/ibex_lockstep.sv
Original file line number Diff line number Diff line change
Expand Up @@ -132,17 +132,18 @@ module ibex_lockstep import ibex_pkg::*; #(
.Width (LockstepOffsetW ),
.ResetValue (LockstepOffsetW'(1'b0) )
) u_rst_shadow_cnt (
.clk_i (clk_i ),
.rst_ni (rst_ni ),
.clr_i (1'b0 ),
.set_i (1'b0 ),
.set_cnt_i ('0 ),
.incr_en_i (1'b1 ),
.decr_en_i (1'b0 ),
.step_i (LockstepOffsetW'(1'b1) ),
.cnt_o (rst_shadow_cnt ),
.cnt_next_o ( ),
.err_o (rst_shadow_cnt_err )
.clk_i (clk_i ),
.rst_ni (rst_ni ),
.clr_i (1'b0 ),
.set_i (1'b0 ),
.set_cnt_i ('0 ),
.incr_en_i (1'b1 ),
.decr_en_i (1'b0 ),
.step_i (LockstepOffsetW'(1'b1) ),
.commit_i (1'b1 ),
.cnt_o (rst_shadow_cnt ),
.cnt_after_commit_o ( ),
.err_o (rst_shadow_cnt_err )
);

// When the LockstepOffset counter value is reached, activate the lockstep
Expand Down
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
Loading
Loading