furiosa_visa_std/vector_engine/op/
mod.rs

1//! Vector Engine operation types and configurations.
2//!
3//! This module defines the operation types for the Vector Engine pipeline.
4//! Semantic implementations (operation functions) are in `op::semantics.rs`.
5
6mod arg_mode;
7mod has_alu;
8pub mod semantics;
9
10pub use arg_mode::{ArgMode, BinaryArgMode, TernaryArgMode, UnaryArgMode};
11pub use has_alu::HasAlu;
12pub use semantics::{HasBinaryOp, HasTernaryOp, HasUnaryOp};
13
14use std::fmt::{self, Display, Formatter};
15
16use super::alu::{FpMulAlu, RngdAlu};
17use furiosa_mapping_macro::primitive;
18
19// ============================================================================
20// Common traits
21// ============================================================================
22
23/// Common trait for Vector Engine operations.
24pub trait VeOperation {
25    /// Returns the argument mode for this operation.
26    fn arg_mode(&self) -> ArgMode;
27}
28
29// ============================================================================
30// Logic cluster
31// ============================================================================
32
33/// Logic cluster operations for i32 (internal, with mode).
34#[derive(Debug, Clone, Copy)]
35pub struct LogicOpI {
36    pub(crate) op: LogicBinaryOpI32,
37    pub(crate) arg_mode: BinaryArgMode,
38}
39
40impl LogicOpI {
41    /// Returns the ALU type for this operation.
42    pub fn alu(&self) -> RngdAlu {
43        self.op.alu()
44    }
45}
46
47impl VeOperation for LogicOpI {
48    fn arg_mode(&self) -> ArgMode {
49        ArgMode::Binary(self.arg_mode)
50    }
51}
52
53/// Logic cluster binary operations for i32 (user-facing, mode-free).
54#[primitive(op::LogicBinaryOpI32)]
55#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
56pub enum LogicBinaryOpI32 {
57    /// Bitwise AND operation.
58    BitAnd,
59    /// Bitwise OR operation.
60    BitOr,
61    /// Bitwise XOR operation.
62    BitXor,
63    /// Left shift operation.
64    LeftShift,
65    /// Logical right shift operation.
66    LogicRightShift,
67    /// Arithmetic right shift operation.
68    ArithRightShift,
69}
70
71impl Display for LogicBinaryOpI32 {
72    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
73        match self {
74            Self::BitAnd => write!(f, "LogicBinaryOpI32::BitAnd"),
75            Self::BitOr => write!(f, "LogicBinaryOpI32::BitOr"),
76            Self::BitXor => write!(f, "LogicBinaryOpI32::BitXor"),
77            Self::LeftShift => write!(f, "LogicBinaryOpI32::LeftShift"),
78            Self::LogicRightShift => write!(f, "LogicBinaryOpI32::LogicRightShift"),
79            Self::ArithRightShift => write!(f, "LogicBinaryOpI32::ArithRightShift"),
80        }
81    }
82}
83
84impl LogicBinaryOpI32 {
85    /// Converts to LogicOpI with default mode (Mode01).
86    pub fn into_logic_op(self) -> LogicOpI {
87        self.with_mode(BinaryArgMode::Mode01)
88    }
89
90    /// Converts to LogicOpI with the specified arg mode.
91    pub fn with_mode(self, mode: BinaryArgMode) -> LogicOpI {
92        LogicOpI {
93            op: self,
94            arg_mode: mode,
95        }
96    }
97
98    /// Returns the ALU type for this operation.
99    pub fn alu(&self) -> RngdAlu {
100        match self {
101            Self::BitAnd => RngdAlu::LogicAnd,
102            Self::BitOr => RngdAlu::LogicOr,
103            Self::BitXor => RngdAlu::LogicXor,
104            Self::LeftShift => RngdAlu::LogicLshift,
105            Self::LogicRightShift | Self::ArithRightShift => RngdAlu::LogicRshift,
106        }
107    }
108}
109
110/// Logic cluster operations for f32 (internal, with mode).
111#[derive(Debug, Clone, Copy)]
112pub struct LogicOpF {
113    pub(crate) op: LogicBinaryOpF32,
114    pub(crate) arg_mode: BinaryArgMode,
115}
116
117impl LogicOpF {
118    /// Returns the ALU type for this operation.
119    pub fn alu(&self) -> RngdAlu {
120        self.op.alu()
121    }
122}
123
124impl VeOperation for LogicOpF {
125    fn arg_mode(&self) -> ArgMode {
126        ArgMode::Binary(self.arg_mode)
127    }
128}
129
130/// Logic cluster binary operations for f32 (user-facing, mode-free).
131#[primitive(op::LogicBinaryOpF32)]
132#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
133pub enum LogicBinaryOpF32 {
134    /// Bitwise AND operation.
135    BitAnd,
136    /// Bitwise OR operation.
137    BitOr,
138    /// Bitwise XOR operation.
139    BitXor,
140}
141
142impl Display for LogicBinaryOpF32 {
143    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
144        match self {
145            Self::BitAnd => write!(f, "LogicBinaryOpF32::BitAnd"),
146            Self::BitOr => write!(f, "LogicBinaryOpF32::BitOr"),
147            Self::BitXor => write!(f, "LogicBinaryOpF32::BitXor"),
148        }
149    }
150}
151
152impl LogicBinaryOpF32 {
153    /// Converts to LogicOpF with default mode (Mode01).
154    pub fn into_logic_op(self) -> LogicOpF {
155        self.with_mode(BinaryArgMode::Mode01)
156    }
157
158    /// Converts to LogicOpF with the specified arg mode.
159    pub fn with_mode(self, mode: BinaryArgMode) -> LogicOpF {
160        LogicOpF {
161            op: self,
162            arg_mode: mode,
163        }
164    }
165
166    /// Returns the ALU type for this operation.
167    pub fn alu(&self) -> RngdAlu {
168        match self {
169            Self::BitAnd => RngdAlu::LogicAnd,
170            Self::BitOr => RngdAlu::LogicOr,
171            Self::BitXor => RngdAlu::LogicXor,
172        }
173    }
174}
175
176// ============================================================================
177// Fxp cluster
178// ============================================================================
179
180/// Fxp cluster operations (internal, with mode).
181#[derive(Debug, Clone, Copy)]
182pub struct FxpOp {
183    pub(crate) op: FxpBinaryOp,
184    pub(crate) arg_mode: BinaryArgMode,
185}
186
187impl FxpOp {
188    /// Returns the ALU type for this operation.
189    pub fn alu(&self) -> RngdAlu {
190        self.op.alu()
191    }
192}
193
194impl VeOperation for FxpOp {
195    fn arg_mode(&self) -> ArgMode {
196        ArgMode::Binary(self.arg_mode)
197    }
198}
199
200/// Fxp cluster binary operations (user-facing, mode-free).
201#[primitive(op::FxpBinaryOp)]
202#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
203pub enum FxpBinaryOp {
204    /// Fixed-point add (wrapping).
205    AddFxp,
206    /// Fixed-point add (saturating).
207    AddFxpSat,
208    /// Fixed-point subtract (wrapping).
209    SubFxp,
210    /// Fixed-point subtract (saturating).
211    SubFxpSat,
212    /// Left shift operation.
213    LeftShift,
214    /// Left shift (saturating).
215    LeftShiftSat,
216    /// Fixed-point multiply.
217    MulFxp,
218    /// Integer multiply.
219    MulInt,
220    /// Logical right shift.
221    LogicRightShift,
222    /// Arithmetic right shift.
223    ArithRightShift,
224    /// Arithmetic right shift with rounding.
225    ArithRightShiftRound,
226}
227
228impl Display for FxpBinaryOp {
229    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
230        match self {
231            Self::AddFxp => write!(f, "FxpBinaryOp::AddFxp"),
232            Self::AddFxpSat => write!(f, "FxpBinaryOp::AddFxpSat"),
233            Self::SubFxp => write!(f, "FxpBinaryOp::SubFxp"),
234            Self::SubFxpSat => write!(f, "FxpBinaryOp::SubFxpSat"),
235            Self::LeftShift => write!(f, "FxpBinaryOp::LeftShift"),
236            Self::LeftShiftSat => write!(f, "FxpBinaryOp::LeftShiftSat"),
237            Self::MulFxp => write!(f, "FxpBinaryOp::MulFxp"),
238            Self::MulInt => write!(f, "FxpBinaryOp::MulInt"),
239            Self::LogicRightShift => write!(f, "FxpBinaryOp::LogicRightShift"),
240            Self::ArithRightShift => write!(f, "FxpBinaryOp::ArithRightShift"),
241            Self::ArithRightShiftRound => write!(f, "FxpBinaryOp::ArithRightShiftRound"),
242        }
243    }
244}
245
246impl FxpBinaryOp {
247    /// Converts to FxpOp with default mode (Mode01).
248    pub fn into_fxp_op(self) -> FxpOp {
249        self.with_mode(BinaryArgMode::Mode01)
250    }
251
252    /// Converts to FxpOp with the specified arg mode.
253    pub fn with_mode(self, mode: BinaryArgMode) -> FxpOp {
254        FxpOp {
255            op: self,
256            arg_mode: mode,
257        }
258    }
259
260    /// Returns the ALU type for this operation.
261    pub fn alu(&self) -> RngdAlu {
262        match self {
263            Self::AddFxp | Self::AddFxpSat | Self::SubFxp | Self::SubFxpSat => RngdAlu::FxpAdd,
264            Self::LeftShift | Self::LeftShiftSat => RngdAlu::FxpLshift,
265            Self::MulFxp | Self::MulInt => RngdAlu::FxpMul,
266            Self::LogicRightShift | Self::ArithRightShift | Self::ArithRightShiftRound => RngdAlu::FxpRshift,
267        }
268    }
269}
270
271// ============================================================================
272// Fp cluster
273// ============================================================================
274
275/// Fp cluster operations (internal, with mode).
276#[derive(Debug, Clone)]
277pub enum FpOp {
278    /// Unary fp operation with op and mode.
279    UnaryOp {
280        /// The unary operation.
281        op: FpUnaryOp,
282        /// The argument mode.
283        mode: UnaryArgMode,
284    },
285    /// Binary fp operation with op and mode.
286    BinaryOp {
287        /// The binary operation.
288        op: FpBinaryOp,
289        /// The argument mode.
290        mode: BinaryArgMode,
291    },
292    /// Ternary fp operation with op and mode.
293    TernaryOp {
294        /// The ternary operation.
295        op: FpTernaryOp,
296        /// The argument mode.
297        mode: TernaryArgMode,
298    },
299}
300
301impl FpOp {
302    /// Returns the ALU type for this operation.
303    pub fn alu(&self) -> RngdAlu {
304        match self {
305            FpOp::UnaryOp { op, .. } => op.alu(),
306            FpOp::BinaryOp { op, .. } => op.alu(),
307            FpOp::TernaryOp { op, .. } => op.alu(),
308        }
309    }
310}
311
312impl VeOperation for FpOp {
313    fn arg_mode(&self) -> ArgMode {
314        match self {
315            FpOp::UnaryOp { mode, .. } => ArgMode::Unary(*mode),
316            FpOp::BinaryOp { mode, .. } => ArgMode::Binary(*mode),
317            FpOp::TernaryOp { mode, .. } => ArgMode::Ternary(*mode),
318        }
319    }
320}
321
322/// Fp unary operations (user-facing, mode-free).
323#[primitive(op::FpUnaryOp)]
324#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
325pub enum FpUnaryOp {
326    /// Exponential function (e^x).
327    Exp,
328    /// Negative exponential function (e^(-x)).
329    NegExp,
330    /// Square root.
331    Sqrt,
332    /// Hyperbolic tangent.
333    Tanh,
334    /// Sigmoid function.
335    Sigmoid,
336    /// Error function.
337    Erf,
338    /// Natural logarithm.
339    Log,
340    /// Sine function.
341    Sin,
342    /// Cosine function.
343    Cos,
344}
345
346impl Display for FpUnaryOp {
347    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
348        match self {
349            Self::Exp => write!(f, "FpUnaryOp::Exp"),
350            Self::NegExp => write!(f, "FpUnaryOp::NegExp"),
351            Self::Sqrt => write!(f, "FpUnaryOp::Sqrt"),
352            Self::Tanh => write!(f, "FpUnaryOp::Tanh"),
353            Self::Sigmoid => write!(f, "FpUnaryOp::Sigmoid"),
354            Self::Erf => write!(f, "FpUnaryOp::Erf"),
355            Self::Log => write!(f, "FpUnaryOp::Log"),
356            Self::Sin => write!(f, "FpUnaryOp::Sin"),
357            Self::Cos => write!(f, "FpUnaryOp::Cos"),
358        }
359    }
360}
361
362impl FpUnaryOp {
363    /// Converts to FpOp with default mode (Mode0).
364    pub fn into_fp_op(self) -> FpOp {
365        self.with_mode(UnaryArgMode::Mode0)
366    }
367
368    /// Converts to FpOp with the specified arg mode.
369    pub fn with_mode(self, mode: UnaryArgMode) -> FpOp {
370        FpOp::UnaryOp { op: self, mode }
371    }
372
373    /// Returns the ALU type for this operation.
374    pub fn alu(&self) -> RngdAlu {
375        match self {
376            Self::Exp | Self::NegExp => RngdAlu::FpExp,
377            _ => RngdAlu::FpFpu,
378        }
379    }
380}
381
382/// Fp binary operations (user-facing, mode-free).
383#[primitive(op::FpBinaryOp)]
384#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
385pub enum FpBinaryOp {
386    /// Floating-point addition.
387    AddF,
388    /// Floating-point subtraction.
389    SubF,
390    /// Floating-point multiplication.
391    MulF(FpMulAlu),
392    /// Masked floating-point multiplication.
393    MaskMulF(FpMulAlu),
394    /// Floating-point division.
395    DivF,
396}
397
398impl FpBinaryOp {
399    /// Converts to FpOp with default mode (Mode01).
400    pub fn into_fp_op(self) -> FpOp {
401        self.with_mode(BinaryArgMode::Mode01)
402    }
403
404    /// Converts to FpOp with the specified arg mode.
405    pub fn with_mode(self, mode: BinaryArgMode) -> FpOp {
406        FpOp::BinaryOp { op: self, mode }
407    }
408
409    /// Returns the ALU type for this operation.
410    pub fn alu(&self) -> RngdAlu {
411        match self {
412            Self::AddF | Self::SubF => RngdAlu::FpFma,
413            Self::MulF(alu) | Self::MaskMulF(alu) => alu.to_alu(),
414            Self::DivF => RngdAlu::FpFpu,
415        }
416    }
417}
418
419/// Fp ternary operations (user-facing, mode-free).
420#[primitive(op::FpTernaryOp)]
421#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
422pub enum FpTernaryOp {
423    /// Fused multiply-add: a * b + c.
424    FmaF,
425    /// Masked fused multiply-add.
426    MaskFmaF,
427}
428
429impl Display for FpTernaryOp {
430    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
431        match self {
432            Self::FmaF => write!(f, "FpTernaryOp::FmaF"),
433            Self::MaskFmaF => write!(f, "FpTernaryOp::MaskFmaF"),
434        }
435    }
436}
437
438impl FpTernaryOp {
439    /// Converts to FpOp with default mode (Mode012).
440    pub fn into_fp_op(self) -> FpOp {
441        self.with_mode(TernaryArgMode::Mode012)
442    }
443
444    /// Converts to FpOp with the specified arg mode.
445    pub fn with_mode(self, mode: TernaryArgMode) -> FpOp {
446        FpOp::TernaryOp { op: self, mode }
447    }
448
449    /// Returns the ALU type for this operation.
450    pub fn alu(&self) -> RngdAlu {
451        RngdAlu::FpFma
452    }
453}
454
455// ============================================================================
456// Intra-Slice Reduce
457// ============================================================================
458
459/// Intra-Slice Reduce operations for i32.
460#[primitive(op::IntraSliceReduceOpI32)]
461#[derive(Debug, Clone, Copy)]
462pub enum IntraSliceReduceOpI32 {
463    /// Saturating addition reduction.
464    AddSat,
465    /// Maximum value reduction.
466    Max,
467    /// Minimum value reduction.
468    Min,
469}
470
471impl IntraSliceReduceOpI32 {
472    /// Returns the ALU type for this operation.
473    pub fn alu(&self) -> RngdAlu {
474        RngdAlu::ReduceAccTree
475    }
476}
477
478/// Intra-Slice Reduce operations for f32.
479#[primitive(op::IntraSliceReduceOpF32)]
480#[derive(Debug, Clone, Copy)]
481pub enum IntraSliceReduceOpF32 {
482    /// Floating-point addition reduction.
483    Add,
484    /// Maximum value reduction.
485    Max,
486    /// Minimum value reduction.
487    Min,
488}
489
490impl IntraSliceReduceOpF32 {
491    /// Returns the ALU type for this operation.
492    pub fn alu(&self) -> RngdAlu {
493        RngdAlu::ReduceAccTree
494    }
495}
496
497// ============================================================================
498// Inter-Slice Reduce (VRU)
499// ============================================================================
500
501/// Inter-slice reduce operations for i32 (VRU).
502#[primitive(op::InterSliceReduceOpI32)]
503#[derive(Debug, Clone, Copy)]
504pub enum InterSliceReduceOpI32 {
505    /// Addition reduction.
506    Add,
507    /// Saturating addition reduction.
508    AddSat,
509    /// Maximum value reduction.
510    Max,
511    /// Minimum value reduction.
512    Min,
513}
514
515/// Inter-slice reduce operations for f32 (VRU).
516#[primitive(op::InterSliceReduceOpF32)]
517#[derive(Debug, Clone, Copy)]
518pub enum InterSliceReduceOpF32 {
519    /// Floating-point addition reduction.
520    Add,
521    /// Maximum value reduction.
522    Max,
523    /// Minimum value reduction.
524    Min,
525    /// Floating-point multiplication reduction.
526    Mul,
527}
528
529// ============================================================================
530// FpDiv
531// ============================================================================
532
533/// Floating Point Division operation (internal, with mode).
534#[primitive(op::FpDivOp)]
535#[derive(Debug, Clone, Copy)]
536pub struct FpDivOp {
537    pub(crate) op: FpDivBinaryOp,
538    pub(crate) mode: BinaryArgMode,
539}
540
541impl FpDivOp {
542    /// Returns the ALU type for this operation.
543    pub fn alu(&self) -> RngdAlu {
544        self.op.alu()
545    }
546}
547
548impl VeOperation for FpDivOp {
549    fn arg_mode(&self) -> ArgMode {
550        ArgMode::Binary(self.mode)
551    }
552}
553
554/// FpDiv binary operations (user-facing, mode-free).
555#[primitive(op::FpDivBinaryOp)]
556#[derive(Debug, Clone, Copy)]
557pub enum FpDivBinaryOp {
558    /// Floating-point division.
559    DivF,
560}
561
562impl Display for FpDivBinaryOp {
563    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
564        match self {
565            Self::DivF => write!(f, "FpDivBinaryOp::DivF"),
566        }
567    }
568}
569
570impl FpDivBinaryOp {
571    /// Converts to FpDivOp with the specified arg mode.
572    #[primitive(op::FpDivBinaryOp::with_mode)]
573    pub fn with_mode(self, mode: BinaryArgMode) -> FpDivOp {
574        FpDivOp { op: self, mode }
575    }
576
577    /// Returns the ALU type for this operation.
578    pub fn alu(&self) -> RngdAlu {
579        RngdAlu::ReduceFpDiv
580    }
581}
582
583// ============================================================================
584// Clip cluster
585// ============================================================================
586
587/// Clip cluster operations for i32 (internal, with mode).
588#[derive(Debug, Clone, Copy)]
589pub struct ClipOpI {
590    pub(crate) op: ClipBinaryOpI32,
591    pub(crate) mode: BinaryArgMode,
592}
593
594impl ClipOpI {
595    /// Returns the ALU type for this operation.
596    pub fn alu(&self) -> RngdAlu {
597        self.op.alu()
598    }
599}
600
601impl VeOperation for ClipOpI {
602    fn arg_mode(&self) -> ArgMode {
603        ArgMode::Binary(self.mode)
604    }
605}
606
607/// Clip binary operations for i32 (user-facing, mode-free).
608#[primitive(op::ClipBinaryOpI32)]
609#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
610pub enum ClipBinaryOpI32 {
611    /// Minimum value.
612    Min,
613    /// Maximum value.
614    Max,
615    /// Absolute minimum value.
616    AbsMin,
617    /// Absolute maximum value.
618    AbsMax,
619    /// Fixed-point add (wrapping).
620    AddFxp,
621    /// Fixed-point add (saturating).
622    AddFxpSat,
623}
624
625impl Display for ClipBinaryOpI32 {
626    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
627        match self {
628            Self::Min => write!(f, "ClipBinaryOpI32::Min"),
629            Self::Max => write!(f, "ClipBinaryOpI32::Max"),
630            Self::AbsMin => write!(f, "ClipBinaryOpI32::AbsMin"),
631            Self::AbsMax => write!(f, "ClipBinaryOpI32::AbsMax"),
632            Self::AddFxp => write!(f, "ClipBinaryOpI32::AddFxp"),
633            Self::AddFxpSat => write!(f, "ClipBinaryOpI32::AddFxpSat"),
634        }
635    }
636}
637
638impl ClipBinaryOpI32 {
639    /// Converts to ClipOpI with default mode (Mode01).
640    pub fn into_clip_op(self) -> ClipOpI {
641        self.with_mode(BinaryArgMode::Mode01)
642    }
643
644    /// Converts to ClipOpI with the specified arg mode.
645    pub fn with_mode(self, mode: BinaryArgMode) -> ClipOpI {
646        ClipOpI { op: self, mode }
647    }
648
649    /// Returns the ALU type for this operation.
650    pub fn alu(&self) -> RngdAlu {
651        match self {
652            Self::AddFxp | Self::AddFxpSat => RngdAlu::ClipAdd,
653            Self::Max | Self::AbsMax => RngdAlu::ClipMax,
654            Self::Min | Self::AbsMin => RngdAlu::ClipMin,
655        }
656    }
657}
658
659/// Clip cluster operations for f32 (internal, with mode).
660#[derive(Debug, Clone, Copy)]
661pub struct ClipOpF {
662    pub(crate) op: ClipBinaryOpF32,
663    pub(crate) mode: BinaryArgMode,
664}
665
666impl ClipOpF {
667    /// Returns the ALU type for this operation.
668    pub fn alu(&self) -> RngdAlu {
669        self.op.alu()
670    }
671}
672
673impl VeOperation for ClipOpF {
674    fn arg_mode(&self) -> ArgMode {
675        ArgMode::Binary(self.mode)
676    }
677}
678
679/// Clip binary operations for f32 (user-facing, mode-free).
680#[primitive(op::ClipBinaryOpF32)]
681#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
682pub enum ClipBinaryOpF32 {
683    /// Minimum value.
684    Min,
685    /// Maximum value.
686    Max,
687    /// Absolute minimum value.
688    AbsMin,
689    /// Absolute maximum value.
690    AbsMax,
691    /// Floating-point addition.
692    Add,
693}
694
695impl Display for ClipBinaryOpF32 {
696    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
697        match self {
698            Self::Min => write!(f, "ClipBinaryOpF32::Min"),
699            Self::Max => write!(f, "ClipBinaryOpF32::Max"),
700            Self::AbsMin => write!(f, "ClipBinaryOpF32::AbsMin"),
701            Self::AbsMax => write!(f, "ClipBinaryOpF32::AbsMax"),
702            Self::Add => write!(f, "ClipBinaryOpF32::Add"),
703        }
704    }
705}
706
707impl ClipBinaryOpF32 {
708    /// Converts to ClipOpF with default mode (Mode01).
709    pub fn into_clip_op(self) -> ClipOpF {
710        self.with_mode(BinaryArgMode::Mode01)
711    }
712
713    /// Converts to ClipOpF with the specified arg mode.
714    pub fn with_mode(self, mode: BinaryArgMode) -> ClipOpF {
715        ClipOpF { op: self, mode }
716    }
717
718    /// Returns the ALU type for this operation.
719    pub fn alu(&self) -> RngdAlu {
720        match self {
721            Self::Add => RngdAlu::ClipAdd,
722            Self::Max | Self::AbsMax => RngdAlu::ClipMax,
723            Self::Min | Self::AbsMin => RngdAlu::ClipMin,
724        }
725    }
726}
727
728// ============================================================================
729// Unified VeOp enum
730// ============================================================================
731
732/// Vector Engine operations (unified enum for runtime storage).
733#[derive(Debug, Clone)]
734pub enum VeOp {
735    /// Logic operations (integer)
736    LogicOpI(LogicOpI),
737    /// Logic operations (fp)
738    LogicOpF(LogicOpF),
739    /// Fxp operations
740    FxpOp(FxpOp),
741    /// Fp operations
742    FpOp(FpOp),
743    /// Intra-Slice Reduce operations (integer)
744    IntraSliceReduceOpI32(IntraSliceReduceOpI32),
745    /// Intra-Slice Reduce operations (fp)
746    IntraSliceReduceOpF32(IntraSliceReduceOpF32),
747    /// Fp Division operation
748    FpDivOp(FpDivOp),
749    /// Clip operations (integer)
750    ClipOpI(ClipOpI),
751    /// Clip operations (fp)
752    ClipOpF(ClipOpF),
753}
754
755impl VeOp {
756    /// Returns the ALU type for this operation.
757    pub fn alu(&self) -> RngdAlu {
758        match self {
759            VeOp::LogicOpI(op) => op.alu(),
760            VeOp::LogicOpF(op) => op.alu(),
761            VeOp::FxpOp(op) => op.alu(),
762            VeOp::FpOp(op) => op.alu(),
763            VeOp::IntraSliceReduceOpI32(op) => op.alu(),
764            VeOp::IntraSliceReduceOpF32(op) => op.alu(),
765            VeOp::FpDivOp(op) => op.alu(),
766            VeOp::ClipOpI(op) => op.alu(),
767            VeOp::ClipOpF(op) => op.alu(),
768        }
769    }
770}
771
772impl VeOperation for VeOp {
773    fn arg_mode(&self) -> ArgMode {
774        match self {
775            VeOp::LogicOpI(op) => op.arg_mode(),
776            VeOp::LogicOpF(op) => op.arg_mode(),
777            VeOp::FxpOp(op) => op.arg_mode(),
778            VeOp::FpOp(op) => op.arg_mode(),
779            VeOp::IntraSliceReduceOpI32(_) | VeOp::IntraSliceReduceOpF32(_) => ArgMode::Unary(UnaryArgMode::Mode0),
780            VeOp::FpDivOp(op) => op.arg_mode(),
781            VeOp::ClipOpI(op) => op.arg_mode(),
782            VeOp::ClipOpF(op) => op.arg_mode(),
783        }
784    }
785}