mirror of
https://github.com/retroSoC/retroSoC.git
synced 2026-11-04 22:32:36 +00:00
feat: refactor and enhance documentation for Linux runtime, boot acceptance, and NPU integration
- Updated fault reference documentation to clarify Linux termination behavior and NPU-P6 requirements. - Enhanced Linux runtime section with emphasis on platform setup and kernel handoff processes. - Revised overview section to include detailed descriptions of NPU capabilities and memory configurations. - Improved product use documentation to specify Linux rootfs behavior and acceptance checkpoints. - Clarified reset summary to differentiate between Linux and smoke/NPU-P6 acceptance processes. - Updated software section to reflect changes in Linux image loading and readiness protocols. - Modified build scripts to support RV64 architecture and ensure proper ELF requirements. - Enhanced NPU compiler to support cycle counting for RV64 and RV32 architectures. - Added tests to validate new configurations and ensure compliance with updated publication contracts.
This commit is contained in:
30 files changed
+539
-135
No files matched your search
+10
-4
@@ -7,6 +7,11 @@ import argparse
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
try:
|
||||
from scripts.hp_tools import require_rv64_elf
|
||||
except ModuleNotFoundError:
|
||||
from hp_tools import require_rv64_elf
|
||||
|
||||
|
||||
def build(args: argparse.Namespace) -> None:
|
||||
output = args.output.resolve()
|
||||
@@ -20,8 +25,8 @@ def build(args: argparse.Namespace) -> None:
|
||||
subprocess.run(
|
||||
[
|
||||
compiler,
|
||||
"-march=rv32imafdc_zicbom_zicsr_zifencei",
|
||||
"-mabi=ilp32d",
|
||||
"-march=rv64imafdc_zicbom_zicsr_zifencei",
|
||||
"-mabi=lp64d",
|
||||
"-nostdlib",
|
||||
"-nostartfiles",
|
||||
"-ffreestanding",
|
||||
@@ -38,20 +43,21 @@ def build(args: argparse.Namespace) -> None:
|
||||
],
|
||||
check=True,
|
||||
)
|
||||
require_rv64_elf(elf)
|
||||
subprocess.run(
|
||||
[objcopy, "-O", "binary", str(elf), str(images / "fw_jump.bin")],
|
||||
check=True,
|
||||
)
|
||||
(images / "retrosoc_hp.dtb").write_bytes(b"SMOK")
|
||||
(images / "Image").write_bytes(b"SMOK")
|
||||
(images / "rootfs.cpio.gz").write_bytes(b"SMOK")
|
||||
(images / "rootfs.cpio").write_bytes(b"SMOK")
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("--source-dir", type=Path, required=True)
|
||||
parser.add_argument("--output", type=Path, required=True)
|
||||
parser.add_argument("--cross", default="riscv32-unknown-elf-")
|
||||
parser.add_argument("--cross", default="riscv64-unknown-elf-")
|
||||
parser.add_argument("--include", type=Path, action="append", default=[])
|
||||
build(parser.parse_args())
|
||||
|
||||
|
||||
+24
-21
@@ -7,6 +7,11 @@ import argparse
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
try:
|
||||
from scripts.hp_tools import require_rv64_elf
|
||||
except ModuleNotFoundError:
|
||||
from hp_tools import require_rv64_elf
|
||||
|
||||
|
||||
def build(args: argparse.Namespace) -> None:
|
||||
output = args.output.resolve()
|
||||
@@ -16,35 +21,33 @@ def build(args: argparse.Namespace) -> None:
|
||||
compiler = f"{args.cross}gcc"
|
||||
objcopy = f"{args.cross}objcopy"
|
||||
command = [
|
||||
compiler,
|
||||
"-march=rv32imafdc_zicbom_zicsr_zifencei",
|
||||
"-mabi=ilp32d",
|
||||
"-nostdlib",
|
||||
"-nostartfiles",
|
||||
"-ffreestanding",
|
||||
"-O3",
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
"-Werror=implicit-function-declaration",
|
||||
"-Werror=return-type",
|
||||
"-Wl,--build-id=none",
|
||||
f"-Wl,-T,{args.linker.resolve()}",
|
||||
"-o",
|
||||
str(elf),
|
||||
str(args.source.resolve()),
|
||||
compiler,
|
||||
"-march=rv64imafdc_zicbom_zicsr_zifencei",
|
||||
"-mabi=lp64d",
|
||||
"-nostdlib",
|
||||
"-nostartfiles",
|
||||
"-ffreestanding",
|
||||
"-O3",
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
"-Werror=implicit-function-declaration",
|
||||
"-Werror=return-type",
|
||||
"-Wl,--build-id=none",
|
||||
f"-Wl,-T,{args.linker.resolve()}",
|
||||
"-o",
|
||||
str(elf),
|
||||
str(args.source.resolve()),
|
||||
]
|
||||
for include in args.include:
|
||||
command.append(f"-I{include.resolve()}")
|
||||
command.extend(str(source.resolve()) for source in args.extra_source)
|
||||
command.extend(args.define)
|
||||
subprocess.run(command, check=True)
|
||||
require_rv64_elf(elf)
|
||||
subprocess.run(
|
||||
[objcopy, "-O", "binary", str(elf), str(images / "fw_jump.bin")],
|
||||
[objcopy, "-O", "binary", str(elf), str(images / "hp_smoke.bin")],
|
||||
check=True,
|
||||
)
|
||||
(images / "retrosoc_hp.dtb").write_bytes(b"SMOK")
|
||||
(images / "Image").write_bytes(b"SMOK")
|
||||
(images / "rootfs.cpio.gz").write_bytes(b"SMOK")
|
||||
|
||||
|
||||
def main() -> None:
|
||||
@@ -52,7 +55,7 @@ def main() -> None:
|
||||
parser.add_argument("--source", type=Path, required=True)
|
||||
parser.add_argument("--linker", type=Path, required=True)
|
||||
parser.add_argument("--output", type=Path, required=True)
|
||||
parser.add_argument("--cross", default="riscv32-unknown-elf-")
|
||||
parser.add_argument("--cross", default="riscv64-unknown-elf-")
|
||||
parser.add_argument("--extra-source", type=Path, action="append", default=[])
|
||||
parser.add_argument("--include", type=Path, action="append", default=[])
|
||||
parser.add_argument("--define", action="append", default=[])
|
||||
|
||||
@@ -261,7 +261,11 @@ static const rs_{prefix}_reloc_t rs_{prefix}_npu_relocations[{len(job.relocation
|
||||
{_c_bytes(f'rs_{prefix}_npu_params', job.params)}
|
||||
|
||||
static uint64_t rs_{prefix}_cycles(void) {{
|
||||
#if defined(__riscv)
|
||||
#if defined(__riscv_xlen) && (__riscv_xlen == 64)
|
||||
uint64_t cycle;
|
||||
__asm__ volatile("rdcycle %0" : "=r"(cycle));
|
||||
return cycle;
|
||||
#elif defined(__riscv)
|
||||
uint32_t high0; uint32_t low; uint32_t high1;
|
||||
do {{ __asm__ volatile("rdcycleh %0" : "=r"(high0));
|
||||
__asm__ volatile("rdcycle %0" : "=r"(low));
|
||||
|
||||
@@ -110,6 +110,32 @@ def build_variants(timestamp: str, log_dir: Path) -> dict[str, Path]:
|
||||
return roots
|
||||
|
||||
|
||||
def qualification_configuration(variants: dict[str, Path]) -> dict[str, object]:
|
||||
selected = ("MINI_MODE", "APP", "SIMU", "HP_CONFIG", "EXT_CLK_HZ")
|
||||
configurations: dict[str, dict[str, str]] = {}
|
||||
for workload, variant in variants.items():
|
||||
manifest = json.loads((variant / "meta/manifest.json").read_text(encoding="utf-8"))
|
||||
configuration = manifest.get("configuration")
|
||||
if not isinstance(configuration, dict) or any(
|
||||
not isinstance(configuration.get(name), str) for name in selected
|
||||
):
|
||||
raise ValueError(f"P6 {workload} manifest lacks its PRODUCT configuration")
|
||||
configurations[workload] = {name: configuration[name] for name in selected}
|
||||
if set(configurations) != {"kws", "vww"} or configurations["kws"] != configurations["vww"]:
|
||||
raise ValueError("P6 workload manifests use different PRODUCT configurations")
|
||||
configuration = configurations["kws"]
|
||||
expected = {
|
||||
"MINI_MODE": "PRODUCT",
|
||||
"APP": "hp_boot",
|
||||
"SIMU": "VERILATOR",
|
||||
"HP_CONFIG": "rv64imafdc_zicbom_max",
|
||||
"EXT_CLK_HZ": "72000000",
|
||||
}
|
||||
if configuration != expected:
|
||||
raise ValueError(f"P6 manifest configuration differs from the frozen target: {configuration}")
|
||||
return {**configuration, "EXT_CLK_HZ": int(configuration["EXT_CLK_HZ"])}
|
||||
|
||||
|
||||
def parse_case_line(line: str) -> dict[str, Any]:
|
||||
if not line.startswith(CASE_PREFIX):
|
||||
raise ValueError("not an NPU-P6 case record")
|
||||
@@ -168,10 +194,10 @@ def package_shard(
|
||||
shard_dir = output / workload / f"shard-{shard_index:03d}"
|
||||
images = shard_dir / "images"
|
||||
images.mkdir(parents=True, exist_ok=True)
|
||||
shutil.copy2(variant / "hp-smoke/images/fw_jump.bin", images / "fw_jump.bin")
|
||||
shutil.copy2(variant / "hp-smoke/images/hp_smoke.bin", images / "fw_jump.bin")
|
||||
shutil.copy2(Path(shard["file"]["path"]), images / "Image")
|
||||
(images / "retrosoc_hp.dtb").write_bytes(b"SMOK")
|
||||
(images / "rootfs.cpio.gz").write_bytes(b"SMOK")
|
||||
(images / "rootfs.cpio").write_bytes(b"SMOK")
|
||||
bundle = shard_dir / "retrosoc_npu_p6.bin"
|
||||
manifest = shard_dir / "bundle.json"
|
||||
completed = run(
|
||||
@@ -396,6 +422,7 @@ def main() -> int:
|
||||
output = args.output_dir.resolve()
|
||||
output.mkdir(parents=True, exist_ok=True)
|
||||
variants = build_variants(args.build_timestamp, output / "build-logs")
|
||||
configuration = qualification_configuration(variants)
|
||||
emulator = variants["kws"] / "sim/verilator/emu"
|
||||
if not emulator.is_file():
|
||||
raise ValueError("P6 PRODUCT Verilator emulator is missing")
|
||||
@@ -441,13 +468,7 @@ def main() -> int:
|
||||
["git", "-C", str(ROOT), "rev-parse", "HEAD"], text=True
|
||||
).strip(),
|
||||
"profile": "configs/ci/ihp130.mk",
|
||||
"configuration": {
|
||||
"MINI_MODE": "PRODUCT",
|
||||
"APP": "hp_boot",
|
||||
"SIMU": "VERILATOR",
|
||||
"HP_CONFIG": "rv32imafdc_zicbom_max",
|
||||
"EXT_CLK_HZ": 72_000_000,
|
||||
},
|
||||
"configuration": configuration,
|
||||
"measurement": {
|
||||
"counter": "HP rdcycle",
|
||||
"reference": "portable INT8 C through CPU Softmax",
|
||||
|
||||
Reference in new issue
Block a user