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

[multitop] Port OTTF and test_rom to multitop #26038

Merged
merged 51 commits into from
Feb 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
83a684e
Add some missing exec_env to several targets
pamaury Feb 3, 2025
1e8f76a
[rules] Add compatibility check about exec_env in binary deps
pamaury Feb 3, 2025
966e3fe
[dif,pinmux] Fix code for multitop and add a DT function for pads.
pamaury Nov 28, 2024
b0fb0d4
[dif,i2c] Remove warning in unittest
pamaury Jan 27, 2025
c297c0e
[flash_ctrl,testutils] Port to devicetables
pamaury Nov 14, 2024
7b0f8b3
[pinmux,testutils] Convert most of it to devicetables
pamaury Nov 14, 2024
9f8468b
[tests] Port gpio_test and gpio_smoketest to multitop
pamaury Jan 27, 2025
31b5af1
[test_rom] Convert test_rom.c to devicetables
pamaury Nov 14, 2024
609e616
[test_rom] Replace direct reference to top_earlgrey by //hw/top:top_lib
pamaury Nov 14, 2024
3ae45fe
[silicon_creator,drivers,ibex] Convert to devicetables
pamaury Nov 14, 2024
f3f0523
[silicon_creator,drivers,uart] Port to devicetables
pamaury Nov 14, 2024
e30ceb2
[silicon_creator,drivers,spi_device] Port to devicetables
pamaury Nov 14, 2024
6957068
[silicon_creator,lib,manifet] Generalize for multitop
pamaury Nov 14, 2024
9813013
[silicon_creator,rom,bootstrap] Convert to devicetables
pamaury Nov 14, 2024
1d7e6cf
[silicon_creator,flash_ctrl] Port to devicetables
pamaury Nov 14, 2024
a841f5c
[silicon_creator,retention_ram] Port to DT
pamaury Nov 26, 2024
28f62a4
[silicon_creator] Remove useless dependency on spi_device.h
pamaury Nov 26, 2024
d904b60
[dif,rstmgr] Conditional compile earlgrey-specific code
pamaury Nov 28, 2024
0873ea0
[testutils,rand] Remove useless dependency on earlgrey
pamaury Nov 28, 2024
dc35de9
[test_rom,start] Make code compatible with multitop
pamaury Jan 28, 2025
d99e5cc
[ottf,start] Remove dependency on earlgrey
pamaury Nov 28, 2024
bf80a85
[test_rom] Fix build dependencies for EB/DJ
pamaury Jan 28, 2025
9e1e29a
[test_rom] Make it compatible with EB/DJ
pamaury Jan 28, 2025
229e18d
[darjeeling] Add execution environment for DV
pamaury Jan 28, 2025
9289641
[rules] Make opentitan_binary top aware
pamaury Jan 28, 2025
277203c
[test_rom] Add darjeeling execution environment
pamaury Jan 28, 2025
5c27da9
[silicon_creator,lifecycle] Port driver to DT
pamaury Nov 28, 2024
1eb35b4
[silicon_creator,hmac] Port driver to DT
pamaury Nov 28, 2024
f49a298
[silicon_creator,boot_svc] Relax dependency on boot_data
pamaury Jan 28, 2025
56e62bb
[sw/device/lib/arch] Make it compatible with multitop
pamaury Nov 28, 2024
6c332ed
[topgen] Add OPENTITAN_IS_<top> def to top linker script
pamaury Jan 29, 2025
7922dc8
[topgen] Fix template to define `rom_ext_virtual` on Darjeeling
pamaury Nov 28, 2024
f647615
[util] Make the ROM image scrambling script handle multiple images
pamaury Nov 28, 2024
cb690d2
[dif,flash_ctrl] A DT initialization function for flash_ctrl_state_t
pamaury Jan 29, 2025
e98782f
[test_rom] Make linker script compatible with darjeeling
pamaury Jan 29, 2025
d68436e
[uart_smoketest] Port to DT
pamaury Nov 28, 2024
1c11d2a
[ottf,isrs] Port to DT
pamaury Nov 28, 2024
f001267
[testing,freertos] Port to DT
pamaury Nov 28, 2024
e3c94ea
[ottf,console] Port to DT
pamaury Nov 28, 2024
95d46c7
[ottf,main] Port to DT
pamaury Nov 28, 2024
9fd9d5a
[testutils,spi_device] Port to DT
pamaury Nov 28, 2024
24cb1d2
[rules,linker] Fix includes paths
pamaury Jan 30, 2025
044fc1f
[ottf] Make linker scripts compatible with multitop
pamaury Jan 30, 2025
5960407
[mask_rom] Enable LTO
pamaury Jan 30, 2025
4b9c3ad
[test_rom] Adjust english_breakfast fake drivers code for multitop
pamaury Jan 30, 2025
02d17f7
[hw/top] Fix opentitan_select_top for out-of-tree users
pamaury Jan 31, 2025
5597b93
[dif] Add DT dependency to MBX and DMA
pamaury Jan 31, 2025
93c707b
[rules] Always add the map file and disassembly to the default info
pamaury Jan 31, 2025
966fd5f
[rom] Prevent LTO for inlining uart_init
pamaury Jan 31, 2025
eacff8c
[rom,chip_info] Mark `kChipInfo` as used so it is not discarded
pamaury Feb 3, 2025
cdb3578
[reggen] Fix rust generator
pamaury Feb 5, 2025
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
126 changes: 106 additions & 20 deletions hw/ip/rom_ctrl/util/scramble_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -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),
},
Comment on lines +47 to +52
Copy link
Contributor

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.

"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,
Expand Down Expand Up @@ -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]:
Expand Down Expand Up @@ -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")
Copy link
Contributor

Choose a reason for hiding this comment

The 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"])
Copy link
Contributor

Choose a reason for hiding this comment

The 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
Expand Down Expand Up @@ -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)
Copy link
Contributor

Choose a reason for hiding this comment

The 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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pinging @Razer6 @sameo, the ROM scrambling change was backported from integrated_dev. I agree that we should revisit this if possible to avoid hardcoding.


# Flatten the file, padding with pseudo-random data and ensuring it's
# exactly scrambler.rom_size_words words long.
Expand Down
2 changes: 1 addition & 1 deletion hw/top/defs.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def opentitan_select_top(values, default):
if type(tops) == "string":
tops = [tops]
for top in tops:
branches["//hw/top:is_{}".format(top)] = value
branches["@lowrisc_opentitan//hw/top:is_{}".format(top)] = value
branches["//conditions:default"] = default
return select(branches)

Expand Down
39 changes: 39 additions & 0 deletions hw/top_darjeeling/BUILD
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",
)
5 changes: 4 additions & 1 deletion hw/top_darjeeling/sw/autogen/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ cc_library(

ld_library(
name = "top_darjeeling_memory",
defines = ["OPENTITAN_TOP_MEMORY_LD=top_darjeeling_memory.ld"],
defines = [
"OPENTITAN_TOP_MEMORY_LD=top_darjeeling_memory.ld",
"OPENTITAN_IS_DARJEELING",
],
includes = ["top_darjeeling_memory.ld"],
target_compatible_with = opentitan_require_top("darjeeling"),
)
4 changes: 2 additions & 2 deletions hw/top_darjeeling/sw/autogen/top_darjeeling_memory.ld
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ MEMORY {
ram_mbox(rwx) : ORIGIN = 0x11000000, LENGTH = 0x1000
rom0(rx) : ORIGIN = 0x00008000, LENGTH = 0x8000
rom1(rx) : ORIGIN = 0x00020000, LENGTH = 0x10000
rom_ext_virtual(rx) : ORIGIN = 0x90000000, LENGTH = None
owner_virtual(rx) : ORIGIN = 0xa0000000, LENGTH = None
rom_ext_virtual(rx) : ORIGIN = 0x90000000, LENGTH = 0x80000
owner_virtual(rx) : ORIGIN = 0xa0000000, LENGTH = 0x80000
}

/**
Expand Down
5 changes: 4 additions & 1 deletion hw/top_earlgrey/sw/autogen/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ cc_library(

ld_library(
name = "top_earlgrey_memory",
defines = ["OPENTITAN_TOP_MEMORY_LD=top_earlgrey_memory.ld"],
defines = [
"OPENTITAN_TOP_MEMORY_LD=top_earlgrey_memory.ld",
"OPENTITAN_IS_EARLGREY",
],
includes = ["top_earlgrey_memory.ld"],
target_compatible_with = opentitan_require_top("earlgrey"),
)
5 changes: 4 additions & 1 deletion hw/top_englishbreakfast/sw/autogen/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ cc_library(

ld_library(
name = "top_englishbreakfast_memory",
defines = ["OPENTITAN_TOP_MEMORY_LD=top_englishbreakfast_memory.ld"],
defines = [
"OPENTITAN_TOP_MEMORY_LD=top_englishbreakfast_memory.ld",
"OPENTITAN_IS_ENGLISHBREAKFAST",
],
includes = ["top_englishbreakfast_memory.ld"],
target_compatible_with = opentitan_require_top("englishbreakfast"),
)
10 changes: 2 additions & 8 deletions rules/linker.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,6 @@ def _ld_library_impl(ctx):
user_link_flags = []
files = []

# Disable non-volatile scratch region and counters if building for english
# breakfast. This should appear before the linker script.
# FIXME Get rid of this.
if "-DOT_IS_ENGLISH_BREAKFAST_REDUCED_SUPPORT_FOR_INTERNAL_USE_ONLY_" in ctx.fragments.cpp.copts:
user_link_flags += [
"-Wl,--defsym=no_ottf_nv_scratch=1",
"-Wl,--defsym=no_ottf_nv_counter=1",
]
if ctx.attr.non_page_aligned_segments:
user_link_flags += [
"-Wl,-nmagic",
Expand Down Expand Up @@ -113,6 +105,8 @@ def _ld_library_impl(ctx):
),
compilation_context = cc_common.create_compilation_context(
defines = depset(ctx.attr.defines),
headers = depset(ctx.files.includes),
includes = depset([f.path for f in ctx.files.includes]),
),
)],
),
Expand Down
10 changes: 10 additions & 0 deletions rules/opentitan/cc.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ load("@lowrisc_opentitan//rules/opentitan:util.bzl", "get_fallback", "get_overri
load("@rules_cc//cc:find_cc_toolchain.bzl", "find_cc_toolchain")
load("//rules/opentitan:toolchain.bzl", "LOCALTOOLS_TOOLCHAIN")
load("//rules/opentitan:util.bzl", "assemble_for_test")
load("//rules/opentitan:providers.bzl", "OpenTitanBinaryInfo")

def _expand(ctx, name, items):
"""Perform location and make_variable expansion on a list of items.
Expand Down Expand Up @@ -231,6 +232,7 @@ def _opentitan_binary(ctx):
providers = []
default_info = []
groups = {}
ot_bin_env_info = {}
for exec_env_target in ctx.attr.exec_env:
exec_env = exec_env_target[ExecEnvInfo]
name = _binary_name(ctx, exec_env)
Expand All @@ -250,6 +252,8 @@ def _opentitan_binary(ctx):
providers.append(exec_env.provider(kind = kind, **provides))
default_info.append(provides["default"])
default_info.append(provides["elf"])
default_info.append(provides["disassembly"])
default_info.append(provides["mapfile"])

# FIXME(cfrantz): logs are a special case and get added into
# the DefaultInfo provider.
Expand All @@ -268,9 +272,11 @@ def _opentitan_binary(ctx):

groups.update(_as_group_info(exec_env.exec_env, signed))
groups.update(_as_group_info(exec_env.exec_env, provides))
ot_bin_env_info[exec_env.provider] = exec_env

providers.append(DefaultInfo(files = depset(default_info)))
providers.append(OutputGroupInfo(**groups))
providers.append(OpenTitanBinaryInfo(exec_env = ot_bin_env_info))
return providers

def _transitive_feature_transition_impl(settings, attr):
Expand Down Expand Up @@ -357,6 +363,10 @@ common_binary_attrs = {
executable = True,
cfg = "exec",
),
"rom_scramble_mode": attr.string(
doc = "ROM scrambling mode.",
default = "base-rom",
),
"immutable_rom_ext_enabled": attr.bool(
doc = "Indicates whether the binary is intended for a chip with the immutable ROM_EXT feature enabled.",
default = False,
Expand Down
Loading
Loading