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"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"env_logger",
|
|
||||||
"json",
|
"json",
|
||||||
"linked-hash-map",
|
"linked-hash-map",
|
||||||
"linked_hash_set",
|
"linked_hash_set",
|
||||||
"llhd",
|
"llhd",
|
||||||
"log",
|
"log",
|
||||||
"num",
|
"num",
|
||||||
|
"pretty_env_logger",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -6,15 +6,15 @@ edition = "2018"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
log = "*"
|
|
||||||
env_logger = "*"
|
|
||||||
clap = "2"
|
clap = "2"
|
||||||
json = "*"
|
json = "*"
|
||||||
llhd = "*"
|
llhd = "*"
|
||||||
|
log = "*"
|
||||||
num = "*"
|
num = "*"
|
||||||
linked_hash_set = "*"
|
linked_hash_set = "*"
|
||||||
linked-hash-map = "*"
|
linked-hash-map = "*"
|
||||||
|
pretty_env_logger = "0.4"
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "x-lint"
|
name = "sv-to-llhd"
|
||||||
path = "src/bin/x-lint.rs"
|
path = "src/bin/sv-to-llhd.rs"
|
||||||
|
|
|
@ -3,8 +3,8 @@ extern crate clap;
|
||||||
extern crate json;
|
extern crate json;
|
||||||
|
|
||||||
use clap::Arg;
|
use clap::Arg;
|
||||||
use cst_to_llhd::cst::{CodeReporter, DescriptionList, Tag, Tools};
|
use cst_to_llhd::cst::{DescriptionList, Tag};
|
||||||
use env_logger;
|
use llhd::opt::{Pass, PassContext};
|
||||||
use std::{
|
use std::{
|
||||||
process::{Command, Stdio},
|
process::{Command, Stdio},
|
||||||
result::Result,
|
result::Result,
|
||||||
|
@ -21,7 +21,7 @@ fn main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main_inner() -> Result<(), std::io::Error> {
|
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!()
|
let matches = app_from_crate!()
|
||||||
.about("x-lint: a linter using both CST and LLHD.")
|
.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()?;
|
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();
|
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 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"];
|
let json_tree = &json_top[sv_file_name]["tree"];
|
||||||
assert!(json_tree["tag"] == Tag::DESCRIPTION_LIST);
|
assert!(json_tree["tag"] == Tag::DESCRIPTION_LIST);
|
||||||
|
|
||||||
let module_list = DescriptionList::codegen(json_tree);
|
let module_list = DescriptionList::codegen(json_tree);
|
||||||
|
|
||||||
// temporary demo
|
for (mut module, _json_module) in module_list {
|
||||||
for (module, json_module) in module_list {
|
let pass_ctx = PassContext;
|
||||||
for entity in module.entities() {
|
llhd::pass::GlobalCommonSubexprElim::run_on_module(&pass_ctx, &mut module);
|
||||||
if entity.input_args().count() == 0 || entity.output_args().count() == 0 {
|
//llhd::pass::InstSimplification::run_on_module(&pass_ctx, &mut module);
|
||||||
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!("");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
llhd::assembly::write_module(std::io::stdout(), &module);
|
llhd::assembly::write_module(std::io::stdout(), &module);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@ use json::JsonValue;
|
||||||
use llhd::{
|
use llhd::{
|
||||||
ir::{Block, Inst, Opcode, Signature, UnitId, UnitKind, UnitName, Value},
|
ir::{Block, Inst, Opcode, Signature, UnitId, UnitKind, UnitName, Value},
|
||||||
ty::{int_ty, signal_ty, Type},
|
ty::{int_ty, signal_ty, Type},
|
||||||
value::TimeValue,
|
|
||||||
};
|
};
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
|
|
||||||
|
@ -185,6 +184,8 @@ impl AlwaysStatement {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
builder.finish(); // hack
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gen_event_expression_list(json: &JsonValue, context: &mut ModuleContext) {
|
fn gen_event_expression_list(json: &JsonValue, context: &mut ModuleContext) {
|
||||||
|
@ -282,11 +283,11 @@ impl AlwaysStatement {
|
||||||
let events: Vec<Value> = inputs
|
let events: Vec<Value> = inputs
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|x| sensitivity_names.contains(&arg_value_to_raw_name[&x]))
|
.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 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);
|
raw_name_to_prb_init.insert(raw_name, prb);
|
||||||
prb
|
x
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
builder.ins().wait(bb_check, events);
|
builder.ins().wait(bb_check, events);
|
||||||
|
@ -357,9 +358,7 @@ impl AlwaysStatement {
|
||||||
|
|
||||||
// initialize basic block "event"
|
// initialize basic block "event"
|
||||||
builder.append_to(bb_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);
|
unit_ctx.bb_head.push(bb_event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,6 +116,7 @@ impl ConditionalStatement {
|
||||||
);
|
);
|
||||||
merge_to_bb_next(bb_if_false_dangled.unwrap(), builder);
|
merge_to_bb_next(bb_if_false_dangled.unwrap(), builder);
|
||||||
} else {
|
} else {
|
||||||
|
builder.delete_block(bb_if_false);
|
||||||
bb_if_false = bb_next;
|
bb_if_false = bb_next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,6 @@ pub struct UnitContext {
|
||||||
pub raw_name_to_arg: HashMap<String, Arg>,
|
pub raw_name_to_arg: HashMap<String, Arg>,
|
||||||
pub raw_name_to_value: HashMap<String, Value>,
|
pub raw_name_to_value: HashMap<String, Value>,
|
||||||
pub raw_name_to_shadow: HashMap<String, Value>,
|
pub raw_name_to_shadow: HashMap<String, Value>,
|
||||||
pub delta_time: Option<Value>,
|
|
||||||
pub bb_head: Vec<Block>,
|
pub bb_head: Vec<Block>,
|
||||||
pub ty_active: Option<Type>,
|
pub ty_active: Option<Type>,
|
||||||
}
|
}
|
||||||
|
@ -73,7 +72,6 @@ impl UnitContext {
|
||||||
raw_name_to_arg: HashMap::new(),
|
raw_name_to_arg: HashMap::new(),
|
||||||
raw_name_to_value: HashMap::new(),
|
raw_name_to_value: HashMap::new(),
|
||||||
raw_name_to_shadow: HashMap::new(),
|
raw_name_to_shadow: HashMap::new(),
|
||||||
delta_time: None,
|
|
||||||
bb_head: Vec::new(),
|
bb_head: Vec::new(),
|
||||||
ty_active: None,
|
ty_active: None,
|
||||||
}
|
}
|
||||||
|
@ -92,7 +90,6 @@ impl UnitContext {
|
||||||
self.raw_name_to_arg.clear();
|
self.raw_name_to_arg.clear();
|
||||||
self.raw_name_to_value.clear();
|
self.raw_name_to_value.clear();
|
||||||
self.raw_name_to_shadow.clear();
|
self.raw_name_to_shadow.clear();
|
||||||
self.delta_time = None;
|
|
||||||
self.bb_head.clear();
|
self.bb_head.clear();
|
||||||
self.ty_active = None;
|
self.ty_active = None;
|
||||||
}
|
}
|
||||||
|
@ -104,7 +101,6 @@ impl UnitContext {
|
||||||
&& self.raw_name_to_arg.is_empty()
|
&& self.raw_name_to_arg.is_empty()
|
||||||
&& self.raw_name_to_value.is_empty()
|
&& self.raw_name_to_value.is_empty()
|
||||||
&& self.raw_name_to_shadow.is_empty()
|
&& self.raw_name_to_shadow.is_empty()
|
||||||
&& self.delta_time.is_none()
|
|
||||||
&& self.bb_head.is_empty()
|
&& self.bb_head.is_empty()
|
||||||
&& self.ty_active.is_none()
|
&& self.ty_active.is_none()
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,14 +21,7 @@ impl Expression {
|
||||||
Some(Tag::NUMBER) => Self::gen_number(json, context),
|
Some(Tag::NUMBER) => Self::gen_number(json, context),
|
||||||
Some(Tag::REFERENCE_CALL_BASE) => Self::gen_reference_value(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::BINARY_EXPRESSION) => Self::gen_binary_expression(json, context),
|
||||||
Some(tag @ Tag::UNARY_PREFIX_EXPRESSION) => {
|
Some(Tag::UNARY_PREFIX_EXPRESSION) => Self::gen_unary_prefix_expression(json, context),
|
||||||
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 @ Tag::CONDITION_EXPRESSION) => {
|
Some(tag @ Tag::CONDITION_EXPRESSION) => {
|
||||||
warn!("TODO: case '{}'", tag);
|
warn!("TODO: case '{}'", tag);
|
||||||
None
|
None
|
||||||
|
@ -126,6 +119,7 @@ impl Expression {
|
||||||
2 => {
|
2 => {
|
||||||
let json_width = &json_children[0];
|
let json_width = &json_children[0];
|
||||||
assert_eq!(json_width["tag"], Tag::DEC_NUMBER);
|
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]["tag"], Tag::BASE_DIGITS);
|
||||||
assert_eq!(json_children[1]["children"].len(), 2);
|
assert_eq!(json_children[1]["children"].len(), 2);
|
||||||
|
@ -133,18 +127,22 @@ impl Expression {
|
||||||
let json_digits = &json_children[1]["children"][1];
|
let json_digits = &json_children[1]["children"][1];
|
||||||
match json_base["tag"].as_str() {
|
match json_base["tag"].as_str() {
|
||||||
Some(Tag::HEX_BASE) => {
|
Some(Tag::HEX_BASE) => {
|
||||||
assert_eq!(json_base["tag"], Tag::HEX_BASE);
|
|
||||||
assert_eq!(json_digits["tag"], Tag::HEX_DIGITS);
|
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) => {
|
Some(Tag::BIN_BASE) => {
|
||||||
assert_eq!(json_base["tag"], Tag::BIN_BASE);
|
|
||||||
assert_eq!(json_digits["tag"], Tag::BIN_DIGITS);
|
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),
|
_ => panic!("unknown error at CST node '{}'", json),
|
||||||
}
|
}
|
||||||
|
|
||||||
error!("FIXME: CST node '{}'", json);
|
|
||||||
panic!()
|
|
||||||
}
|
}
|
||||||
_ => panic!("unknown error at CST node '{}'", json),
|
_ => panic!("unknown error at CST node '{}'", json),
|
||||||
}
|
}
|
||||||
|
@ -156,8 +154,8 @@ impl Expression {
|
||||||
fn gen_binary_expression(json: &JsonValue, context: &mut ModuleContext) -> Option<Value> {
|
fn gen_binary_expression(json: &JsonValue, context: &mut ModuleContext) -> Option<Value> {
|
||||||
let json_children = &json["children"];
|
let json_children = &json["children"];
|
||||||
assert_eq!(json_children.len(), 3);
|
assert_eq!(json_children.len(), 3);
|
||||||
let opt_opd_l = Self::codegen_internal(&json_children[0], context);
|
let operand_l = Self::codegen_internal(&json_children[0], context);
|
||||||
let opt_opd_r = Self::codegen_internal(&json_children[2], context);
|
let operand_r = Self::codegen_internal(&json_children[2], context);
|
||||||
|
|
||||||
if context.unit_ctx.data.is_some() {
|
if context.unit_ctx.data.is_some() {
|
||||||
let unit_ctx = &mut context.unit_ctx;
|
let unit_ctx = &mut context.unit_ctx;
|
||||||
|
@ -165,12 +163,12 @@ impl Expression {
|
||||||
let mut builder = UnitContext::builder(&mut unit_ctx.data);
|
let mut builder = UnitContext::builder(&mut unit_ctx.data);
|
||||||
builder.append_to(bb_head);
|
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);
|
error!("FIXME: CST node '{}'", json);
|
||||||
panic!();
|
panic!();
|
||||||
}
|
}
|
||||||
let opd_l = opt_opd_l.unwrap();
|
let opd_l = operand_l.unwrap();
|
||||||
let opd_r = opt_opd_r.unwrap();
|
let opd_r = operand_r.unwrap();
|
||||||
|
|
||||||
match json_children[1]["tag"].as_str() {
|
match json_children[1]["tag"].as_str() {
|
||||||
Some("+") => {
|
Some("+") => {
|
||||||
|
@ -181,6 +179,10 @@ impl Expression {
|
||||||
let value = builder.ins().sub(opd_l, opd_r);
|
let value = builder.ins().sub(opd_l, opd_r);
|
||||||
Some(value)
|
Some(value)
|
||||||
}
|
}
|
||||||
|
Some("==") => {
|
||||||
|
let value = builder.ins().eq(opd_l, opd_r);
|
||||||
|
Some(value)
|
||||||
|
}
|
||||||
Some(tag) => {
|
Some(tag) => {
|
||||||
error!("FIXME: case '{}' missing", tag);
|
error!("FIXME: case '{}' missing", tag);
|
||||||
None
|
None
|
||||||
|
@ -191,4 +193,29 @@ impl Expression {
|
||||||
None
|
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 crate::cst::{Expression, ModuleContext, Tag, Tools, UnitContext};
|
||||||
use json::JsonValue;
|
use json::JsonValue;
|
||||||
use llhd::ir::Block;
|
use llhd::{ir::Block, value::TimeValue};
|
||||||
|
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use log::{debug, error, info, trace, warn};
|
use log::{debug, error, info, trace, warn};
|
||||||
|
@ -61,10 +61,11 @@ impl NonblockingAssignmentStatement {
|
||||||
let mut builder = UnitContext::builder(&mut unit_ctx.data);
|
let mut builder = UnitContext::builder(&mut unit_ctx.data);
|
||||||
builder.append_to(bb_head);
|
builder.append_to(bb_head);
|
||||||
|
|
||||||
|
let delta_time = builder.ins().const_time(TimeValue::new(num::zero(), 1, 0));
|
||||||
builder.ins().drv(
|
builder.ins().drv(
|
||||||
unit_ctx.raw_name_to_value[lvalue_name],
|
unit_ctx.raw_name_to_value[lvalue_name],
|
||||||
opt_expr.unwrap(),
|
opt_expr.unwrap(),
|
||||||
unit_ctx.delta_time.unwrap(),
|
delta_time,
|
||||||
);
|
);
|
||||||
|
|
||||||
Some(bb_head)
|
Some(bb_head)
|
||||||
|
|
Loading…
Reference in New Issue