aisimulate_core/perfmodel/common/error.rs
1// SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4//! Crate-wide error type.
5//!
6//! `lib.rs` re-exports `AicError` so the FFI surface and other callers can
7//! use it without depending on this module path. The operator-layer
8//! `PerformanceResult` companion type lives in `operators/base.rs`.
9
10use std::path::PathBuf;
11
12use thiserror::Error;
13
14/// All errors surfaced by the Rust core.
15#[derive(Debug, Error)]
16pub enum AicError {
17 #[error("unsupported schema version for {kind}: got {got}, expected {expected}")]
18 UnsupportedSchemaVersion {
19 kind: &'static str,
20 got: u32,
21 expected: u32,
22 },
23 #[error("invalid engine config: {0}")]
24 InvalidEngineConfig(String),
25 #[error("engine spec wire-format error: {0}")]
26 EngineSpec(String),
27 #[error("invalid forward pass metrics: {0}")]
28 InvalidForwardPassMetrics(String),
29 #[error("unsupported model for Rust core estimator: {0}")]
30 UnsupportedModel(String),
31 #[error("failed to find AIC data roots: {0}")]
32 DataRoot(String),
33 #[error("model config error: {0}")]
34 ModelConfig(String),
35 #[error("perf database error: {0}")]
36 PerfDatabase(String),
37 /// A quant mode's compute dtype has no `*_tc_flops` entry in the system
38 /// YAML. Mirrors Python's `MissingSystemFlopsError`: the platform either
39 /// lacks hardware for that dtype or the YAML is incomplete — never
40 /// extrapolate a fictional throughput from bf16.
41 #[error("missing system flops: {0}")]
42 MissingSystemFlops(String),
43 /// The HYBRID/EMPIRICAL path found no calibration data for the requested
44 /// slice — no own-shape, cross-shape, or sibling transfer reference.
45 /// Mirrors Python's `EmpiricalNotImplementedError`: a coverage gap, never
46 /// converted into a fabricated `SOL / constant` value.
47 #[error("empirical estimation not implemented: {0}")]
48 EmpiricalNotImplemented(String),
49 /// The analytic SOL path cannot represent an operator required by the
50 /// requested estimate. Mirrors Python's `SolNotImplementedError` so an
51 /// optional SOL comparison can distinguish a coverage gap from an invalid
52 /// configuration or a programming error.
53 #[error("SOL estimation not implemented: {0}")]
54 SolNotImplemented(String),
55 #[error("I/O error at {path}: {source}")]
56 Io {
57 path: PathBuf,
58 #[source]
59 source: std::io::Error,
60 },
61 #[error("YAML error at {path}: {source}")]
62 Yaml {
63 path: PathBuf,
64 #[source]
65 source: serde_yaml::Error,
66 },
67 #[error("Parquet error at {path}: {source}")]
68 Parquet {
69 path: PathBuf,
70 #[source]
71 source: parquet::errors::ParquetError,
72 },
73}
74
75impl AicError {
76 /// The "missing silicon data" class that HYBRID converts into an
77 /// empirical estimate. Mirrors Python's
78 /// `_MISSING_SILICON_DATA_EXCEPTIONS` (`PerfDataNotAvailableError`,
79 /// `InterpolationDataNotAvailableError`) — the same set `Op::Fallback`
80 /// catches. `EmpiricalNotImplemented` is deliberately NOT in this set:
81 /// it is the terminal miss raised after the empirical path itself found
82 /// no calibration data.
83 pub fn is_missing_perf_data(&self) -> bool {
84 matches!(self, Self::PerfDatabase(_) | Self::Io { .. })
85 }
86}