1#[cfg(feature = "gen")]
2extern crate cc;
3#[cfg(feature = "module")]
4extern crate fnv;
5extern crate regex;
6#[cfg(feature = "module")]
7extern crate syn;
8
9#[cfg(feature = "gen")]
10pub mod gen;
11#[cfg(feature = "module")]
12pub mod module;
13
14use regex::Regex;
15use std::env;
16use std::path::{Path, PathBuf};
17use std::process::Command;
18use std::str::from_utf8;
19
20fn check_verilator_bin(path: &Path) -> bool {
21 path.join("verilator_bin").is_file()
22}
23
24fn check_verilator_root(root: &Path) -> bool {
25 root.join("include/verilated.cpp").is_file()
26}
27
28pub fn verilator_version() -> Option<(u32, u32)> {
30 let re = Regex::new(r"^Verilator (\d{1}).(\d{3})").expect("Failed to create version regex");
31 let output = Command::new("verilator_bin")
32 .arg("--version")
33 .output()
34 .ok()?;
35 let stdout = from_utf8(&output.stdout).ok()?;
36 let captures = re.captures(stdout)?;
37 let major = captures[1].parse::<u32>().ok()?;
38 let minor = captures[2].parse::<u32>().ok()?;
39 Some((major, minor))
40}
41
42pub fn find_verilator_root() -> Option<PathBuf> {
43 env::split_paths(&env::var_os("PATH").unwrap_or_default())
44 .find(|p| check_verilator_bin(p.as_ref()))
45 .and_then(|p| {
46 let mut cmd = Command::new(p.join("verilator_bin"));
47 cmd.arg("--getenv").arg("VERILATOR_ROOT");
48
49 cmd.output().ok().map(|output| {
50 PathBuf::from(String::from_utf8_lossy(&output.stdout).trim())
52 })
53 })
54 .or_else(|| env::var("VERILATOR_ROOT").map(PathBuf::from).ok())
55 .and_then(|p| {
56 if check_verilator_root(p.as_ref()) {
57 Some(p)
58 } else {
59 None
60 }
61 })
62}