verilator/
lib.rs

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
28/// Parse the version of verilator on `$PATH`
29pub 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                // Report what verilator says is ${VERILATOR_ROOT}
51                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}