Skip to content
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
26 changes: 24 additions & 2 deletions docs/export/minerva.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ export MINERVA_CALIBRATION_NPZ=/secure/project/calibration.npz
export MINERVA_KEY_FILE=/secure/project/device.key
export MINERVA_RUN_CMAKE=true
export MINERVA_RUN_CTEST=true
export MINERVA_HOST_ADAPTER_SOURCE=/secure/project/minerva_runtime_adapter.c
export MINERVA_HOST_INCLUDE_DIRS=/opt/libminerva/include
export MINERVA_HOST_LIBRARY_DIRS=/opt/libminerva/lib
export MINERVA_HOST_LIBRARIES=minerva
```

Do not commit real device keys. `include/secrets.example.h` contains placeholders only.
Expand Down Expand Up @@ -65,6 +69,7 @@ build/minerva/TinySecureMlp/
host/
CMakeLists.txt
main.c
runtime_adapter.example.c
reference-input.txt
reference-output.txt
observed-output.txt # optional output from a real host run
Expand All @@ -76,17 +81,30 @@ build/minerva/TinySecureMlp/

Host verification checks package structure, generated weight files, `model.npz` integrity, placeholder secret hygiene, and SKaiNET reference fixture generation. The packager writes deterministic `host/reference-input.txt` and `host/reference-output.txt` files and records them in `manifest.json`. A real host run can write comma- or whitespace-separated float outputs to `host/observed-output.txt` for zero-config parity comparison.

The generated host harness has a stable adapter ABI:

```c
int minerva_run_inference(const float *input, int input_count, float *output, int output_count);
```

Copy `host/runtime_adapter.example.c` outside the generated bundle, wire that function to the pinned libminerva runtime, then point CMake at the adapter source. This keeps SKaiNET from hard-coding unverified libminerva runtime entry point names.

Add these metadata keys to opt into CMake, CTest, and parity comparison with a custom host output file:

```kotlin
metadata = mapOf(
MinervaHostVerificationMetadata.RUN_CMAKE_BUILD to "true",
MinervaHostVerificationMetadata.RUN_CTEST to "true",
MinervaHostVerificationMetadata.HOST_OUTPUT_PATH to "host-output.txt"
MinervaHostVerificationMetadata.HOST_OUTPUT_PATH to "host-output.txt",
MinervaHostVerificationMetadata.HOST_ADAPTER_SOURCE to "/secure/project/minerva_runtime_adapter.c",
MinervaHostVerificationMetadata.HOST_INCLUDE_DIRS to "/opt/libminerva/include",
MinervaHostVerificationMetadata.HOST_LIBRARY_DIRS to "/opt/libminerva/lib",
MinervaHostVerificationMetadata.HOST_LIBRARIES to "minerva"
)
```

`HOST_OUTPUT_PATH` is optional when the host run writes `host/observed-output.txt`.
The include, library directory, and library values are passed to CMake as semicolon-separated lists, matching CMake list syntax.

CI recipe:

Expand All @@ -97,7 +115,11 @@ CI recipe:
-Pminerva.runtimeRoot="$MINERVA_RUNTIME_ROOT" \
-Pminerva.compilerScript="$MINERVA_COMPILER_SCRIPT" \
-Pminerva.calibrationNpz="$MINERVA_CALIBRATION_NPZ" \
-Pminerva.keyFile="$MINERVA_KEY_FILE"
-Pminerva.keyFile="$MINERVA_KEY_FILE" \
-Pminerva.hostVerification.hostAdapterSource="$MINERVA_HOST_ADAPTER_SOURCE" \
-Pminerva.hostVerification.hostIncludeDirs="$MINERVA_HOST_INCLUDE_DIRS" \
-Pminerva.hostVerification.hostLibraryDirs="$MINERVA_HOST_LIBRARY_DIRS" \
-Pminerva.hostVerification.hostLibraries="$MINERVA_HOST_LIBRARIES"
```

`minervaHostVerification` is skipped by default. When enabled, it runs `jvmTest` and `runMinervaTinyMlpSample` with CMake and CTest host verification enabled unless `-Pminerva.hostVerification.runCmakeBuild=false` or `-Pminerva.hostVerification.runCTest=false` is set.
Expand Down
27 changes: 25 additions & 2 deletions docs/modules/ROOT/pages/how-to/minerva-export.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ export MINERVA_CALIBRATION_NPZ=/secure/project/calibration.npz
export MINERVA_KEY_FILE=/secure/project/device.key
export MINERVA_RUN_CMAKE=true
export MINERVA_RUN_CTEST=true
export MINERVA_HOST_ADAPTER_SOURCE=/secure/project/minerva_runtime_adapter.c
export MINERVA_HOST_INCLUDE_DIRS=/opt/libminerva/include
export MINERVA_HOST_LIBRARY_DIRS=/opt/libminerva/lib
export MINERVA_HOST_LIBRARIES=minerva
----

`MINERVA_KEY_FILE` and the generated `include/secrets.example.h` are placeholders for integration. Do not commit real device keys or derived secrets.
Expand Down Expand Up @@ -128,6 +132,7 @@ build/minerva/TinySecureMlp/
host/
CMakeLists.txt
main.c
runtime_adapter.example.c
reference-input.txt
reference-output.txt
observed-output.txt # optional output from a real host run
Expand All @@ -141,20 +146,34 @@ The manifest records the target, quantization, libminerva root, compiler command

Host verification always checks the package structure, generated weight files, `model.npz` integrity, and placeholder secret hygiene. It also writes and validates deterministic `host/reference-input.txt` and `host/reference-output.txt` fixtures.

The generated host harness has a stable adapter ABI:

[source,c]
----
int minerva_run_inference(const float *input, int input_count, float *output, int output_count);
----

Copy `host/runtime_adapter.example.c` outside the generated bundle, wire that function to the pinned libminerva runtime, then point CMake at the adapter source. This keeps SKaiNET from hard-coding unverified libminerva runtime entry point names.

Use these metadata keys to opt into external host checks:

[source,kotlin]
----
metadata = mapOf(
MinervaHostVerificationMetadata.RUN_CMAKE_BUILD to "true",
MinervaHostVerificationMetadata.RUN_CTEST to "true",
MinervaHostVerificationMetadata.HOST_OUTPUT_PATH to "host-output.txt"
MinervaHostVerificationMetadata.HOST_OUTPUT_PATH to "host-output.txt",
MinervaHostVerificationMetadata.HOST_ADAPTER_SOURCE to "/secure/project/minerva_runtime_adapter.c",
MinervaHostVerificationMetadata.HOST_INCLUDE_DIRS to "/opt/libminerva/include",
MinervaHostVerificationMetadata.HOST_LIBRARY_DIRS to "/opt/libminerva/lib",
MinervaHostVerificationMetadata.HOST_LIBRARIES to "minerva"
)
----

`RUN_CMAKE_BUILD` configures and builds `host/CMakeLists.txt`. `RUN_CTEST` runs the packaged CTest smoke test. `HOST_OUTPUT_PATH` lets a real host run write comma- or whitespace-separated float outputs that are compared with the SKaiNET reference output using `hostVerificationTolerance`.

`HOST_OUTPUT_PATH` is optional when the host run writes the default `host/observed-output.txt` file.
The include, library directory, and library values are passed to CMake as semicolon-separated lists, matching CMake list syntax.

Local CI recipe:

Expand All @@ -166,7 +185,11 @@ Local CI recipe:
-Pminerva.runtimeRoot="$MINERVA_RUNTIME_ROOT" \
-Pminerva.compilerScript="$MINERVA_COMPILER_SCRIPT" \
-Pminerva.calibrationNpz="$MINERVA_CALIBRATION_NPZ" \
-Pminerva.keyFile="$MINERVA_KEY_FILE"
-Pminerva.keyFile="$MINERVA_KEY_FILE" \
-Pminerva.hostVerification.hostAdapterSource="$MINERVA_HOST_ADAPTER_SOURCE" \
-Pminerva.hostVerification.hostIncludeDirs="$MINERVA_HOST_INCLUDE_DIRS" \
-Pminerva.hostVerification.hostLibraryDirs="$MINERVA_HOST_LIBRARY_DIRS" \
-Pminerva.hostVerification.hostLibraries="$MINERVA_HOST_LIBRARIES"
----

The Gradle `minervaHostVerification` task is gated. It only runs when `minerva.hostVerification.enabled=true`, `minerva.runtimeRoot`, and `minerva.compilerScript` are present. When enabled, it runs `jvmTest` and `runMinervaTinyMlpSample` with `MINERVA_RUN_CMAKE=true` and `MINERVA_RUN_CTEST=true` by default. Override `-Pminerva.hostVerification.runCmakeBuild=false` or `-Pminerva.hostVerification.runCTest=false` only for runtime bring-up.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,10 @@ public final class sk/ainet/compile/minerva/MinervaHostVerification {
public final class sk/ainet/compile/minerva/MinervaHostVerificationMetadata {
public static final field CMAKE_EXECUTABLE Ljava/lang/String;
public static final field CTEST_EXECUTABLE Ljava/lang/String;
public static final field HOST_ADAPTER_SOURCE Ljava/lang/String;
public static final field HOST_INCLUDE_DIRS Ljava/lang/String;
public static final field HOST_LIBRARIES Ljava/lang/String;
public static final field HOST_LIBRARY_DIRS Ljava/lang/String;
public static final field HOST_OUTPUT_PATH Ljava/lang/String;
public static final field INSTANCE Lsk/ainet/compile/minerva/MinervaHostVerificationMetadata;
public static final field RUN_CMAKE_BUILD Ljava/lang/String;
Expand Down
20 changes: 20 additions & 0 deletions skainet-compile/skainet-compile-minerva/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ val minervaCalibrationNpz = providers.gradleProperty("minerva.calibrationNpz")
val minervaRunCmakeBuild = providers.gradleProperty("minerva.hostVerification.runCmakeBuild")
val minervaRunCTest = providers.gradleProperty("minerva.hostVerification.runCTest")
val minervaHostOutputPath = providers.gradleProperty("minerva.hostVerification.hostOutputPath")
val minervaHostAdapterSource = providers.gradleProperty("minerva.hostVerification.hostAdapterSource")
val minervaHostIncludeDirs = providers.gradleProperty("minerva.hostVerification.hostIncludeDirs")
val minervaHostLibraryDirs = providers.gradleProperty("minerva.hostVerification.hostLibraryDirs")
val minervaHostLibraries = providers.gradleProperty("minerva.hostVerification.hostLibraries")
val minervaRunCmakeBuildForSample = minervaRunCmakeBuild
.orElse(providers.environmentVariable("MINERVA_RUN_CMAKE"))
.orElse(minervaHostVerificationEnabled.map { it.toString() })
Expand All @@ -64,6 +68,10 @@ tasks.register("minervaHostVerification") {
inputs.property("minerva.hostVerification.runCmakeBuild", minervaRunCmakeBuildForSample)
inputs.property("minerva.hostVerification.runCTest", minervaRunCTestForSample)
inputs.property("minerva.hostVerification.hostOutputPath", minervaHostOutputPath.orElse(""))
inputs.property("minerva.hostVerification.hostAdapterSource", minervaHostAdapterSource.orElse(""))
inputs.property("minerva.hostVerification.hostIncludeDirs", minervaHostIncludeDirs.orElse(""))
inputs.property("minerva.hostVerification.hostLibraryDirs", minervaHostLibraryDirs.orElse(""))
inputs.property("minerva.hostVerification.hostLibraries", minervaHostLibraries.orElse(""))
}

tasks.register<JavaExec>("runMinervaTinyMlpSample") {
Expand Down Expand Up @@ -101,4 +109,16 @@ tasks.register<JavaExec>("runMinervaTinyMlpSample") {
minervaHostOutputPath.orElse(providers.environmentVariable("MINERVA_HOST_OUTPUT_PATH")).orNull?.let {
environment("MINERVA_HOST_OUTPUT_PATH", it)
}
minervaHostAdapterSource.orElse(providers.environmentVariable("MINERVA_HOST_ADAPTER_SOURCE")).orNull?.let {
environment("MINERVA_HOST_ADAPTER_SOURCE", it)
}
minervaHostIncludeDirs.orElse(providers.environmentVariable("MINERVA_HOST_INCLUDE_DIRS")).orNull?.let {
environment("MINERVA_HOST_INCLUDE_DIRS", it)
}
minervaHostLibraryDirs.orElse(providers.environmentVariable("MINERVA_HOST_LIBRARY_DIRS")).orNull?.let {
environment("MINERVA_HOST_LIBRARY_DIRS", it)
}
minervaHostLibraries.orElse(providers.environmentVariable("MINERVA_HOST_LIBRARIES")).orNull?.let {
environment("MINERVA_HOST_LIBRARIES", it)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ public object MinervaHostVerificationMetadata {
public const val CMAKE_EXECUTABLE: String = "minerva.hostVerification.cmakeExecutable"
public const val CTEST_EXECUTABLE: String = "minerva.hostVerification.ctestExecutable"
public const val HOST_OUTPUT_PATH: String = "minerva.hostVerification.hostOutputPath"
public const val HOST_ADAPTER_SOURCE: String = "minerva.hostVerification.hostAdapterSource"
public const val HOST_INCLUDE_DIRS: String = "minerva.hostVerification.hostIncludeDirs"
public const val HOST_LIBRARY_DIRS: String = "minerva.hostVerification.hostLibraryDirs"
public const val HOST_LIBRARIES: String = "minerva.hostVerification.hostLibraries"
}

/**
Expand Down
Loading
Loading