Fix a bug in conditional statement

This commit is contained in:
Guojie Luo 2022-03-21 23:26:17 +08:00
parent c0191515e6
commit 0ddac7d312
8 changed files with 66 additions and 78 deletions

2
Cargo.lock generated
View File

@ -125,13 +125,13 @@ name = "cst-to-llhd"
version = "0.1.0"
dependencies = [
"clap",
"env_logger",
"json",
"linked-hash-map",
"linked_hash_set",
"llhd",
"log",
"num",
"pretty_env_logger",
]
[[package]]

View File

@ -6,15 +6,15 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
log = "*"
env_logger = "*"
clap = "2"
json = "*"
llhd = "*"
log = "*"
num = "*"
linked_hash_set = "*"
linked-hash-map = "*"
pretty_env_logger = "0.4"
[[bin]]
name = "x-lint"
path = "src/bin/x-lint.rs"
name = "sv-to-llhd"
path = "src/bin/sv-to-llhd.rs"

View File

@ -3,8 +3,8 @@ extern crate clap;
extern crate json;
use clap::Arg;
use cst_to_llhd::cst::{CodeReporter, DescriptionList, Tag, Tools};
use env_logger;
use cst_to_llhd::cst::{DescriptionList, Tag};
use llhd::opt::{Pass, PassContext};
use std::{
process::{Command, Stdio},
result::Result,
@ -21,7 +21,7 @@ fn main() {
}
fn main_inner() -> Result<(), std::io::Error> {
env_logger::builder().format_timestamp(None).init();
pretty_env_logger::init_custom_env("X_LINT_LOG");
let matches = app_from_crate!()
.about("x-lint: a linter using both CST and LLHD.")
@ -65,9 +65,6 @@ fn main_inner() -> Result<(), std::io::Error> {
let sed_output = sed_output_child.wait_with_output()?;
//verible_output_child.wait()?;
//tr_output_child.wait()?;
ret = String::from_utf8(sed_output.stdout).unwrap();
}
}
@ -80,48 +77,15 @@ fn main_inner() -> Result<(), std::io::Error> {
let sv_file_name = json_top.entries().next().unwrap().0;
let code_reporter = CodeReporter::new(sv_file_name);
let json_tree = &json_top[sv_file_name]["tree"];
assert!(json_tree["tag"] == Tag::DESCRIPTION_LIST);
let module_list = DescriptionList::codegen(json_tree);
// temporary demo
for (module, json_module) in module_list {
for entity in module.entities() {
if entity.input_args().count() == 0 || entity.output_args().count() == 0 {
let json_terminal = Tools::match_tags(
vec![json_module],
vec![
Tag::MODULE_DECLARATION,
Tag::MODULE_HEADER,
Tag::SYMBOL_IDENTIFIER,
],
);
assert_eq!(json_terminal.len(), 1);
let start = json_terminal[0]["start"]
.to_string()
.parse::<usize>()
.unwrap();
let line_no = code_reporter.line_no(start);
println!(
"{}:{} | {}",
sv_file_name,
line_no + 1,
code_reporter.line(line_no)
);
println!(
r#"[warning] missing ports: entity "{}" has {} input ports and {} output ports"#,
entity.name(),
entity.input_args().count(),
entity.output_args().count()
);
println!("");
}
}
for (mut module, _json_module) in module_list {
let pass_ctx = PassContext;
llhd::pass::GlobalCommonSubexprElim::run_on_module(&pass_ctx, &mut module);
//llhd::pass::InstSimplification::run_on_module(&pass_ctx, &mut module);
llhd::assembly::write_module(std::io::stdout(), &module);
}

View File

@ -3,7 +3,6 @@ use json::JsonValue;
use llhd::{
ir::{Block, Inst, Opcode, Signature, UnitId, UnitKind, UnitName, Value},
ty::{int_ty, signal_ty, Type},
value::TimeValue,
};
use std::collections::{HashMap, HashSet};
@ -185,6 +184,8 @@ impl AlwaysStatement {
}
}
}
builder.finish(); // hack
}
fn gen_event_expression_list(json: &JsonValue, context: &mut ModuleContext) {
@ -282,11 +283,11 @@ impl AlwaysStatement {
let events: Vec<Value> = inputs
.iter()
.filter(|x| sensitivity_names.contains(&arg_value_to_raw_name[&x]))
.map(|x| {
.map(|&x| {
let raw_name = &arg_value_to_raw_name[&x];
let prb = builder.ins().prb(*x);
let prb = builder.ins().prb(x);
raw_name_to_prb_init.insert(raw_name, prb);
prb
x
})
.collect();
builder.ins().wait(bb_check, events);
@ -357,9 +358,7 @@ impl AlwaysStatement {
// initialize basic block "event"
builder.append_to(bb_event);
let delta_time = builder.ins().const_time(TimeValue::new(num::zero(), 1, 0));
unit_ctx.delta_time = Some(delta_time);
unit_ctx.bb_head.push(bb_event);
}
}

View File

@ -116,6 +116,7 @@ impl ConditionalStatement {
);
merge_to_bb_next(bb_if_false_dangled.unwrap(), builder);
} else {
builder.delete_block(bb_if_false);
bb_if_false = bb_next;
}
}

View File

@ -22,7 +22,6 @@ pub struct UnitContext {
pub raw_name_to_arg: HashMap<String, Arg>,
pub raw_name_to_value: HashMap<String, Value>,
pub raw_name_to_shadow: HashMap<String, Value>,
pub delta_time: Option<Value>,
pub bb_head: Vec<Block>,
pub ty_active: Option<Type>,
}
@ -73,7 +72,6 @@ impl UnitContext {
raw_name_to_arg: HashMap::new(),
raw_name_to_value: HashMap::new(),
raw_name_to_shadow: HashMap::new(),
delta_time: None,
bb_head: Vec::new(),
ty_active: None,
}
@ -92,7 +90,6 @@ impl UnitContext {
self.raw_name_to_arg.clear();
self.raw_name_to_value.clear();
self.raw_name_to_shadow.clear();
self.delta_time = None;
self.bb_head.clear();
self.ty_active = None;
}
@ -104,7 +101,6 @@ impl UnitContext {
&& self.raw_name_to_arg.is_empty()
&& self.raw_name_to_value.is_empty()
&& self.raw_name_to_shadow.is_empty()
&& self.delta_time.is_none()
&& self.bb_head.is_empty()
&& self.ty_active.is_none()
}

View File

@ -21,14 +21,7 @@ impl Expression {
Some(Tag::NUMBER) => Self::gen_number(json, context),
Some(Tag::REFERENCE_CALL_BASE) => Self::gen_reference_value(json, context),
Some(Tag::BINARY_EXPRESSION) => Self::gen_binary_expression(json, context),
Some(tag @ Tag::UNARY_PREFIX_EXPRESSION) => {
let json_children = &json["children"];
assert_eq!(json_children.len(), 2);
Self::codegen_internal(&json_children[1], context);
warn!("TODO: case '{}'", tag);
None
}
Some(Tag::UNARY_PREFIX_EXPRESSION) => Self::gen_unary_prefix_expression(json, context),
Some(tag @ Tag::CONDITION_EXPRESSION) => {
warn!("TODO: case '{}'", tag);
None
@ -126,6 +119,7 @@ impl Expression {
2 => {
let json_width = &json_children[0];
assert_eq!(json_width["tag"], Tag::DEC_NUMBER);
let w = json_width["text"].to_string().parse::<usize>().unwrap();
assert_eq!(json_children[1]["tag"], Tag::BASE_DIGITS);
assert_eq!(json_children[1]["children"].len(), 2);
@ -133,18 +127,22 @@ impl Expression {
let json_digits = &json_children[1]["children"][1];
match json_base["tag"].as_str() {
Some(Tag::HEX_BASE) => {
assert_eq!(json_base["tag"], Tag::HEX_BASE);
assert_eq!(json_digits["tag"], Tag::HEX_DIGITS);
let v =
usize::from_str_radix(json_digits["text"].as_str().unwrap(), 16)
.unwrap();
let num = builder.ins().const_int((w, v));
Some(num)
}
Some(Tag::BIN_BASE) => {
assert_eq!(json_base["tag"], Tag::BIN_BASE);
assert_eq!(json_digits["tag"], Tag::BIN_DIGITS);
let v = usize::from_str_radix(json_digits["text"].as_str().unwrap(), 2)
.unwrap();
let num = builder.ins().const_int((w, v));
Some(num)
}
_ => panic!("unknown error at CST node '{}'", json),
}
error!("FIXME: CST node '{}'", json);
panic!()
}
_ => panic!("unknown error at CST node '{}'", json),
}
@ -156,8 +154,8 @@ impl Expression {
fn gen_binary_expression(json: &JsonValue, context: &mut ModuleContext) -> Option<Value> {
let json_children = &json["children"];
assert_eq!(json_children.len(), 3);
let opt_opd_l = Self::codegen_internal(&json_children[0], context);
let opt_opd_r = Self::codegen_internal(&json_children[2], context);
let operand_l = Self::codegen_internal(&json_children[0], context);
let operand_r = Self::codegen_internal(&json_children[2], context);
if context.unit_ctx.data.is_some() {
let unit_ctx = &mut context.unit_ctx;
@ -165,12 +163,12 @@ impl Expression {
let mut builder = UnitContext::builder(&mut unit_ctx.data);
builder.append_to(bb_head);
if opt_opd_l.is_none() || opt_opd_r.is_none() {
if operand_l.is_none() || operand_r.is_none() {
error!("FIXME: CST node '{}'", json);
panic!();
}
let opd_l = opt_opd_l.unwrap();
let opd_r = opt_opd_r.unwrap();
let opd_l = operand_l.unwrap();
let opd_r = operand_r.unwrap();
match json_children[1]["tag"].as_str() {
Some("+") => {
@ -181,6 +179,10 @@ impl Expression {
let value = builder.ins().sub(opd_l, opd_r);
Some(value)
}
Some("==") => {
let value = builder.ins().eq(opd_l, opd_r);
Some(value)
}
Some(tag) => {
error!("FIXME: case '{}' missing", tag);
None
@ -191,4 +193,29 @@ impl Expression {
None
}
}
fn gen_unary_prefix_expression(json: &JsonValue, context: &mut ModuleContext) -> Option<Value> {
let json_children = &json["children"];
assert_eq!(json_children.len(), 2);
let expr = Self::codegen_internal(&json_children[1], context);
if context.unit_ctx.data.is_some() {
let unit_ctx = &mut context.unit_ctx;
let bb_head = *unit_ctx.bb_head.last().unwrap();
let mut builder = UnitContext::builder(&mut unit_ctx.data);
builder.append_to(bb_head);
match json_children[0]["tag"].as_str() {
Some("!") => {
let ty = &builder.unit().value_type(expr.unwrap());
let zero = builder.ins().const_zero(ty);
let value = builder.ins().neq(expr.unwrap(), zero);
Some(value)
}
_ => panic!("unknown error at CST node '{}'", json),
}
} else {
None
}
}
}

View File

@ -1,6 +1,6 @@
use crate::cst::{Expression, ModuleContext, Tag, Tools, UnitContext};
use json::JsonValue;
use llhd::ir::Block;
use llhd::{ir::Block, value::TimeValue};
#[allow(unused_imports)]
use log::{debug, error, info, trace, warn};
@ -61,10 +61,11 @@ impl NonblockingAssignmentStatement {
let mut builder = UnitContext::builder(&mut unit_ctx.data);
builder.append_to(bb_head);
let delta_time = builder.ins().const_time(TimeValue::new(num::zero(), 1, 0));
builder.ins().drv(
unit_ctx.raw_name_to_value[lvalue_name],
opt_expr.unwrap(),
unit_ctx.delta_time.unwrap(),
delta_time,
);
Some(bb_head)