Simplify some code

This commit is contained in:
Guojie Luo 2022-03-22 08:48:58 +08:00
parent 24c3b5128d
commit 47b085e249
3 changed files with 131 additions and 134 deletions

View File

@ -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);

View File

@ -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
},
)
}
}

View File

@ -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
},
)
}
}