use furiosa_mapping::M;
use crate::scalar::Scalar;
pub(crate) use furiosa_opt_lower::{BITS_PER_BYTE, FLIT_BYTES};
pub(crate) const CLUSTER_SIZES: [usize; 2] = [1, 2];
pub(crate) const PACKET_ALIGN_BYTES: usize = 8;
pub(crate) const SLICE_SIZES: [usize; 3] = [64, 128, 256];
pub(crate) fn assert_cluster_size<Cluster: M>() {
const {
let mut i = 0;
let mut ok = false;
while i < CLUSTER_SIZES.len() {
ok |= CLUSTER_SIZES[i] == Cluster::SIZE;
i += 1;
}
assert!(ok, "Cluster size must be 1 or 2");
};
}
pub(crate) fn assert_slice_size<Slice: M>() {
const {
let mut i = 0;
let mut ok = false;
while i < SLICE_SIZES.len() {
ok |= SLICE_SIZES[i] == Slice::SIZE;
i += 1;
}
assert!(ok, "Slice size must be one of 64 | 128 | 256");
};
}
pub(crate) fn assert_packet_aligned_by_access_width<D: Scalar, Packet: M>() {
const {
assert!(
size_in_bytes(D::BITS, Packet::SIZE).is_multiple_of(PACKET_ALIGN_BYTES),
"Packet size must be 8-byte aligned"
);
};
}
pub(crate) fn assert_packet_aligned_by_access_width_max_flit<D: Scalar, Packet: M>() {
const {
let bytes = size_in_bytes(D::BITS, Packet::SIZE);
assert!(
bytes != 0 && bytes.is_multiple_of(PACKET_ALIGN_BYTES) && bytes <= FLIT_BYTES,
"Packet size must be 8, 16, 24, or 32 bytes"
);
};
}
pub(crate) fn assert_packet_one_flit<D: Scalar, Packet: M>() {
const {
assert!(
size_in_bytes(D::BITS, Packet::SIZE) == FLIT_BYTES,
"Packet size must be exactly one flit (32 bytes)"
);
};
}
pub(crate) fn assert_packet_one_or_two_flit<D: Scalar, Packet: M>() {
const {
let bytes = size_in_bytes(D::BITS, Packet::SIZE);
assert!(
bytes == FLIT_BYTES || bytes == 2 * FLIT_BYTES,
"Packet size must be one or two flits (32 or 64 bytes)"
);
};
}
pub(crate) fn assert_dm_to_dm_dimension_preserved<Chip: M, Chip2: M, Cluster: M, Cluster2: M, Slice: M, Slice2: M>() {
assert_chip_preserved::<Chip, Chip2>();
assert_cluster_preserved::<Cluster, Cluster2>();
assert_slice_preserved::<Slice, Slice2>();
}
pub(crate) fn assert_reshape_dimension_preserved<Chip: M, Chip2: M, Cluster: M, Cluster2: M, Slice: M, Slice2: M>() {
assert_chip_preserved::<Chip, Chip2>();
assert_cluster_preserved::<Cluster, Cluster2>();
assert_slice_preserved::<Slice, Slice2>();
}
pub(crate) fn assert_hbm_reshape_dimension_preserved<Chip: M, Chip2: M, Element: M, Element2: M>() {
assert_chip_preserved::<Chip, Chip2>();
assert_element_preserved::<Element, Element2>();
}
fn assert_chip_preserved<Chip: M, Chip2: M>() {
const { assert!(Chip::SIZE == Chip2::SIZE, "Chip size must be preserved") };
}
fn assert_cluster_preserved<Cluster: M, Cluster2: M>() {
const { assert!(Cluster::SIZE == Cluster2::SIZE, "Cluster size must be preserved") };
}
fn assert_slice_preserved<Slice: M, Slice2: M>() {
const { assert!(Slice::SIZE == Slice2::SIZE, "Slice size must be preserved") };
}
fn assert_element_preserved<Element: M, Element2: M>() {
const { assert!(Element::SIZE == Element2::SIZE, "Element size must be preserved") };
}
pub(crate) const fn size_in_bytes(bits: usize, length: usize) -> usize {
assert!(
(length * bits).is_multiple_of(BITS_PER_BYTE),
"total bits must be byte-aligned"
);
(length * bits) / BITS_PER_BYTE
}