use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum OptTarget {
Latency,
Size,
Energy,
Precision,
Bandwidth,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum RequantPrecision {
#[default]
Q0_31,
Q0_15,
}
#[derive(Debug, Clone, Copy)]
pub struct Tune {
pub fold_zero_zp: bool,
pub ternary_fast_path: bool,
pub shared_requant: bool,
pub bram_clock_enable: bool,
pub requant_precision: RequantPrecision,
pub parallelism: u32,
pub fuse_conv_relu: bool,
pub arena_plan: bool,
pub ic_parallelism: u32,
}
impl Default for Tune {
fn default() -> Self {
Self::for_target(OptTarget::Precision)
}
}
impl Tune {
pub fn for_target(t: OptTarget) -> Self {
match t {
OptTarget::Latency => Self {
fold_zero_zp: true,
ternary_fast_path: false,
shared_requant: false,
bram_clock_enable: false,
requant_precision: RequantPrecision::Q0_31,
parallelism: 4,
fuse_conv_relu: true,
arena_plan: true,
ic_parallelism: 1,
},
OptTarget::Size => Self {
fold_zero_zp: true,
ternary_fast_path: true,
shared_requant: true,
bram_clock_enable: false,
requant_precision: RequantPrecision::Q0_15,
parallelism: 1,
fuse_conv_relu: true,
arena_plan: true,
ic_parallelism: 1,
},
OptTarget::Energy => Self {
fold_zero_zp: true,
ternary_fast_path: true,
shared_requant: true,
bram_clock_enable: true,
requant_precision: RequantPrecision::Q0_15,
parallelism: 1,
fuse_conv_relu: true,
arena_plan: true,
ic_parallelism: 4, },
OptTarget::Precision => Self {
fold_zero_zp: true,
ternary_fast_path: false,
shared_requant: false,
bram_clock_enable: false,
requant_precision: RequantPrecision::Q0_31,
parallelism: 1,
fuse_conv_relu: true,
arena_plan: true,
ic_parallelism: 1,
},
OptTarget::Bandwidth => Self {
..Self::for_target(OptTarget::Size)
},
}
}
}
impl fmt::Display for Tune {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"Tune {{ fold_zp={} ternary_fast={} shared_requant={} \
bram_en={} requant={:?} P={} P_ic={} }}",
self.fold_zero_zp,
self.ternary_fast_path,
self.shared_requant,
self.bram_clock_enable,
self.requant_precision,
self.parallelism,
self.ic_parallelism,
)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn presets_are_internally_coherent() {
let t = Tune::for_target(OptTarget::Latency);
assert!(!t.ternary_fast_path);
assert!(!t.bram_clock_enable);
let t = Tune::for_target(OptTarget::Size);
assert!(t.ternary_fast_path);
assert!(t.shared_requant);
assert_eq!(t.requant_precision, RequantPrecision::Q0_15);
let t = Tune::for_target(OptTarget::Energy);
assert!(t.ternary_fast_path);
assert!(t.bram_clock_enable);
assert_eq!(t.requant_precision, RequantPrecision::Q0_15);
let t = Tune::for_target(OptTarget::Precision);
assert!(!t.ternary_fast_path);
assert!(!t.shared_requant);
assert_eq!(t.requant_precision, RequantPrecision::Q0_31);
}
}