Simplify some code
This commit is contained in:
parent
24c3b5128d
commit
47b085e249
|
@ -2,9 +2,9 @@ use crate::cst::{Expression, ModuleContext, Statement, SymbolKind, Tag, Tools, U
|
|||
use json::JsonValue;
|
||||
use llhd::{
|
||||
ir::{Block, Inst, Opcode, Signature, UnitId, UnitKind, UnitName, Value},
|
||||
ty::{int_ty, signal_ty, Type},
|
||||
ty::{int_ty, signal_ty},
|
||||
};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use log::{debug, error, info, trace, warn};
|
||||
|
@ -128,7 +128,6 @@ impl AlwaysStatement {
|
|||
builder.ins().br(bb_first);
|
||||
|
||||
// remove blocks with a single jump
|
||||
// to-do: consider using dead-code-elimination in llhd
|
||||
{
|
||||
let single_inst_blocks: Vec<Block> = builder
|
||||
.unit()
|
||||
|
@ -187,7 +186,7 @@ impl AlwaysStatement {
|
|||
}
|
||||
|
||||
fn gen_event_expression_list(json: &JsonValue, context: &mut ModuleContext) {
|
||||
let mut sensitivity_list = Vec::new();
|
||||
let mut sensitivity_list = HashMap::new();
|
||||
|
||||
let json_expressions = Tools::match_tags(
|
||||
vec![json],
|
||||
|
@ -197,22 +196,21 @@ impl AlwaysStatement {
|
|||
let json_children = &json_expression["children"];
|
||||
assert!(json_children.len() == 1 || json_children.len() == 2);
|
||||
|
||||
warn!("WARN: not yet support complex event expressions");
|
||||
match json_children[0]["tag"].as_str() {
|
||||
Some(Tag::POS_EDGE) => {
|
||||
let symbol =
|
||||
Expression::gen_reference_name(&json_children[1]["children"][0], context);
|
||||
sensitivity_list.push((symbol, Tag::POS_EDGE));
|
||||
sensitivity_list.insert(symbol, Tag::POS_EDGE);
|
||||
}
|
||||
Some(Tag::NEG_EDGE) => {
|
||||
let symbol =
|
||||
Expression::gen_reference_name(&json_children[1]["children"][0], context);
|
||||
sensitivity_list.push((symbol, Tag::NEG_EDGE));
|
||||
sensitivity_list.insert(symbol, Tag::NEG_EDGE);
|
||||
}
|
||||
Some(Tag::EXPRESSION) => {
|
||||
let symbol =
|
||||
Expression::gen_reference_name(&json_children[0]["children"][0], context);
|
||||
sensitivity_list.push((symbol, Tag::EVENT_EXPRESSION));
|
||||
sensitivity_list.insert(symbol, Tag::EVENT_EXPRESSION);
|
||||
}
|
||||
_ => panic!("unknown error at CST node '{}'", json),
|
||||
}
|
||||
|
@ -236,19 +234,6 @@ impl AlwaysStatement {
|
|||
raw_name_to_value.insert(name.clone(), value);
|
||||
}
|
||||
|
||||
let sensitivity_names: HashSet<String> =
|
||||
sensitivity_list.iter().map(|(x, _)| x.clone()).collect();
|
||||
let sensitivity_list_plus: Vec<(String, &str, Type)> = sensitivity_list
|
||||
.iter()
|
||||
.map(|(x, y)| {
|
||||
(
|
||||
x.clone(),
|
||||
y.clone(),
|
||||
builder.unit().value_type(raw_name_to_value[x]),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
|
||||
let bb_zero = builder.block();
|
||||
let bb_init = builder.named_block("init");
|
||||
let bb_check = builder.named_block("check");
|
||||
|
@ -280,7 +265,7 @@ impl AlwaysStatement {
|
|||
let inputs: Vec<Value> = builder.unit().input_args().collect();
|
||||
let events: Vec<Value> = inputs
|
||||
.iter()
|
||||
.filter(|x| sensitivity_names.contains(&arg_value_to_raw_name[&x]))
|
||||
.filter(|x| sensitivity_list.contains_key(&arg_value_to_raw_name[&x]))
|
||||
.map(|&x| {
|
||||
let raw_name = &arg_value_to_raw_name[&x];
|
||||
let prb = builder.ins().prb(x);
|
||||
|
@ -299,52 +284,44 @@ impl AlwaysStatement {
|
|||
let output_prb = builder.ins().prb(*output);
|
||||
builder.ins().st(*output_shadow, output_prb);
|
||||
});
|
||||
let mut zeros = HashMap::new();
|
||||
let mut last_event = None;
|
||||
for (i, (raw_name, tag, value_type)) in sensitivity_list_plus.iter().enumerate() {
|
||||
let v = raw_name_to_value[raw_name];
|
||||
for (i, (raw_name, tag)) in sensitivity_list.iter().enumerate() {
|
||||
let val = raw_name_to_value[raw_name];
|
||||
let ty = builder.unit().value_type(val);
|
||||
let prb_init = raw_name_to_prb_init[raw_name];
|
||||
let prb = builder.ins().prb(v);
|
||||
let prb = builder.ins().prb(val);
|
||||
|
||||
let (name, event) = if *tag == Tag::POS_EDGE || *tag == Tag::NEG_EDGE {
|
||||
let zero = if zeros.contains_key(value_type) {
|
||||
zeros[value_type]
|
||||
} else {
|
||||
let z = builder.ins().const_zero(value_type.unwrap_signal());
|
||||
zeros.insert(value_type.clone(), z);
|
||||
z
|
||||
};
|
||||
let (mut n, v) = if *tag == Tag::POS_EDGE {
|
||||
let eq = builder.ins().eq(prb_init, zero);
|
||||
let neq = builder.ins().neq(prb, zero);
|
||||
(String::from("posedge"), builder.ins().and(eq, neq))
|
||||
} else {
|
||||
let neq = builder.ins().neq(prb_init, zero);
|
||||
let eq = builder.ins().eq(prb, zero);
|
||||
(String::from("negedge"), builder.ins().and(neq, eq))
|
||||
let (name, event) = {
|
||||
let (mut n, v) = match *tag {
|
||||
Tag::POS_EDGE => {
|
||||
let zero = builder.ins().const_zero(ty.unwrap_signal());
|
||||
let eq = builder.ins().eq(prb_init, zero);
|
||||
let neq = builder.ins().neq(prb, zero);
|
||||
(String::from("posedge"), builder.ins().and(eq, neq))
|
||||
}
|
||||
Tag::NEG_EDGE => {
|
||||
let zero = builder.ins().const_zero(ty.unwrap_signal());
|
||||
let neq = builder.ins().neq(prb_init, zero);
|
||||
let eq = builder.ins().eq(prb, zero);
|
||||
(String::from("negedge"), builder.ins().and(neq, eq))
|
||||
}
|
||||
_ => (String::from("impledge"), builder.ins().neq(prb_init, prb)),
|
||||
};
|
||||
if i > 0 {
|
||||
n = format!("{}{}", n, i);
|
||||
}
|
||||
(n, v)
|
||||
} else {
|
||||
let n = if i > 0 {
|
||||
format!("impledge{}", i - 1)
|
||||
} else {
|
||||
String::from("impledge")
|
||||
};
|
||||
let v = builder.ins().neq(prb_init, prb);
|
||||
(n, v)
|
||||
};
|
||||
builder.set_name(event, name);
|
||||
|
||||
if i > 0 {
|
||||
let event_or = builder.ins().or(last_event.unwrap(), event);
|
||||
if i > 1 {
|
||||
builder.set_name(event_or, format!("event_or{}", i - 1))
|
||||
let name = if i > 1 {
|
||||
format!("event_or{}", i - 1)
|
||||
} else {
|
||||
builder.set_name(event_or, String::from("event_or"));
|
||||
}
|
||||
String::from("event_or")
|
||||
};
|
||||
builder.set_name(event_or, name);
|
||||
last_event = Some(event_or);
|
||||
} else {
|
||||
last_event = Some(event);
|
||||
|
|
|
@ -9,48 +9,7 @@ pub struct CaseStatement {}
|
|||
|
||||
impl CaseStatement {
|
||||
pub fn codegen(json: &JsonValue, context: &mut ModuleContext) -> Option<Block> {
|
||||
let (json_expression, json_case_items, json_default_statement) = {
|
||||
let js_expression = Tools::match_tags(
|
||||
vec![json],
|
||||
vec![Tag::CASE_STATEMENT, Tag::PAREN_GROUP, Tag::EXPRESSION],
|
||||
);
|
||||
assert_eq!(js_expression.len(), 1);
|
||||
|
||||
let js_case_items: Vec<_> = Tools::match_tags(
|
||||
vec![json],
|
||||
vec![Tag::CASE_STATEMENT, Tag::CASE_ITEM_LIST, Tag::CASE_ITEM],
|
||||
)
|
||||
.iter()
|
||||
.map(|js_case_item| {
|
||||
let js_children = &js_case_item["children"];
|
||||
assert_eq!(js_children.len(), 3);
|
||||
|
||||
let js_case_expressions =
|
||||
Tools::match_tags(js_children[0].members().collect(), vec![Tag::EXPRESSION]);
|
||||
|
||||
let js_statement = &js_children[2];
|
||||
|
||||
(js_case_expressions, js_statement)
|
||||
})
|
||||
.collect();
|
||||
assert!(js_case_items.len() > 0);
|
||||
|
||||
let js_default_item = Tools::match_tags(
|
||||
vec![json],
|
||||
vec![Tag::CASE_STATEMENT, Tag::CASE_ITEM_LIST, Tag::DEFAULT_ITEM],
|
||||
);
|
||||
assert!(js_default_item.len() <= 1);
|
||||
|
||||
(
|
||||
js_expression[0],
|
||||
js_case_items,
|
||||
if js_default_item.len() > 0 {
|
||||
Some(&js_default_item[0]["children"][2])
|
||||
} else {
|
||||
None
|
||||
},
|
||||
)
|
||||
};
|
||||
let (json_expression, json_case_items, json_default_statement) = Self::analyze(json);
|
||||
|
||||
Expression::codegen(json_expression, context);
|
||||
|
||||
|
@ -68,4 +27,53 @@ impl CaseStatement {
|
|||
warn!("TODO: finish codegen()");
|
||||
None
|
||||
}
|
||||
|
||||
fn analyze(
|
||||
json: &JsonValue,
|
||||
) -> (
|
||||
&JsonValue,
|
||||
Vec<(Vec<&JsonValue>, &JsonValue)>,
|
||||
Option<&JsonValue>,
|
||||
) {
|
||||
let json_expression = Tools::match_tags(
|
||||
vec![json],
|
||||
vec![Tag::CASE_STATEMENT, Tag::PAREN_GROUP, Tag::EXPRESSION],
|
||||
);
|
||||
assert_eq!(json_expression.len(), 1);
|
||||
|
||||
let json_case_items: Vec<_> = Tools::match_tags(
|
||||
vec![json],
|
||||
vec![Tag::CASE_STATEMENT, Tag::CASE_ITEM_LIST, Tag::CASE_ITEM],
|
||||
)
|
||||
.iter()
|
||||
.map(|json_case_item| {
|
||||
let json_children = &json_case_item["children"];
|
||||
assert_eq!(json_children.len(), 3);
|
||||
|
||||
let json_case_expressions =
|
||||
Tools::match_tags(json_children[0].members().collect(), vec![Tag::EXPRESSION]);
|
||||
|
||||
let json_statement = &json_children[2];
|
||||
|
||||
(json_case_expressions, json_statement)
|
||||
})
|
||||
.collect();
|
||||
assert!(json_case_items.len() > 0);
|
||||
|
||||
let json_default_item = Tools::match_tags(
|
||||
vec![json],
|
||||
vec![Tag::CASE_STATEMENT, Tag::CASE_ITEM_LIST, Tag::DEFAULT_ITEM],
|
||||
);
|
||||
assert!(json_default_item.len() <= 1);
|
||||
|
||||
(
|
||||
json_expression[0],
|
||||
json_case_items,
|
||||
if json_default_item.len() > 0 {
|
||||
Some(&json_default_item[0]["children"][2])
|
||||
} else {
|
||||
None
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,36 +9,13 @@ pub struct ConditionalStatement {}
|
|||
|
||||
impl ConditionalStatement {
|
||||
pub fn codegen(json: &JsonValue, context: &mut ModuleContext) -> Option<Block> {
|
||||
let json_if_header = Tools::match_tags(
|
||||
vec![json],
|
||||
vec![
|
||||
Tag::CONDITIONAL_STATEMENT,
|
||||
Tag::IF_CLAUSE,
|
||||
Tag::IF_HEADER,
|
||||
Tag::PAREN_GROUP,
|
||||
Tag::EXPRESSION,
|
||||
],
|
||||
);
|
||||
assert_eq!(json_if_header.len(), 1);
|
||||
|
||||
let json_if_body = Tools::match_tags(
|
||||
vec![json],
|
||||
vec![Tag::CONDITIONAL_STATEMENT, Tag::IF_CLAUSE, Tag::IF_BODY],
|
||||
);
|
||||
assert_eq!(json_if_body.len(), 1);
|
||||
|
||||
let json_else_body = Tools::match_tags(
|
||||
vec![json],
|
||||
vec![Tag::CONDITIONAL_STATEMENT, Tag::ELSE_CLAUSE, Tag::ELSE_BODY],
|
||||
);
|
||||
assert!(json_else_body.len() <= 1);
|
||||
let has_else_body = json_else_body.len() > 0;
|
||||
let (json_if_header, json_if_body, json_else_body) = Self::analyze(json);
|
||||
|
||||
if context.unit_ctx.data.is_none() {
|
||||
Expression::codegen(json_if_header[0], context);
|
||||
Self::visit_ite_body(json_if_body[0], context);
|
||||
if json_else_body.len() > 0 {
|
||||
Self::visit_ite_body(json_else_body[0], context);
|
||||
Expression::codegen(json_if_header, context);
|
||||
Self::visit_ite_body(json_if_body, context);
|
||||
if json_else_body.is_some() {
|
||||
Self::visit_ite_body(json_else_body.unwrap(), context);
|
||||
}
|
||||
return None;
|
||||
}
|
||||
|
@ -71,19 +48,18 @@ impl ConditionalStatement {
|
|||
};
|
||||
|
||||
// traverse json_if_header
|
||||
let expr_if_header = Expression::codegen(json_if_header[0], context);
|
||||
let expr_if_header = Expression::codegen(json_if_header, context);
|
||||
|
||||
// traverse json_if_body with active basic block "if_true"
|
||||
context.unit_ctx.bb_head.push(bb_if_true);
|
||||
let bb_if_true_dangled = Self::visit_ite_body(json_if_body[0], context);
|
||||
let bb_if_true_dangled = Self::visit_ite_body(json_if_body, context);
|
||||
context.unit_ctx.bb_head.pop();
|
||||
|
||||
// traverse json_else_body with active basic block "if_false"
|
||||
context.unit_ctx.bb_head.push(bb_if_false);
|
||||
let bb_if_false_dangled = if has_else_body {
|
||||
Self::visit_ite_body(json_else_body[0], context)
|
||||
} else {
|
||||
None
|
||||
let bb_if_false_dangled = match json_else_body {
|
||||
Some(x) => Self::visit_ite_body(x, context),
|
||||
None => None,
|
||||
};
|
||||
context.unit_ctx.bb_head.pop();
|
||||
|
||||
|
@ -94,7 +70,7 @@ impl ConditionalStatement {
|
|||
assert!(
|
||||
bb_if_true_dangled.is_some(),
|
||||
"FIXME: CST node '{}'",
|
||||
json_if_body[0]
|
||||
json_if_body
|
||||
);
|
||||
let bb_next = builder.block();
|
||||
|
||||
|
@ -108,11 +84,11 @@ impl ConditionalStatement {
|
|||
|
||||
merge_to_bb_next(bb_if_true_dangled.unwrap(), builder);
|
||||
|
||||
if has_else_body {
|
||||
if json_else_body.is_some() {
|
||||
assert!(
|
||||
bb_if_false_dangled.is_some(),
|
||||
"FIXME: CST node '{}'",
|
||||
json_else_body[0]
|
||||
json_else_body.unwrap()
|
||||
);
|
||||
merge_to_bb_next(bb_if_false_dangled.unwrap(), builder);
|
||||
} else {
|
||||
|
@ -128,7 +104,7 @@ impl ConditionalStatement {
|
|||
assert!(
|
||||
expr_if_header.is_some(),
|
||||
"FIXME: CST node '{}'",
|
||||
json_if_header[0]
|
||||
json_if_header
|
||||
);
|
||||
builder
|
||||
.ins()
|
||||
|
@ -158,4 +134,40 @@ impl ConditionalStatement {
|
|||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn analyze(json: &JsonValue) -> (&JsonValue, &JsonValue, Option<&JsonValue>) {
|
||||
let json_if_header = Tools::match_tags(
|
||||
vec![json],
|
||||
vec![
|
||||
Tag::CONDITIONAL_STATEMENT,
|
||||
Tag::IF_CLAUSE,
|
||||
Tag::IF_HEADER,
|
||||
Tag::PAREN_GROUP,
|
||||
Tag::EXPRESSION,
|
||||
],
|
||||
);
|
||||
assert_eq!(json_if_header.len(), 1);
|
||||
|
||||
let json_if_body = Tools::match_tags(
|
||||
vec![json],
|
||||
vec![Tag::CONDITIONAL_STATEMENT, Tag::IF_CLAUSE, Tag::IF_BODY],
|
||||
);
|
||||
assert_eq!(json_if_body.len(), 1);
|
||||
|
||||
let json_else_body = Tools::match_tags(
|
||||
vec![json],
|
||||
vec![Tag::CONDITIONAL_STATEMENT, Tag::ELSE_CLAUSE, Tag::ELSE_BODY],
|
||||
);
|
||||
assert!(json_else_body.len() <= 1);
|
||||
|
||||
(
|
||||
json_if_header[0],
|
||||
json_if_body[0],
|
||||
if json_else_body.len() > 0 {
|
||||
Some(json_else_body[0])
|
||||
} else {
|
||||
None
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue