Work on a correct instantiation of ExtUnit
This commit is contained in:
parent
b0ffc2cfaa
commit
e46dbbcd7c
|
@ -3,7 +3,7 @@ extern crate clap;
|
|||
extern crate json;
|
||||
|
||||
use clap::Arg;
|
||||
use cst_to_llhd::cst::{CodeReporter, DescriptionList, Tag, Tools};
|
||||
use cst_to_llhd::cst::{CodeReporter, DescriptionList, Logger, Tag, Tools};
|
||||
use std::{
|
||||
process::{Command, Stdio},
|
||||
result::Result,
|
||||
|
@ -119,6 +119,8 @@ fn main_inner() -> Result<(), std::io::Error> {
|
|||
println!("{}", module.dump());
|
||||
}
|
||||
|
||||
Logger::print();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
@ -1,19 +1,16 @@
|
|||
use crate::cst::{ModuleContext, ProceduralTimingControlStatement, Tag, Tools};
|
||||
use crate::cst::{Logger, ModuleContext, ProceduralTimingControlStatement, Tag, Tools};
|
||||
use json::JsonValue;
|
||||
use llhd::ir::{Signature, Unit, UnitBuilder, UnitData, UnitKind, UnitName};
|
||||
use llhd::ir::{Signature, UnitBuilder, UnitData, UnitId, UnitKind, UnitName};
|
||||
use llhd::ty::{int_ty, signal_ty};
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub struct AlwaysStatement {}
|
||||
|
||||
impl AlwaysStatement {
|
||||
pub fn codegen<'a>(json: &JsonValue, context: &'a mut ModuleContext) -> Unit<'a> {
|
||||
let mut proc_data = UnitData::new(
|
||||
UnitKind::Process,
|
||||
UnitName::local(format!("{}.always.{}", context.name, context.process.len())),
|
||||
Signature::new(),
|
||||
);
|
||||
let mut _proc_builder = UnitBuilder::new_anonymous(&mut proc_data);
|
||||
let proc_id = context.module.add_unit(proc_data);
|
||||
context.process.push(proc_id);
|
||||
pub fn codegen(json: &JsonValue, context: &mut ModuleContext) -> UnitId {
|
||||
let me = "AlwaysStatement::codegen()";
|
||||
assert!(context.lvalues.is_empty());
|
||||
assert!(context.rvalues.is_empty());
|
||||
|
||||
match json["children"][0]["tag"].as_str() {
|
||||
Some(Tag::ALWAYS) => {
|
||||
|
@ -28,16 +25,47 @@ impl AlwaysStatement {
|
|||
ProceduralTimingControlStatement::codegen(json_statement[0], context);
|
||||
}
|
||||
Some(Tag::ALWAYS_COMB) => {
|
||||
println!("TODO: implmenent AlwaysComb::codegen()");
|
||||
Logger::insert(format!("TODO: implmenent AlwaysComb::codegen()"));
|
||||
}
|
||||
Some(x) => {
|
||||
println!("FIXME: missing {}", x);
|
||||
Logger::insert(format!("FIXME: missing {}", x));
|
||||
}
|
||||
_ => {
|
||||
panic!();
|
||||
}
|
||||
}
|
||||
|
||||
context.module.unit(proc_id)
|
||||
let mut arg_name = HashMap::new();
|
||||
let proc_signature = {
|
||||
let mut ret = Signature::new();
|
||||
for lvalue in &context.lvalues {
|
||||
if context.symbol_info.contains_key(lvalue) {
|
||||
let width = context.symbol_info[lvalue].width.clone();
|
||||
let arg = ret.add_output(signal_ty(int_ty(width)));
|
||||
arg_name.insert(arg, lvalue);
|
||||
} else {
|
||||
Logger::insert(format!("FIXME: {} not found in {}", lvalue, me));
|
||||
}
|
||||
}
|
||||
ret
|
||||
};
|
||||
let mut proc_data = UnitData::new(
|
||||
UnitKind::Process,
|
||||
UnitName::local(format!("{}.always.{}", context.name, context.process.len())),
|
||||
proc_signature,
|
||||
);
|
||||
let mut proc_builder = UnitBuilder::new_anonymous(&mut proc_data);
|
||||
for (arg, name) in arg_name {
|
||||
let value = proc_builder.arg_value(arg);
|
||||
proc_builder.set_name(value, name.to_string());
|
||||
}
|
||||
|
||||
let proc_id = context.module.add_unit(proc_data);
|
||||
context.process.push(proc_id);
|
||||
|
||||
context.lvalues.clear();
|
||||
context.rvalues.clear();
|
||||
|
||||
proc_id
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
use crate::cst::ModuleContext;
|
||||
use crate::cst::{Logger, ModuleContext};
|
||||
use json::JsonValue;
|
||||
|
||||
pub struct CaseStatement {}
|
||||
|
||||
impl CaseStatement {
|
||||
pub fn codegen(_json: &JsonValue, _context: &ModuleContext) {
|
||||
println!("TODO: implement CaseStatement::codegen()");
|
||||
Logger::insert(format!("TODO: implement CaseStatement::codegen()"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ use json::JsonValue;
|
|||
pub struct ConditionalStatement {}
|
||||
|
||||
impl ConditionalStatement {
|
||||
pub fn codegen(json: &JsonValue, context: &ModuleContext) {
|
||||
pub fn codegen(json: &JsonValue, context: &mut ModuleContext) {
|
||||
let json_if_header = Tools::match_tags(
|
||||
vec![json],
|
||||
vec![
|
||||
|
@ -35,13 +35,13 @@ impl ConditionalStatement {
|
|||
}
|
||||
}
|
||||
|
||||
fn visit_if_body(json: &JsonValue, context: &ModuleContext) {
|
||||
fn visit_if_body(json: &JsonValue, context: &mut ModuleContext) {
|
||||
let json_child = &json["children"];
|
||||
assert_eq!(json_child.len(), 1);
|
||||
Statement::codegen(&json_child[0], context);
|
||||
}
|
||||
|
||||
fn visit_else_body(json: &JsonValue, context: &ModuleContext) {
|
||||
fn visit_else_body(json: &JsonValue, context: &mut ModuleContext) {
|
||||
let json_child = &json["children"];
|
||||
assert_eq!(json_child.len(), 1);
|
||||
Statement::codegen(&json_child[0], context);
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
use llhd::ir::{Arg, Module, UnitId};
|
||||
use std::collections::HashMap;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
pub struct ModuleContext {
|
||||
pub name: String,
|
||||
pub module: Module,
|
||||
pub arg_info: HashMap<Arg, ArgInfo>,
|
||||
pub symbol_info: HashMap<String, SymbolInfo>,
|
||||
pub arg_name: HashMap<Arg, String>,
|
||||
pub process: Vec<UnitId>,
|
||||
pub lvalues: HashSet<String>,
|
||||
pub rvalues: HashSet<String>,
|
||||
}
|
||||
|
||||
pub struct ArgInfo {
|
||||
pub name: String,
|
||||
pub struct SymbolInfo {
|
||||
pub width: usize,
|
||||
}
|
||||
|
||||
|
@ -18,16 +20,18 @@ impl ModuleContext {
|
|||
Self {
|
||||
name: String::new(),
|
||||
module: Module::new(),
|
||||
arg_info: HashMap::new(),
|
||||
symbol_info: HashMap::new(),
|
||||
arg_name: HashMap::new(),
|
||||
process: Vec::new(),
|
||||
lvalues: HashSet::new(),
|
||||
rvalues: HashSet::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ArgInfo {
|
||||
pub fn new(name: &String, width: &usize) -> Self {
|
||||
impl SymbolInfo {
|
||||
pub fn new(width: &usize) -> Self {
|
||||
Self {
|
||||
name: name.to_string(),
|
||||
width: width.clone(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
use crate::cst::ModuleContext;
|
||||
use crate::cst::{Logger, ModuleContext};
|
||||
use json::JsonValue;
|
||||
|
||||
pub struct EventExpressionList {}
|
||||
|
||||
impl EventExpressionList {
|
||||
pub fn codegen(_json: &JsonValue, _context: &ModuleContext) {
|
||||
println!("TODO: implement EventExpressionList::codegen()");
|
||||
Logger::insert(format!("TODO: implement EventExpressionList::codegen()"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,63 @@
|
|||
use crate::cst::ModuleContext;
|
||||
use crate::cst::{Logger, ModuleContext, Tag, Tools};
|
||||
use json::JsonValue;
|
||||
|
||||
pub struct Expression {}
|
||||
|
||||
impl Expression {
|
||||
pub fn codegen(_json: &JsonValue, _context: &ModuleContext) {
|
||||
println!("TODO: implement Expression::codegen()");
|
||||
pub fn codegen(json: &JsonValue, context: &ModuleContext) {
|
||||
let json_child = &json["children"];
|
||||
assert_eq!(json["tag"], Tag::EXPRESSION);
|
||||
assert_eq!(json_child.len(), 1);
|
||||
Self::codegen_internal(&json_child[0], context);
|
||||
}
|
||||
|
||||
fn codegen_internal(json: &JsonValue, context: &ModuleContext) {
|
||||
let me = "Expression::codegen()";
|
||||
|
||||
match json["tag"].as_str() {
|
||||
Some(Tag::NUMBER) => {
|
||||
Logger::insert(format!("FIXME: handle {} in {}", Tag::NUMBER, me));
|
||||
}
|
||||
Some(Tag::REFERENCE_CALL_BASE) => {
|
||||
Logger::insert(format!(
|
||||
"FIXME: handle {} in {}",
|
||||
Tag::REFERENCE_CALL_BASE,
|
||||
me
|
||||
));
|
||||
}
|
||||
Some(Tag::UNARY_PREFIX_EXPRESSION) => {
|
||||
let json_children = &json["children"];
|
||||
assert_eq!(json_children.len(), 2);
|
||||
Self::codegen_internal(&json_children[1], context);
|
||||
|
||||
Logger::insert(format!(
|
||||
"TODO: complete the rest of {} in {}",
|
||||
Tag::UNARY_PREFIX_EXPRESSION,
|
||||
me
|
||||
));
|
||||
}
|
||||
Some(Tag::BINARY_EXPRESSION) => {
|
||||
let json_children = &json["children"];
|
||||
assert_eq!(json_children.len(), 3);
|
||||
Self::codegen_internal(&json_children[0], context);
|
||||
Self::codegen_internal(&json_children[2], context);
|
||||
|
||||
Logger::insert(format!(
|
||||
"TODO: complete the rest of {} in {}",
|
||||
Tag::BINARY_EXPRESSION,
|
||||
me
|
||||
));
|
||||
}
|
||||
Some(Tag::PAREN_GROUP) => {
|
||||
let json_expression =
|
||||
Tools::match_tags(vec![json], vec![Tag::PAREN_GROUP, Tag::EXPRESSION]);
|
||||
assert_eq!(json_expression.len(), 1);
|
||||
Self::codegen(&json_expression[0], context);
|
||||
}
|
||||
Some(x) => {
|
||||
Logger::insert(format!("FIXME: handle {} in {}", x, me));
|
||||
}
|
||||
_ => panic!(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ mod tools;
|
|||
use always_statement::AlwaysStatement;
|
||||
use case_statement::CaseStatement;
|
||||
use conditional_statement::ConditionalStatement;
|
||||
use context::{ArgInfo, ModuleContext};
|
||||
use context::{ModuleContext, SymbolInfo};
|
||||
use event_expression_list::EventExpressionList;
|
||||
use expression::Expression;
|
||||
use module_declaration::ModuleDeclaration;
|
||||
|
@ -27,4 +27,4 @@ use statement::Statement;
|
|||
|
||||
pub use description_list::DescriptionList;
|
||||
pub use tags::Tag;
|
||||
pub use tools::{CodeReporter, Tools};
|
||||
pub use tools::{CodeReporter, Logger, Tools};
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::cst::{AlwaysStatement, ArgInfo, ModuleContext, Tag, Tools};
|
||||
use crate::cst::{AlwaysStatement, ModuleContext, SymbolInfo, Tag, Tools};
|
||||
use json::JsonValue;
|
||||
use llhd::ir::{
|
||||
ExtUnit, InstBuilder, Module, Signature, UnitBuilder, UnitData, UnitKind, UnitName,
|
||||
ExtUnit, InstBuilder, Module, Signature, UnitBuilder, UnitData, UnitId, UnitKind, UnitName,
|
||||
};
|
||||
use llhd::ty::{int_ty, signal_ty};
|
||||
|
||||
|
@ -17,29 +17,38 @@ impl ModuleDeclaration {
|
|||
|
||||
let mut entity_builder = UnitBuilder::new_anonymous(&mut entity_data);
|
||||
|
||||
for (arg, arg_info) in context.arg_info.iter() {
|
||||
for (arg, arg_name) in context.arg_name.iter() {
|
||||
let value = entity_builder.arg_value(*arg);
|
||||
entity_builder.set_name(value, arg_info.name.to_string());
|
||||
entity_builder.set_name(value, arg_name.to_string());
|
||||
}
|
||||
|
||||
let process_list: Vec<ExtUnit> = Tools::match_tags(
|
||||
let json_always_statement = &Tools::match_tags(
|
||||
vec![json],
|
||||
vec![
|
||||
Tag::MODULE_DECLARATION,
|
||||
Tag::MODULE_ITEM_LIST,
|
||||
Tag::ALWAYS_STATEMENT,
|
||||
],
|
||||
)
|
||||
.iter()
|
||||
.map(|&x| {
|
||||
let proc = AlwaysStatement::codegen(x, &mut context);
|
||||
entity_builder.add_extern(proc.name().clone(), proc.sig().clone())
|
||||
})
|
||||
.collect();
|
||||
);
|
||||
let ext_to_proc = json_always_statement
|
||||
.iter()
|
||||
.map(|&x| {
|
||||
let proc_id = AlwaysStatement::codegen(x, &mut context);
|
||||
let proc = context.module.unit(proc_id);
|
||||
let ext_proc = entity_builder.add_extern(proc.name().clone(), proc.sig().clone());
|
||||
(ext_proc, proc_id)
|
||||
})
|
||||
.collect::<Vec<(ExtUnit, UnitId)>>();
|
||||
|
||||
let mut inst_builder = InstBuilder::new(&mut entity_builder);
|
||||
for process in process_list {
|
||||
inst_builder.inst(process, vec![], vec![]); // FIXME
|
||||
|
||||
for (ext_proc, proc_id) in ext_to_proc {
|
||||
let unit = context.module.unit(proc_id); // FIXME: should be entity_builder.unit()
|
||||
inst_builder.inst(
|
||||
ext_proc,
|
||||
unit.input_args().into_iter().collect(),
|
||||
unit.output_args().into_iter().collect(),
|
||||
);
|
||||
}
|
||||
|
||||
entity_builder.finish();
|
||||
|
@ -82,11 +91,17 @@ impl ModuleDeclaration {
|
|||
|
||||
for (name, width) in input_info {
|
||||
let arg = signature.add_input(signal_ty(int_ty(width.clone())));
|
||||
context.arg_info.insert(arg, ArgInfo::new(name, width));
|
||||
context
|
||||
.symbol_info
|
||||
.insert(name.to_string(), SymbolInfo::new(width));
|
||||
context.arg_name.insert(arg, name.to_string());
|
||||
}
|
||||
for (name, width) in output_info {
|
||||
let arg = signature.add_output(signal_ty(int_ty(width.clone())));
|
||||
context.arg_info.insert(arg, ArgInfo::new(name, width));
|
||||
context
|
||||
.symbol_info
|
||||
.insert(name.to_string(), SymbolInfo::new(width));
|
||||
context.arg_name.insert(arg, name.to_string());
|
||||
}
|
||||
|
||||
signature
|
||||
|
|
|
@ -1,10 +1,41 @@
|
|||
use crate::cst::ModuleContext;
|
||||
use crate::cst::{Expression, Logger, ModuleContext, Tag, Tools};
|
||||
use json::JsonValue;
|
||||
|
||||
pub struct NonblockingAssignmentStatement {}
|
||||
|
||||
impl NonblockingAssignmentStatement {
|
||||
pub fn codegen(_json: &JsonValue, _context: &ModuleContext) {
|
||||
println!("TODO: implement NonblockingAssignmentStatement::codegen()");
|
||||
pub fn codegen(json: &JsonValue, context: &mut ModuleContext) {
|
||||
assert_eq!(json["tag"], Tag::NONBLOCKING_ASSIGNMENT_STATEMENT);
|
||||
|
||||
let (json_lpvalue, json_expression) = {
|
||||
let json_children = &json["children"];
|
||||
assert_eq!(json_children.len(), 4);
|
||||
assert_eq!(json_children[1]["tag"], "<=");
|
||||
assert_eq!(json_children[3]["tag"], ";");
|
||||
|
||||
(&json_children[0], &json_children[2])
|
||||
};
|
||||
|
||||
let json_symbol_identifier = Tools::match_tags(
|
||||
vec![json_lpvalue],
|
||||
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);
|
||||
context
|
||||
.lvalues
|
||||
.insert(json_symbol_identifier[0]["text"].to_string());
|
||||
|
||||
Expression::codegen(json_expression, context);
|
||||
|
||||
Logger::insert(format!(
|
||||
"TODO: complete the rest of NonblockingAssignmentStatement::codegen()"
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,12 +4,15 @@ use json::JsonValue;
|
|||
pub struct ProceduralTimingControlStatement {}
|
||||
|
||||
impl ProceduralTimingControlStatement {
|
||||
pub fn codegen(json: &JsonValue, context: &ModuleContext) {
|
||||
pub fn codegen(json: &JsonValue, context: &mut ModuleContext) {
|
||||
assert_eq!(json["tag"], Tag::PROCEDURAL_TIMING_CONTROL_STATEMENT);
|
||||
assert_eq!(json["children"].len(), 2);
|
||||
|
||||
let json_event_control = &json["children"][0];
|
||||
let json_statement = &json["children"][1];
|
||||
let (json_event_control, json_statement) = {
|
||||
let json_children = &json["children"];
|
||||
assert_eq!(json_children.len(), 2);
|
||||
|
||||
(&json_children[0], &json_children[1])
|
||||
};
|
||||
|
||||
let json_event_expression_list = Tools::match_tags(
|
||||
vec![json_event_control],
|
||||
|
|
|
@ -4,7 +4,7 @@ use json::JsonValue;
|
|||
pub struct SeqBlock {}
|
||||
|
||||
impl SeqBlock {
|
||||
pub fn codegen(json: &JsonValue, context: &ModuleContext) {
|
||||
pub fn codegen(json: &JsonValue, context: &mut ModuleContext) {
|
||||
let json_block_item_statement_list = {
|
||||
let json_vec = Tools::match_tags(
|
||||
vec![json],
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
use crate::cst::{
|
||||
CaseStatement, ConditionalStatement, ModuleContext, NonblockingAssignmentStatement, SeqBlock,
|
||||
Tag,
|
||||
CaseStatement, ConditionalStatement, Logger, ModuleContext, NonblockingAssignmentStatement,
|
||||
SeqBlock, Tag,
|
||||
};
|
||||
use json::JsonValue;
|
||||
|
||||
pub struct Statement {}
|
||||
|
||||
impl Statement {
|
||||
pub fn codegen(json: &JsonValue, context: &ModuleContext) {
|
||||
pub fn codegen(json: &JsonValue, context: &mut ModuleContext) {
|
||||
match json["tag"].as_str() {
|
||||
Some(Tag::SEQ_BLOCK) => SeqBlock::codegen(json, context),
|
||||
Some(Tag::CONDITIONAL_STATEMENT) => ConditionalStatement::codegen(json, context),
|
||||
|
@ -16,7 +16,7 @@ impl Statement {
|
|||
NonblockingAssignmentStatement::codegen(json, context)
|
||||
}
|
||||
Some(x) => {
|
||||
println!("FIXME: missing {}", x);
|
||||
Logger::insert(format!("FIXME: missing {}", x));
|
||||
}
|
||||
_ => panic!(),
|
||||
};
|
||||
|
|
|
@ -19,7 +19,15 @@ impl Tag {
|
|||
pub const DIMENSION_RANGE: &'static str = "kDimensionRange";
|
||||
pub const SYMBOL_IDENTIFIER: &'static str = "SymbolIdentifier";
|
||||
|
||||
pub const LP_VALUE: &'static str = "kLPValue";
|
||||
pub const REFERENCE_CALL_BASE: &'static str = "kReferenceCallBase";
|
||||
pub const REFERENCE: &'static str = "kReference";
|
||||
pub const LOCAL_ROOT: &'static str = "kLocalRoot";
|
||||
|
||||
pub const EXPRESSION: &'static str = "kExpression";
|
||||
pub const UNARY_PREFIX_EXPRESSION: &'static str = "kUnaryPrefixExpression";
|
||||
pub const BINARY_EXPRESSION: &'static str = "kBinaryExpression";
|
||||
|
||||
pub const NUMBER: &'static str = "kNumber";
|
||||
pub const DEC_NUMBER: &'static str = "TK_DecNumber";
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use json::JsonValue;
|
||||
use std::collections::HashSet;
|
||||
use std::{
|
||||
fs::File,
|
||||
io::{BufRead, BufReader},
|
||||
|
@ -20,6 +21,30 @@ impl Tools {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct Logger {}
|
||||
|
||||
static mut LOGGER_MESSAGES: Vec<String> = Vec::new();
|
||||
|
||||
impl Logger {
|
||||
pub fn insert(msg: String) {
|
||||
unsafe {
|
||||
LOGGER_MESSAGES.push(msg);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn print() {
|
||||
let mut msg = HashSet::new();
|
||||
unsafe {
|
||||
for m in &LOGGER_MESSAGES {
|
||||
if !msg.contains(&m) {
|
||||
println!("{}", m);
|
||||
msg.insert(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CodeReporter {
|
||||
file_name: String,
|
||||
line_breakers: Vec<usize>,
|
||||
|
|
Loading…
Reference in New Issue