#[macro_export]
macro_rules! conv2d_micro_kernel {
($name:ident, $nr:expr, $mr:expr) => {
fn $name<T: $crate::common::CommonBounds>(
inp: $crate::common::Pointer<T>,
kernel: $crate::common::Pointer<T>,
mut out: $crate::common::Pointer<T>,
icb: i64,
osw: i64,
kernel_idx: &mut i64,
[k, j, l]: [i64; 3],
[kh, kw]: [i64; 2],
[step_height, step_width]: [i64; 2],
_: [i64; 2],
_: [i64; 2],
[ish, isw]: [i64; 2],
[owr, ocr]: [i64; 2],
[dh, dw]: [i64; 2],
first_ic_iter: bool,
) {
use $crate::types::vectors::traits::VecTrait;
use $crate::types::math::NormalOut;
let mut c_local = if first_ic_iter {
[[T::Vec::splat(T::ZERO); $nr]; $mr]
} else {
let mut c_local = [[T::Vec::splat(T::ZERO); $nr]; $mr];
if ocr == $nr * T::Vec::SIZE as i64 {
for mr in 0..owr {
unsafe {
let out_ptr = out.ptr.offset(((mr + k) * osw + j) as isize);
$crate::re_exports::seq_macro::seq!(NR in 0..$nr {
let ptr = out_ptr.add(NR * T::Vec::SIZE) as *const T::Vec;
c_local[mr as usize][NR] = ptr.read_unaligned();
});
}
}
} else {
for mr in 0..owr {
let reg = c_local[mr as usize].as_mut_ptr() as *mut T;
for nr in 0..ocr as i64 {
let val = out[(mr + k) * osw + j + nr];
unsafe { reg.add(nr as usize).write(val) };
}
}
}
c_local
};
for n in 0..kh {
let in_y = l * step_height + n * dh;
for m in 0..kw {
for ii in 0..icb {
let kernel = unsafe { kernel.ptr.add(*kernel_idx as usize) };
$crate::re_exports::seq_macro::seq!(NR in 0..$nr {
let b_vec~NR = unsafe {
*(kernel.add(NR * <T as $crate::types::TypeCommon>::Vec::SIZE)
as *const <T as $crate::types::TypeCommon>::Vec)
};
}
);
#[allow(unused_mut)]
let mut a_vec;
$crate::re_exports::seq_macro::seq!(MR in 0..$mr {
let in_x = (k + MR) * step_width + m * dw;
a_vec = <T as $crate::types::TypeCommon>::Vec::splat(inp[in_y * ish + in_x * isw + ii]);
$crate::re_exports::seq_macro::seq!(NR in 0..$nr {
c_local[MR][NR] = a_vec._mul_add(b_vec~NR, c_local[MR][NR]);
});
}
);
*kernel_idx += $nr * T::Vec::SIZE as i64;
}
}
}
if ocr == $nr * T::Vec::SIZE as i64 {
for mr in 0..owr {
unsafe {
let out_ptr = out.ptr.offset(((mr + k) * osw + j) as isize);
$crate::re_exports::seq_macro::seq!(NR in 0..$nr {
let vec = c_local[mr as usize][NR];
let ptr = out_ptr.add(NR * T::Vec::SIZE) as *mut T::Vec;
ptr.write_unaligned(vec);
});
}
}
} else {
for mr in 0..owr {
let reg = c_local[mr as usize].as_ptr() as *const T;
for nr in 0..ocr as i64 {
out[(mr + k) * osw + j + nr] =
unsafe { reg.add(nr as usize).read() };
}
}
}
}
};
}
#[macro_export]
macro_rules! conv2d_mixed_precision_micro_kernel {
($name:ident, $nr:expr, $mr:expr, $nr2:expr) => {
fn $name<T: $crate::common::CommonBounds, IM: $crate::common::CommonBounds>(
inp: $crate::common::Pointer<IM>,
kernel: $crate::common::Pointer<IM>,
mut out: $crate::common::Pointer<T>,
icb: i64,
osw: i64,
kernel_idx: &mut i64,
[k, j, l]: [i64; 3],
[kh, kw]: [i64; 2],
[step_height, step_width]: [i64; 2],
_: [i64; 2],
_: [i64; 2],
[ish, isw]: [i64; 2],
[owr, ocr]: [i64; 2],
[dh, dw]: [i64; 2],
first_ic_iter: bool,
vec_cast: fn(*const T) -> IM::Vec,
vec_cast_back: fn(*const IM::Vec) -> T::Vec,
cast: fn(T) -> IM,
cast_back: fn(IM) -> T,
) {
use $crate::types::vectors::traits::VecTrait;
use $crate::types::math::NormalOut;
let mut c_local = if first_ic_iter {
[[IM::Vec::splat(IM::ZERO); $nr2]; $mr]
} else {
let mut c_local = [[IM::Vec::splat(IM::ZERO); $nr2]; $mr];
if ocr == $nr2 * IM::Vec::SIZE as i64 {
for mr in 0..owr {
let reg = c_local[mr as usize].as_mut_ptr() as *mut IM::Vec;
let out_ptr = unsafe { out.ptr.offset(((mr + k) * osw + j) as isize) } as *const T;
$crate::re_exports::seq_macro::seq!(NR in 0..$nr2 {
unsafe { reg.add(NR as usize).write(vec_cast(out_ptr.add(NR * IM::Vec::SIZE))) };
});
}
} else {
for mr in 0..owr {
let reg = c_local[mr as usize].as_mut_ptr() as *mut IM;
for nr in 0..ocr as i64 {
let val = cast(out[(mr + k) * osw + j + nr]);
unsafe { reg.add(nr as usize).write(val) };
}
}
}
c_local
};
for n in 0..kh {
let in_y = l * step_height + n * dh;
for m in 0..kw {
for ii in 0..icb {
let kernel = unsafe { kernel.ptr.add(*kernel_idx as usize) };
$crate::re_exports::seq_macro::seq!(NR in 0..$nr2 {
let b_vec~NR = unsafe {
*(kernel.add(NR * <IM as $crate::types::TypeCommon>::Vec::SIZE)
as *const <IM as $crate::types::TypeCommon>::Vec)
};
}
);
#[allow(unused_mut)]
let mut a_vec;
$crate::re_exports::seq_macro::seq!(MR in 0..$mr {
let in_x = (k + MR) * step_width + m * dw;
a_vec = <IM as $crate::types::TypeCommon>::Vec::splat(inp[in_y * ish + in_x * isw + ii]);
$crate::re_exports::seq_macro::seq!(NR in 0..$nr2 {
c_local[MR][NR] = a_vec._mul_add(b_vec~NR, c_local[MR][NR]);
});
}
);
*kernel_idx += $nr2 * IM::Vec::SIZE as i64;
}
}
}
if ocr == $nr2 * IM::Vec::SIZE as i64 {
for mr in 0..owr {
let out_ptr = unsafe { out.ptr.offset(((mr + k) * osw + j) as isize) } as *mut T::Vec;
for i in 0..$nr2 / (IM::BYTE_SIZE as i64 / T::BYTE_SIZE as i64) {
let c_local_ptr = c_local[mr as usize].as_ptr() as *const IM::Vec;
let res = vec_cast_back(unsafe { c_local_ptr.offset(i as isize) });
unsafe { out_ptr.offset(i as isize).write_unaligned(res) };
}
}
} else {
for mr in 0..owr {
let reg = c_local[mr as usize].as_ptr() as *const IM;
for nr in 0..ocr as i64 {
out[(mr + k) * osw + j + nr] =
cast_back(unsafe { reg.add(nr as usize).read() });
}
}
}
}
};
}
#[macro_export]
macro_rules! conv2d_micro_kernel_with_padding {
($name:ident, $nr:expr, $mr:expr) => {
fn $name<T: $crate::common::CommonBounds>(
inp: $crate::common::Pointer<T>,
kernel: $crate::common::Pointer<T>,
mut out: $crate::common::Pointer<T>,
icb: i64,
osw: i64,
kernel_idx: &mut i64,
[k, j, l]: [i64; 3],
[kh, kw]: [i64; 2],
[step_height, step_width]: [i64; 2],
[ph_start, pw_start]: [i64; 2],
[img_height, img_width]: [i64; 2],
[ish, isw]: [i64; 2],
[owr, ocr]: [i64; 2],
[dh, dw]: [i64; 2],
first_ic_iter: bool,
) {
use $crate::types::vectors::traits::VecTrait;
use $crate::types::math::NormalOut;
let mut c_local = [[T::Vec::splat(T::ZERO); $nr]; $mr];
for n in 0..kh {
let in_y = l * step_height + n * dh - ph_start;
if in_y < 0 || in_y >= img_height {
*kernel_idx += icb * kw * $nr * T::Vec::SIZE as i64;
continue;
}
for m in 0..kw {
let max_in_x = (k + $mr - 1) * step_width + m * dw - pw_start;
let min_in_x = k * step_width + m * dw - pw_start;
if min_in_x >= 0 && max_in_x < img_width {
for ii in 0..icb {
let kernel = unsafe { kernel.ptr.add(*kernel_idx as usize) };
$crate::re_exports::seq_macro::seq!(NR in 0..$nr {
let b_vec~NR = unsafe {
*(kernel.add(NR * <T as $crate::types::TypeCommon>::Vec::SIZE)
as *const <T as $crate::types::TypeCommon>::Vec)
};
}
);
#[allow(unused_mut)]
let mut a_vec;
$crate::re_exports::seq_macro::seq!(MR in 0..$mr {
let in_x = (k + MR) * step_width + m * dw - pw_start;
a_vec = <T as $crate::types::TypeCommon>::Vec::splat(inp[in_y * ish + in_x * isw + ii]);
$crate::re_exports::seq_macro::seq!(NR in 0..$nr {
c_local[MR][NR] = a_vec._mul_add(b_vec~NR, c_local[MR][NR]);
});
}
);
*kernel_idx += $nr * T::Vec::SIZE as i64;
}
} else {
for ii in 0..icb {
let kernel = unsafe { kernel.ptr.add(*kernel_idx as usize) };
$crate::re_exports::seq_macro::seq!(NR in 0..$nr {
let b_vec~NR = unsafe {
*(kernel.add(NR * <T as $crate::types::TypeCommon>::Vec::SIZE)
as *const <T as $crate::types::TypeCommon>::Vec)
};
}
);
#[allow(unused_mut)]
let mut a_vec;
$crate::re_exports::seq_macro::seq!(MR in 0..$mr {
let in_x = (k + MR) * step_width + m * dw - pw_start;
if in_x >= 0 && in_x < img_width {
a_vec = <T as $crate::types::TypeCommon>::Vec::splat(inp[in_y * ish + in_x * isw + ii]);
$crate::re_exports::seq_macro::seq!(NR in 0..$nr {
c_local[MR][NR] = a_vec._mul_add(b_vec~NR, c_local[MR][NR]);
});
}
}
);
*kernel_idx += $nr * T::Vec::SIZE as i64;
}
}
}
}
if first_ic_iter {
for mr in 0..owr {
let reg = c_local[mr as usize].as_ptr() as *const T;
for nr in 0..ocr as i64 {
out[(mr + k) * osw + j + nr] =
unsafe { reg.add(nr as usize).read() };
}
}
} else {
for mr in 0..owr {
let reg = c_local[mr as usize].as_ptr() as *const T;
for nr in 0..ocr as i64 {
let val = out[(mr + k) * osw + j + nr];
out[(mr + k) * osw + j + nr] =
val._add(unsafe { reg.add(nr as usize).read() });
}
}
}
}
};
}
#[macro_export]
macro_rules! conv2d_mixed_precision_micro_kernel_with_padding {
($name:ident, $nr:expr, $mr:expr, $nr2:expr) => {
fn $name<T: $crate::common::CommonBounds, IM: $crate::common::CommonBounds>(
inp: $crate::common::Pointer<IM>,
kernel: $crate::common::Pointer<IM>,
mut out: $crate::common::Pointer<T>,
icb: i64,
osw: i64,
kernel_idx: &mut i64,
[k, j, l]: [i64; 3],
[kh, kw]: [i64; 2],
[step_height, step_width]: [i64; 2],
[ph_start, pw_start]: [i64; 2],
[img_height, img_width]: [i64; 2],
[ish, isw]: [i64; 2],
[owr, ocr]: [i64; 2],
[dh, dw]: [i64; 2],
first_ic_iter: bool,
vec_cast: fn(*const T) -> IM::Vec,
vec_cast_back: fn(*const IM::Vec) -> T::Vec,
cast: fn(T) -> IM,
cast_back: fn(IM) -> T,
) {
use $crate::types::vectors::traits::VecTrait;
use $crate::types::math::NormalOut;
let mut c_local = if first_ic_iter {
[[IM::Vec::splat(IM::ZERO); $nr2]; $mr]
} else {
let mut c_local = [[IM::Vec::splat(IM::ZERO); $nr2]; $mr];
if ocr == $nr2 * IM::Vec::SIZE as i64 {
for mr in 0..owr {
let reg = c_local[mr as usize].as_mut_ptr() as *mut IM::Vec;
let out_ptr = unsafe { out.ptr.offset(((mr + k) * osw + j) as isize) } as *const T;
$crate::re_exports::seq_macro::seq!(NR in 0..$nr2 {
unsafe { reg.add(NR as usize).write(vec_cast(out_ptr.add(NR * IM::Vec::SIZE))) };
});
}
} else {
for mr in 0..owr {
let reg = c_local[mr as usize].as_mut_ptr() as *mut IM;
for nr in 0..ocr as i64 {
let val = cast(out[(mr + k) * osw + j + nr]);
unsafe { reg.add(nr as usize).write(val) };
}
}
}
c_local
};
for n in 0..kh {
let in_y = l * step_height + n * dh - ph_start;
if in_y < 0 || in_y >= img_height {
*kernel_idx += icb * kw * $nr * T::Vec::SIZE as i64;
continue;
}
for m in 0..kw {
let max_in_x = (k + $mr - 1) * step_width + m * dw - pw_start;
let min_in_x = k * step_width + m * dw - pw_start;
if min_in_x >= 0 && max_in_x < img_width {
for ii in 0..icb {
let kernel = unsafe { kernel.ptr.add(*kernel_idx as usize) };
$crate::re_exports::seq_macro::seq!(NR in 0..$nr2 {
let b_vec~NR = unsafe {
*(kernel.add(NR * <IM as $crate::types::TypeCommon>::Vec::SIZE)
as *const <IM as $crate::types::TypeCommon>::Vec)
};
}
);
#[allow(unused_mut)]
let mut a_vec;
$crate::re_exports::seq_macro::seq!(MR in 0..$mr {
let in_x = (k + MR) * step_width + m * dw - pw_start;
a_vec = <IM as $crate::types::TypeCommon>::Vec::splat(inp[in_y * ish + in_x * isw + ii]);
$crate::re_exports::seq_macro::seq!(NR in 0..$nr2 {
c_local[MR][NR] = a_vec._mul_add(b_vec~NR, c_local[MR][NR]);
});
}
);
*kernel_idx += $nr2 * IM::Vec::SIZE as i64;
}
} else {
for ii in 0..icb {
let kernel = unsafe { kernel.ptr.add(*kernel_idx as usize) };
$crate::re_exports::seq_macro::seq!(NR in 0..$nr2 {
let b_vec~NR = unsafe {
*(kernel.add(NR * <IM as $crate::types::TypeCommon>::Vec::SIZE)
as *const <IM as $crate::types::TypeCommon>::Vec)
};
}
);
#[allow(unused_mut)]
let mut a_vec;
$crate::re_exports::seq_macro::seq!(MR in 0..$mr {
let in_x = (k + MR) * step_width + m * dw - pw_start;
if in_x >= 0 && in_x < img_width {
a_vec = <IM as $crate::types::TypeCommon>::Vec::splat(inp[in_y * ish + in_x * isw + ii]);
$crate::re_exports::seq_macro::seq!(NR in 0..$nr2 {
c_local[MR][NR] = a_vec._mul_add(b_vec~NR, c_local[MR][NR]);
});
}
});
*kernel_idx += $nr2 * IM::Vec::SIZE as i64;
}
}
}
}
if ocr == $nr2 * IM::Vec::SIZE as i64 {
for mr in 0..owr {
let out_ptr = unsafe { out.ptr.offset(((mr + k) * osw + j) as isize) } as *mut T::Vec;
for i in 0..$nr2 / (IM::BYTE_SIZE as i64 / T::BYTE_SIZE as i64) {
let c_local_ptr = c_local[mr as usize].as_ptr() as *const IM::Vec;
let res = vec_cast_back(unsafe { c_local_ptr.offset(i as isize) });
unsafe { out_ptr.offset(i as isize).write_unaligned(res) };
}
}
} else {
for mr in 0..owr {
let reg = c_local[mr as usize].as_ptr() as *const IM;
for nr in 0..ocr as i64 {
out[(mr + k) * osw + j + nr] =
cast_back(unsafe { reg.add(nr as usize).read() });
}
}
}
}
};
}