use std::path::PathBuf;
use veryl_analyzer::ir as air;
use veryl_analyzer::{Analyzer, Context};
use veryl_metadata::Metadata;
use veryl_parser::Parser;
use veryl_simulator::ir::Event;
use veryl_simulator::ir::{self, Ir};
use veryl_simulator::{Config, Simulator};
#[derive(clap::Parser)]
pub struct Opt {
pub path: Option<PathBuf>,
#[arg(long)]
pub cycle: Option<usize>,
#[arg(long)]
pub use_4state: bool,
#[arg(long)]
pub use_jit: bool,
#[arg(long)]
pub dump_cranelift: bool,
#[arg(long)]
pub dump_asm: bool,
#[arg(long)]
pub disable_ff_opt: bool,
}
impl From<Opt> for Config {
fn from(value: Opt) -> Self {
let mut ret = Self {
use_jit: value.use_jit,
use_4state: value.use_4state,
dump_cranelift: value.dump_cranelift,
dump_asm: value.dump_asm,
disable_ff_opt: value.disable_ff_opt,
..Default::default()
};
ret.apply_env();
ret
}
}
fn build(code: &str, top: &str, config: &Config) -> Ir {
let metadata = Metadata::create_default("prj").unwrap();
let parser = Parser::parse(code, &"").unwrap();
let analyzer = Analyzer::new(&metadata);
let mut context = Context::default();
let mut ir = air::Ir::default();
analyzer.analyze_pass1("prj", &parser.veryl);
Analyzer::analyze_post_pass1();
analyzer.analyze_pass2("prj", &parser.veryl, &mut context, Some(&mut ir));
ir::build_ir(&ir, top.into(), config).expect("Failed to build IR")
}
fn main() {
use clap::Parser;
let opt = Opt::parse();
let code = if let Some(path) = &opt.path {
std::fs::read_to_string(path).unwrap()
} else {
r#"
module Top #(
param N: u32 = 1000,
)(
clk: input clock,
rst: input reset,
cnt: output logic<32>[N],
) {
for i in 0..N: g {
always_ff {
if_reset {
cnt[i] = 0;
} else {
cnt[i] += 1;
}
}
}
}
"#
.to_string()
};
let code = &code;
let cycle = opt.cycle.unwrap_or(1000000);
let config: Config = opt.into();
let ir = build(code, "Top", &config);
let mut sim = Simulator::new(ir, None);
let clk = sim.get_clock("clk").unwrap();
let rst = sim.get_reset("rst").unwrap();
sim.step(&Event::Initial);
sim.step(&rst);
for _ in 0..cycle {
sim.step(&clk);
}
println!("{}", sim.ir.dump_variables());
let (jit, total) = sim.ir.jit_stats();
if total > 0 {
let pct = jit as f64 / total as f64 * 100.0;
eprintln!("JIT: {jit}/{total} statements ({pct:.1}%)");
}
eprintln!("FF commit entries: {}", sim.ir.ff_commit_entries.len());
eprintln!(
"FF buffer: {} bytes, Comb buffer: {} bytes",
sim.ir.ff_values.len(),
sim.ir.comb_values.len()
);
let (cj, ci, ej, ei) = sim.ir.detailed_stats();
eprintln!(" comb: {cj} JIT + {ci} interp = {}", cj + ci);
eprintln!(" event: {ej} JIT + {ei} interp = {}", ej + ei);
veryl_analyzer::stopwatch::dump();
}