Remove lvalues and rvalues from context

This commit is contained in:
Guojie Luo 2022-05-21 00:24:15 +08:00
parent 88632042e2
commit e53cee4959
12 changed files with 223 additions and 183 deletions

34
Cargo.lock generated
View File

@ -126,9 +126,8 @@ name = "cst-to-llhd"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"clap", "clap",
"indexmap",
"json", "json",
"linked-hash-map",
"linked_hash_set",
"llhd", "llhd",
"log", "log",
"num", "num",
@ -155,6 +154,12 @@ dependencies = [
"termcolor", "termcolor",
] ]
[[package]]
name = "hashbrown"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
[[package]] [[package]]
name = "hermit-abi" name = "hermit-abi"
version = "0.1.19" version = "0.1.19"
@ -183,6 +188,16 @@ dependencies = [
"quick-error", "quick-error",
] ]
[[package]]
name = "indexmap"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee"
dependencies = [
"autocfg",
"hashbrown",
]
[[package]] [[package]]
name = "itertools" name = "itertools"
version = "0.9.0" version = "0.9.0"
@ -216,21 +231,6 @@ version = "0.2.121"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efaa7b300f3b5fe8eb6bf21ce3895e1751d9665086af2d64b42f19701015ff4f" checksum = "efaa7b300f3b5fe8eb6bf21ce3895e1751d9665086af2d64b42f19701015ff4f"
[[package]]
name = "linked-hash-map"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3"
[[package]]
name = "linked_hash_set"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47186c6da4d81ca383c7c47c1bfc80f4b95f4720514d860a5407aaf4233f9588"
dependencies = [
"linked-hash-map",
]
[[package]] [[package]]
name = "llhd" name = "llhd"
version = "0.16.0" version = "0.16.0"

View File

@ -12,8 +12,7 @@ llhd = "*"
log = "*" log = "*"
num = "0.3.1" num = "0.3.1"
num-bigint = "0.3.3" num-bigint = "0.3.3"
linked_hash_set = "*" indexmap = "*"
linked-hash-map = "*"
pretty_env_logger = "0.4" pretty_env_logger = "0.4"
[[bin]] [[bin]]

View File

@ -1,9 +1,9 @@
use crate::{ use crate::{
cst::{Expression, ModuleContext, Statement, SymbolKind, Tag, UnitContext}, cst::{Expression, ModuleContext, Statement, SymbolKind, Tag, UnitContext},
tools::Tools, tools::{EventControl, Tools},
}; };
use indexmap::{map::IndexMap, set::IndexSet};
use json::JsonValue; use json::JsonValue;
use linked_hash_map::LinkedHashMap as HashMap;
use llhd::{ use llhd::{
ir::{Signature, UnitId, UnitKind, UnitName, Value}, ir::{Signature, UnitId, UnitKind, UnitName, Value},
ty::{int_ty, signal_ty}, ty::{int_ty, signal_ty},
@ -55,41 +55,44 @@ impl AlwaysStatement {
(json_event_control[0], &json_children[1]) (json_event_control[0], &json_children[1])
}; };
// first traversal let proc_names = EventControl::process_names(json);
assert!(context.unit_ctx.is_empty());
Self::gen_event_expression_list(json_event_expression_list, context);
Statement::codegen(json_statement, context);
assert!(context.unit_ctx.raw_name_to_arg.is_empty()); assert!(context.unit_ctx.raw_name_to_arg.is_empty());
let proc_signature = { let proc_signature = {
let mut ret = Signature::new(); let mut sig = Signature::new();
for lvalue in &context.unit_ctx.lvalues { for lvalue in &proc_names.lvalues {
if context.symbol.contains_key(lvalue) { if context.symbol.contains_key(lvalue) {
let symbol = &context.symbol[lvalue]; let symbol = &context.symbol[lvalue];
assert_ne!(symbol.kind, SymbolKind::Param); assert_ne!(symbol.kind, SymbolKind::Param);
let width = symbol.value.width.clone(); let width = symbol.value.width.clone();
let arg = ret.add_output(signal_ty(int_ty(width))); let arg = sig.add_output(signal_ty(int_ty(width)));
context.unit_ctx.raw_name_to_arg.insert(lvalue.clone(), arg); context.unit_ctx.raw_name_to_arg.insert(lvalue.clone(), arg);
} else { } else {
error!("FIXME: symbol '{}' not found", lvalue); error!("FIXME: symbol '{}' not found", lvalue);
} }
} }
let rvalues: Vec<String> = context let mut rvalues = [
.unit_ctx proc_names.posedges.clone(),
.rvalues proc_names.negedges.clone(),
.iter() proc_names.levels.clone(),
.filter(|&x| !context.unit_ctx.lvalues.contains(x)) proc_names.ctrl_values.clone(),
.map(|x| x.clone()) proc_names.rvalues.clone(),
]
.iter()
.fold(IndexSet::new(), |acc, hs| acc.union(hs).cloned().collect());
rvalues = rvalues
.into_iter()
.filter(|x| !proc_names.lvalues.contains(x))
.collect(); .collect();
for rvalue in &rvalues { for rvalue in &rvalues {
if context.symbol.contains_key(rvalue) { if context.symbol.contains_key(rvalue) {
let symbol = &context.symbol[rvalue]; let symbol = &context.symbol[rvalue];
if symbol.kind != SymbolKind::Param { if symbol.kind != SymbolKind::Param {
let width = symbol.value.width.clone(); let width = symbol.value.width.clone();
let arg = ret.add_input(signal_ty(int_ty(width))); let arg = sig.add_input(signal_ty(int_ty(width)));
context.unit_ctx.raw_name_to_arg.insert(rvalue.clone(), arg); context.unit_ctx.raw_name_to_arg.insert(rvalue.clone(), arg);
} }
} else { } else {
@ -97,7 +100,7 @@ impl AlwaysStatement {
} }
} }
ret sig
}; };
context.unit_ctx.new_data( context.unit_ctx.new_data(
@ -110,8 +113,15 @@ impl AlwaysStatement {
proc_signature, proc_signature,
); );
// second traversal Self::gen_event_expression_list(
Self::gen_event_expression_list(json_event_expression_list, context); json_event_expression_list,
proc_names
.rvalues
.union(&proc_names.ctrl_values)
.cloned()
.collect(),
context,
);
Statement::codegen(json_statement, context); Statement::codegen(json_statement, context);
Tools::beautify(&mut context.unit_ctx); Tools::beautify(&mut context.unit_ctx);
@ -120,8 +130,12 @@ impl AlwaysStatement {
context.module.add_unit(context.unit_ctx.drop_data()) context.module.add_unit(context.unit_ctx.drop_data())
} }
fn gen_event_expression_list<'a>(json: &'a JsonValue, context: &mut ModuleContext<'a>) { fn gen_event_expression_list<'a>(
let mut sensitivity_list = HashMap::new(); json: &'a JsonValue,
rvalues: IndexSet<String>,
context: &mut ModuleContext<'a>,
) {
let mut sensitivity_list = IndexMap::new();
let json_expressions = Tools::match_tags( let json_expressions = Tools::match_tags(
vec![json], vec![json],
@ -133,18 +147,15 @@ impl AlwaysStatement {
match json_children[0]["tag"].as_str() { match json_children[0]["tag"].as_str() {
Some(Tag::POS_EDGE) => { Some(Tag::POS_EDGE) => {
let symbol = let symbol = Expression::gen_reference_name(&json_children[1]["children"][0]);
Expression::gen_reference_name(&json_children[1]["children"][0], context);
sensitivity_list.insert(symbol, Tag::POS_EDGE); sensitivity_list.insert(symbol, Tag::POS_EDGE);
} }
Some(Tag::NEG_EDGE) => { Some(Tag::NEG_EDGE) => {
let symbol = let symbol = Expression::gen_reference_name(&json_children[1]["children"][0]);
Expression::gen_reference_name(&json_children[1]["children"][0], context);
sensitivity_list.insert(symbol, Tag::NEG_EDGE); sensitivity_list.insert(symbol, Tag::NEG_EDGE);
} }
Some(Tag::EXPRESSION) => { Some(Tag::EXPRESSION) => {
let symbol = let symbol = Expression::gen_reference_name(&json_children[0]["children"][0]);
Expression::gen_reference_name(&json_children[0]["children"][0], context);
sensitivity_list.insert(symbol, Tag::EVENT_EXPRESSION); sensitivity_list.insert(symbol, Tag::EVENT_EXPRESSION);
} }
_ => panic!("unknown error at CST node '{}'", json), _ => panic!("unknown error at CST node '{}'", json),
@ -156,12 +167,11 @@ impl AlwaysStatement {
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 = &mut unit_ctx.raw_name_to_shadow; let raw_name_to_shadow = &mut unit_ctx.raw_name_to_shadow;
let raw_name_to_arg = &unit_ctx.raw_name_to_arg; let raw_name_to_arg = &unit_ctx.raw_name_to_arg;
let rvalues = &unit_ctx.rvalues;
let mut builder = UnitContext::builder(&mut unit_ctx.data); let mut builder = UnitContext::builder(&mut unit_ctx.data);
let mut arg_value_to_raw_name = HashMap::new(); let mut arg_value_to_raw_name = IndexMap::new();
let mut raw_name_to_prb_init = HashMap::new(); let mut raw_name_to_prb_init = IndexMap::new();
for (name, arg) in raw_name_to_arg { for (name, arg) in raw_name_to_arg {
let value = builder.arg_value(*arg); let value = builder.arg_value(*arg);
context context
@ -202,9 +212,9 @@ impl AlwaysStatement {
builder.append_to(bb_init); builder.append_to(bb_init);
let inputs: Vec<Value> = builder.unit().input_args().collect(); let inputs: Vec<Value> = builder.unit().input_args().collect();
let events: Vec<Value> = inputs let events: Vec<Value> = inputs
.iter() .into_iter()
.filter(|x| sensitivity_list.contains_key(&arg_value_to_raw_name[&x])) .filter(|&x| sensitivity_list.contains_key(&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);

View File

@ -1,6 +1,5 @@
use indexmap::map::IndexMap;
use json::JsonValue; use json::JsonValue;
use linked_hash_map::LinkedHashMap;
use linked_hash_set::LinkedHashSet;
use llhd::{ use llhd::{
ir::{ ir::{
Arg, Block, Inst, Module, Signature, Unit, UnitBuilder, UnitData, UnitKind, UnitName, Value, Arg, Block, Inst, Module, Signature, Unit, UnitBuilder, UnitData, UnitKind, UnitName, Value,
@ -13,15 +12,12 @@ use std::{collections::HashMap, fmt};
pub struct ModuleContext<'a> { pub struct ModuleContext<'a> {
pub name: String, pub name: String,
pub module: Module, pub module: Module,
pub symbol: LinkedHashMap<String, SymbolInfo<'a>>, pub symbol: IndexMap<String, SymbolInfo<'a>>,
pub unit_ctx: UnitContext, pub unit_ctx: UnitContext,
pub syntax_table: SyntaxTable<'a>, pub syntax_table: SyntaxTable<'a>,
} }
pub struct UnitContext { pub struct UnitContext {
pub lvalues: LinkedHashSet<String>,
pub rvalues: LinkedHashSet<String>,
pub data: Option<UnitData>, pub data: Option<UnitData>,
pub raw_name_to_arg: HashMap<String, Arg>, pub raw_name_to_arg: HashMap<String, Arg>,
@ -71,7 +67,7 @@ impl<'a> ModuleContext<'a> {
Self { Self {
name: String::new(), name: String::new(),
module: Module::new(), module: Module::new(),
symbol: LinkedHashMap::new(), symbol: IndexMap::new(),
unit_ctx: UnitContext::new(), unit_ctx: UnitContext::new(),
syntax_table: SyntaxTable::new(json), syntax_table: SyntaxTable::new(json),
} }
@ -81,8 +77,6 @@ impl<'a> ModuleContext<'a> {
impl UnitContext { impl UnitContext {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
lvalues: LinkedHashSet::new(),
rvalues: LinkedHashSet::new(),
data: None, data: None,
raw_name_to_arg: HashMap::new(), raw_name_to_arg: HashMap::new(),
raw_name_to_value: HashMap::new(), raw_name_to_value: HashMap::new(),
@ -93,8 +87,6 @@ impl UnitContext {
} }
pub fn drop(&mut self) -> Self { pub fn drop(&mut self) -> Self {
let ret = Self { let ret = Self {
lvalues: self.lvalues.iter().map(|x| x.clone()).collect(),
rvalues: self.rvalues.iter().map(|x| x.clone()).collect(),
data: self.data.take(), data: self.data.take(),
raw_name_to_arg: self.raw_name_to_arg.drain().collect(), raw_name_to_arg: self.raw_name_to_arg.drain().collect(),
raw_name_to_value: self.raw_name_to_value.drain().collect(), raw_name_to_value: self.raw_name_to_value.drain().collect(),
@ -114,8 +106,6 @@ impl UnitContext {
} }
pub fn clear(&mut self) { pub fn clear(&mut self) {
self.lvalues.clear();
self.rvalues.clear();
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();
@ -125,8 +115,6 @@ impl UnitContext {
pub fn is_empty(&self) -> bool { pub fn is_empty(&self) -> bool {
self.data.is_none() self.data.is_none()
&& self.lvalues.is_empty()
&& self.rvalues.is_empty()
&& 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()

View File

@ -15,8 +15,8 @@ use log::{debug, error, info, trace, warn};
pub struct Expression {} pub struct Expression {}
impl Expression { impl Expression {
pub fn gen_reference_name(json: &JsonValue, context: &mut ModuleContext) -> String { pub fn gen_reference_name(json: &JsonValue) -> String {
Self::gen_reference_call(json, context).0 Self::gen_reference_call(json).0
} }
pub fn codegen<'a>(json: &'a JsonValue, context: &mut ModuleContext<'a>) -> Option<Value> { pub fn codegen<'a>(json: &'a JsonValue, context: &mut ModuleContext<'a>) -> Option<Value> {
@ -44,10 +44,7 @@ impl Expression {
} }
} }
fn gen_reference_call( fn gen_reference_call(json: &JsonValue) -> (String, Option<(usize, usize)>) {
json: &JsonValue,
context: &mut ModuleContext,
) -> (String, Option<(usize, usize)>) {
let json_symbol_identifier = Tools::match_tags( let json_symbol_identifier = Tools::match_tags(
vec![json], vec![json],
vec![ vec![
@ -97,13 +94,12 @@ impl Expression {
}; };
let symbol = &json_symbol_identifier[0]["text"]; let symbol = &json_symbol_identifier[0]["text"];
context.unit_ctx.rvalues.insert(symbol.to_string());
(symbol.to_string(), range) (symbol.to_string(), range)
} }
fn gen_reference_value(json: &JsonValue, context: &mut ModuleContext) -> Option<Value> { fn gen_reference_value(json: &JsonValue, context: &mut ModuleContext) -> Option<Value> {
let (symbol, range) = Self::gen_reference_call(json, context); let (symbol, range) = Self::gen_reference_call(json);
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;

View File

@ -259,7 +259,7 @@ impl<'a> ModuleDeclaration {
named_port_symbol_path.to_vec(), named_port_symbol_path.to_vec(),
); );
if json_symbol.len() == 1 { if json_symbol.len() == 1 {
let symbol = &Expression::gen_reference_name(json_symbol[0], context); let symbol = &Expression::gen_reference_name(json_symbol[0]);
Some(context.unit_ctx.raw_name_to_value[symbol]) Some(context.unit_ctx.raw_name_to_value[symbol])
} else { } else {
let json_number = Tools::match_tags( let json_number = Tools::match_tags(
@ -303,7 +303,7 @@ impl<'a> ModuleDeclaration {
.enumerate() .enumerate()
{ {
let json_expr = pos_port_list[&index]; let json_expr = pos_port_list[&index];
let arg = &Expression::gen_reference_name(json_expr, context); let arg = &Expression::gen_reference_name(json_expr);
let v = context.unit_ctx.raw_name_to_value[arg]; let v = context.unit_ctx.raw_name_to_value[arg];
if arg_info.kind == SymbolKind::Input { if arg_info.kind == SymbolKind::Input {
inputs.push(v); inputs.push(v);

View File

@ -43,7 +43,6 @@ impl NetVariableAssignment {
}; };
let lvalue_name = &json_lpvalue["text"].to_string(); let lvalue_name = &json_lpvalue["text"].to_string();
context.unit_ctx.lvalues.insert(lvalue_name.clone());
let lvalue = context.unit_ctx.raw_name_to_value.get(lvalue_name); let lvalue = context.unit_ctx.raw_name_to_value.get(lvalue_name);
if lvalue.is_some() { if lvalue.is_some() {
assert!(context.unit_ctx.data.is_some()); assert!(context.unit_ctx.data.is_some());

View File

@ -36,7 +36,6 @@ impl NonblockingAssignmentStatement {
(json_symbol_identifier[0], &json_children[2]) (json_symbol_identifier[0], &json_children[2])
}; };
let lvalue_name = &json_lpvalue["text"].to_string(); let lvalue_name = &json_lpvalue["text"].to_string();
context.unit_ctx.lvalues.insert(lvalue_name.clone());
if context.unit_ctx.raw_name_to_value.contains_key(lvalue_name) { if context.unit_ctx.raw_name_to_value.contains_key(lvalue_name) {
assert!(context.unit_ctx.raw_name_to_arg.contains_key(lvalue_name)); assert!(context.unit_ctx.raw_name_to_arg.contains_key(lvalue_name));
assert!(context.unit_ctx.data.is_some()); assert!(context.unit_ctx.data.is_some());

View File

@ -0,0 +1,67 @@
use std::{
fs::File,
io::{BufRead, BufReader},
};
#[allow(unused_imports)]
use log::{debug, error, info, trace, warn};
pub struct CodeReporter {
file_name: String,
line_breakers: Vec<usize>,
}
impl CodeReporter {
pub fn new(file_name: &str) -> Self {
Self {
file_name: file_name.to_string(),
line_breakers: Self::read_line_breakers(file_name),
}
}
pub fn line_no(&self, key: usize) -> usize {
self.line_no_rec(key, 0, self.line_breakers.len() - 1)
}
pub fn line(&self, line_no: usize) -> String {
let reader = BufReader::new(
File::open(self.file_name.as_str())
.expect(format!(r#"file "{}" not found"#, self.file_name.as_str()).as_str()),
);
reader.lines().nth(line_no).unwrap().unwrap()
}
pub fn line_count(&self) -> usize {
self.line_breakers.len()
}
fn read_line_breakers(file_name: &str) -> Vec<usize> {
let reader = BufReader::new(
File::open(file_name).expect(format!(r#"file "{}" not found"#, file_name).as_str()),
);
let mut line_breakers = Vec::new();
line_breakers.push(0);
for line in reader.lines() {
let line_no = 1 + line_breakers.last().unwrap() + line.unwrap().len();
line_breakers.push(line_no);
}
line_breakers
}
fn line_no_rec(&self, key: usize, left: usize, right: usize) -> usize {
if left + 1 >= right {
left
} else {
let mid = (left + right) / 2;
if key < self.line_breakers[mid] {
self.line_no_rec(key, left, mid)
} else {
self.line_no_rec(key, mid, right)
}
}
}
}

View File

@ -1,54 +1,74 @@
use crate::{cst::Tag, tools::Tools}; use crate::{cst::Tag, tools::Tools};
use indexmap::set::IndexSet;
use json::JsonValue; use json::JsonValue;
use std::{collections::HashSet, iter::FromIterator}; use std::iter::FromIterator;
#[allow(unused_imports)] #[allow(unused_imports)]
use log::{debug, error, info, trace, warn}; use log::{debug, error, info, trace, warn};
pub struct ProcessNames {
pub posedges: IndexSet<String>,
pub negedges: IndexSet<String>,
pub levels: IndexSet<String>,
pub lvalues: IndexSet<String>,
pub rvalues: IndexSet<String>,
pub ctrl_values: IndexSet<String>,
}
impl ProcessNames {
pub fn new() -> Self {
Self {
posedges: IndexSet::new(),
negedges: IndexSet::new(),
levels: IndexSet::new(),
lvalues: IndexSet::new(),
rvalues: IndexSet::new(),
ctrl_values: IndexSet::new(),
}
}
}
pub struct EventControl {} pub struct EventControl {}
impl EventControl { impl EventControl {
pub fn clock_and_reset_names(json: &JsonValue) -> (HashSet<String>, HashSet<String>) { pub fn clock_and_reset_names(json: &JsonValue) -> (IndexSet<String>, IndexSet<String>) {
let mut clock_names: HashSet<String> = HashSet::new(); let mut clock_names: IndexSet<String> = IndexSet::new();
let mut reset_names: HashSet<String> = HashSet::new(); let mut reset_names: IndexSet<String> = IndexSet::new();
let json_always_statements = Tools::collect_tag(json, Tag::ALWAYS_STATEMENT); let json_always_statements = Tools::collect_tag(json, Tag::ALWAYS_STATEMENT);
for json_always_statement in json_always_statements { for json_always_statement in json_always_statements {
let (json_events, json_body) = Self::events_and_body(json_always_statement); let (json_events, json_body) = Self::events_and_body(json_always_statement);
let (json_posedge_names, json_negedge_names, json_level_names) = let (posedge_names, negedge_names, level_names) = Self::event_names(json_events);
Self::event_names(json_events);
let (json_lvalues, json_rvalues, json_ctrl_values) = Self::value_names(json_body); let (lvalues, rvalues, ctrl_values) = Self::value_names(json_body);
let json_top_ctrl_values = Self::top_ctrl_values(json_body); let top_ctrl_values = Self::top_ctrl_values(json_body);
let json_edge_names = [json_posedge_names.clone(), json_negedge_names.clone()].concat(); let edge_names: IndexSet<_> = posedge_names.union(&negedge_names).cloned().collect();
let json_sens_names = [json_edge_names.clone(), json_level_names.clone()].concat(); let sens_names: IndexSet<_> = edge_names.union(&level_names).cloned().collect();
let json_data_values: HashSet<String> = let data_values: IndexSet<String> = lvalues.union(&rvalues).cloned().collect();
json_lvalues.union(&json_rvalues).cloned().collect(); let all_values: IndexSet<String> = data_values.union(&ctrl_values).cloned().collect();
let json_all_values: HashSet<String> =
json_data_values.union(&json_ctrl_values).cloned().collect();
let local_clock_names: HashSet<String> = HashSet::from_iter( let local_clock_names: IndexSet<String> = IndexSet::from_iter(
json_edge_names edge_names
.clone() .clone()
.into_iter() .into_iter()
.filter(|x| !json_all_values.contains(x)), .filter(|x| !all_values.contains(x)),
); );
let local_reset_names: HashSet<String> = HashSet::from_iter( let local_reset_names: IndexSet<String> = IndexSet::from_iter(
json_sens_names sens_names
.clone() .clone()
.into_iter() .into_iter()
.filter(|x| !json_data_values.contains(x) && json_top_ctrl_values.contains(x)), .filter(|x| !data_values.contains(x) && top_ctrl_values.contains(x)),
); );
trace!("edge_names {:?}", json_edge_names); trace!("edge_names {:?}", edge_names);
trace!("sens_names {:?}", json_sens_names); trace!("sens_names {:?}", sens_names);
trace!("data_values {:?}", json_data_values); trace!("data_values {:?}", data_values);
trace!("all_values {:?}", json_all_values); trace!("all_values {:?}", all_values);
trace!("top_ctrl_values {:?}", json_top_ctrl_values); trace!("top_ctrl_values {:?}", top_ctrl_values);
clock_names = clock_names.union(&local_clock_names).cloned().collect(); clock_names = clock_names.union(&local_clock_names).cloned().collect();
reset_names = reset_names.union(&local_reset_names).cloned().collect(); reset_names = reset_names.union(&local_reset_names).cloned().collect();
@ -59,6 +79,24 @@ impl EventControl {
(clock_names, reset_names) (clock_names, reset_names)
} }
pub fn process_names(json_always_statement: &JsonValue) -> ProcessNames {
let (json_events, json_body) = Self::events_and_body(json_always_statement);
let (posedge_names, negedge_names, level_names) = Self::event_names(json_events);
let (lvalues, rvalues, ctrl_values) = Self::value_names(json_body);
let mut names = ProcessNames::new();
names.posedges = posedge_names;
names.negedges = negedge_names;
names.levels = level_names;
names.lvalues = lvalues.into_iter().collect();
names.rvalues = rvalues.into_iter().collect();
names.ctrl_values = ctrl_values.into_iter().collect();
names
}
fn events_and_body(json: &JsonValue) -> (Vec<&JsonValue>, &JsonValue) { fn events_and_body(json: &JsonValue) -> (Vec<&JsonValue>, &JsonValue) {
assert_eq!(json["tag"], Tag::ALWAYS_STATEMENT); assert_eq!(json["tag"], Tag::ALWAYS_STATEMENT);
let (json_events, json_body) = { let (json_events, json_body) = {
@ -90,10 +128,12 @@ impl EventControl {
(json_events, json_body) (json_events, json_body)
} }
fn event_names(json_events: Vec<&JsonValue>) -> (Vec<String>, Vec<String>, Vec<String>) { fn event_names(
let mut json_posedge_names = Vec::new(); json_events: Vec<&JsonValue>,
let mut json_negedge_names = Vec::new(); ) -> (IndexSet<String>, IndexSet<String>, IndexSet<String>) {
let mut json_level_names = Vec::new(); let mut posedge_names = IndexSet::new();
let mut negedge_names = IndexSet::new();
let mut level_names = IndexSet::new();
let json_id = |x: &JsonValue| -> String { let json_id = |x: &JsonValue| -> String {
let json_symbol_identifiers = Tools::collect_tag(&x, Tag::SYMBOL_IDENTIFIER); let json_symbol_identifiers = Tools::collect_tag(&x, Tag::SYMBOL_IDENTIFIER);
@ -104,20 +144,22 @@ impl EventControl {
for json_event in json_events { for json_event in json_events {
match json_event["children"][0]["tag"].as_str() { match json_event["children"][0]["tag"].as_str() {
Some(Tag::POS_EDGE) => { Some(Tag::POS_EDGE) => {
json_posedge_names.push(json_id(json_event)); posedge_names.insert(json_id(json_event));
} }
Some(Tag::NEG_EDGE) => { Some(Tag::NEG_EDGE) => {
json_negedge_names.push(json_id(json_event)); negedge_names.insert(json_id(json_event));
} }
_ => { _ => {
json_level_names.push(json_id(json_event)); level_names.insert(json_id(json_event));
} }
} }
} }
(json_posedge_names, json_negedge_names, json_level_names) (posedge_names, negedge_names, level_names)
} }
fn value_names(json_body: &JsonValue) -> (HashSet<String>, HashSet<String>, HashSet<String>) { fn value_names(
json_body: &JsonValue,
) -> (IndexSet<String>, IndexSet<String>, IndexSet<String>) {
let json_assignments = [ let json_assignments = [
Tools::collect_tag(json_body, Tag::NONBLOCKING_ASSIGNMENT_STATEMENT), Tools::collect_tag(json_body, Tag::NONBLOCKING_ASSIGNMENT_STATEMENT),
Tools::collect_tag(json_body, Tag::NET_VARIABLE_ASSIGNMENT), Tools::collect_tag(json_body, Tag::NET_VARIABLE_ASSIGNMENT),
@ -136,21 +178,21 @@ impl EventControl {
] ]
.concat(); .concat();
let json_lvalues = HashSet::from_iter( let json_lvalues = IndexSet::from_iter(
json_assignments json_assignments
.iter() .iter()
.map(|x| Tools::collect_tag(&x["children"][0], Tag::SYMBOL_IDENTIFIER)) .map(|x| Tools::collect_tag(&x["children"][0], Tag::SYMBOL_IDENTIFIER))
.flatten() .flatten()
.map(|x| x["text"].to_string()), .map(|x| x["text"].to_string()),
); );
let json_rvalues = HashSet::from_iter( let json_rvalues = IndexSet::from_iter(
json_assignments json_assignments
.iter() .iter()
.map(|x| Tools::collect_tag(&x["children"][2], Tag::SYMBOL_IDENTIFIER)) .map(|x| Tools::collect_tag(&x["children"][2], Tag::SYMBOL_IDENTIFIER))
.flatten() .flatten()
.map(|x| x["text"].to_string()), .map(|x| x["text"].to_string()),
); );
let json_ctrl_values = HashSet::from_iter( let json_ctrl_values = IndexSet::from_iter(
json_conditions json_conditions
.iter() .iter()
.map(|x| Tools::collect_tag(x, Tag::SYMBOL_IDENTIFIER)) .map(|x| Tools::collect_tag(x, Tag::SYMBOL_IDENTIFIER))
@ -161,7 +203,7 @@ impl EventControl {
(json_lvalues, json_rvalues, json_ctrl_values) (json_lvalues, json_rvalues, json_ctrl_values)
} }
fn top_ctrl_values(json_body: &JsonValue) -> HashSet<String> { fn top_ctrl_values(json_body: &JsonValue) -> IndexSet<String> {
let json_statement = { let json_statement = {
let mut ret = json_body; let mut ret = json_body;
loop { loop {
@ -182,7 +224,7 @@ impl EventControl {
} }
} }
}; };
HashSet::from_iter( IndexSet::from_iter(
Tools::match_tags( Tools::match_tags(
vec![json_statement], vec![json_statement],
vec![ vec![

View File

@ -1,5 +1,7 @@
pub mod code_reporter;
pub mod event_control; pub mod event_control;
mod tools; pub mod tools;
pub use event_control::EventControl; pub use code_reporter::CodeReporter;
pub use tools::{CodeReporter, Tools}; pub use event_control::{EventControl, ProcessNames};
pub use tools::Tools;

View File

@ -4,8 +4,6 @@ use llhd::ir::{Block, Inst, Opcode};
use std::{ use std::{
cell::RefCell, cell::RefCell,
collections::{HashMap, HashSet, VecDeque}, collections::{HashMap, HashSet, VecDeque},
fs::File,
io::{BufRead, BufReader},
iter::FromIterator, iter::FromIterator,
process::{Command, Stdio}, process::{Command, Stdio},
rc::Rc, rc::Rc,
@ -279,63 +277,3 @@ impl Tools {
modules modules
} }
} }
pub struct CodeReporter {
file_name: String,
line_breakers: Vec<usize>,
}
impl CodeReporter {
pub fn new(file_name: &str) -> Self {
Self {
file_name: file_name.to_string(),
line_breakers: Self::read_line_breakers(file_name),
}
}
pub fn line_no(&self, key: usize) -> usize {
self.line_no_rec(key, 0, self.line_breakers.len() - 1)
}
pub fn line(&self, line_no: usize) -> String {
let reader = BufReader::new(
File::open(self.file_name.as_str())
.expect(format!(r#"file "{}" not found"#, self.file_name.as_str()).as_str()),
);
reader.lines().nth(line_no).unwrap().unwrap()
}
pub fn line_count(&self) -> usize {
self.line_breakers.len()
}
fn read_line_breakers(file_name: &str) -> Vec<usize> {
let reader = BufReader::new(
File::open(file_name).expect(format!(r#"file "{}" not found"#, file_name).as_str()),
);
let mut line_breakers = Vec::new();
line_breakers.push(0);
for line in reader.lines() {
let line_no = 1 + line_breakers.last().unwrap() + line.unwrap().len();
line_breakers.push(line_no);
}
line_breakers
}
fn line_no_rec(&self, key: usize, left: usize, right: usize) -> usize {
if left + 1 >= right {
left
} else {
let mid = (left + right) / 2;
if key < self.line_breakers[mid] {
self.line_no_rec(key, left, mid)
} else {
self.line_no_rec(key, mid, right)
}
}
}
}