Debug case statement by supporting other semantics
This commit is contained in:
parent
83dfd6e618
commit
f3f7113dc5
|
@ -84,7 +84,7 @@ fn main_inner() -> Result<(), std::io::Error> {
|
||||||
|
|
||||||
for (mut module, _json_module) in module_list {
|
for (mut module, _json_module) in module_list {
|
||||||
let pass_ctx = PassContext;
|
let pass_ctx = PassContext;
|
||||||
llhd::pass::GlobalCommonSubexprElim::run_on_module(&pass_ctx, &mut module);
|
//llhd::pass::GlobalCommonSubexprElim::run_on_module(&pass_ctx, &mut module);
|
||||||
//llhd::pass::InstSimplification::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);
|
llhd::assembly::write_module(std::io::stdout(), &module);
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,8 +137,11 @@ impl CaseStatement {
|
||||||
let json_children = &json_case_item["children"];
|
let json_children = &json_case_item["children"];
|
||||||
assert_eq!(json_children.len(), 3);
|
assert_eq!(json_children.len(), 3);
|
||||||
|
|
||||||
let json_case_expressions =
|
let json_case_expressions = Tools::match_tags(
|
||||||
Tools::match_tags(json_children[0].members().collect(), vec![Tag::EXPRESSION]);
|
vec![&json_children[0]],
|
||||||
|
vec![Tag::EXPRESSION_LIST, Tag::EXPRESSION],
|
||||||
|
);
|
||||||
|
assert!(json_case_expressions.len() > 0);
|
||||||
|
|
||||||
let json_statement = &json_children[2];
|
let json_statement = &json_children[2];
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ use linked_hash_set::LinkedHashSet;
|
||||||
use llhd::{
|
use llhd::{
|
||||||
ir::{Arg, Block, Module, Signature, UnitBuilder, UnitData, UnitKind, UnitName, Value},
|
ir::{Arg, Block, Module, Signature, UnitBuilder, UnitData, UnitKind, UnitName, Value},
|
||||||
ty::Type,
|
ty::Type,
|
||||||
|
value::IntValue,
|
||||||
};
|
};
|
||||||
use std::{collections::HashMap, fmt};
|
use std::{collections::HashMap, fmt};
|
||||||
|
|
||||||
|
@ -10,6 +11,7 @@ pub struct ModuleContext {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub module: Module,
|
pub module: Module,
|
||||||
pub symbol: LinkedHashMap<String, SymbolInfo>,
|
pub symbol: LinkedHashMap<String, SymbolInfo>,
|
||||||
|
pub param: LinkedHashMap<String, IntValue>,
|
||||||
pub unit_ctx: UnitContext,
|
pub unit_ctx: UnitContext,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,6 +60,7 @@ impl ModuleContext {
|
||||||
name: String::new(),
|
name: String::new(),
|
||||||
module: Module::new(),
|
module: Module::new(),
|
||||||
symbol: LinkedHashMap::new(),
|
symbol: LinkedHashMap::new(),
|
||||||
|
param: LinkedHashMap::new(),
|
||||||
unit_ctx: UnitContext::new(),
|
unit_ctx: UnitContext::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
use crate::cst::{ModuleContext, Tag, Tools, UnitContext};
|
use crate::cst::{ModuleContext, Tag, Tools, UnitContext};
|
||||||
use json::JsonValue;
|
use json::JsonValue;
|
||||||
use llhd::ir::Value;
|
use llhd::{
|
||||||
|
ir::{UnitBuilder, Value},
|
||||||
|
ty::int_ty,
|
||||||
|
value::IntValue,
|
||||||
|
};
|
||||||
|
use num::BigInt;
|
||||||
|
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use log::{debug, error, info, trace, warn};
|
use log::{debug, error, info, trace, warn};
|
||||||
|
@ -26,9 +31,8 @@ impl Expression {
|
||||||
warn!("TODO: case '{}'", tag);
|
warn!("TODO: case '{}'", tag);
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
Some(tag @ Tag::CONCATENATION_EXPRESSION) => {
|
Some(Tag::CONCATENATION_EXPRESSION) => {
|
||||||
warn!("TODO: case '{}'", tag);
|
Self::gen_concatenation_expression(json, context)
|
||||||
None
|
|
||||||
}
|
}
|
||||||
Some(Tag::PAREN_GROUP) => {
|
Some(Tag::PAREN_GROUP) => {
|
||||||
let json_expression =
|
let json_expression =
|
||||||
|
@ -67,85 +71,96 @@ impl Expression {
|
||||||
let raw_name_to_value = &mut unit_ctx.raw_name_to_value;
|
let raw_name_to_value = &mut unit_ctx.raw_name_to_value;
|
||||||
let raw_name_to_shadow = &unit_ctx.raw_name_to_shadow;
|
let raw_name_to_shadow = &unit_ctx.raw_name_to_shadow;
|
||||||
|
|
||||||
assert!(
|
if raw_name_to_value.contains_key(&symbol) {
|
||||||
raw_name_to_value.contains_key(&symbol),
|
let value = raw_name_to_value[&symbol];
|
||||||
"symbol '{}' not found",
|
let shadow = raw_name_to_shadow.get(&symbol).cloned();
|
||||||
symbol
|
|
||||||
);
|
|
||||||
let value = raw_name_to_value[&symbol];
|
|
||||||
|
|
||||||
let shadow = raw_name_to_shadow.get(&symbol).cloned();
|
let mut builder = UnitContext::builder(&mut unit_ctx.data);
|
||||||
|
let bb_head = *unit_ctx.bb_head.last().unwrap();
|
||||||
|
builder.append_to(bb_head);
|
||||||
|
|
||||||
let mut builder = UnitContext::builder(&mut unit_ctx.data);
|
Some(match shadow {
|
||||||
let bb_head = *unit_ctx.bb_head.last().unwrap();
|
None => builder.ins().prb(value),
|
||||||
builder.append_to(bb_head);
|
Some(s) => builder.ins().ld(s),
|
||||||
|
})
|
||||||
|
} else if context.param.contains_key(&symbol) {
|
||||||
|
let mut builder = UnitContext::builder(&mut unit_ctx.data);
|
||||||
|
let bb_head = *unit_ctx.bb_head.last().unwrap();
|
||||||
|
builder.append_to(bb_head);
|
||||||
|
|
||||||
Some(match shadow {
|
Some(builder.ins().const_int(context.param[&symbol].clone()))
|
||||||
None => builder.ins().prb(value),
|
} else {
|
||||||
Some(s) => builder.ins().ld(s),
|
panic!("unknown error at CST node {}", json);
|
||||||
})
|
}
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gen_number(json: &JsonValue, context: &mut ModuleContext) -> Option<Value> {
|
pub fn parse_number(json: &JsonValue) -> IntValue {
|
||||||
let json_children = &json["children"];
|
let json_children = &json["children"];
|
||||||
|
|
||||||
|
match json_children.len() {
|
||||||
|
1 => {
|
||||||
|
let json_child = &json_children[0];
|
||||||
|
match json_child["tag"].as_str() {
|
||||||
|
Some(Tag::DEC_NUMBER) => {
|
||||||
|
let value = BigInt::parse_bytes(
|
||||||
|
json_child["text"].as_str().unwrap().as_bytes(),
|
||||||
|
10,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
let count_bits = |x: &BigInt| -> usize {
|
||||||
|
8 * x.to_biguint().unwrap().to_bytes_be().len()
|
||||||
|
};
|
||||||
|
|
||||||
|
IntValue::from_signed(count_bits(&value), value)
|
||||||
|
}
|
||||||
|
_ => panic!("unknown error at CST node '{}'", json_child),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
2 => {
|
||||||
|
let json_width = &json_children[0];
|
||||||
|
assert_eq!(json_width["tag"], Tag::DEC_NUMBER);
|
||||||
|
assert_eq!(json_children[1]["tag"], Tag::BASE_DIGITS);
|
||||||
|
assert_eq!(json_children[1]["children"].len(), 2);
|
||||||
|
let json_base = &json_children[1]["children"][0];
|
||||||
|
let json_digits = &json_children[1]["children"][1];
|
||||||
|
let radix = match json_base["tag"].as_str() {
|
||||||
|
Some(Tag::HEX_BASE) => {
|
||||||
|
assert_eq!(json_digits["tag"], Tag::HEX_DIGITS);
|
||||||
|
16
|
||||||
|
}
|
||||||
|
Some(Tag::BIN_BASE) => {
|
||||||
|
assert_eq!(json_digits["tag"], Tag::BIN_DIGITS);
|
||||||
|
2
|
||||||
|
}
|
||||||
|
Some(Tag::DEC_BASE) => {
|
||||||
|
assert_eq!(json_digits["tag"], Tag::DEC_DIGITS);
|
||||||
|
10
|
||||||
|
}
|
||||||
|
_ => panic!("unknown error at CST node '{}'", json),
|
||||||
|
};
|
||||||
|
let width = json_width["text"].to_string().parse::<usize>().unwrap();
|
||||||
|
let value =
|
||||||
|
BigInt::parse_bytes(json_digits["text"].as_str().unwrap().as_bytes(), radix)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
IntValue::from_signed(width, value)
|
||||||
|
}
|
||||||
|
_ => panic!("unknown error at CST node '{}'", json),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gen_number(json: &JsonValue, context: &mut ModuleContext) -> Option<Value> {
|
||||||
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;
|
||||||
let bb_head = *unit_ctx.bb_head.last().unwrap();
|
let bb_head = *unit_ctx.bb_head.last().unwrap();
|
||||||
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 value = builder.ins().const_int(Self::parse_number(json));
|
||||||
|
|
||||||
match json_children.len() {
|
Some(value)
|
||||||
1 => {
|
|
||||||
let json_child = &json_children[0];
|
|
||||||
match json_child["tag"].as_str() {
|
|
||||||
Some(Tag::DEC_NUMBER) => {
|
|
||||||
let w = unit_ctx
|
|
||||||
.ty_active
|
|
||||||
.as_ref()
|
|
||||||
.unwrap()
|
|
||||||
.unwrap_signal()
|
|
||||||
.unwrap_int();
|
|
||||||
let v = json_child["text"].to_string().parse::<usize>().unwrap();
|
|
||||||
let num = builder.ins().const_int((w, v));
|
|
||||||
Some(num)
|
|
||||||
}
|
|
||||||
_ => panic!("unknown error at CST node '{}'", json_child),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
let json_base = &json_children[1]["children"][0];
|
|
||||||
let json_digits = &json_children[1]["children"][1];
|
|
||||||
match json_base["tag"].as_str() {
|
|
||||||
Some(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_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),
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -187,6 +202,29 @@ impl Expression {
|
||||||
let value = builder.ins().and(opd_l, opd_r);
|
let value = builder.ins().and(opd_l, opd_r);
|
||||||
Some(value)
|
Some(value)
|
||||||
}
|
}
|
||||||
|
Some("&&") => {
|
||||||
|
let nez = |x: Value, builder: &mut UnitBuilder| -> Value {
|
||||||
|
let ty = &builder.unit().value_type(x);
|
||||||
|
let zero = builder.ins().const_zero(ty);
|
||||||
|
builder.ins().neq(x, zero)
|
||||||
|
};
|
||||||
|
let nez_l = nez(opd_l, &mut builder);
|
||||||
|
let nez_r = nez(opd_r, &mut builder);
|
||||||
|
let value = builder.ins().and(nez_l, nez_r);
|
||||||
|
Some(value)
|
||||||
|
}
|
||||||
|
Some("^") => {
|
||||||
|
let value = builder.ins().xor(opd_l, opd_r);
|
||||||
|
Some(value)
|
||||||
|
}
|
||||||
|
Some(">=") => {
|
||||||
|
let value = builder.ins().sge(opd_l, opd_r);
|
||||||
|
Some(value)
|
||||||
|
}
|
||||||
|
Some("<=") => {
|
||||||
|
let value = builder.ins().sle(opd_l, opd_r);
|
||||||
|
Some(value)
|
||||||
|
}
|
||||||
Some(tag) => {
|
Some(tag) => {
|
||||||
error!("FIXME: case '{}' missing", tag);
|
error!("FIXME: case '{}' missing", tag);
|
||||||
None
|
None
|
||||||
|
@ -216,10 +254,64 @@ impl Expression {
|
||||||
let value = builder.ins().neq(expr.unwrap(), zero);
|
let value = builder.ins().neq(expr.unwrap(), zero);
|
||||||
Some(value)
|
Some(value)
|
||||||
}
|
}
|
||||||
|
Some("~") => {
|
||||||
|
let value = builder.ins().not(expr.unwrap());
|
||||||
|
Some(value)
|
||||||
|
}
|
||||||
_ => panic!("unknown error at CST node '{}'", json),
|
_ => panic!("unknown error at CST node '{}'", json),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn gen_concatenation_expression(
|
||||||
|
json: &JsonValue,
|
||||||
|
context: &mut ModuleContext,
|
||||||
|
) -> Option<Value> {
|
||||||
|
let json_expressions = Tools::match_tags(
|
||||||
|
vec![json],
|
||||||
|
vec![
|
||||||
|
Tag::CONCATENATION_EXPRESSION,
|
||||||
|
Tag::OPEN_RANGE_LIST,
|
||||||
|
Tag::EXPRESSION,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
let expressions: Vec<_> = json_expressions
|
||||||
|
.iter()
|
||||||
|
.rev()
|
||||||
|
.map(|x| Self::codegen(x, context))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
let widths: Vec<_> = expressions
|
||||||
|
.iter()
|
||||||
|
.map(|e| {
|
||||||
|
let v = e.unwrap();
|
||||||
|
let ty = builder.unit().value_type(v);
|
||||||
|
assert!(ty.is_int(), "FIXME: type '{}'", ty);
|
||||||
|
ty.unwrap_int()
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
let tot_width = widths.iter().map(|&x| x).reduce(|x, y| x + y).unwrap();
|
||||||
|
|
||||||
|
let mut last_slice = builder.ins().const_zero(&int_ty(tot_width));
|
||||||
|
let mut width = 0;
|
||||||
|
for (i, e) in expressions.iter().enumerate() {
|
||||||
|
let v = e.unwrap();
|
||||||
|
let w = widths[i];
|
||||||
|
last_slice = builder.ins().ins_slice(last_slice, v, width, w);
|
||||||
|
width += w;
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(last_slice)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use crate::cst::{AlwaysStatement, ModuleContext, SymbolInfo, SymbolKind, Tag, Tools};
|
use crate::cst::{AlwaysStatement, Expression, ModuleContext, SymbolInfo, SymbolKind, Tag, Tools};
|
||||||
use json::JsonValue;
|
use json::JsonValue;
|
||||||
use llhd::ir::{
|
use llhd::{
|
||||||
ExtUnit, Module, Signature, UnitBuilder, UnitData, UnitId, UnitKind, UnitName, Value,
|
ir::{ExtUnit, Module, Signature, UnitBuilder, UnitData, UnitId, UnitKind, UnitName, Value},
|
||||||
|
ty::{int_ty, signal_ty},
|
||||||
};
|
};
|
||||||
use llhd::ty::{int_ty, signal_ty};
|
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
|
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
|
@ -62,8 +62,9 @@ impl ModuleDeclaration {
|
||||||
raw_name_set.insert(raw_name.to_string());
|
raw_name_set.insert(raw_name.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut declare = |info_list: &Vec<(String, usize)>, kind: SymbolKind| {
|
let mut declare = |info_list: &Vec<(String, usize, Option<&JsonValue>)>,
|
||||||
for (name, width) in info_list {
|
kind: SymbolKind| {
|
||||||
|
for (name, width, _) in info_list {
|
||||||
if !context.symbol.contains_key(name) {
|
if !context.symbol.contains_key(name) {
|
||||||
let n = name.to_string();
|
let n = name.to_string();
|
||||||
let w = width.clone();
|
let w = width.clone();
|
||||||
|
@ -75,7 +76,7 @@ impl ModuleDeclaration {
|
||||||
|
|
||||||
match kind {
|
match kind {
|
||||||
SymbolKind::Reg | SymbolKind::Wire => {
|
SymbolKind::Reg | SymbolKind::Wire => {
|
||||||
for (name, width) in info_list {
|
for (name, width, _) in info_list {
|
||||||
if !raw_name_set.contains(name) {
|
if !raw_name_set.contains(name) {
|
||||||
let n = name.to_string();
|
let n = name.to_string();
|
||||||
let w = width.clone();
|
let w = width.clone();
|
||||||
|
@ -92,6 +93,13 @@ impl ModuleDeclaration {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
SymbolKind::Param => {
|
||||||
|
for (name, _, jn) in info_list {
|
||||||
|
let n = name.to_string();
|
||||||
|
let v = Expression::parse_number(jn.unwrap());
|
||||||
|
context.param.insert(n, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
x => warn!("TODO: case '{}'", x),
|
x => warn!("TODO: case '{}'", x),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -340,7 +348,7 @@ impl ModuleDeclaration {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_reg_info(json: &JsonValue) -> Vec<(String, usize)> {
|
fn get_reg_info(json: &JsonValue) -> Vec<(String, usize, Option<&JsonValue>)> {
|
||||||
let base_path = [
|
let base_path = [
|
||||||
Tag::MODULE_DECLARATION,
|
Tag::MODULE_DECLARATION,
|
||||||
Tag::MODULE_ITEM_LIST,
|
Tag::MODULE_ITEM_LIST,
|
||||||
|
@ -384,7 +392,7 @@ impl ModuleDeclaration {
|
||||||
Self::get_var_info(json_regs, name_path.to_vec(), dim_path.to_vec())
|
Self::get_var_info(json_regs, name_path.to_vec(), dim_path.to_vec())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_wire_info(json: &JsonValue) -> Vec<(String, usize)> {
|
fn get_wire_info(json: &JsonValue) -> Vec<(String, usize, Option<&JsonValue>)> {
|
||||||
let base_path = [
|
let base_path = [
|
||||||
Tag::MODULE_DECLARATION,
|
Tag::MODULE_DECLARATION,
|
||||||
Tag::MODULE_ITEM_LIST,
|
Tag::MODULE_ITEM_LIST,
|
||||||
|
@ -419,11 +427,11 @@ impl ModuleDeclaration {
|
||||||
Self::get_var_info(json_wires, name_path.to_vec(), dim_path.to_vec())
|
Self::get_var_info(json_wires, name_path.to_vec(), dim_path.to_vec())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_var_info(
|
fn get_var_info<'a>(
|
||||||
json_vec: Vec<&JsonValue>,
|
json_vec: Vec<&'a JsonValue>,
|
||||||
name_path: Vec<&str>,
|
name_path: Vec<&str>,
|
||||||
dim_path: Vec<&str>,
|
dim_path: Vec<&str>,
|
||||||
) -> Vec<(String, usize)> {
|
) -> Vec<(String, usize, Option<&'a JsonValue>)> {
|
||||||
json_vec
|
json_vec
|
||||||
.iter()
|
.iter()
|
||||||
.map(|&json| {
|
.map(|&json| {
|
||||||
|
@ -434,8 +442,8 @@ impl ModuleDeclaration {
|
||||||
|
|
||||||
json_names
|
json_names
|
||||||
.iter()
|
.iter()
|
||||||
.map(|x| (x["text"].to_string(), width))
|
.map(|x| (x["text"].to_string(), width, None)) // hack
|
||||||
.collect::<Vec<(String, usize)>>()
|
.collect::<Vec<(String, usize, Option<&JsonValue>)>>()
|
||||||
})
|
})
|
||||||
.flatten()
|
.flatten()
|
||||||
.collect()
|
.collect()
|
||||||
|
@ -455,7 +463,7 @@ impl ModuleDeclaration {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_param_info(json: &JsonValue) -> Vec<(String, usize)> {
|
fn get_param_info(json: &JsonValue) -> Vec<(String, usize, Option<&JsonValue>)> {
|
||||||
let base_path = [
|
let base_path = [
|
||||||
Tag::MODULE_DECLARATION,
|
Tag::MODULE_DECLARATION,
|
||||||
Tag::MODULE_ITEM_LIST,
|
Tag::MODULE_ITEM_LIST,
|
||||||
|
@ -469,12 +477,11 @@ impl ModuleDeclaration {
|
||||||
Tag::SYMBOL_IDENTIFIER,
|
Tag::SYMBOL_IDENTIFIER,
|
||||||
];
|
];
|
||||||
|
|
||||||
let dim_path = [
|
let num_path = [
|
||||||
Tag::PARAM_DECLARATION,
|
Tag::PARAM_DECLARATION,
|
||||||
Tag::TRAILING_ASSIGN,
|
Tag::TRAILING_ASSIGN,
|
||||||
Tag::EXPRESSION,
|
Tag::EXPRESSION,
|
||||||
Tag::NUMBER,
|
Tag::NUMBER,
|
||||||
Tag::DEC_NUMBER,
|
|
||||||
];
|
];
|
||||||
|
|
||||||
let json_params: Vec<&JsonValue> = Tools::match_tags(vec![json], base_path.to_vec())
|
let json_params: Vec<&JsonValue> = Tools::match_tags(vec![json], base_path.to_vec())
|
||||||
|
@ -489,12 +496,15 @@ impl ModuleDeclaration {
|
||||||
let json_names = Tools::match_tags(vec![json], name_path.to_vec());
|
let json_names = Tools::match_tags(vec![json], name_path.to_vec());
|
||||||
assert_eq!(json_names.len(), 1);
|
assert_eq!(json_names.len(), 1);
|
||||||
|
|
||||||
let json_dims = Tools::match_tags(vec![json], dim_path.to_vec());
|
let json_num = Tools::match_tags(vec![json], num_path.to_vec());
|
||||||
assert_eq!(json_dims.len(), 1);
|
assert_eq!(json_num.len(), 1);
|
||||||
|
let v = Expression::parse_number(json_num[0]);
|
||||||
|
|
||||||
let width = json_dims[0]["text"].to_string().parse::<usize>().unwrap();
|
(
|
||||||
|
json_names[0]["text"].to_string(),
|
||||||
(json_names[0]["text"].to_string(), width)
|
v.width,
|
||||||
|
Some(json_num[0]),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use crate::cst::{Expression, ModuleContext, Tag, Tools};
|
use crate::cst::{Expression, ModuleContext, Tag, Tools, UnitContext};
|
||||||
use json::JsonValue;
|
use json::JsonValue;
|
||||||
|
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};
|
||||||
|
@ -7,37 +8,77 @@ use log::{debug, error, info, trace, warn};
|
||||||
pub struct NetVariableAssignment {}
|
pub struct NetVariableAssignment {}
|
||||||
|
|
||||||
impl NetVariableAssignment {
|
impl NetVariableAssignment {
|
||||||
pub fn codegen(json: &JsonValue, context: &mut ModuleContext) {
|
pub fn codegen(json: &JsonValue, context: &mut ModuleContext) -> Option<Block> {
|
||||||
assert_eq!(json["tag"], Tag::NET_VARIABLE_ASSIGNMENT);
|
|
||||||
|
|
||||||
let (json_lpvalue, json_expression) = {
|
let (json_lpvalue, json_expression) = {
|
||||||
|
assert_eq!(json["tag"], Tag::NET_VARIABLE_ASSIGNMENT);
|
||||||
|
|
||||||
let json_children = &json["children"];
|
let json_children = &json["children"];
|
||||||
assert_eq!(json_children.len(), 4);
|
assert_eq!(json_children.len(), 4);
|
||||||
assert_eq!(json_children[1]["tag"], "=");
|
assert_eq!(json_children[1]["tag"], "=");
|
||||||
assert_eq!(json_children[3]["tag"], ";");
|
assert_eq!(json_children[3]["tag"], ";");
|
||||||
|
|
||||||
(&json_children[0], &json_children[2])
|
let json_symbol_identifier = Tools::match_tags(
|
||||||
|
vec![&json_children[0]],
|
||||||
|
vec![
|
||||||
|
Tag::LP_VALUE,
|
||||||
|
Tag::REFERENCE_CALL_BASE,
|
||||||
|
Tag::REFERENCE,
|
||||||
|
Tag::LOCAL_ROOT,
|
||||||
|
Tag::UNQUALIFIED_ID,
|
||||||
|
Tag::SYMBOL_IDENTIFIER,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
assert_eq!(json_symbol_identifier.len(), 1);
|
||||||
|
|
||||||
|
(json_symbol_identifier[0], &json_children[2])
|
||||||
};
|
};
|
||||||
|
|
||||||
let json_symbol_identifier = Tools::match_tags(
|
let lvalue_name = &json_lpvalue["text"].to_string();
|
||||||
vec![json_lpvalue],
|
context.unit_ctx.lvalues.insert(lvalue_name.clone());
|
||||||
vec![
|
if context.unit_ctx.raw_name_to_value.contains_key(lvalue_name) {
|
||||||
Tag::LP_VALUE,
|
assert!(context.unit_ctx.raw_name_to_arg.contains_key(lvalue_name));
|
||||||
Tag::REFERENCE_CALL_BASE,
|
assert!(context.unit_ctx.data.is_some());
|
||||||
Tag::REFERENCE,
|
let arg = context.unit_ctx.raw_name_to_arg[lvalue_name];
|
||||||
Tag::LOCAL_ROOT,
|
let builder = &UnitContext::builder(&mut context.unit_ctx.data);
|
||||||
Tag::UNQUALIFIED_ID,
|
// set active Type
|
||||||
Tag::SYMBOL_IDENTIFIER,
|
context.unit_ctx.ty_active = Some(builder.unit().sig().arg_type(arg));
|
||||||
],
|
}
|
||||||
);
|
|
||||||
assert_eq!(json_symbol_identifier.len(), 1);
|
|
||||||
context
|
|
||||||
.unit_ctx
|
|
||||||
.lvalues
|
|
||||||
.insert(json_symbol_identifier[0]["text"].to_string());
|
|
||||||
|
|
||||||
Expression::codegen(json_expression, context);
|
let opt_expr = Expression::codegen(json_expression, context);
|
||||||
|
|
||||||
warn!("TODO: finish codegen()");
|
if context.unit_ctx.raw_name_to_value.contains_key(lvalue_name) {
|
||||||
|
// unset active Type
|
||||||
|
context.unit_ctx.ty_active = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let unit_ctx = &mut context.unit_ctx;
|
||||||
|
if unit_ctx.data.is_some() {
|
||||||
|
if opt_expr.is_none() {
|
||||||
|
error!("FIXME: CST node '{}'", json_expression.to_string());
|
||||||
|
panic!();
|
||||||
|
}
|
||||||
|
|
||||||
|
let bb_head = *unit_ctx.bb_head.last().unwrap();
|
||||||
|
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(),
|
||||||
|
delta_time,
|
||||||
|
);
|
||||||
|
if unit_ctx.raw_name_to_shadow.contains_key(lvalue_name) {
|
||||||
|
warn!("TODO: double check");
|
||||||
|
builder.ins().st(
|
||||||
|
unit_ctx.raw_name_to_shadow[lvalue_name],
|
||||||
|
unit_ctx.raw_name_to_value[lvalue_name],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(bb_head)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,10 +19,7 @@ impl Statement {
|
||||||
Some(Tag::NONBLOCKING_ASSIGNMENT_STATEMENT) => {
|
Some(Tag::NONBLOCKING_ASSIGNMENT_STATEMENT) => {
|
||||||
NonblockingAssignmentStatement::codegen(json, context)
|
NonblockingAssignmentStatement::codegen(json, context)
|
||||||
}
|
}
|
||||||
Some(Tag::NET_VARIABLE_ASSIGNMENT) => {
|
Some(Tag::NET_VARIABLE_ASSIGNMENT) => NetVariableAssignment::codegen(json, context),
|
||||||
NetVariableAssignment::codegen(json, context);
|
|
||||||
None
|
|
||||||
}
|
|
||||||
_ => panic!("unknown error at CST node '{}'", json),
|
_ => panic!("unknown error at CST node '{}'", json),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,11 +45,13 @@ impl Tag {
|
||||||
pub const REFERENCE: &'static str = "kReference";
|
pub const REFERENCE: &'static str = "kReference";
|
||||||
pub const LOCAL_ROOT: &'static str = "kLocalRoot";
|
pub const LOCAL_ROOT: &'static str = "kLocalRoot";
|
||||||
|
|
||||||
|
pub const EXPRESSION_LIST: &'static str = "kExpressionList";
|
||||||
pub const EXPRESSION: &'static str = "kExpression";
|
pub const EXPRESSION: &'static str = "kExpression";
|
||||||
pub const BINARY_EXPRESSION: &'static str = "kBinaryExpression";
|
pub const BINARY_EXPRESSION: &'static str = "kBinaryExpression";
|
||||||
pub const UNARY_PREFIX_EXPRESSION: &'static str = "kUnaryPrefixExpression";
|
pub const UNARY_PREFIX_EXPRESSION: &'static str = "kUnaryPrefixExpression";
|
||||||
pub const CONDITION_EXPRESSION: &'static str = "kConditionExpression";
|
pub const CONDITION_EXPRESSION: &'static str = "kConditionExpression";
|
||||||
pub const CONCATENATION_EXPRESSION: &'static str = "kConcatenationExpression";
|
pub const CONCATENATION_EXPRESSION: &'static str = "kConcatenationExpression";
|
||||||
|
pub const OPEN_RANGE_LIST: &'static str = "kOpenRangeList";
|
||||||
|
|
||||||
pub const NUMBER: &'static str = "kNumber";
|
pub const NUMBER: &'static str = "kNumber";
|
||||||
pub const BASE_DIGITS: &'static str = "kBaseDigits";
|
pub const BASE_DIGITS: &'static str = "kBaseDigits";
|
||||||
|
@ -58,6 +60,8 @@ impl Tag {
|
||||||
pub const HEX_DIGITS: &'static str = "TK_HexDigits";
|
pub const HEX_DIGITS: &'static str = "TK_HexDigits";
|
||||||
pub const BIN_BASE: &'static str = "TK_BinBase";
|
pub const BIN_BASE: &'static str = "TK_BinBase";
|
||||||
pub const BIN_DIGITS: &'static str = "TK_BinDigits";
|
pub const BIN_DIGITS: &'static str = "TK_BinDigits";
|
||||||
|
pub const DEC_BASE: &'static str = "TK_DecBase";
|
||||||
|
pub const DEC_DIGITS: &'static str = "TK_DecDigits";
|
||||||
|
|
||||||
pub const ALWAYS_STATEMENT: &'static str = "kAlwaysStatement";
|
pub const ALWAYS_STATEMENT: &'static str = "kAlwaysStatement";
|
||||||
pub const ALWAYS: &'static str = "always";
|
pub const ALWAYS: &'static str = "always";
|
||||||
|
|
Loading…
Reference in New Issue