Add executable x-lint

This commit is contained in:
Guojie Luo 2022-02-19 15:29:58 +08:00
parent d3c4fbc626
commit 43ce73e5e2
3 changed files with 108 additions and 15 deletions

View File

@ -2,9 +2,8 @@
extern crate clap;
extern crate json;
mod cst;
use clap::Arg;
use cst_to_llhd::cst::{DescriptionList, Tag};
use std::{fs::File, io::Read, result::Result};
fn main() {
@ -42,21 +41,11 @@ fn main_inner() -> Result<(), String> {
println!("");
let json_tree = &json_top[sv_file_name]["tree"];
assert!(json_tree["tag"] == cst::Tag::DESCRIPTION_LIST);
assert!(json_tree["tag"] == Tag::DESCRIPTION_LIST);
let module_list = cst::DescriptionList::codegen(json_tree);
let module_list = DescriptionList::codegen(json_tree);
for module in module_list {
println!("{}", module.dump());
for entity in module.entities() {
println!(
r#"entity "{}" has {} input ports and {} output ports"#,
entity.name(),
entity.input_args().count(),
entity.output_args().count()
);
println!("");
}
}
Ok(())

104
src/bin/x-lint.rs Normal file
View File

@ -0,0 +1,104 @@
#[macro_use]
extern crate clap;
extern crate json;
use clap::Arg;
use cst_to_llhd::cst::{DescriptionList, Tag};
use std::{
process::{Command, Stdio},
result::Result,
};
fn main() {
match main_inner() {
Ok(_) => (),
Err(e) => {
eprintln!("Error: {}", e);
std::process::exit(1);
}
}
}
fn main_inner() -> Result<(), std::io::Error> {
let matches = app_from_crate!()
.about("x-lint: a linter using both CST and LLHD.")
.arg(
Arg::with_name("input")
.help("the Verilog file for linting")
.required(true),
)
.get_matches();
let json_raw = {
let mut ret = String::new();
let input = matches.value_of("input").unwrap();
let cmd_verible = "verible-verilog-syntax";
let cmd_tr = "tr";
let cmd_sed = "sed";
let mut verible_output_child = Command::new("verible-verilog-syntax")
.args(&["--printtree", "--export_json", input])
.stdout(Stdio::piped())
.spawn()
.expect(cmd_not_found(cmd_verible).as_str());
if let Some(verible_output) = verible_output_child.stdout.take() {
let mut tr_output_child = Command::new("tr")
.args(&["-d", r#"' \t\n'"#])
.stdin(verible_output)
.stdout(Stdio::piped())
.spawn()
.expect(cmd_not_found(cmd_tr).as_str());
verible_output_child.wait()?;
if let Some(tr_output) = tr_output_child.stdout.take() {
let sed_output_child = Command::new("sed")
.args(&["-e", r#"s/,null//g"#, "-e", r#"s/null,//g"#])
.stdin(tr_output)
.stdout(Stdio::piped())
.spawn()
.expect(cmd_not_found(cmd_sed).as_str());
let sed_output = sed_output_child.wait_with_output()?;
tr_output_child.wait()?;
ret = String::from_utf8(sed_output.stdout).unwrap();
}
}
ret
};
let json_top = json::parse(json_raw.as_str()).unwrap();
assert!(json_top.len() == 1);
let sv_file_name = json_top.entries().next().unwrap().0;
println!(r#"codegen from CST to LLHD for "{}" ..."#, sv_file_name);
println!("");
let json_tree = &json_top[sv_file_name]["tree"];
assert!(json_tree["tag"] == Tag::DESCRIPTION_LIST);
let module_list = DescriptionList::codegen(json_tree);
for module in module_list {
for entity in module.entities() {
println!(
r#"entity "{}" has {} input ports and {} output ports"#,
entity.name(),
entity.input_args().count(),
entity.output_args().count()
);
println!("");
}
}
Ok(())
}
fn cmd_not_found(cmd: &str) -> String {
format!(r#"command "{}" not found"#, cmd)
}

View File

@ -14,7 +14,7 @@ EOF
)
if [[ -f $verilog ]] ; then
verible-verilog-syntax --printtree --export_json $verilog | tr -d ' \t\n' | sed "s/,null//g" | sed "s/null,//g" | jq
verible-verilog-syntax --printtree --export_json $verilog | tr -d ' \t\n' | sed -e "s/,null//g" -e "s/null,//g" | jq
else
echo "$usage"
echo ""