-
Notifications
You must be signed in to change notification settings - Fork 807
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
[multitop] Port OTTF and test_rom to multitop #26038
Changes from all commits
83a684e
1e8f76a
966e3fe
b0fb0d4
c297c0e
7b0f8b3
9f8468b
31b5af1
609e616
3ae45fe
f3f0523
e30ceb2
6957068
9813013
1d7e6cf
a841f5c
28f62a4
d904b60
0873ea0
dc35de9
d99e5cc
bf80a85
9e1e29a
229e18d
9289641
277203c
5c27da9
1eb35b4
f49a298
56e62bb
6c332ed
7922dc8
f647615
cb690d2
e98782f
d68436e
1c11d2a
f001267
e3c94ea
95d46c7
9fd9d5a
24cb1d2
044fc1f
5960407
4b9c3ad
02d17f7
5597b93
93c707b
966fd5f
eacff8c
cdb3578
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,8 +16,55 @@ | |
from util.design.secded_gen import ecc_encode_some # type: ignore | ||
from util.design.secded_gen import load_secded_config | ||
|
||
ROM_BASE_WORD = 0x8000 // 4 | ||
ROM_SIZE_WORDS = 8192 | ||
|
||
class MemCtrlParams: | ||
def __init__( | ||
self, ctrl_name: str, | ||
memory_type: str, | ||
module_type: str, | ||
scr_key: str, scr_key_width: int, | ||
nonce: str, nonce_width: int | ||
): | ||
'''A memory controller parameters constructor | ||
@ctrl_name is the memory controller IP block name (e.g. 'rom_ctrl0' for the base ROM) | ||
@memory_type is the memory type this memory controller run ('rom' or 'ram') | ||
@module_type is the HJSON module type for this memory controller (e.g. 'rom_ctrl') | ||
@scr_key is the scrambling key entry name in the HJSON file | ||
@scr_key_width is the expected scrambling key width | ||
@nonce is the nonce entry name in the HJSON file | ||
@nonce_width is the expected nonce width | ||
''' | ||
self.ctrl_name = ctrl_name | ||
self.memory_type = memory_type | ||
self.module_type = module_type | ||
self.scr_key = scr_key | ||
self.scr_key_width = scr_key_width | ||
self.nonce = nonce | ||
self.nonce_width = nonce_width | ||
|
||
|
||
MEM_CTRL_PARAMS = { | ||
"earlgrey": { | ||
'base-rom': MemCtrlParams('rom_ctrl', | ||
'rom', 'rom_ctrl', | ||
'RndCnstScrKey', 128, | ||
'RndCnstScrNonce', 64), | ||
}, | ||
"darjeeling": { | ||
'base-rom': MemCtrlParams('rom_ctrl0', | ||
'rom', 'rom_ctrl', | ||
'RndCnstScrKey', 128, | ||
'RndCnstScrNonce', 64), | ||
'second-rom': MemCtrlParams('rom_ctrl1', | ||
'rom', 'rom_ctrl', | ||
'RndCnstScrKey', 128, | ||
'RndCnstScrNonce', 64), | ||
'sram': MemCtrlParams('sram_ctrl_main', | ||
'ram', 'sram_ctrl', | ||
'RndCnstSramKey', 128, | ||
'RndCnstramNonce', 128), | ||
} | ||
} | ||
|
||
PRESENT_SBOX4 = [ | ||
0xc, 0x5, 0x6, 0xb, | ||
|
@@ -110,32 +157,37 @@ class Scrambler: | |
subst_perm_rounds = 2 | ||
num_rounds_half = 3 | ||
|
||
def __init__(self, nonce: int, key: int, rom_size_words: int, hash_file: IO[str]): | ||
def __init__(self, nonce: int, key: int, rom_base: int, rom_size_words: int, | ||
hash_file: IO[str]): | ||
a-will marked this conversation as resolved.
Show resolved
Hide resolved
|
||
assert 0 <= nonce < (1 << 64) | ||
assert 0 <= key < (1 << 128) | ||
assert 0 < rom_size_words < (1 << 64) | ||
|
||
self.nonce = nonce | ||
self.key = key | ||
self.rom_size_words = rom_size_words | ||
self.rom_base = rom_base | ||
|
||
self.config = load_secded_config() | ||
self.hash_file = hash_file | ||
|
||
self._addr_width = (rom_size_words - 1).bit_length() | ||
|
||
@staticmethod | ||
def _get_rom_ctrl(modules: List[object]) -> _UDict: | ||
rom_ctrls = [] # type: List[_UDict] | ||
def _get_mem_ctrl(modules: List[object], type: str, name: str) -> _UDict: | ||
mem_ctrls = [] # type: List[_UDict] | ||
for entry in modules: | ||
assert isinstance(entry, dict) | ||
entry_type = entry.get('type') | ||
assert isinstance(entry_type, str) | ||
entry_name = entry.get('name') | ||
assert isinstance(entry_name, str) | ||
|
||
if entry_type == 'rom_ctrl': | ||
rom_ctrls.append(entry) | ||
if entry_type == type and entry_name == name: | ||
mem_ctrls.append(entry) | ||
|
||
assert len(rom_ctrls) == 1 | ||
return rom_ctrls[0] | ||
assert len(mem_ctrls) == 1 | ||
return mem_ctrls[0] | ||
|
||
@staticmethod | ||
def _get_params(module: _UDict) -> Dict[str, _UDict]: | ||
|
@@ -164,23 +216,56 @@ def _get_param_value(params: Dict[str, _UDict], name: str, | |
return int_val | ||
|
||
@staticmethod | ||
def from_hjson_path(path: str, rom_size_words: int, hash_file: IO[str]) -> 'Scrambler': | ||
assert 0 < rom_size_words | ||
def _get_size_words(module: _UDict, memory_type: str) -> int: | ||
memory = module.get("memory") | ||
assert isinstance(memory, dict) | ||
memory = memory.get(memory_type) | ||
assert isinstance(memory, dict) | ||
size_words_bytes_str = memory.get("size") | ||
assert isinstance(size_words_bytes_str, str) | ||
size_words_bytes = int(size_words_bytes_str, 16) | ||
assert size_words_bytes % 4 == 0 | ||
return size_words_bytes // 4 | ||
|
||
@staticmethod | ||
def _get_base(module: _UDict, memory_type: str) -> int: | ||
base = module.get("base_addrs") | ||
assert isinstance(base, dict) | ||
base_addr_rom = base.get(memory_type) | ||
assert isinstance(base_addr_rom, dict) | ||
base_addr = base_addr_rom.get("hart") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Probably the address space should become an argument (later). I kind of wonder how the base address factors in, though, especially if it turns out that a ROM is accessible from multiple address spaces. |
||
assert isinstance(base_addr, str) | ||
return int(base_addr, 16) | ||
|
||
@staticmethod | ||
def from_hjson_path(path: str, mode: str, hash_file: IO[str]) -> 'Scrambler': | ||
with open(path) as handle: | ||
top = hjson.load(handle, use_decimal=True) | ||
|
||
assert isinstance(top, dict) | ||
modules = top.get('module') | ||
assert isinstance(modules, list) | ||
|
||
rom_ctrl = Scrambler._get_rom_ctrl(modules) | ||
|
||
params = Scrambler._get_params(rom_ctrl) | ||
nonce = Scrambler._get_param_value(params, 'RndCnstScrNonce', 64) | ||
key = Scrambler._get_param_value(params, 'RndCnstScrKey', 128) | ||
|
||
return Scrambler(nonce, key, rom_size_words, hash_file) | ||
print(top["name"]) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this a stray debugging print? |
||
assert top["name"] in MEM_CTRL_PARAMS, "top {} is not supported".format(top["name"]) | ||
mem_ctrl_params = MEM_CTRL_PARAMS[top["name"]] | ||
assert mode in mem_ctrl_params, \ | ||
"mode {} is not supported in top {}".format(mode, top["name"]) | ||
mc_params = mem_ctrl_params[mode] | ||
|
||
mem_ctrl = Scrambler._get_mem_ctrl(modules, | ||
mc_params.module_type, | ||
mc_params.ctrl_name) | ||
size_words = Scrambler._get_size_words(mem_ctrl, mc_params.memory_type) | ||
base = Scrambler._get_base(mem_ctrl, mc_params.memory_type) | ||
params = Scrambler._get_params(mem_ctrl) | ||
nonce = Scrambler._get_param_value(params, | ||
mc_params.nonce, | ||
mc_params.nonce_width) | ||
key = Scrambler._get_param_value(params, | ||
mc_params.scr_key, | ||
mc_params.scr_key_width) | ||
return Scrambler(nonce, key, base, size_words, hash_file) | ||
|
||
def flatten(self, mem: MemFile) -> MemFile: | ||
'''Flatten and pad mem up to the correct size | ||
|
@@ -355,15 +440,16 @@ def add_hash(self, scr_mem: MemFile) -> None: | |
def main() -> int: | ||
parser = argparse.ArgumentParser() | ||
parser.add_argument('hjson') | ||
parser.add_argument('mode') | ||
parser.add_argument('infile', type=argparse.FileType('rb')) | ||
parser.add_argument('outfile', type=argparse.FileType('w')) | ||
parser.add_argument('hashfile', type=argparse.FileType('w')) | ||
|
||
args = parser.parse_args() | ||
scrambler = Scrambler.from_hjson_path(args.hjson, ROM_SIZE_WORDS, args.hashfile) | ||
scrambler = Scrambler.from_hjson_path(args.hjson, args.mode, args.hashfile) | ||
|
||
# Load the input ELF file | ||
clr_mem = MemFile.load_elf32(args.infile, 4 * ROM_BASE_WORD) | ||
clr_mem = MemFile.load_elf32(args.infile, scrambler.rom_base) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, I see, the base address is used merely for loading from the right section in an ELF. This feels slightly backwards, like the raw binary (untranslated from address 0) should be used here. But this isn't a change from the status quo, so nothing to do about it here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
||
# Flatten the file, padding with pseudo-random data and ensuring it's | ||
# exactly scrambler.rom_size_words words long. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,42 @@ | ||
# Copyright lowRISC contributors (OpenTitan project). | ||
# Licensed under the Apache License, Version 2.0, see LICENSE for details. | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
load( | ||
"//rules/opentitan:defs.bzl", | ||
"DEFAULT_TEST_FAILURE_MSG", | ||
"DEFAULT_TEST_SUCCESS_MSG", | ||
"sim_dv", | ||
) | ||
|
||
package(default_visibility = ["//visibility:public"]) | ||
|
||
########################################################################### | ||
# Sim DV Environments | ||
# | ||
# The sim_dv_base target is only meant to be used for building ROMs and | ||
# other items without `testonly=True`. | ||
########################################################################### | ||
# Remark: we must use a different name from earlgrey because the test point | ||
# names are derived from the exec_env's target named | ||
sim_dv( | ||
name = "sim_dv_base", | ||
design = "darjeeling", | ||
exec_env = "sim_dv", | ||
extract_sw_logs = "//util/device_sw_utils:extract_sw_logs_db", | ||
flash_scramble_tool = "//util/design:gen-flash-img", | ||
libs = [ | ||
"//sw/device/lib/arch:boot_stage_rom_ext", | ||
"//sw/device/lib/arch:sim_dv", | ||
], | ||
linker_script = "//sw/device/lib/testing/test_framework:ottf_ld_silicon_creator_slot_a", | ||
rom_scramble_config = "//hw/top_darjeeling/data/autogen:top_darjeeling.gen.hjson", | ||
) | ||
|
||
sim_dv( | ||
name = "sim_dv", | ||
testonly = True, | ||
base = ":sim_dv_base", | ||
exec_env = "sim_dv", | ||
rom = "//sw/device/lib/testing/test_rom:test_rom", | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hehe, you know I always get concerned when I see hard-coded parameters for known tops. We can make this better later, though.