mod arg_mode;
mod has_alu;
pub mod semantics;
pub use arg_mode::{ArgMode, BinaryArgMode, TernaryArgMode};
pub use has_alu::HasAlu;
pub use semantics::{HasBinaryOp, HasTernaryOp, HasUnaryOp};
use std::fmt::{self, Display, Formatter};
use super::alu::{FpMulAlu, RngdAlu};
use furiosa_opt_macro::primitive;
pub trait VeOperation {
fn arg_mode(&self) -> ArgMode;
}
#[derive(Debug, Clone, Copy)]
pub struct LogicOpI {
pub(crate) op: LogicBinaryOpI32,
pub(crate) arg_mode: BinaryArgMode,
}
impl LogicOpI {
pub fn alu(&self) -> RngdAlu {
self.op.alu()
}
}
impl VeOperation for LogicOpI {
fn arg_mode(&self) -> ArgMode {
ArgMode::Binary(self.arg_mode)
}
}
#[primitive(op::LogicBinaryOpI32)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum LogicBinaryOpI32 {
BitAnd,
BitOr,
BitXor,
LeftShift,
LogicRightShift,
ArithRightShift,
}
impl Display for LogicBinaryOpI32 {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
Self::BitAnd => write!(f, "LogicBinaryOpI32::BitAnd"),
Self::BitOr => write!(f, "LogicBinaryOpI32::BitOr"),
Self::BitXor => write!(f, "LogicBinaryOpI32::BitXor"),
Self::LeftShift => write!(f, "LogicBinaryOpI32::LeftShift"),
Self::LogicRightShift => write!(f, "LogicBinaryOpI32::LogicRightShift"),
Self::ArithRightShift => write!(f, "LogicBinaryOpI32::ArithRightShift"),
}
}
}
impl LogicBinaryOpI32 {
pub fn into_logic_op(self) -> LogicOpI {
self.with_mode(BinaryArgMode::Mode01)
}
pub fn with_mode(self, mode: BinaryArgMode) -> LogicOpI {
LogicOpI {
op: self,
arg_mode: mode,
}
}
pub fn alu(&self) -> RngdAlu {
match self {
Self::BitAnd => RngdAlu::LogicAnd,
Self::BitOr => RngdAlu::LogicOr,
Self::BitXor => RngdAlu::LogicXor,
Self::LeftShift => RngdAlu::LogicLshift,
Self::LogicRightShift | Self::ArithRightShift => RngdAlu::LogicRshift,
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct LogicOpF {
pub(crate) op: LogicBinaryOpF32,
pub(crate) arg_mode: BinaryArgMode,
}
impl LogicOpF {
pub fn alu(&self) -> RngdAlu {
self.op.alu()
}
}
impl VeOperation for LogicOpF {
fn arg_mode(&self) -> ArgMode {
ArgMode::Binary(self.arg_mode)
}
}
#[primitive(op::LogicBinaryOpF32)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum LogicBinaryOpF32 {
BitAnd,
BitOr,
BitXor,
}
impl Display for LogicBinaryOpF32 {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
Self::BitAnd => write!(f, "LogicBinaryOpF32::BitAnd"),
Self::BitOr => write!(f, "LogicBinaryOpF32::BitOr"),
Self::BitXor => write!(f, "LogicBinaryOpF32::BitXor"),
}
}
}
impl LogicBinaryOpF32 {
pub fn into_logic_op(self) -> LogicOpF {
self.with_mode(BinaryArgMode::Mode01)
}
pub fn with_mode(self, mode: BinaryArgMode) -> LogicOpF {
LogicOpF {
op: self,
arg_mode: mode,
}
}
pub fn alu(&self) -> RngdAlu {
match self {
Self::BitAnd => RngdAlu::LogicAnd,
Self::BitOr => RngdAlu::LogicOr,
Self::BitXor => RngdAlu::LogicXor,
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct FxpOp {
pub(crate) op: FxpBinaryOp,
pub(crate) arg_mode: BinaryArgMode,
}
impl FxpOp {
pub fn alu(&self) -> RngdAlu {
self.op.alu()
}
}
impl VeOperation for FxpOp {
fn arg_mode(&self) -> ArgMode {
ArgMode::Binary(self.arg_mode)
}
}
#[primitive(op::FxpBinaryOp)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum FxpBinaryOp {
AddFxp,
AddFxpSat,
SubFxp,
SubFxpSat,
LeftShift,
LeftShiftSat,
MulFxp,
MulInt,
LogicRightShift,
ArithRightShift,
ArithRightShiftRound,
}
impl Display for FxpBinaryOp {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
Self::AddFxp => write!(f, "FxpBinaryOp::AddFxp"),
Self::AddFxpSat => write!(f, "FxpBinaryOp::AddFxpSat"),
Self::SubFxp => write!(f, "FxpBinaryOp::SubFxp"),
Self::SubFxpSat => write!(f, "FxpBinaryOp::SubFxpSat"),
Self::LeftShift => write!(f, "FxpBinaryOp::LeftShift"),
Self::LeftShiftSat => write!(f, "FxpBinaryOp::LeftShiftSat"),
Self::MulFxp => write!(f, "FxpBinaryOp::MulFxp"),
Self::MulInt => write!(f, "FxpBinaryOp::MulInt"),
Self::LogicRightShift => write!(f, "FxpBinaryOp::LogicRightShift"),
Self::ArithRightShift => write!(f, "FxpBinaryOp::ArithRightShift"),
Self::ArithRightShiftRound => write!(f, "FxpBinaryOp::ArithRightShiftRound"),
}
}
}
impl FxpBinaryOp {
pub fn into_fxp_op(self) -> FxpOp {
self.with_mode(BinaryArgMode::Mode01)
}
pub fn with_mode(self, mode: BinaryArgMode) -> FxpOp {
FxpOp {
op: self,
arg_mode: mode,
}
}
pub fn alu(&self) -> RngdAlu {
match self {
Self::AddFxp | Self::AddFxpSat | Self::SubFxp | Self::SubFxpSat => RngdAlu::FxpAdd,
Self::LeftShift | Self::LeftShiftSat => RngdAlu::FxpLshift,
Self::MulFxp | Self::MulInt => RngdAlu::FxpMul,
Self::LogicRightShift | Self::ArithRightShift | Self::ArithRightShiftRound => RngdAlu::FxpRshift,
}
}
}
#[derive(Debug, Clone)]
pub enum FpOp {
UnaryOp {
op: FpUnaryOp,
},
BinaryOp {
op: FpBinaryOp,
mode: BinaryArgMode,
},
TernaryOp {
op: FpTernaryOp,
mode: TernaryArgMode,
},
}
impl FpOp {
pub fn alu(&self) -> RngdAlu {
match self {
FpOp::UnaryOp { op, .. } => op.alu(),
FpOp::BinaryOp { op, .. } => op.alu(),
FpOp::TernaryOp { op, .. } => op.alu(),
}
}
}
impl VeOperation for FpOp {
fn arg_mode(&self) -> ArgMode {
match self {
FpOp::UnaryOp { .. } => ArgMode::Unary,
FpOp::BinaryOp { mode, .. } => ArgMode::Binary(*mode),
FpOp::TernaryOp { mode, .. } => ArgMode::Ternary(*mode),
}
}
}
#[primitive(op::FpUnaryOp)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum FpUnaryOp {
Exp,
NegExp,
Sqrt,
Tanh,
Sigmoid,
Erf,
Log,
Sin,
Cos,
}
impl Display for FpUnaryOp {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
Self::Exp => write!(f, "FpUnaryOp::Exp"),
Self::NegExp => write!(f, "FpUnaryOp::NegExp"),
Self::Sqrt => write!(f, "FpUnaryOp::Sqrt"),
Self::Tanh => write!(f, "FpUnaryOp::Tanh"),
Self::Sigmoid => write!(f, "FpUnaryOp::Sigmoid"),
Self::Erf => write!(f, "FpUnaryOp::Erf"),
Self::Log => write!(f, "FpUnaryOp::Log"),
Self::Sin => write!(f, "FpUnaryOp::Sin"),
Self::Cos => write!(f, "FpUnaryOp::Cos"),
}
}
}
impl FpUnaryOp {
pub fn into_fp_op(self) -> FpOp {
FpOp::UnaryOp { op: self }
}
pub fn alu(&self) -> RngdAlu {
match self {
Self::Exp | Self::NegExp => RngdAlu::FpExp,
_ => RngdAlu::FpFpu,
}
}
}
#[primitive(op::FpBinaryOp)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum FpBinaryOp {
AddF,
SubF,
MulF(FpMulAlu),
MaskMulF(FpMulAlu),
DivF,
}
impl FpBinaryOp {
pub fn into_fp_op(self) -> FpOp {
self.with_mode(BinaryArgMode::Mode01)
}
pub fn with_mode(self, mode: BinaryArgMode) -> FpOp {
FpOp::BinaryOp { op: self, mode }
}
pub fn alu(&self) -> RngdAlu {
match self {
Self::AddF | Self::SubF => RngdAlu::FpFma,
Self::MulF(alu) | Self::MaskMulF(alu) => alu.to_alu(),
Self::DivF => RngdAlu::FpFpu,
}
}
}
#[primitive(op::FpTernaryOp)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum FpTernaryOp {
FmaF,
MaskFmaF,
}
impl Display for FpTernaryOp {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
Self::FmaF => write!(f, "FpTernaryOp::FmaF"),
Self::MaskFmaF => write!(f, "FpTernaryOp::MaskFmaF"),
}
}
}
impl FpTernaryOp {
pub fn into_fp_op(self) -> FpOp {
self.with_mode(TernaryArgMode::Mode012)
}
pub fn with_mode(self, mode: TernaryArgMode) -> FpOp {
FpOp::TernaryOp { op: self, mode }
}
pub fn alu(&self) -> RngdAlu {
RngdAlu::FpFma
}
}
#[primitive(op::IntraSliceReduceOpI32)]
#[derive(Debug, Clone, Copy)]
pub enum IntraSliceReduceOpI32 {
AddSat,
Max,
Min,
}
impl IntraSliceReduceOpI32 {
pub fn alu(&self) -> RngdAlu {
RngdAlu::ReduceAccTree
}
}
#[primitive(op::IntraSliceReduceOpF32)]
#[derive(Debug, Clone, Copy)]
pub enum IntraSliceReduceOpF32 {
Add,
Max,
Min,
}
impl IntraSliceReduceOpF32 {
pub fn alu(&self) -> RngdAlu {
RngdAlu::ReduceAccTree
}
}
#[primitive(op::InterSliceReduceOpI32)]
#[derive(Debug, Clone, Copy)]
pub enum InterSliceReduceOpI32 {
Add,
AddSat,
Max,
Min,
}
#[primitive(op::InterSliceReduceOpF32)]
#[derive(Debug, Clone, Copy)]
pub enum InterSliceReduceOpF32 {
Add,
Max,
Min,
Mul,
}
#[primitive(op::FpDivOp)]
#[derive(Debug, Clone, Copy)]
pub struct FpDivOp {
pub(crate) op: FpDivBinaryOp,
pub(crate) mode: BinaryArgMode,
}
impl FpDivOp {
pub fn alu(&self) -> RngdAlu {
self.op.alu()
}
}
impl VeOperation for FpDivOp {
fn arg_mode(&self) -> ArgMode {
ArgMode::Binary(self.mode)
}
}
#[primitive(op::FpDivBinaryOp)]
#[derive(Debug, Clone, Copy)]
pub enum FpDivBinaryOp {
DivF,
}
impl Display for FpDivBinaryOp {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
Self::DivF => write!(f, "FpDivBinaryOp::DivF"),
}
}
}
impl FpDivBinaryOp {
#[primitive(op::FpDivBinaryOp::with_mode)]
pub fn with_mode(self, mode: BinaryArgMode) -> FpDivOp {
FpDivOp { op: self, mode }
}
pub fn alu(&self) -> RngdAlu {
RngdAlu::ReduceFpDiv
}
}
#[derive(Debug, Clone, Copy)]
pub struct ClipOpI {
pub(crate) op: ClipBinaryOpI32,
pub(crate) mode: BinaryArgMode,
}
impl ClipOpI {
pub fn alu(&self) -> RngdAlu {
self.op.alu()
}
}
impl VeOperation for ClipOpI {
fn arg_mode(&self) -> ArgMode {
ArgMode::Binary(self.mode)
}
}
#[primitive(op::ClipBinaryOpI32)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ClipBinaryOpI32 {
Min,
Max,
AbsMin,
AbsMax,
AddFxp,
AddFxpSat,
}
impl Display for ClipBinaryOpI32 {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
Self::Min => write!(f, "ClipBinaryOpI32::Min"),
Self::Max => write!(f, "ClipBinaryOpI32::Max"),
Self::AbsMin => write!(f, "ClipBinaryOpI32::AbsMin"),
Self::AbsMax => write!(f, "ClipBinaryOpI32::AbsMax"),
Self::AddFxp => write!(f, "ClipBinaryOpI32::AddFxp"),
Self::AddFxpSat => write!(f, "ClipBinaryOpI32::AddFxpSat"),
}
}
}
impl ClipBinaryOpI32 {
pub fn into_clip_op(self) -> ClipOpI {
self.with_mode(BinaryArgMode::Mode01)
}
pub fn with_mode(self, mode: BinaryArgMode) -> ClipOpI {
ClipOpI { op: self, mode }
}
pub fn alu(&self) -> RngdAlu {
match self {
Self::AddFxp | Self::AddFxpSat => RngdAlu::ClipAdd,
Self::Max | Self::AbsMax => RngdAlu::ClipMax,
Self::Min | Self::AbsMin => RngdAlu::ClipMin,
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct ClipOpF {
pub(crate) op: ClipBinaryOpF32,
pub(crate) mode: BinaryArgMode,
}
impl ClipOpF {
pub fn alu(&self) -> RngdAlu {
self.op.alu()
}
}
impl VeOperation for ClipOpF {
fn arg_mode(&self) -> ArgMode {
ArgMode::Binary(self.mode)
}
}
#[primitive(op::ClipBinaryOpF32)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ClipBinaryOpF32 {
Min,
Max,
AbsMin,
AbsMax,
Add,
}
impl Display for ClipBinaryOpF32 {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
Self::Min => write!(f, "ClipBinaryOpF32::Min"),
Self::Max => write!(f, "ClipBinaryOpF32::Max"),
Self::AbsMin => write!(f, "ClipBinaryOpF32::AbsMin"),
Self::AbsMax => write!(f, "ClipBinaryOpF32::AbsMax"),
Self::Add => write!(f, "ClipBinaryOpF32::Add"),
}
}
}
impl ClipBinaryOpF32 {
pub fn into_clip_op(self) -> ClipOpF {
self.with_mode(BinaryArgMode::Mode01)
}
pub fn with_mode(self, mode: BinaryArgMode) -> ClipOpF {
ClipOpF { op: self, mode }
}
pub fn alu(&self) -> RngdAlu {
match self {
Self::Add => RngdAlu::ClipAdd,
Self::Max | Self::AbsMax => RngdAlu::ClipMax,
Self::Min | Self::AbsMin => RngdAlu::ClipMin,
}
}
}
#[derive(Debug, Clone)]
pub enum VeOp {
LogicOpI(LogicOpI),
LogicOpF(LogicOpF),
FxpOp(FxpOp),
FpOp(FpOp),
IntraSliceReduceOpI32(IntraSliceReduceOpI32),
IntraSliceReduceOpF32(IntraSliceReduceOpF32),
FpDivOp(FpDivOp),
ClipOpI(ClipOpI),
ClipOpF(ClipOpF),
}
impl VeOp {
pub fn alu(&self) -> RngdAlu {
match self {
VeOp::LogicOpI(op) => op.alu(),
VeOp::LogicOpF(op) => op.alu(),
VeOp::FxpOp(op) => op.alu(),
VeOp::FpOp(op) => op.alu(),
VeOp::IntraSliceReduceOpI32(op) => op.alu(),
VeOp::IntraSliceReduceOpF32(op) => op.alu(),
VeOp::FpDivOp(op) => op.alu(),
VeOp::ClipOpI(op) => op.alu(),
VeOp::ClipOpF(op) => op.alu(),
}
}
}
impl VeOperation for VeOp {
fn arg_mode(&self) -> ArgMode {
match self {
VeOp::LogicOpI(op) => op.arg_mode(),
VeOp::LogicOpF(op) => op.arg_mode(),
VeOp::FxpOp(op) => op.arg_mode(),
VeOp::FpOp(op) => op.arg_mode(),
VeOp::IntraSliceReduceOpI32(_) | VeOp::IntraSliceReduceOpF32(_) => ArgMode::Unary,
VeOp::FpDivOp(op) => op.arg_mode(),
VeOp::ClipOpI(op) => op.arg_mode(),
VeOp::ClipOpF(op) => op.arg_mode(),
}
}
}