Skip to main content

logicaffeine_compile/spatial/passes/
mod.rs

1//! The target-parametric passes: every one is `fn(&SpatialProgram, &SpatialTarget) -> Result<SpatialProgram, SpatialReject>`,
2//! reads only the program and the descriptor, and leaves `validate()` holding. The order is pinned in
3//! [`super::pipeline::PASS_ORDER`]. There is no strategy input anywhere: `tile` chooses the plan by the cost
4//! model, `fuse_readers` re-derives the same comparison, and every later pass is a function of the structure.
5
6pub mod compose;
7pub mod from_q8;
8pub mod from_qwen_ops;
9pub mod from_tensor_op;
10pub mod forward;
11pub mod fuse_generic;
12pub mod fuse_readers;
13pub mod pack;
14pub mod persist;
15pub mod place;
16pub use crate::tensor_graph::front as recognize_stages;
17pub mod section_shape;
18pub mod shard;
19pub mod size_buffers;
20pub mod synthesize_handshakes;
21pub mod tile;
22pub mod verify;
23
24use super::eval::ChoreoFault;
25use super::ir::{AccPolicy, GroupId, IrViolation, Site};
26use super::target::{HandshakeKind, Interconnect};
27use crate::codegen_sva::fabric_target::Precision;
28use crate::tensor_recognize::{ElementwiseReject, MatmulReject, ReductionReject};
29
30/// Why a program cannot become (or stay) a spatial program on a target — typed, never a silent fallback.
31#[derive(Clone, Debug, PartialEq)]
32pub enum SpatialReject {
33    Parse(String),
34    Unrecognized {
35        matmul: MatmulReject,
36        elementwise: ElementwiseReject,
37        reduction: ReductionReject,
38    },
39    NotLowered(&'static str),
40    MissingCompute {
41        needed: &'static str,
42        target: &'static str,
43    },
44    MissingPrecision {
45        needed: Precision,
46        target: &'static str,
47    },
48    MissingHandshake {
49        needed: HandshakeKind,
50        target: &'static str,
51    },
52    MissingInterconnect {
53        needed: Interconnect,
54        target: &'static str,
55    },
56    NoLegalTiling {
57        rows_t: usize,
58        cols_t: usize,
59        k_tiles: usize,
60        acc_tiles: usize,
61        sites: usize,
62    },
63    LocalMemExceeded {
64        site: Site,
65        needed_bytes: usize,
66        budget_bytes: usize,
67    },
68    AccTilesExceeded {
69        needed: usize,
70        available: usize,
71        acc: AccPolicy,
72    },
73    TooManyEngines {
74        site: Site,
75        needed: usize,
76        available: u8,
77    },
78    GroupCountMismatch {
79        group: GroupId,
80        counts: Vec<(Site, usize)>,
81    },
82    WrongPhase {
83        pass: &'static str,
84        expected: &'static str,
85        found: super::ir::Phase,
86    },
87    Unverified(ChoreoFault),
88    Invalid(IrViolation),
89    /// The scalar (decision-fabric) front end refused the body in its own words — an op outside the
90    /// compare/arith/branch family, a runtime-bound slice, a value kind it does not carry.
91    ScalarFrontEnd(String),
92    /// A weight the deployment stores Q8_0 whose declared values are not an int8 multiple of a scale per 32 rows.
93    NotQ8_0 {
94        weight: String,
95    },
96}
97
98impl From<IrViolation> for SpatialReject {
99    fn from(v: IrViolation) -> Self {
100        SpatialReject::Invalid(v)
101    }
102}
103
104/// The loop variables the choreography addresses tiles with.
105pub const LV_ITEM_Y: super::ir::LoopVar = super::ir::LoopVar(0);
106pub const LV_ITEM_X: super::ir::LoopVar = super::ir::LoopVar(1);
107pub const LV_KBLOCK: super::ir::LoopVar = super::ir::LoopVar(2);
108pub const LV_SUB_H: super::ir::LoopVar = super::ir::LoopVar(3);
109pub const LV_SUB_W: super::ir::LoopVar = super::ir::LoopVar(4);
110pub const LV_ITEM: super::ir::LoopVar = super::ir::LoopVar(5);
111
112/// A [`ComputeOp::Generic`](crate::spatial::ir::ComputeOp::Generic)'s own iteration space: the rows inside a tile, and the columns across the
113/// operand's tiles. Distinct from the choreography's loop variables above, which index WORK; these
114/// index the ELEMENTS one compute stage walks, and are the axes an access map may omit to broadcast.
115///
116/// [`ComputeOp::Generic`]: super::ir::ComputeOp::Generic
117pub const LV_GEN_ROW: super::ir::LoopVar = super::ir::LoopVar(6);
118pub const LV_GEN_COL: super::ir::LoopVar = super::ir::LoopVar(7);
119/// A [`ComputeOp::Generic`]'s CONTRACTION axis: the third iteration variable, summed at every `(row, col)` point —
120/// `C[r, c] = Σ_k A[r, k]·B[k, c]` — so a small matrix product is one stage. Maps step along it; the output never does.
121///
122/// [`ComputeOp::Generic`]: super::ir::ComputeOp::Generic
123pub const LV_GEN_K: super::ir::LoopVar = super::ir::LoopVar(8);