use crate::ir::graph::*;
pub fn print(graph: &ScGraph) -> String {
let mut out = String::new();
out.push_str(&format!("sc.graph @{} {{\n", graph.name));
for op in &graph.ops {
out.push_str(" ");
match op {
ScOp::Input { id, name, ty } => {
out.push_str(&format!("{} = sc.input \"{}\" : {}\n", id, name, ty));
}
ScOp::Output { name, source, .. } => {
out.push_str(&format!("sc.output \"{}\" {}\n", name, source));
}
ScOp::Constant { id, value, ty } => {
let val_str = match value {
ScConst::F64(v) => format!("{v}"),
ScConst::I64(v) => format!("{v}"),
ScConst::U64(v) => format!("{v}"),
ScConst::F64Vec(v) => format!(
"[{}]",
v.iter()
.map(|x| format!("{x}"))
.collect::<Vec<_>>()
.join(", ")
),
ScConst::I64Vec(v) => format!(
"[{}]",
v.iter()
.map(|x| format!("{x}"))
.collect::<Vec<_>>()
.join(", ")
),
};
out.push_str(&format!("{} = sc.constant {} : {}\n", id, val_str, ty));
}
ScOp::Encode {
id,
prob,
length,
seed,
} => {
out.push_str(&format!(
"{} = sc.encode {}, length={}, seed=0x{:04X} : bitstream<{}>\n",
id, prob, length, seed, length
));
}
ScOp::BitwiseAnd { id, lhs, rhs } => {
out.push_str(&format!("{} = sc.and {}, {} : bitstream\n", id, lhs, rhs));
}
ScOp::BitwiseXor { id, lhs, rhs } => {
out.push_str(&format!("{} = sc.xor {}, {} : bitstream\n", id, lhs, rhs));
}
ScOp::Popcount { id, input } => {
out.push_str(&format!("{} = sc.popcount {} : u64\n", id, input));
}
ScOp::Reduce { id, input, mode } => {
out.push_str(&format!(
"{} = sc.reduce {}, mode={} : rate\n",
id, input, mode
));
}
ScOp::LifStep {
id,
current,
leak,
gain,
noise,
params,
} => {
out.push_str(&format!(
"{} = sc.lif_step {}, leak={}, gain={}, noise={}, \
dw={}, frac={}, vt={}, rp={} : (bool, fixed<{},{}>)\n",
id,
current,
leak,
gain,
noise,
params.data_width,
params.fraction,
params.v_threshold,
params.refractory_period,
params.data_width,
params.fraction
));
}
ScOp::DenseForward {
id,
inputs,
weights,
leak,
gain,
params,
} => {
out.push_str(&format!(
"{} = sc.dense_forward {}, weights={}, leak={}, gain={}, \
ni={}, nn={}, len={} : vec<bool,{}>\n",
id,
inputs,
weights,
leak,
gain,
params.n_inputs,
params.n_neurons,
params.stream_length,
params.n_neurons
));
}
ScOp::GraphForward {
id,
features,
adjacency,
n_nodes,
n_features,
} => {
out.push_str(&format!(
"{} = sc.graph_forward {}, adj={}, nodes={}, features={} : rate\n",
id, features, adjacency, n_nodes, n_features
));
}
ScOp::SoftmaxAttention { id, q, k, v, dim_k } => {
out.push_str(&format!(
"{} = sc.softmax_attention {}, {}, {}, dim_k={} : rate\n",
id, q, k, v, dim_k
));
}
ScOp::KuramotoStep {
id,
phases,
omega,
coupling,
dt,
} => {
out.push_str(&format!(
"{} = sc.kuramoto_step {}, omega={}, K={}, dt={} : rate\n",
id, phases, omega, coupling, dt
));
}
ScOp::Scale { id, input, factor } => {
out.push_str(&format!(
"{} = sc.scale {}, factor={} : rate\n",
id, input, factor
));
}
ScOp::Offset { id, input, offset } => {
out.push_str(&format!(
"{} = sc.offset {}, offset={} : rate\n",
id, input, offset
));
}
ScOp::DivConst { id, input, divisor } => {
out.push_str(&format!(
"{} = sc.div_const {}, divisor={} : u64\n",
id, input, divisor
));
}
}
}
out.push_str("}\n");
out
}