Fix a bug in conditional statement
This commit is contained in:
parent
c0191515e6
commit
0ddac7d312
|
@ -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]]
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue