Skip to content

Commit 59a6b8d

Browse files
Merge pull request #271 from SKaiNET-developers/feature/255-stablehlo
Feature/255 stablehlo
2 parents 84e6121 + c7df247 commit 59a6b8d

91 files changed

Lines changed: 18915 additions & 123 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 334 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,334 @@
1+
# StableHLO Backend Completion Design Document
2+
3+
## Overview
4+
5+
This design document outlines the completion of the StableHLO backend for SKaiNET, which will enable compilation of computational graphs to StableHLO MLIR format. The current implementation provides basic functionality for add, matmul, and relu operations but needs to be expanded to support the full range of SKaiNET operations including mathematical operations, neural network layers, shape manipulations, and activation functions.
6+
7+
The StableHLO backend will serve as a bridge between SKaiNET's high-level DSL and low-level optimized execution through XLA and other MLIR-based compilation toolchains.
8+
9+
## Architecture
10+
11+
### Current Architecture
12+
13+
The existing implementation consists of:
14+
- `StableHloModule` data class for representing MLIR output
15+
- `toStableHlo()` function for converting ComputeGraph to MLIR
16+
- Basic operation mapping for add, matmul, and relu
17+
- Simple SSA value management and type mapping
18+
19+
### Enhanced Architecture
20+
21+
The enhanced architecture will include:
22+
23+
1. **Operation Registry System**: A pluggable system for registering StableHLO operation converters
24+
2. **Type System Integration**: Comprehensive mapping between SKaiNET and MLIR type systems
25+
3. **Optimization Framework**: Infrastructure for applying StableHLO-specific optimizations
26+
4. **Validation System**: MLIR syntax and semantic validation
27+
5. **Error Handling**: Comprehensive error reporting and fallback mechanisms
28+
29+
### Component Hierarchy
30+
31+
```
32+
skainet-compile-hlo/
33+
├── core/
34+
│ ├── StableHloModule.kt (existing)
35+
│ ├── StableHloConverter.kt (new)
36+
│ └── StableHloRegistry.kt (new)
37+
├── operations/
38+
│ ├── MathOperations.kt (new)
39+
│ ├── LinalgOperations.kt (new)
40+
│ ├── NeuralNetOperations.kt (new)
41+
│ ├── ShapeOperations.kt (new)
42+
│ └── ActivationOperations.kt (new)
43+
├── types/
44+
│ ├── TypeMapper.kt (new)
45+
│ └── ShapeInference.kt (new)
46+
├── validation/
47+
│ └── MlirValidator.kt (new)
48+
└── optimization/
49+
└── StableHloOptimizer.kt (new)
50+
```
51+
52+
## Components and Interfaces
53+
54+
### StableHloConverter
55+
56+
The main converter class that orchestrates the conversion process:
57+
58+
```kotlin
59+
public class StableHloConverter(
60+
private val registry: StableHloOperationRegistry,
61+
private val typeMapper: TypeMapper,
62+
private val validator: MlirValidator? = null
63+
) {
64+
public fun convert(graph: ComputeGraph, functionName: String = "main"): StableHloModule
65+
public fun convertWithOptimization(graph: ComputeGraph, optimizer: StableHloOptimizer): StableHloModule
66+
}
67+
```
68+
69+
### StableHloOperationRegistry
70+
71+
A registry system for operation converters:
72+
73+
```kotlin
74+
public interface StableHloOperationConverter {
75+
public val supportedOperations: Set<String>
76+
public fun convert(
77+
node: GraphNode,
78+
operands: List<String>,
79+
context: ConversionContext
80+
): ConversionResult
81+
}
82+
83+
public class StableHloOperationRegistry {
84+
public fun register(converter: StableHloOperationConverter)
85+
public fun getConverter(operationName: String): StableHloOperationConverter?
86+
public fun getSupportedOperations(): Set<String>
87+
}
88+
```
89+
90+
### TypeMapper
91+
92+
Handles type system mapping between SKaiNET and MLIR:
93+
94+
```kotlin
95+
public class TypeMapper {
96+
public fun mapDType(dtype: String): String
97+
public fun mapTensorType(spec: TensorSpec): String
98+
public fun mapFunctionSignature(inputs: List<TensorSpec>, outputs: List<TensorSpec>): String
99+
public fun inferBroadcastType(left: TensorSpec, right: TensorSpec): TensorSpec
100+
}
101+
```
102+
103+
### ConversionContext
104+
105+
Context object for maintaining state during conversion:
106+
107+
```kotlin
108+
public class ConversionContext(
109+
private val valueNames: MutableMap<String, String>,
110+
private val typeMapper: TypeMapper,
111+
private val stringBuilder: StringBuilder
112+
) {
113+
public fun getValueName(nodeId: String): String?
114+
public fun setValueName(nodeId: String, valueName: String)
115+
public fun nextTempValue(): String
116+
public fun emitOperation(operation: String)
117+
public fun emitComment(comment: String)
118+
}
119+
```
120+
121+
## Data Models
122+
123+
### StableHloModule (Enhanced)
124+
125+
```kotlin
126+
public data class StableHloModule(
127+
val content: String,
128+
val functionName: String,
129+
val inputSpecs: List<TensorSpec>,
130+
val outputSpecs: List<TensorSpec>,
131+
val metadata: Map<String, Any> = emptyMap()
132+
) {
133+
public fun validate(): ValidationResult
134+
public fun optimize(optimizer: StableHloOptimizer): StableHloModule
135+
}
136+
```
137+
138+
### ConversionResult
139+
140+
```kotlin
141+
public sealed class ConversionResult {
142+
public data class Success(
143+
val outputValueName: String,
144+
val emittedOperations: List<String>
145+
) : ConversionResult()
146+
147+
public data class Failure(
148+
val error: String,
149+
val fallbackComment: String? = null
150+
) : ConversionResult()
151+
152+
public data class Unsupported(
153+
val operationName: String,
154+
val reason: String
155+
) : ConversionResult()
156+
}
157+
```
158+
159+
### OperationMapping
160+
161+
```kotlin
162+
public data class OperationMapping(
163+
val skainetOperation: String,
164+
val stableHloOperation: String,
165+
val attributeMapping: Map<String, String> = emptyMap(),
166+
val customConverter: ((GraphNode, List<String>, ConversionContext) -> ConversionResult)? = null
167+
)
168+
```
169+
170+
## Correctness Properties
171+
172+
*A property is a characteristic or behavior that should hold true across all valid executions of a system-essentially, a formal statement about what the system should do. Properties serve as the bridge between human-readable specifications and machine-verifiable correctness guarantees.*
173+
174+
### Property Reflection
175+
176+
After reviewing all properties identified in the prework, several redundancies were identified:
177+
- Properties 1.2 and 5.1 both address MLIR syntax validation - consolidated into Property 1
178+
- Properties about infrastructure (4.1, 4.3, 4.4, 5.4, 5.5, 6.3, 6.4, 6.5) are design concerns rather than testable behaviors
179+
- Properties can be grouped by functional area for better organization
180+
181+
### Correctness Properties
182+
183+
Property 1: Valid MLIR Generation
184+
*For any* ComputeGraph containing supported operations, the generated StableHLO MLIR code should be syntactically valid and parseable by MLIR tools
185+
**Validates: Requirements 1.1, 1.2, 5.1**
186+
187+
Property 2: SSA Form Preservation
188+
*For any* sequence of chained operations in a ComputeGraph, the generated MLIR should maintain proper SSA form with correct value dependencies
189+
**Validates: Requirements 1.3**
190+
191+
Property 3: Type Mapping Correctness
192+
*For any* TensorSpec with specified shape and data type, the emitted MLIR type annotations should correctly represent the SKaiNET types using appropriate MLIR syntax
193+
**Validates: Requirements 1.4, 3.1, 3.5**
194+
195+
Property 4: Error Handling Consistency
196+
*For any* unsupported operation in a ComputeGraph, the system should emit clear error messages or fallback comments without crashing
197+
**Validates: Requirements 1.5, 5.3**
198+
199+
Property 5: Mathematical Operation Mapping
200+
*For any* mathematical operation (add, subtract, multiply, divide), the generated StableHLO should contain the corresponding arithmetic operation with correct operands
201+
**Validates: Requirements 2.1**
202+
203+
Property 6: Linear Algebra Operation Mapping
204+
*For any* linear algebra operation (matmul, transpose), the generated StableHLO should contain the appropriate stablehlo.dot_general or stablehlo.transpose operation
205+
**Validates: Requirements 2.2**
206+
207+
Property 7: Activation Function Implementation
208+
*For any* activation function (relu, sigmoid, softmax), the generated StableHLO should implement the function using appropriate primitive operations
209+
**Validates: Requirements 2.3**
210+
211+
Property 8: Convolutional Operation Mapping
212+
*For any* conv2d operation, the generated StableHLO should contain stablehlo.convolution with properly mapped attributes
213+
**Validates: Requirements 2.4**
214+
215+
Property 9: Shape Operation Mapping
216+
*For any* shape operation (reshape, flatten, squeeze, unsqueeze), the generated StableHLO should contain appropriate stablehlo.reshape or stablehlo.broadcast_in_dim operations
217+
**Validates: Requirements 2.5**
218+
219+
Property 10: Dynamic Shape Handling
220+
*For any* tensor with dynamic dimensions, the generated MLIR should use correct dynamic dimension syntax (? in tensor types)
221+
**Validates: Requirements 3.2**
222+
223+
Property 11: Broadcasting Operation Generation
224+
*For any* operation requiring broadcasting between tensors of different shapes, the system should emit explicit broadcast operations in StableHLO
225+
**Validates: Requirements 3.3**
226+
227+
Property 12: Type Conversion Handling
228+
*For any* operation involving mixed data types, the system should emit appropriate type conversion operations in StableHLO
229+
**Validates: Requirements 3.4**
230+
231+
Property 13: Constant Value Handling
232+
*For any* constant value in the computation graph, the generated StableHLO should contain stablehlo.constant operations with correct attributes
233+
**Validates: Requirements 4.2**
234+
235+
Property 14: Control Flow Mapping
236+
*For any* control flow construct in the graph, the system should emit appropriate stablehlo.if or stablehlo.while operations
237+
**Validates: Requirements 4.5**
238+
239+
Property 15: Round-trip Validation
240+
*For any* generated StableHLO module, parsing and re-processing should preserve the essential computational semantics
241+
**Validates: Requirements 5.2**
242+
243+
Property 16: ComputeGraph Interface Compatibility
244+
*For any* valid ComputeGraph implementation, the StableHLO backend should successfully process it without interface violations
245+
**Validates: Requirements 6.1**
246+
247+
Property 17: Operation Metadata Integration
248+
*For any* operation with KSP-generated metadata, the StableHLO backend should correctly utilize the metadata for conversion
249+
**Validates: Requirements 6.2**
250+
251+
## Error Handling
252+
253+
The error handling strategy will include:
254+
255+
1. **Validation Errors**: Pre-conversion validation of graph structure and operation compatibility
256+
2. **Conversion Errors**: Graceful handling of unsupported operations with fallback comments
257+
3. **Type Errors**: Clear error messages for type incompatibilities
258+
4. **MLIR Syntax Errors**: Post-generation validation with detailed error reporting
259+
260+
### Error Categories
261+
262+
```kotlin
263+
public sealed class StableHloError {
264+
public data class UnsupportedOperation(
265+
val operationName: String,
266+
val nodeId: String,
267+
val reason: String
268+
) : StableHloError()
269+
270+
public data class TypeMappingError(
271+
val sourceType: String,
272+
val context: String
273+
) : StableHloError()
274+
275+
public data class GraphValidationError(
276+
val message: String,
277+
val nodeId: String? = null
278+
) : StableHloError()
279+
280+
public data class MlirSyntaxError(
281+
val line: Int,
282+
val column: Int,
283+
val message: String
284+
) : StableHloError()
285+
}
286+
```
287+
288+
## Testing Strategy
289+
290+
### Unit Testing Approach
291+
292+
Unit tests will focus on:
293+
- Individual operation converters with known inputs and expected outputs
294+
- Type mapping functions with various SKaiNET types
295+
- Error handling with invalid inputs
296+
- MLIR syntax validation with malformed inputs
297+
298+
### Property-Based Testing Approach
299+
300+
Property-based tests will use **Kotest Property Testing** framework and will verify:
301+
- Universal properties across all supported operations
302+
- Type system correctness across random tensor specifications
303+
- SSA form preservation across random graph structures
304+
- Error handling consistency across various failure scenarios
305+
306+
Each property-based test will run a minimum of 100 iterations to ensure comprehensive coverage of the input space.
307+
308+
### Integration Testing
309+
310+
Integration tests will verify:
311+
- End-to-end conversion of complete neural network models
312+
- Compatibility with existing SKaiNET execution contexts
313+
- Performance characteristics of generated StableHLO code
314+
315+
### Test Data Generation
316+
317+
Smart generators will be implemented for:
318+
- Random but valid ComputeGraph instances
319+
- Tensor specifications with realistic shapes and types
320+
- Operation sequences that form valid neural network patterns
321+
- Edge cases like empty graphs, single-node graphs, and deeply nested structures
322+
323+
## Implementation Plan
324+
325+
The implementation will follow an incremental approach:
326+
327+
1. **Core Infrastructure**: Implement the converter framework and registry system
328+
2. **Basic Operations**: Extend support for all mathematical and linear algebra operations
329+
3. **Neural Network Operations**: Add support for convolutions, pooling, and activations
330+
4. **Shape Operations**: Implement reshape, broadcast, and dimension manipulation operations
331+
5. **Advanced Features**: Add optimization passes and validation systems
332+
6. **Integration**: Ensure compatibility with existing SKaiNET infrastructure
333+
334+
Each phase will include comprehensive testing and validation before proceeding to the next phase.

0 commit comments

Comments
 (0)