use std::marker::PhantomData;
use furiosa_mapping::*;
use furiosa_opt_macro::primitive;
use super::VeTensorShape;
use super::VectorFinalTensor;
use crate::array_vec::ArrayVec;
use crate::backend::Backend;
use crate::context::*;
use crate::engine::vector::MAX_TAGS;
use crate::engine::vector::alu::RngdAlu;
use crate::engine::vector::branch::{TagMode, apply_branch_config};
use crate::engine::vector::layer::{FpToFxp, FxpToFp};
use crate::engine::vector::op::semantics::{HasBinaryOp, HasTernaryOp, HasUnaryOp};
use crate::engine::vector::op::{
BinaryArgMode, ClipBinaryOpF32, ClipBinaryOpI32, FpBinaryOp, FpDivBinaryOp, FpTernaryOp, FpUnaryOp, FxpBinaryOp,
HasAlu, InterSliceReduceOpF32, InterSliceReduceOpI32, IntraSliceReduceOpF32, IntraSliceReduceOpI32,
LogicBinaryOpF32, LogicBinaryOpI32, TernaryArgMode,
};
use crate::engine::vector::operand::OperandTag;
use crate::prelude::TagFilter;
use crate::runtime::CurrentBackend;
use crate::scalar::Opt;
use crate::tensor::*;
use crate::engine::vector::operand::{
BinaryOperandTag, IntoOperands, IntoTernaryOperandTags, StashTransition, TernaryOperandTag, VeRhs,
};
use crate::engine::vector::scalar::VeScalar;
use crate::engine::vector::stage::markers as stage;
use crate::engine::vector::stage::markers::CanTransitionTo;
use crate::engine::vector::stage::markers::VeOrder;
use crate::engine::vector::stage::markers::Way::{self, Way4, Way8};
use crate::engine::vector::stage::state::VeState;
use crate::engine::vector::stash_slot::{Fresh, Occupied, StashSlot};
use crate::engine::vector::tensor::verify::{
verify_vector_narrow_split, verify_vector_narrow_trim, verify_vector_widen_concat, verify_vector_widen_pad,
};
use super::vector_tensor_pair::VectorTensorPair;
#[derive(Debug)]
pub struct VectorInitTensor<'l, const T: Tu, D: VeScalar, Chip: M, Cluster: M, Slice: M, Time: M, Packet: M> {
pub(crate) ctx: &'l mut TuContext<{ T }>,
pub(crate) inner: Tensor<D, VeTensorShape<Chip, Cluster, Slice, Time, Packet>>,
}
impl<'l, const T: Tu, D: VeScalar, Chip: M, Cluster: M, Slice: M, Time: M, Packet: M>
VectorInitTensor<'l, T, D, Chip, Cluster, Slice, Time, Packet>
{
pub fn new(
ctx: &'l mut TuContext<{ T }>,
inner: Tensor<D, VeTensorShape<Chip, Cluster, Slice, Time, Packet>>,
) -> Self {
Self { ctx, inner }
}
}
#[derive(Debug)]
pub struct VeTensorData<
S: stage::Stage,
D: VeScalar,
Chip: M,
Cluster: M,
Slice: M,
Time: M,
Packet: M,
StashD: VeScalar,
Stash: StashSlot<StashD>,
const VE_ORDER: VeOrder,
FS: stage::VeTensorContext = stage::Standalone,
const W: Way = { Way8 },
> {
pub(crate) inner: Tensor<D, VeTensorShape<Chip, Cluster, Slice, Time, Packet>>,
pub(crate) tag: Tensor<u8, VeTensorShape<Chip, Cluster, Slice, Time, Packet>>,
pub(crate) ve_state: VeState<StashD, Stash>,
pub(crate) _stage: PhantomData<S>,
pub(crate) _filter_state: PhantomData<FS>,
}
#[derive(Debug)]
pub struct VectorTensor<
'l,
const T: Tu,
S: stage::Stage,
D: VeScalar,
Chip: M,
Cluster: M,
Slice: M,
Time: M,
Packet: M,
StashD: VeScalar,
Stash: StashSlot<StashD>,
const VE_ORDER: VeOrder,
FS: stage::VeTensorContext = stage::Standalone,
const W: Way = { Way8 },
> {
pub(crate) ctx: &'l mut TuContext<{ T }>,
pub(crate) data: VeTensorData<S, D, Chip, Cluster, Slice, Time, Packet, StashD, Stash, VE_ORDER, FS, W>,
}
impl<
S: stage::Stage,
D: VeScalar,
Chip: M,
Cluster: M,
Slice: M,
Time: M,
Packet: M,
StashD: VeScalar,
Stash: StashSlot<StashD>,
FS: stage::VeTensorContext,
const W: Way,
const VE_ORDER: VeOrder,
> VeTensorData<S, D, Chip, Cluster, Slice, Time, Packet, StashD, Stash, VE_ORDER, FS, W>
{
pub fn ve_state_mut(&mut self) -> &mut VeState<StashD, Stash> {
&mut self.ve_state
}
pub fn ve_state(&self) -> &VeState<StashD, Stash> {
&self.ve_state
}
pub fn inner(&self) -> &Tensor<D, VeTensorShape<Chip, Cluster, Slice, Time, Packet>> {
&self.inner
}
pub fn tag(&self) -> &Tensor<u8, VeTensorShape<Chip, Cluster, Slice, Time, Packet>> {
&self.tag
}
pub fn into_parts(
self,
) -> (
Tensor<D, VeTensorShape<Chip, Cluster, Slice, Time, Packet>>,
Tensor<u8, VeTensorShape<Chip, Cluster, Slice, Time, Packet>>,
VeState<StashD, Stash>,
) {
(self.inner, self.tag, self.ve_state)
}
pub(crate) fn apply_binary<NextStage: stage::Stage, NextFS: stage::VeTensorContext>(
mut self,
alu: RngdAlu,
op_fn: impl Fn(D, D) -> D + Sync,
operands: &ArrayVec<BinaryOperandTag<D, VeTensorShape<Chip, Cluster, Slice, Time, Packet>>, MAX_TAGS>,
) -> VeTensorData<NextStage, D, Chip, Cluster, Slice, Time, Packet, StashD, Stash, VE_ORDER, NextFS, W> {
let uses_stash = operands.iter().any(|op| matches!(op.operand0, VeRhs::Stash));
let stash_data: Option<Tensor<D, VeTensorShape<Chip, Cluster, Slice, Time, Packet>>> = if uses_stash {
self.ve_state.force_clone_stash_as()
} else {
None
};
self.ve_state.use_alu(alu);
let result = apply_binary_op(&self.inner, &self.tag, op_fn, operands.as_slice(), stash_data.as_ref());
VeTensorData {
inner: result,
tag: self.tag,
ve_state: self.ve_state,
_stage: PhantomData,
_filter_state: PhantomData,
}
}
}
impl<
S: stage::Stage,
D: VeScalar,
Chip: M,
Cluster: M,
Slice: M,
Time: M,
Packet: M,
StashD: VeScalar,
Stash: StashSlot<StashD>,
FS: stage::VeTensorContext,
const W: Way,
const VE_ORDER: VeOrder,
> VeTensorData<S, D, Chip, Cluster, Slice, Time, Packet, StashD, Stash, VE_ORDER, FS, W>
{
pub(crate) fn apply_stash_transition<Op: StashTransition<StashD, Stash>>(
self,
) -> VeTensorData<S, D, Chip, Cluster, Slice, Time, Packet, StashD, Op::Next, VE_ORDER, FS, W> {
VeTensorData {
inner: self.inner,
tag: self.tag,
ve_state: Op::transition(self.ve_state),
_stage: PhantomData,
_filter_state: PhantomData,
}
}
}
impl<
'l,
const T: Tu,
S: stage::Stage,
D: VeScalar,
Chip: M,
Cluster: M,
Slice: M,
Time: M,
Packet: M,
StashD: VeScalar,
Stash: StashSlot<StashD>,
FS: stage::VeTensorContext,
const W: Way,
const VE_ORDER: VeOrder,
> VectorTensor<'l, T, S, D, Chip, Cluster, Slice, Time, Packet, StashD, Stash, VE_ORDER, FS, W>
{
pub fn into_parts(
self,
) -> (
&'l mut TuContext<{ T }>,
Tensor<D, VeTensorShape<Chip, Cluster, Slice, Time, Packet>>,
Tensor<u8, VeTensorShape<Chip, Cluster, Slice, Time, Packet>>,
VeState<StashD, Stash>,
) {
let (inner, tag, ve_state) = self.data.into_parts();
(self.ctx, inner, tag, ve_state)
}
pub fn into_ctx_and_data(
self,
) -> (
&'l mut TuContext<{ T }>,
VeTensorData<S, D, Chip, Cluster, Slice, Time, Packet, StashD, Stash, VE_ORDER, FS, W>,
) {
(self.ctx, self.data)
}
pub fn ve_state_mut(&mut self) -> &mut VeState<StashD, Stash> {
self.data.ve_state_mut()
}
pub fn ve_state(&self) -> &VeState<StashD, Stash> {
self.data.ve_state()
}
pub fn inner(&self) -> &Tensor<D, VeTensorShape<Chip, Cluster, Slice, Time, Packet>> {
self.data.inner()
}
pub fn tag(&self) -> &Tensor<u8, VeTensorShape<Chip, Cluster, Slice, Time, Packet>> {
self.data.tag()
}
pub fn data(&self) -> &VeTensorData<S, D, Chip, Cluster, Slice, Time, Packet, StashD, Stash, VE_ORDER, FS, W> {
&self.data
}
pub fn data_mut(
&mut self,
) -> &mut VeTensorData<S, D, Chip, Cluster, Slice, Time, Packet, StashD, Stash, VE_ORDER, FS, W> {
&mut self.data
}
pub fn from_parts(
ctx: &'l mut TuContext<{ T }>,
inner: Tensor<D, VeTensorShape<Chip, Cluster, Slice, Time, Packet>>,
tag: Tensor<u8, VeTensorShape<Chip, Cluster, Slice, Time, Packet>>,
ve_state: VeState<StashD, Stash>,
) -> Self {
Self {
ctx,
data: VeTensorData {
inner,
tag,
ve_state,
_stage: PhantomData,
_filter_state: PhantomData,
},
}
}
pub fn from_ctx_and_data(
ctx: &'l mut TuContext<{ T }>,
data: VeTensorData<S, D, Chip, Cluster, Slice, Time, Packet, StashD, Stash, VE_ORDER, FS, W>,
) -> Self {
Self { ctx, data }
}
pub(crate) fn do_binary<NextStage: stage::Stage, NextFS: stage::VeTensorContext>(
self,
op: impl HasAlu + HasBinaryOp<D>,
mode: Option<BinaryArgMode>,
operands: ArrayVec<BinaryOperandTag<D, VeTensorShape<Chip, Cluster, Slice, Time, Packet>>, MAX_TAGS>,
) -> VectorTensor<'l, T, NextStage, D, Chip, Cluster, Slice, Time, Packet, StashD, Stash, VE_ORDER, NextFS, W> {
let data = self.data.apply_binary(op.alu(), op.binary_op_fn(mode), &operands);
VectorTensor { ctx: self.ctx, data }
}
}
impl<
S: stage::Stashable,
D: VeScalar,
Chip: M,
Cluster: M,
Slice: M,
Time: M,
Packet: M,
const W: Way,
const VE_ORDER: VeOrder,
> VeTensorData<S, D, Chip, Cluster, Slice, Time, Packet, D, Fresh, VE_ORDER, stage::Standalone, W>
{
pub fn stash(
self,
) -> VeTensorData<
S,
D,
Chip,
Cluster,
Slice,
Time,
Packet,
D,
Occupied<D, VeTensorShape<Chip, Cluster, Slice, Time, Packet>>,
VE_ORDER,
stage::Standalone,
W,
> {
let new_ve_state = self.ve_state.stash(&self.inner);
VeTensorData {
inner: self.inner,
tag: self.tag,
ve_state: new_ve_state,
_stage: PhantomData,
_filter_state: PhantomData,
}
}
}
impl<
'l,
const T: Tu,
S: stage::Stashable,
D: VeScalar,
Chip: M,
Cluster: M,
Slice: M,
Time: M,
Packet: M,
const W: Way,
const VE_ORDER: VeOrder,
> VectorTensor<'l, T, S, D, Chip, Cluster, Slice, Time, Packet, D, Fresh, VE_ORDER, stage::Standalone, W>
{
#[primitive(VectorTensor::vector_stash)]
pub fn vector_stash(
self,
) -> VectorTensor<
'l,
T,
S,
D,
Chip,
Cluster,
Slice,
Time,
Packet,
D,
Occupied<D, VeTensorShape<Chip, Cluster, Slice, Time, Packet>>,
VE_ORDER,
stage::Standalone,
W,
> {
let new_ve_state = self.data.ve_state.stash(&self.data.inner);
VectorTensor {
ctx: self.ctx,
data: VeTensorData {
inner: self.data.inner,
tag: self.data.tag,
ve_state: new_ve_state,
_stage: PhantomData,
_filter_state: PhantomData,
},
}
}
}
impl<
'l,
const T: Tu,
S: stage::Stage,
D: VeScalar,
Chip: M,
Cluster: M,
Slice: M,
Time: M,
Packet: M,
StashD: VeScalar,
Stash: StashSlot<StashD>,
FS: stage::Commitable,
const VE_ORDER: VeOrder,
> VectorTensor<'l, T, S, D, Chip, Cluster, Slice, Time, Packet, StashD, Stash, VE_ORDER, FS, { Way8 }>
{
#[primitive(VectorTensor::vector_final)]
pub fn vector_final(self) -> VectorFinalTensor<'l, T, D, Chip, Cluster, Slice, Time, Packet> {
VectorFinalTensor::new(self.ctx, self.data.inner)
}
}
impl<
'l,
const T: Tu,
S: stage::IntraSliceStage + stage::CanTransitionTo<stage::InterSliceReduce>,
Chip: M,
Cluster: M,
Slice: M,
Time: M,
Packet: M,
StashD: VeScalar,
Stash: StashSlot<StashD>,
FS: stage::Commitable,
>
VectorTensor<
'l,
T,
S,
i32,
Chip,
Cluster,
Slice,
Time,
Packet,
StashD,
Stash,
{ VeOrder::IntraFirst },
FS,
{ Way8 },
>
{
#[primitive(VectorTensor::vector_inter_slice_reduce)]
pub fn vector_inter_slice_reduce<OutSlice: M, OutTime: M>(
self,
op: InterSliceReduceOpI32,
) -> VectorInterSliceReduceTensor<'l, T, i32, Chip, Cluster, OutSlice, OutTime, Packet, { VeOrder::IntraFirst }>
{
let reduced = self.data.inner.reduce(op.reduce_fn(), op.identity(), true);
create_inter_slice_reduce_tensor(self.ctx, reduced)
}
}
impl<
'l,
const T: Tu,
S: stage::IntraSliceStage + stage::CanTransitionTo<stage::InterSliceReduce>,
Chip: M,
Cluster: M,
Slice: M,
Time: M,
Packet: M,
StashD: VeScalar,
Stash: StashSlot<StashD>,
FS: stage::Commitable,
>
VectorTensor<
'l,
T,
S,
f32,
Chip,
Cluster,
Slice,
Time,
Packet,
StashD,
Stash,
{ VeOrder::IntraFirst },
FS,
{ Way8 },
>
{
#[primitive(VectorTensor::vector_inter_slice_reduce)]
pub fn vector_inter_slice_reduce<OutSlice: M, OutTime: M>(
self,
op: InterSliceReduceOpF32,
) -> VectorInterSliceReduceTensor<'l, T, f32, Chip, Cluster, OutSlice, OutTime, Packet, { VeOrder::IntraFirst }>
{
let reduced = self.data.inner.reduce(op.reduce_fn(), op.identity(), true);
create_inter_slice_reduce_tensor(self.ctx, reduced)
}
}
pub(crate) fn create_inter_slice_reduce_tensor<
'l,
const T: Tu,
D: VeScalar,
Chip: M,
Cluster: M,
Slice: M,
Time: M,
Packet: M,
const VE_ORDER: VeOrder,
>(
ctx: &'l mut TuContext<{ T }>,
inner: Tensor<D, VeTensorShape<Chip, Cluster, Slice, Time, Packet>>,
) -> VectorInterSliceReduceTensor<'l, T, D, Chip, Cluster, Slice, Time, Packet, VE_ORDER> {
VectorTensor {
ctx,
data: VeTensorData {
inner,
tag: Tensor::uninit(),
ve_state: VeState::new(),
_stage: PhantomData,
_filter_state: PhantomData,
},
}
}
impl<'l, const T: Tu, D: VeScalar, Chip: M, Cluster: M, Slice: M, Time: M, Packet: M>
VectorInitTensor<'l, T, D, Chip, Cluster, Slice, Time, Packet>
{
#[primitive(VectorInitTensor::vector_intra_slice_tag)]
pub fn vector_intra_slice_tag(
self,
branch: TagMode,
) -> VectorBranchTensor<'l, T, D, Chip, Cluster, Slice, Time, Packet, D, Fresh, { VeOrder::IntraFirst }> {
VectorBranchTensor::new(self.ctx, self.inner, branch)
}
#[primitive(VectorInitTensor::vector_intra_slice_unzip)]
pub fn vector_intra_slice_unzip<I: AxisName, TileTime: M, SplitTime: M>(
self,
) -> VectorTensorPair<'l, T, D, stage::Tag, Chip, Cluster, Slice, SplitTime, Packet> {
VectorTensorPair::new::<I, Time, TileTime>(self.ctx, self.inner)
}
}
impl<'l, const T: Tu, Chip: M, Cluster: M, Slice: M, Time: M, Packet: M>
VectorInitTensor<'l, T, i32, Chip, Cluster, Slice, Time, Packet>
{
#[primitive(VectorInitTensor::vector_inter_slice_reduce)]
pub fn vector_inter_slice_reduce<OutSlice: M, OutTime: M>(
self,
op: InterSliceReduceOpI32,
) -> VectorInterSliceReduceTensor<'l, T, i32, Chip, Cluster, OutSlice, OutTime, Packet, { VeOrder::InterFirst }>
{
let reduced = self.inner.reduce(op.reduce_fn(), op.identity(), true);
create_inter_slice_reduce_tensor(self.ctx, reduced)
}
}
impl<'l, const T: Tu, Chip: M, Cluster: M, Slice: M, Time: M, Packet: M>
VectorInitTensor<'l, T, f32, Chip, Cluster, Slice, Time, Packet>
{
#[primitive(VectorInitTensor::vector_inter_slice_reduce)]
pub fn vector_inter_slice_reduce<OutSlice: M, OutTime: M>(
self,
op: InterSliceReduceOpF32,
) -> VectorInterSliceReduceTensor<'l, T, f32, Chip, Cluster, OutSlice, OutTime, Packet, { VeOrder::InterFirst }>
{
let reduced = self.inner.reduce(op.reduce_fn(), op.identity(), true);
create_inter_slice_reduce_tensor(self.ctx, reduced)
}
}
pub type VectorInterSliceReduceTensor<'l, const T: Tu, D, Chip, Cluster, Slice, Time, Packet, const VE_ORDER: VeOrder> =
VectorTensor<
'l,
T,
stage::InterSliceReduce,
D,
Chip,
Cluster,
Slice,
Time,
Packet,
D,
Fresh,
VE_ORDER,
stage::Standalone,
{ Way8 },
>;
impl<
'l,
const T: Tu,
S: stage::InterSliceStage + stage::CanTransitionTo<stage::Tag>,
D: VeScalar,
Chip: M,
Cluster: M,
Slice: M,
Time: M,
Packet: M,
StashD: VeScalar,
Stash: StashSlot<StashD>,
FS: stage::Commitable,
> VectorTensor<'l, T, S, D, Chip, Cluster, Slice, Time, Packet, StashD, Stash, { VeOrder::InterFirst }, FS, { Way8 }>
{
#[primitive(VectorTensor::vector_intra_slice_tag)]
pub fn vector_intra_slice_tag(
self,
branch: TagMode,
) -> VectorBranchTensor<'l, T, D, Chip, Cluster, Slice, Time, Packet, D, Fresh, { VeOrder::InterFirst }> {
VectorBranchTensor::new(self.ctx, self.data.inner, branch)
}
}
pub type VectorBranchTensor<
'l,
const T: Tu,
D,
Chip,
Cluster,
Slice,
Time,
Packet,
StashD,
Stash,
const VE_ORDER: VeOrder,
FS = stage::Standalone,
const W: Way = { Way8 },
> = VectorTensor<'l, T, stage::Tag, D, Chip, Cluster, Slice, Time, Packet, StashD, Stash, VE_ORDER, FS, W>;
impl<'l, const T: Tu, D: VeScalar, Chip: M, Cluster: M, Slice: M, Time: M, Packet: M, const VE_ORDER: VeOrder>
VectorBranchTensor<'l, T, D, Chip, Cluster, Slice, Time, Packet, D, Fresh, VE_ORDER>
{
pub fn new(
ctx: &'l mut TuContext<{ T }>,
inner: Tensor<D, VeTensorShape<Chip, Cluster, Slice, Time, Packet>>,
branch_config: TagMode,
) -> Self {
assert_eq!(
Packet::SIZE,
8,
"VectorTensor requires Packet of 8 elements (one flit) in Way8 mode, got {}",
Packet::SIZE,
);
let tag = apply_branch_config(&inner, &branch_config);
Self::from_parts(ctx, inner, tag, VeState::new())
}
}
pub type VectorLogicTensor<
'l,
const T: Tu,
D,
Chip,
Cluster,
Slice,
Time,
Packet,
StashD,
Stash,
const VE_ORDER: VeOrder,
FS = stage::Standalone,
const W: Way = { Way8 },
> = VectorTensor<'l, T, stage::Logic, D, Chip, Cluster, Slice, Time, Packet, StashD, Stash, VE_ORDER, FS, W>;
pub type VectorFxpTensor<
'l,
const T: Tu,
D,
Chip,
Cluster,
Slice,
Time,
Packet,
StashD,
Stash,
const VE_ORDER: VeOrder,
FS = stage::Standalone,
const W: Way = { Way8 },
> = VectorTensor<'l, T, stage::Fxp, D, Chip, Cluster, Slice, Time, Packet, StashD, Stash, VE_ORDER, FS, W>;
pub type VectorFxpToFpTensor<
'l,
const T: Tu,
D,
Chip,
Cluster,
Slice,
Time,
Packet,
StashD,
Stash,
const VE_ORDER: VeOrder,
FS = stage::Standalone,
const W: Way = { Way8 },
> = VectorTensor<'l, T, stage::FxpToFp, D, Chip, Cluster, Slice, Time, Packet, StashD, Stash, VE_ORDER, FS, W>;
pub type VectorNarrowTensor<
'l,
const T: Tu,
D,
Chip,
Cluster,
Slice,
Time,
Packet,
StashD,
Stash,
const VE_ORDER: VeOrder,
FS = stage::Standalone,
const W: Way = { Way4 },
> = VectorTensor<'l, T, stage::Narrow, D, Chip, Cluster, Slice, Time, Packet, StashD, Stash, VE_ORDER, FS, W>;
pub type VectorFpTensor<
'l,
const T: Tu,
D,
Chip,
Cluster,
Slice,
Time,
Packet,
StashD,
Stash,
const VE_ORDER: VeOrder,
FS = stage::Standalone,
const W: Way = { Way4 },
> = VectorTensor<'l, T, stage::Fp, D, Chip, Cluster, Slice, Time, Packet, StashD, Stash, VE_ORDER, FS, W>;
pub type VectorIntraSliceReduceTensor<
'l,
const T: Tu,
D,
Chip,
Cluster,
Slice,
Time,
Packet,
StashD,
Stash,
const VE_ORDER: VeOrder,
FS = stage::Standalone,
const W: Way = { Way4 },
> = VectorTensor<'l, T, stage::IntraSliceReduce, D, Chip, Cluster, Slice, Time, Packet, StashD, Stash, VE_ORDER, FS, W>;
pub type VectorFpDivTensor<
'l,
const T: Tu,
D,
Chip,
Cluster,
Slice,
Time,
Packet,
StashD,
Stash,
const VE_ORDER: VeOrder,
FS = stage::Standalone,
const W: Way = { Way4 },
> = VectorTensor<'l, T, stage::FpDiv, D, Chip, Cluster, Slice, Time, Packet, StashD, Stash, VE_ORDER, FS, W>;
pub type VectorWidenTensor<
'l,
const T: Tu,
D,
Chip,
Cluster,
Slice,
Time,
Packet,
StashD,
Stash,
const VE_ORDER: VeOrder,
FS = stage::Standalone,
const W: Way = { Way8 },
> = VectorTensor<'l, T, stage::Widen, D, Chip, Cluster, Slice, Time, Packet, StashD, Stash, VE_ORDER, FS, W>;
pub type VectorFpToFxpTensor<
'l,
const T: Tu,
D,
Chip,
Cluster,
Slice,
Time,
Packet,
StashD,
Stash,
const VE_ORDER: VeOrder,
FS = stage::Standalone,
const W: Way = { Way8 },
> = VectorTensor<'l, T, stage::FpToFxp, D, Chip, Cluster, Slice, Time, Packet, StashD, Stash, VE_ORDER, FS, W>;
pub type VectorClipTensor<
'l,
const T: Tu,
D,
Chip,
Cluster,
Slice,
Time,
Packet,
StashD,
Stash,
const VE_ORDER: VeOrder,
FS = stage::Standalone,
const W: Way = { Way8 },
> = VectorTensor<'l, T, stage::Clip, D, Chip, Cluster, Slice, Time, Packet, StashD, Stash, VE_ORDER, FS, W>;
pub type VectorFilterTensor<
'l,
const T: Tu,
D,
Chip,
Cluster,
Slice,
Time,
Packet,
StashD,
Stash,
const VE_ORDER: VeOrder,
FS = stage::Standalone,
const W: Way = { Way8 },
> = VectorTensor<'l, T, stage::Filter, D, Chip, Cluster, Slice, Time, Packet, StashD, Stash, VE_ORDER, FS, W>;
fn blend_operand<D: VeScalar, Mapping: M>(
out: &<CurrentBackend as Backend>::Storage<D>,
operand0: &VeRhs<D, Mapping>,
tag: &Tensor<u8, Mapping>,
stash_data: Option<&Tensor<D, Mapping>>,
blend: impl Fn(D, D, u8) -> D + Sync,
) -> <CurrentBackend as Backend>::Storage<D> {
match operand0 {
VeRhs::Vrf { data } => CurrentBackend::zip3_with(out, &data.inner, &tag.inner, blend),
VeRhs::Stash => {
let stash = stash_data.expect("VeRhs::Stash operand requires stash_data; caller must supply it");
CurrentBackend::zip3_with(out, &stash.inner, &tag.inner, blend)
}
VeRhs::Const { v } => {
let rhs = Tensor::<D, Mapping>::splat(*v);
CurrentBackend::zip3_with(out, &rhs.inner, &tag.inner, blend)
}
}
}
pub(super) fn apply_binary_op<D: VeScalar, Mapping: M>(
data: &Tensor<D, Mapping>,
tag: &Tensor<u8, Mapping>,
op: impl Fn(D, D) -> D + Sync,
operands: &[BinaryOperandTag<D, Mapping>],
stash_data: Option<&Tensor<D, Mapping>>,
) -> Tensor<D, Mapping> {
let mut out = data.inner.clone();
for operand in operands {
let filter = operand.tag_filter();
let blend = |o: D, r: D, t: u8| if filter.matches(Opt::Init(t)) { op(o, r) } else { o };
out = blend_operand(&out, operand.operand0(), tag, stash_data, blend);
}
Tensor::from_inner(out)
}
pub(super) fn apply_unary_op<D: VeScalar, Mapping: M>(
data: &Tensor<D, Mapping>,
op: impl Fn(D) -> D + Sync,
) -> Tensor<D, Mapping> {
data.map(op)
}
pub(super) fn apply_ternary_op<Mapping: M>(
data: &Tensor<f32, Mapping>,
tag: &Tensor<u8, Mapping>,
op: impl Fn(f32, f32, f32) -> f32 + Sync,
operands: &[TernaryOperandTag<Mapping>],
stash_data: Option<&Tensor<f32, Mapping>>,
) -> Tensor<f32, Mapping> {
let mut out = data.inner.clone();
for operand in operands {
let filter = operand.tag_filter();
let rhs1 = operand.operand1();
let blend = |o: f32, r: f32, t: u8| {
if filter.matches(Opt::Init(t)) {
op(o, r, rhs1)
} else {
o
}
};
out = blend_operand(&out, operand.operand0(), tag, stash_data, blend);
}
Tensor::from_inner(out)
}
impl<
'l,
const T: Tu,
S,
Chip: M,
Cluster: M,
Slice: M,
Time: M,
Packet: M,
StashD: VeScalar,
Stash: StashSlot<StashD>,
FS: stage::VeTensorContext,
const VE_ORDER: VeOrder,
> VectorTensor<'l, T, S, i32, Chip, Cluster, Slice, Time, Packet, StashD, Stash, VE_ORDER, FS, { Way8 }>
where
S: stage::Stage + CanTransitionTo<stage::Logic>,
{
#[primitive(VectorTensor::vector_logic)]
pub fn vector_logic<Op>(
self,
op: LogicBinaryOpI32,
operand: Op,
) -> VectorLogicTensor<'l, T, i32, Chip, Cluster, Slice, Time, Packet, StashD, Op::Next, VE_ORDER>
where
Op: IntoOperands<i32, VeTensorShape<Chip, Cluster, Slice, Time, Packet>> + StashTransition<StashD, Stash>,
{
let vt = self.do_binary::<stage::Logic, stage::Standalone>(op, None, operand.into_operands());
VectorTensor {
ctx: vt.ctx,
data: vt.data.apply_stash_transition::<Op>(),
}
}
#[primitive(VectorTensor::vector_logic_with_mode)]
pub fn vector_logic_with_mode<Op>(
self,
op: LogicBinaryOpI32,
mode: BinaryArgMode,
operand: Op,
) -> VectorLogicTensor<'l, T, i32, Chip, Cluster, Slice, Time, Packet, StashD, Op::Next, VE_ORDER>
where
Op: IntoOperands<i32, VeTensorShape<Chip, Cluster, Slice, Time, Packet>> + StashTransition<StashD, Stash>,
{
let vt = self.do_binary::<stage::Logic, stage::Standalone>(op, Some(mode), operand.into_operands());
VectorTensor {
ctx: vt.ctx,
data: vt.data.apply_stash_transition::<Op>(),
}
}
}
impl<
'l,
const T: Tu,
S,
Chip: M,
Cluster: M,
Slice: M,
Time: M,
Packet: M,
StashD: VeScalar,
Stash: StashSlot<StashD>,
FS: stage::VeTensorContext,
const VE_ORDER: VeOrder,
> VectorTensor<'l, T, S, f32, Chip, Cluster, Slice, Time, Packet, StashD, Stash, VE_ORDER, FS, { Way8 }>
where
S: stage::Stage + CanTransitionTo<stage::Logic>,
{
#[primitive(VectorTensor::vector_logic)]
pub fn vector_logic<Op>(
self,
op: LogicBinaryOpF32,
operand: Op,
) -> VectorLogicTensor<'l, T, f32, Chip, Cluster, Slice, Time, Packet, StashD, Op::Next, VE_ORDER>
where
Op: IntoOperands<f32, VeTensorShape<Chip, Cluster, Slice, Time, Packet>> + StashTransition<StashD, Stash>,
{
let vt = self.do_binary::<stage::Logic, stage::Standalone>(op, None, operand.into_operands());
VectorTensor {
ctx: vt.ctx,
data: vt.data.apply_stash_transition::<Op>(),
}
}
#[primitive(VectorTensor::vector_logic_with_mode)]
pub fn vector_logic_with_mode<Op>(
self,
op: LogicBinaryOpF32,
mode: BinaryArgMode,
operand: Op,
) -> VectorLogicTensor<'l, T, f32, Chip, Cluster, Slice, Time, Packet, StashD, Op::Next, VE_ORDER>
where
Op: IntoOperands<f32, VeTensorShape<Chip, Cluster, Slice, Time, Packet>> + StashTransition<StashD, Stash>,
{
let vt = self.do_binary::<stage::Logic, stage::Standalone>(op, Some(mode), operand.into_operands());
VectorTensor {
ctx: vt.ctx,
data: vt.data.apply_stash_transition::<Op>(),
}
}
}
impl<
'l,
const T: Tu,
S,
Chip: M,
Cluster: M,
Slice: M,
Time: M,
Packet: M,
StashD: VeScalar,
Stash: StashSlot<StashD>,
FS: stage::VeTensorContext,
const VE_ORDER: VeOrder,
> VectorTensor<'l, T, S, i32, Chip, Cluster, Slice, Time, Packet, StashD, Stash, VE_ORDER, FS, { Way8 }>
where
S: stage::Stage + CanTransitionTo<stage::Fxp>,
{
#[primitive(VectorTensor::vector_fxp)]
pub fn vector_fxp<Op>(
self,
op: FxpBinaryOp,
operand: Op,
) -> VectorFxpTensor<'l, T, i32, Chip, Cluster, Slice, Time, Packet, StashD, Op::Next, VE_ORDER>
where
Op: IntoOperands<i32, VeTensorShape<Chip, Cluster, Slice, Time, Packet>> + StashTransition<StashD, Stash>,
{
let vt = self.do_binary::<stage::Fxp, stage::Standalone>(op, None, operand.into_operands());
VectorTensor {
ctx: vt.ctx,
data: vt.data.apply_stash_transition::<Op>(),
}
}
#[primitive(VectorTensor::vector_fxp_with_mode)]
pub fn vector_fxp_with_mode<Op>(
self,
op: FxpBinaryOp,
mode: BinaryArgMode,
operand: Op,
) -> VectorFxpTensor<'l, T, i32, Chip, Cluster, Slice, Time, Packet, StashD, Op::Next, VE_ORDER>
where
Op: IntoOperands<i32, VeTensorShape<Chip, Cluster, Slice, Time, Packet>> + StashTransition<StashD, Stash>,
{
let vt = self.do_binary::<stage::Fxp, stage::Standalone>(op, Some(mode), operand.into_operands());
VectorTensor {
ctx: vt.ctx,
data: vt.data.apply_stash_transition::<Op>(),
}
}
}
impl<
'l,
const T: Tu,
S,
Chip: M,
Cluster: M,
Slice: M,
Time: M,
Packet: M,
StashD: VeScalar,
Stash: StashSlot<StashD>,
FS: stage::VeTensorContext,
const VE_ORDER: VeOrder,
> VectorTensor<'l, T, S, i32, Chip, Cluster, Slice, Time, Packet, StashD, Stash, VE_ORDER, FS, { Way8 }>
where
S: stage::Stage + CanTransitionTo<stage::FxpToFp>,
{
#[primitive(VectorTensor::vector_fxp_to_fp)]
pub fn vector_fxp_to_fp(
self,
int_width: u32,
) -> VectorFxpToFpTensor<'l, T, f32, Chip, Cluster, Slice, Time, Packet, StashD, Stash, VE_ORDER> {
let op = FxpToFp::new(int_width);
let op_fn = op.op_fn();
let result = self.inner().map(&op_fn);
let (ctx, _inner, tag, ve_state) = self.into_parts();
VectorFxpToFpTensor::from_parts(ctx, result, tag, ve_state)
}
}
impl<
'l,
const T: Tu,
S,
D: VeScalar,
Chip: M,
Cluster: M,
Slice: M,
Time: M,
Packet: M,
StashD: VeScalar,
Stash: StashSlot<StashD>,
FS: stage::VeTensorContext,
const VE_ORDER: VeOrder,
> VectorTensor<'l, T, S, D, Chip, Cluster, Slice, Time, Packet, StashD, Stash, VE_ORDER, FS, { Way8 }>
where
S: stage::Stage + CanTransitionTo<stage::Narrow>,
{
#[primitive(VectorTensor::vector_narrow_split)]
pub fn vector_narrow_split<Time2: M, Packet2: M>(
self,
) -> VectorNarrowTensor<'l, T, D, Chip, Cluster, Slice, Time2, Packet2, StashD, Stash, VE_ORDER, FS, { Way4 }> {
verify_vector_narrow_split::<Time, Packet, Time2, Packet2>();
let (ctx, inner, tag, ve_state) = self.into_parts();
let split_inner = inner.transpose::<VeTensorShape<Chip, Cluster, Slice, Time2, Packet2>>(true);
let split_eid = tag.transpose::<VeTensorShape<Chip, Cluster, Slice, Time2, Packet2>>(true);
VectorNarrowTensor::from_parts(ctx, split_inner, split_eid, ve_state)
}
}
impl<
'l,
const T: Tu,
S,
D: VeScalar,
Chip: M,
Cluster: M,
Slice: M,
Time: M,
Packet: M,
StashD: VeScalar,
Stash: StashSlot<StashD>,
FS: stage::VeTensorContext,
const VE_ORDER: VeOrder,
> VectorTensor<'l, T, S, D, Chip, Cluster, Slice, Time, Packet, StashD, Stash, VE_ORDER, FS, { Way8 }>
where
S: stage::Stage + CanTransitionTo<stage::Narrow>,
{
#[primitive(VectorTensor::vector_narrow_trim)]
pub fn vector_narrow_trim<Packet2: M>(
self,
) -> VectorNarrowTensor<'l, T, D, Chip, Cluster, Slice, Time, Packet2, StashD, Stash, VE_ORDER, FS, { Way4 }> {
verify_vector_narrow_trim::<Packet, Packet2>();
let (ctx, inner, tag, ve_state) = self.into_parts();
let stripped = inner.transpose::<VeTensorShape<Chip, Cluster, Slice, Time, Packet2>>(true);
let stripped_eid = tag.transpose::<VeTensorShape<Chip, Cluster, Slice, Time, Packet2>>(true);
VectorNarrowTensor::from_parts(ctx, stripped, stripped_eid, ve_state)
}
}
impl<
'l,
const T: Tu,
S,
Chip: M,
Cluster: M,
Slice: M,
Time: M,
Packet: M,
StashD: VeScalar,
Stash: StashSlot<StashD>,
FS: stage::VeTensorContext,
const VE_ORDER: VeOrder,
> VectorTensor<'l, T, S, f32, Chip, Cluster, Slice, Time, Packet, StashD, Stash, VE_ORDER, FS, { Way4 }>
where
S: stage::Stage + CanTransitionTo<stage::Fp>,
{
#[primitive(VectorTensor::vector_fp_unary)]
pub fn vector_fp_unary(
mut self,
op: FpUnaryOp,
) -> VectorFpTensor<'l, T, f32, Chip, Cluster, Slice, Time, Packet, StashD, Stash, VE_ORDER> {
self.ve_state_mut().use_alu(op.alu());
let result = apply_unary_op(self.inner(), op.unary_op_fn());
let (ctx, _inner, tag, ve_state) = self.into_parts();
VectorFpTensor::from_parts(ctx, result, tag, ve_state)
}
#[primitive(VectorTensor::vector_fp_binary)]
pub fn vector_fp_binary<Op>(
self,
op: FpBinaryOp,
operand: Op,
) -> VectorFpTensor<'l, T, f32, Chip, Cluster, Slice, Time, Packet, StashD, Op::Next, VE_ORDER>
where
Op: IntoOperands<f32, VeTensorShape<Chip, Cluster, Slice, Time, Packet>> + StashTransition<StashD, Stash>,
{
let operands = operand.into_operands();
let vt = self.do_binary::<stage::Fp, stage::Standalone>(op, None, operands);
VectorTensor {
ctx: vt.ctx,
data: vt.data.apply_stash_transition::<Op>(),
}
}
#[primitive(VectorTensor::vector_fp_binary_with_mode)]
pub fn vector_fp_binary_with_mode<Op>(
self,
op: FpBinaryOp,
mode: BinaryArgMode,
operand: Op,
) -> VectorFpTensor<'l, T, f32, Chip, Cluster, Slice, Time, Packet, StashD, Op::Next, VE_ORDER>
where
Op: IntoOperands<f32, VeTensorShape<Chip, Cluster, Slice, Time, Packet>> + StashTransition<StashD, Stash>,
{
let operands = operand.into_operands();
let vt = self.do_binary::<stage::Fp, stage::Standalone>(op, Some(mode), operands);
VectorTensor {
ctx: vt.ctx,
data: vt.data.apply_stash_transition::<Op>(),
}
}
#[primitive(VectorTensor::vector_fp_ternary)]
pub fn vector_fp_ternary<Op>(
self,
op: FpTernaryOp,
operands: Op,
) -> VectorFpTensor<'l, T, f32, Chip, Cluster, Slice, Time, Packet, StashD, Op::Next, VE_ORDER>
where
Op: IntoTernaryOperandTags<VeTensorShape<Chip, Cluster, Slice, Time, Packet>> + StashTransition<StashD, Stash>,
{
self.vector_fp_ternary_with_mode(op, TernaryArgMode::Mode012, operands)
}
#[primitive(VectorTensor::vector_fp_ternary_with_mode)]
pub fn vector_fp_ternary_with_mode<Op>(
mut self,
op: FpTernaryOp,
mode: TernaryArgMode,
operands: Op,
) -> VectorFpTensor<'l, T, f32, Chip, Cluster, Slice, Time, Packet, StashD, Op::Next, VE_ORDER>
where
Op: IntoTernaryOperandTags<VeTensorShape<Chip, Cluster, Slice, Time, Packet>> + StashTransition<StashD, Stash>,
{
let operands = operands.into_ternary_operands();
let stash_data: Option<Tensor<f32, VeTensorShape<Chip, Cluster, Slice, Time, Packet>>> =
self.ve_state().force_clone_stash_as();
self.ve_state_mut().use_alu(op.alu());
let op_fn = op.ternary_op_fn(Some(mode));
let result = apply_ternary_op(
self.inner(),
self.tag(),
op_fn,
operands.as_slice(),
stash_data.as_ref(),
);
let (ctx, _inner, tag, ve_state) = self.into_parts();
let data = VeTensorData {
inner: result,
tag,
ve_state,
_stage: PhantomData,
_filter_state: PhantomData,
}
.apply_stash_transition::<Op>();
VectorFpTensor::from_ctx_and_data(ctx, data)
}
}
fn verify_reduce_label(time: Mapping, packet: Mapping, out_time: Mapping, out_packet: Mapping, reduce_label: &Ident) {
furiosa_opt_lower::config_reduce_label(&time, &packet, &out_time, &out_packet, reduce_label)
.unwrap_or_else(|message| panic!("{message}"));
}
fn reduce_tag<Chip: M, Cluster: M, Slice: M, Time: M, Packet: M, OutTime: M, OutPacket: M>(
tag: Tensor<u8, VeTensorShape<Chip, Cluster, Slice, Time, Packet>>,
) -> Tensor<u8, VeTensorShape<Chip, Cluster, Slice, OutTime, OutPacket>> {
tag.reduce::<VeTensorShape<Chip, Cluster, Slice, OutTime, OutPacket>>(|_, y| y, 0, false)
}
impl<
'l,
const T: Tu,
S,
Chip: M,
Cluster: M,
Slice: M,
Time: M,
Packet: M,
StashD: VeScalar,
Stash: StashSlot<StashD>,
FS: stage::VeTensorContext,
const VE_ORDER: VeOrder,
> VectorTensor<'l, T, S, i32, Chip, Cluster, Slice, Time, Packet, StashD, Stash, VE_ORDER, FS, { Way4 }>
where
S: stage::Stage + CanTransitionTo<stage::IntraSliceReduce>,
{
#[primitive(VectorTensor::vector_intra_slice_reduce)]
pub fn vector_intra_slice_reduce<Reduce: AxisName, OutTime: M, OutPacket: M>(
mut self,
op: IntraSliceReduceOpI32,
) -> VectorIntraSliceReduceTensor<
'l,
T,
i32,
Chip,
Cluster,
Slice,
OutTime,
OutPacket,
StashD,
Stash,
VE_ORDER,
stage::Standalone,
{ Way4 },
>
{
self.ve_state_mut().use_alu(op.alu());
let (ctx, inner, tag, ve_state) = self.into_parts();
verify_reduce_label(
Time::to_value(),
Packet::to_value(),
OutTime::to_value(),
OutPacket::to_value(),
&Reduce::NAME,
);
let reduced_inner = inner.reduce::<VeTensorShape<Chip, Cluster, Slice, OutTime, OutPacket>>(
op.reduce_fn(),
op.identity(),
false,
);
let reduced_eid = reduce_tag::<Chip, Cluster, Slice, Time, Packet, OutTime, OutPacket>(tag);
VectorIntraSliceReduceTensor::from_parts(ctx, reduced_inner, reduced_eid, ve_state)
}
}
impl<
'l,
const T: Tu,
S,
Chip: M,
Cluster: M,
Slice: M,
Time: M,
Packet: M,
StashD: VeScalar,
Stash: StashSlot<StashD>,
FS: stage::VeTensorContext,
const VE_ORDER: VeOrder,
> VectorTensor<'l, T, S, f32, Chip, Cluster, Slice, Time, Packet, StashD, Stash, VE_ORDER, FS, { Way4 }>
where
S: stage::Stage + CanTransitionTo<stage::IntraSliceReduce>,
{
#[primitive(VectorTensor::vector_intra_slice_reduce)]
pub fn vector_intra_slice_reduce<Reduce: AxisName, OutTime: M, OutPacket: M>(
mut self,
op: IntraSliceReduceOpF32,
) -> VectorIntraSliceReduceTensor<
'l,
T,
f32,
Chip,
Cluster,
Slice,
OutTime,
OutPacket,
StashD,
Stash,
VE_ORDER,
stage::Standalone,
{ Way4 },
>
{
self.ve_state_mut().use_alu(op.alu());
let (ctx, inner, tag, ve_state) = self.into_parts();
verify_reduce_label(
Time::to_value(),
Packet::to_value(),
OutTime::to_value(),
OutPacket::to_value(),
&Reduce::NAME,
);
let reduced_inner = inner.reduce::<VeTensorShape<Chip, Cluster, Slice, OutTime, OutPacket>>(
op.reduce_fn(),
op.identity(),
false,
);
let reduced_eid = reduce_tag::<Chip, Cluster, Slice, Time, Packet, OutTime, OutPacket>(tag);
VectorIntraSliceReduceTensor::from_parts(ctx, reduced_inner, reduced_eid, ve_state)
}
}
impl<
'l,
const T: Tu,
S,
Chip: M,
Cluster: M,
Slice: M,
Time: M,
Packet: M,
StashD: VeScalar,
Stash: StashSlot<StashD>,
FS: stage::VeTensorContext,
const VE_ORDER: VeOrder,
> VectorTensor<'l, T, S, f32, Chip, Cluster, Slice, Time, Packet, StashD, Stash, VE_ORDER, FS, { Way4 }>
where
S: stage::Stage + CanTransitionTo<stage::FpDiv>,
{
#[primitive(VectorTensor::vector_fp_div)]
pub fn vector_fp_div<Op>(
self,
operand: Op,
) -> VectorFpDivTensor<'l, T, f32, Chip, Cluster, Slice, Time, Packet, StashD, Op::Next, VE_ORDER, FS, { Way4 }>
where
Op: IntoOperands<f32, VeTensorShape<Chip, Cluster, Slice, Time, Packet>> + StashTransition<StashD, Stash>,
{
let vt = self.do_binary::<stage::FpDiv, FS>(FpDivBinaryOp::DivF, None, operand.into_operands());
VectorTensor {
ctx: vt.ctx,
data: vt.data.apply_stash_transition::<Op>(),
}
}
#[primitive(VectorTensor::vector_fp_div_with_mode)]
pub fn vector_fp_div_with_mode<Op>(
self,
mode: BinaryArgMode,
operand: Op,
) -> VectorFpDivTensor<'l, T, f32, Chip, Cluster, Slice, Time, Packet, StashD, Op::Next, VE_ORDER, FS, { Way4 }>
where
Op: IntoOperands<f32, VeTensorShape<Chip, Cluster, Slice, Time, Packet>> + StashTransition<StashD, Stash>,
{
let vt = self.do_binary::<stage::FpDiv, FS>(FpDivBinaryOp::DivF, Some(mode), operand.into_operands());
VectorTensor {
ctx: vt.ctx,
data: vt.data.apply_stash_transition::<Op>(),
}
}
}
impl<
'l,
const T: Tu,
S,
D: VeScalar,
Chip: M,
Cluster: M,
Slice: M,
Time: M,
Packet: M,
StashD: VeScalar,
Stash: StashSlot<StashD>,
FS: stage::VeTensorContext,
const VE_ORDER: VeOrder,
> VectorTensor<'l, T, S, D, Chip, Cluster, Slice, Time, Packet, StashD, Stash, VE_ORDER, FS, { Way4 }>
where
S: stage::Stage + CanTransitionTo<stage::Widen>,
{
#[primitive(VectorTensor::vector_widen_concat)]
pub fn vector_widen_concat<Time2: M, Packet2: M>(
self,
) -> VectorWidenTensor<'l, T, D, Chip, Cluster, Slice, Time2, Packet2, StashD, Stash, VE_ORDER, FS, { Way8 }> {
verify_vector_widen_concat::<Time, Packet, Time2, Packet2>();
let (ctx, inner, tag, ve_state) = self.into_parts();
let concat_inner = inner.transpose::<VeTensorShape<Chip, Cluster, Slice, Time2, Packet2>>(true);
let concat_eid = tag.transpose::<VeTensorShape<Chip, Cluster, Slice, Time2, Packet2>>(true);
VectorWidenTensor::from_parts(ctx, concat_inner, concat_eid, ve_state)
}
}
impl<
'l,
const T: Tu,
S,
D: VeScalar,
Chip: M,
Cluster: M,
Slice: M,
Time: M,
Packet: M,
StashD: VeScalar,
Stash: StashSlot<StashD>,
FS: stage::VeTensorContext,
const VE_ORDER: VeOrder,
> VectorTensor<'l, T, S, D, Chip, Cluster, Slice, Time, Packet, StashD, Stash, VE_ORDER, FS, { Way4 }>
where
S: stage::Stage + CanTransitionTo<stage::Widen>,
{
#[primitive(VectorTensor::vector_widen_pad)]
pub fn vector_widen_pad<Packet2: M>(
self,
) -> VectorWidenTensor<'l, T, D, Chip, Cluster, Slice, Time, Packet2, StashD, Stash, VE_ORDER, FS, { Way8 }> {
verify_vector_widen_pad::<Packet, Packet2>();
let (ctx, inner, tag, ve_state) = self.into_parts();
let padded = inner.transpose::<VeTensorShape<Chip, Cluster, Slice, Time, Packet2>>(true);
let padded_eid = tag.transpose::<VeTensorShape<Chip, Cluster, Slice, Time, Packet2>>(true);
VectorWidenTensor::from_parts(ctx, padded, padded_eid, ve_state)
}
}
impl<
'l,
const T: Tu,
S,
Chip: M,
Cluster: M,
Slice: M,
Time: M,
Packet: M,
StashD: VeScalar,
Stash: StashSlot<StashD>,
FS: stage::VeTensorContext,
const VE_ORDER: VeOrder,
> VectorTensor<'l, T, S, f32, Chip, Cluster, Slice, Time, Packet, StashD, Stash, VE_ORDER, FS, { Way8 }>
where
S: stage::Stage + CanTransitionTo<stage::FpToFxp>,
{
#[primitive(VectorTensor::vector_fp_to_fxp)]
pub fn vector_fp_to_fxp(
self,
int_width: u32,
) -> VectorFpToFxpTensor<'l, T, i32, Chip, Cluster, Slice, Time, Packet, StashD, Stash, VE_ORDER> {
let op = FpToFxp::new(int_width);
let op_fn = op.op_fn();
let result = self.inner().map(&op_fn);
let (ctx, _inner, tag, ve_state) = self.into_parts();
VectorFpToFxpTensor::from_parts(ctx, result, tag, ve_state)
}
}
impl<
'l,
const T: Tu,
S,
Chip: M,
Cluster: M,
Slice: M,
Time: M,
Packet: M,
StashD: VeScalar,
Stash: StashSlot<StashD>,
FS: stage::VeTensorContext,
const VE_ORDER: VeOrder,
> VectorTensor<'l, T, S, i32, Chip, Cluster, Slice, Time, Packet, StashD, Stash, VE_ORDER, FS, { Way8 }>
where
S: stage::Stage + CanTransitionTo<stage::Clip>,
{
#[primitive(VectorTensor::vector_clip)]
pub fn vector_clip<Op>(
self,
op: ClipBinaryOpI32,
operand: Op,
) -> VectorClipTensor<'l, T, i32, Chip, Cluster, Slice, Time, Packet, StashD, Op::Next, VE_ORDER>
where
Op: IntoOperands<i32, VeTensorShape<Chip, Cluster, Slice, Time, Packet>> + StashTransition<StashD, Stash>,
{
let vt = self.do_binary::<stage::Clip, stage::Standalone>(op, None, operand.into_operands());
VectorTensor {
ctx: vt.ctx,
data: vt.data.apply_stash_transition::<Op>(),
}
}
#[primitive(VectorTensor::vector_clip_with_mode)]
pub fn vector_clip_with_mode<Op>(
self,
op: ClipBinaryOpI32,
mode: BinaryArgMode,
operand: Op,
) -> VectorClipTensor<'l, T, i32, Chip, Cluster, Slice, Time, Packet, StashD, Op::Next, VE_ORDER>
where
Op: IntoOperands<i32, VeTensorShape<Chip, Cluster, Slice, Time, Packet>> + StashTransition<StashD, Stash>,
{
let vt = self.do_binary::<stage::Clip, stage::Standalone>(op, Some(mode), operand.into_operands());
VectorTensor {
ctx: vt.ctx,
data: vt.data.apply_stash_transition::<Op>(),
}
}
}
impl<
'l,
const T: Tu,
S,
Chip: M,
Cluster: M,
Slice: M,
Time: M,
Packet: M,
StashD: VeScalar,
Stash: StashSlot<StashD>,
FS: stage::VeTensorContext,
const VE_ORDER: VeOrder,
> VectorTensor<'l, T, S, f32, Chip, Cluster, Slice, Time, Packet, StashD, Stash, VE_ORDER, FS, { Way8 }>
where
S: stage::Stage + CanTransitionTo<stage::Clip>,
{
#[primitive(VectorTensor::vector_clip)]
pub fn vector_clip<Op>(
self,
op: ClipBinaryOpF32,
operand: Op,
) -> VectorClipTensor<'l, T, f32, Chip, Cluster, Slice, Time, Packet, StashD, Op::Next, VE_ORDER>
where
Op: IntoOperands<f32, VeTensorShape<Chip, Cluster, Slice, Time, Packet>> + StashTransition<StashD, Stash>,
{
let vt = self.do_binary::<stage::Clip, stage::Standalone>(op, None, operand.into_operands());
VectorTensor {
ctx: vt.ctx,
data: vt.data.apply_stash_transition::<Op>(),
}
}
#[primitive(VectorTensor::vector_clip_with_mode)]
pub fn vector_clip_with_mode<Op>(
self,
op: ClipBinaryOpF32,
mode: BinaryArgMode,
operand: Op,
) -> VectorClipTensor<'l, T, f32, Chip, Cluster, Slice, Time, Packet, StashD, Op::Next, VE_ORDER>
where
Op: IntoOperands<f32, VeTensorShape<Chip, Cluster, Slice, Time, Packet>> + StashTransition<StashD, Stash>,
{
let vt = self.do_binary::<stage::Clip, stage::Standalone>(op, Some(mode), operand.into_operands());
VectorTensor {
ctx: vt.ctx,
data: vt.data.apply_stash_transition::<Op>(),
}
}
}
impl<
'l,
const T: Tu,
S,
D: VeScalar,
Chip: M,
Cluster: M,
Slice: M,
Time: M,
Packet: M,
StashD: VeScalar,
Stash: StashSlot<StashD>,
const VE_ORDER: VeOrder,
> VectorTensor<'l, T, S, D, Chip, Cluster, Slice, Time, Packet, StashD, Stash, VE_ORDER, stage::Standalone, { Way8 }>
where
S: stage::Stage + CanTransitionTo<stage::Filter>,
{
#[primitive(VectorTensor::vector_filter)]
pub fn vector_filter<Time2: M>(
self,
_config: TagFilter,
) -> VectorFilterTensor<
'l,
T,
D,
Chip,
Cluster,
Slice,
Time2,
Packet,
StashD,
Stash,
VE_ORDER,
stage::Standalone,
{ Way8 },
> {
todo!("Implement vector_filter operation")
}
}