Skip to content

Commit

Permalink
[otp_ctrl/dv] Replace hardcoded offsets with templating
Browse files Browse the repository at this point in the history
Signed-off-by: Michael Schaffner <[email protected]>
  • Loading branch information
msfschaffner committed Jan 24, 2024
1 parent 4264697 commit fa224ad
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 37 deletions.
43 changes: 24 additions & 19 deletions hw/ip/otp_ctrl/data/otp_ctrl_scoreboard.sv.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ read_locked_csr_parts = [part for part in otp_mmap.config["partitions"] if
part["read_lock"] == "CSR"]
write_locked_digest_parts = [part for part in otp_mmap.config["partitions"] if
part["write_lock"] == "Digest"]
buf_parts_without_lc = [part for part in otp_mmap.config["partitions"] if
part["variant"] == "Buffered"]
secret_parts = [part for part in otp_mmap.config["partitions"] if
part["secret"]]
%>\
class otp_ctrl_scoreboard #(type CFG_T = otp_ctrl_env_cfg)
extends cip_base_scoreboard #(
Expand Down Expand Up @@ -94,25 +98,24 @@ class otp_ctrl_scoreboard #(type CFG_T = otp_ctrl_env_cfg)
virtual task process_wipe_mem();
forever begin
@(posedge cfg.backdoor_clear_mem) begin
bit [SCRAMBLE_DATA_SIZE-1:0] data = descramble_data(0, Secret0Idx);
bit [SCRAMBLE_DATA_SIZE-1:0] data;
otp_a = '{default:0};
otp_lc_data = '{default:0};
% for part in secret_parts:
<%
part_name = Name.from_snake_case(part["name"])
part_name_camel = part_name.as_camel_case()
%>\
// secret partitions have been scrambled before writing to OTP.
// here calculate the pre-srambled raw data when clearing internal OTP to all 0s.
for (int i = SECRET0_START_ADDR; i <= SECRET0_END_ADDR; i++) begin
otp_a[i] = ((i - SECRET0_START_ADDR) % 2) ? data[SCRAMBLE_DATA_SIZE-1:TL_DW] :
data[TL_DW-1:0];
end
data = descramble_data(0, Secret1Idx);
for (int i = SECRET1_START_ADDR; i <= SECRET1_END_ADDR; i++) begin
otp_a[i] = ((i - SECRET1_START_ADDR) % 2) ? data[SCRAMBLE_DATA_SIZE-1:TL_DW] :
data[TL_DW-1:0];
end
data = descramble_data(0, Secret2Idx);
for (int i = SECRET2_START_ADDR; i <= SECRET2_END_ADDR; i++) begin
otp_a[i] = ((i - SECRET2_START_ADDR) % 2) ? data[SCRAMBLE_DATA_SIZE-1:TL_DW] :
data[TL_DW-1:0];
data = descramble_data(0, ${part_name_camel}Idx);
for (int i = ${part_name_camel}Offset / TL_SIZE;
i <= ${part_name_camel}DigestOffset / TL_SIZE - 1;
i++) begin
otp_a[i] = ((i - ${part_name_camel}Offset / TL_SIZE) % 2) ?
data[SCRAMBLE_DATA_SIZE-1:TL_DW] : data[TL_DW-1:0];
end
% endfor
`uvm_info(`gfn, "clear internal memory and digest", UVM_HIGH)
cfg.backdoor_clear_mem = 0;
dai_wr_ip = 0;
Expand Down Expand Up @@ -1151,11 +1154,13 @@ class otp_ctrl_scoreboard #(type CFG_T = otp_ctrl_env_cfg)
dai_digest_ip = part_idx;
end
case (part_idx)
HwCfg0Idx: mem_q = otp_a[HW_CFG0_START_ADDR:HW_CFG0_END_ADDR];
HwCfg1Idx: mem_q = otp_a[HW_CFG1_START_ADDR:HW_CFG1_END_ADDR];
Secret0Idx: mem_q = otp_a[SECRET0_START_ADDR:SECRET0_END_ADDR];
Secret1Idx: mem_q = otp_a[SECRET1_START_ADDR:SECRET1_END_ADDR];
Secret2Idx: mem_q = otp_a[SECRET2_START_ADDR:SECRET2_END_ADDR];
% for part in buf_parts_without_lc:
<%
part_name = Name.from_snake_case(part["name"])
part_name_camel = part_name.as_camel_case()
%>\
${part_name_camel}Idx: mem_q = otp_a[${part_name_camel}Offset / TL_SIZE : ${part_name_camel}DigestOffset / TL_SIZE - 1];
% endfor
default: begin
`uvm_fatal(`gfn, $sformatf("Access unexpected partition %0d", part_idx))
end
Expand Down
9 changes: 9 additions & 0 deletions hw/ip/otp_ctrl/dv/env/otp_ctrl_env_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ package otp_ctrl_env_pkg;

parameter uint DIGEST_SIZE = 8;
parameter uint SW_WINDOW_BASE_ADDR = 'h1000;
<<<<<<< HEAD
parameter uint SW_WINDOW_SIZE = 512 * 4;

// convert byte into TLUL width size
Expand Down Expand Up @@ -70,16 +71,24 @@ package otp_ctrl_env_pkg;
parameter uint SECRET2_START_ADDR = Secret2Offset / (TL_DW / 8);
parameter uint SECRET2_DIGEST_ADDR = Secret2DigestOffset / (TL_DW / 8);
parameter uint SECRET2_END_ADDR = SECRET2_DIGEST_ADDR - 1;
=======
parameter uint SW_WINDOW_SIZE = NumSwCfgWindowWords * 4;
>>>>>>> 53eb5972a8 ([otp_ctrl/dv] Replace hardcoded offsets with templating)

parameter uint TL_SIZE = (TL_DW / 8);
// LC has its own storage in scb
<<<<<<< HEAD
parameter uint OTP_ARRAY_SIZE = (VendorTestSize + CreatorSwCfgSize + OwnerSwCfgSize +
HwCfg0Size + Secret0Size + Secret1Size + Secret2Size)
/ (TL_DW / 8);
=======
// we can use the LC offset here because it will always be the last partition.
<<<<<<< HEAD
parameter uint OTP_ARRAY_SIZE = LcTransitionCntOffset / (TL_DW / 8);
>>>>>>> 538f1fe6fc ([otp_ctrl/dv] Use more generated constants in DV env)
=======
parameter uint OTP_ARRAY_SIZE = LcTransitionCntOffset / TL_SIZE;
>>>>>>> 53eb5972a8 ([otp_ctrl/dv] Replace hardcoded offsets with templating)

parameter int OTP_ADDR_WIDTH = 11;

Expand Down
40 changes: 25 additions & 15 deletions hw/ip/otp_ctrl/dv/env/otp_ctrl_scoreboard.sv
Original file line number Diff line number Diff line change
Expand Up @@ -88,24 +88,35 @@ class otp_ctrl_scoreboard #(type CFG_T = otp_ctrl_env_cfg)
virtual task process_wipe_mem();
forever begin
@(posedge cfg.backdoor_clear_mem) begin
bit [SCRAMBLE_DATA_SIZE-1:0] data = descramble_data(0, Secret0Idx);
bit [SCRAMBLE_DATA_SIZE-1:0] data;
otp_a = '{default:0};
otp_lc_data = '{default:0};
// secret partitions have been scrambled before writing to OTP.
// here calculate the pre-srambled raw data when clearing internal OTP to all 0s.
for (int i = SECRET0_START_ADDR; i <= SECRET0_END_ADDR; i++) begin
otp_a[i] = ((i - SECRET0_START_ADDR) % 2) ? data[SCRAMBLE_DATA_SIZE-1:TL_DW] :
data[TL_DW-1:0];
data = descramble_data(0, Secret0Idx);
for (int i = Secret0Offset / TL_SIZE;
i <= Secret0DigestOffset / TL_SIZE - 1;
i++) begin
otp_a[i] = ((i - Secret0Offset / TL_SIZE) % 2) ?
data[SCRAMBLE_DATA_SIZE-1:TL_DW] : data[TL_DW-1:0];
end
// secret partitions have been scrambled before writing to OTP.
// here calculate the pre-srambled raw data when clearing internal OTP to all 0s.
data = descramble_data(0, Secret1Idx);
for (int i = SECRET1_START_ADDR; i <= SECRET1_END_ADDR; i++) begin
otp_a[i] = ((i - SECRET1_START_ADDR) % 2) ? data[SCRAMBLE_DATA_SIZE-1:TL_DW] :
data[TL_DW-1:0];
for (int i = Secret1Offset / TL_SIZE;
i <= Secret1DigestOffset / TL_SIZE - 1;
i++) begin
otp_a[i] = ((i - Secret1Offset / TL_SIZE) % 2) ?
data[SCRAMBLE_DATA_SIZE-1:TL_DW] : data[TL_DW-1:0];
end
// secret partitions have been scrambled before writing to OTP.
// here calculate the pre-srambled raw data when clearing internal OTP to all 0s.
data = descramble_data(0, Secret2Idx);
for (int i = SECRET2_START_ADDR; i <= SECRET2_END_ADDR; i++) begin
otp_a[i] = ((i - SECRET2_START_ADDR) % 2) ? data[SCRAMBLE_DATA_SIZE-1:TL_DW] :
data[TL_DW-1:0];
for (int i = Secret2Offset / TL_SIZE;
i <= Secret2DigestOffset / TL_SIZE - 1;
i++) begin
otp_a[i] = ((i - Secret2Offset / TL_SIZE) % 2) ?
data[SCRAMBLE_DATA_SIZE-1:TL_DW] : data[TL_DW-1:0];
end
`uvm_info(`gfn, "clear internal memory and digest", UVM_HIGH)
cfg.backdoor_clear_mem = 0;
Expand Down Expand Up @@ -1151,11 +1162,10 @@ class otp_ctrl_scoreboard #(type CFG_T = otp_ctrl_env_cfg)
dai_digest_ip = part_idx;
end
case (part_idx)
HwCfg0Idx: mem_q = otp_a[HW_CFG0_START_ADDR:HW_CFG0_END_ADDR];
HwCfg1Idx: mem_q = otp_a[HW_CFG1_START_ADDR:HW_CFG1_END_ADDR];
Secret0Idx: mem_q = otp_a[SECRET0_START_ADDR:SECRET0_END_ADDR];
Secret1Idx: mem_q = otp_a[SECRET1_START_ADDR:SECRET1_END_ADDR];
Secret2Idx: mem_q = otp_a[SECRET2_START_ADDR:SECRET2_END_ADDR];
HwCfg0Idx: mem_q = otp_a[HwCfg0Offset / TL_SIZE : HwCfg0DigestOffset / TL_SIZE - 1];
Secret0Idx: mem_q = otp_a[Secret0Offset / TL_SIZE : Secret0DigestOffset / TL_SIZE - 1];
Secret1Idx: mem_q = otp_a[Secret1Offset / TL_SIZE : Secret1DigestOffset / TL_SIZE - 1];
Secret2Idx: mem_q = otp_a[Secret2Offset / TL_SIZE : Secret2DigestOffset / TL_SIZE - 1];
default: begin
`uvm_fatal(`gfn, $sformatf("Access unexpected partition %0d", part_idx))
end
Expand Down
12 changes: 9 additions & 3 deletions util/design/lib/OtpMemMap.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ def _calc_size(part: Dict, size: int):
return size


def _validate_part(part: Dict, key_names: List[str]):
def _validate_part(part: Dict, key_names: List[str], is_last: bool):
'''Validates a partition within the OTP memory map'''
part.setdefault("name", "unknown_name")
part.setdefault("variant", "Unbuffered")
Expand All @@ -130,6 +130,12 @@ def _validate_part(part: Dict, key_names: List[str]):
if part["variant"] not in ["Unbuffered", "Buffered", "LifeCycle"]:
raise RuntimeError("Invalid partition type {}".format(part["variant"]))

# the DV and HW assumes that the last partition is always the life cycle
# partition.
if (part["variant"] == "LifeCycle") != is_last:
raise RuntimeError("The last partition must always be the life cycle"
"partition")

if part["key_sel"] not in (["NoKey"] + key_names):
raise RuntimeError("Invalid key sel {}".format(part["key_sel"]))

Expand Down Expand Up @@ -248,8 +254,8 @@ def _validate_mmap(config: Dict):

# validate inputs before use
allocated = 0
for part in config["partitions"]:
_validate_part(part, key_names)
for k, part in enumerate(config["partitions"]):
_validate_part(part, key_names, k == (len(config["partitions"]) - 1))
allocated += part['size']

# distribute unallocated bits
Expand Down

0 comments on commit fa224ad

Please sign in to comment.