Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor msb check and emittion #1154

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 45 additions & 13 deletions crates/analyzer/src/handlers/check_msb_lsb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::msb_table;
use crate::namespace::Namespace;
use crate::namespace_table;
use crate::symbol::Type as SymType;
use crate::symbol::{SymbolKind, TypeKind};
use crate::symbol::{Direction, SymbolKind, TypeKind};
use crate::symbol_path::{SymbolPath, SymbolPathNamespace};
use crate::symbol_table;
use veryl_parser::veryl_grammar_trait::*;
Expand Down Expand Up @@ -40,10 +40,11 @@ impl Handler for CheckMsbLsb<'_> {
}
}

fn trace_type(r#type: &SymType, namespace: &Namespace) -> Vec<SymType> {
let mut ret = vec![r#type.clone()];
fn trace_type(r#type: &SymType, namespace: &Namespace) -> Vec<(SymType, Option<SymbolKind>)> {
let mut ret = vec![(r#type.clone(), None)];
if let TypeKind::UserDefined(ref x) = r#type.kind {
if let Ok(symbol) = symbol_table::resolve((&SymbolPath::new(x), namespace)) {
ret.last_mut().unwrap().1 = Some(symbol.found.kind.clone());
if let SymbolKind::TypeDef(ref x) = symbol.found.kind {
ret.append(&mut trace_type(&x.r#type, namespace));
}
Expand Down Expand Up @@ -73,32 +74,63 @@ impl VerylGrammarTrait for CheckMsbLsb<'_> {
{
let namespace = &x.found.namespace;

let r#type = match x.found.kind {
SymbolKind::Variable(x) => Some(x.r#type),
SymbolKind::Port(x) => x.r#type,
_ => None,
let via_interface = x.full_path.iter().any(|path| {
let symbol = symbol_table::get(*path).unwrap();
match symbol.kind {
SymbolKind::Port(x) => {
matches!(x.direction, Direction::Interface | Direction::Modport)
}
SymbolKind::Instance(_) => true,
_ => false,
}
});
let r#type = if !via_interface {
match x.found.kind {
SymbolKind::Variable(x) => Some(x.r#type),
SymbolKind::Port(x) => x.r#type,
SymbolKind::Parameter(x) => Some(x.r#type),
SymbolKind::StructMember(x) => Some(x.r#type),
SymbolKind::UnionMember(x) => Some(x.r#type),
_ => None,
}
} else {
None
};

if let Some(x) = r#type {
let types = trace_type(&x, namespace);
let mut select_dimension = *self.select_dimension.last().unwrap();

let mut expression = None;
for t in types {
let mut demension_number = None;
for (i, (t, k)) in types.iter().enumerate() {
if select_dimension < t.array.len() {
expression = t.array.get(select_dimension).cloned();
demension_number = Some(select_dimension + 1);
break;
}
select_dimension -= t.array.len();

if select_dimension < t.width.len() {
expression = t.width.get(select_dimension).cloned();
demension_number = Some(select_dimension + 1);
break;
}
select_dimension -= t.width.len();

if select_dimension == 0
&& (i + 1) == types.len()
&& matches!(
k,
Some(SymbolKind::Enum(_))
| Some(SymbolKind::Struct(_))
| Some(SymbolKind::Union(_))
)
{
demension_number = Some(0);
break;
}
}

if let Some(expression) = expression {
msb_table::insert(arg.msb_token.token.id, &expression);
if let Some(demension_number) = demension_number {
msb_table::insert(arg.msb_token.token.id, demension_number);
true
} else {
false
Expand Down
15 changes: 7 additions & 8 deletions crates/analyzer/src/msb_table.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
use std::cell::RefCell;
use std::collections::HashMap;
use veryl_parser::resource_table::TokenId;
use veryl_parser::veryl_grammar_trait::Expression;

#[derive(Clone, Default, Debug)]
pub struct MsbTable {
table: HashMap<TokenId, Expression>,
table: HashMap<TokenId, usize>,
}

impl MsbTable {
pub fn insert(&mut self, id: TokenId, expression: &Expression) {
self.table.insert(id, expression.clone());
pub fn insert(&mut self, id: TokenId, dimension_number: usize) {
self.table.insert(id, dimension_number);
}

pub fn get(&self, id: TokenId) -> Option<&Expression> {
pub fn get(&self, id: TokenId) -> Option<&usize> {
self.table.get(&id)
}

Expand All @@ -24,11 +23,11 @@ impl MsbTable {

thread_local!(static MSB_TABLE: RefCell<MsbTable> = RefCell::new(MsbTable::default()));

pub fn insert(id: TokenId, expression: &Expression) {
MSB_TABLE.with(|f| f.borrow_mut().insert(id, expression))
pub fn insert(id: TokenId, dimension_number: usize) {
MSB_TABLE.with(|f| f.borrow_mut().insert(id, dimension_number))
}

pub fn get(id: TokenId) -> Option<Expression> {
pub fn get(id: TokenId) -> Option<usize> {
MSB_TABLE.with(|f| f.borrow().get(id).cloned())
}

Expand Down
56 changes: 56 additions & 0 deletions crates/analyzer/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1771,6 +1771,62 @@ fn unknown_msb() {

let errors = analyze(code);
assert!(matches!(errors[0], AnalyzerError::UnknownMsb { .. }));

let code = r#"
interface InterfaceA {
var a: logic<2>;
modport mp {
a: input
}
}
module ModuleA (
if_a: modport InterfaceA::mp
) {
let a: logic = if_a.a[msb];
}
"#;

let errors = analyze(code);
assert!(matches!(errors[0], AnalyzerError::UnknownMsb { .. }));

let code = r#"
interface InterfaceA #(
param W: u32 = 2
){
var a: logic<W>;
}
module ModuleA {
inst if_a: InterfaceA;
assign if_a.a = 0;
let a: logic = if_a.a[msb];
}
"#;

let errors = analyze(code);
assert!(matches!(errors[0], AnalyzerError::UnknownMsb { .. }));

let code = r#"
package PackageA::<W: const> {
struct StructA {
a: logic<W>,
}
}
package PackageB {
const B: u32 = 2;
}
package PackageC {
const C: bit<2> = 0;
}
module ModuleA {
var a: PackageA::<PackageB::B>::StructA;
assign a.a = 0;
let _b: logic = a.a[msb];
let _c: logic = PackageC::C[msb];
}
"#;

let errors = analyze(code);
assert!(errors.is_empty());
}

#[test]
Expand Down
36 changes: 31 additions & 5 deletions crates/emitter/src/emitter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ pub struct Emitter {
assignment_lefthand_side: Option<ExpressionIdentifier>,
generic_map: Vec<GenericMap>,
source_map: Option<SourceMap>,
resolved_identifier: Vec<String>,
}

impl Default for Emitter {
Expand Down Expand Up @@ -108,6 +109,7 @@ impl Default for Emitter {
assignment_lefthand_side: None,
generic_map: Vec::new(),
source_map: None,
resolved_identifier: Vec::new(),
}
}
}
Expand Down Expand Up @@ -900,6 +902,12 @@ impl Emitter {
(None, prefix.is_some())
}
}

fn push_resolved_identifier(&mut self, x: &str) {
if let Some(identifier) = self.resolved_identifier.last_mut() {
identifier.push_str(x);
}
}
}

fn is_var_declaration(arg: &StatementBlockItem) -> bool {
Expand Down Expand Up @@ -1057,10 +1065,15 @@ impl VerylWalker for Emitter {

/// Semantic action for non-terminal 'Msb'
fn msb(&mut self, arg: &Msb) {
let expression = msb_table::get(arg.msb_token.token.id).unwrap();
self.str("((");
self.expression(&expression);
self.str(") - 1)");
let identifier = self.resolved_identifier.last().unwrap();
let demension_number = msb_table::get(arg.msb_token.token.id).unwrap();

let text = if demension_number == 0 {
format!("($bits({}) - 1)", identifier)
} else {
format!("($size({}, {}) - 1)", identifier, demension_number)
};
self.token(&arg.msb_token.replace(&text));
}

/// Semantic action for non-terminal 'Param'
Expand All @@ -1085,7 +1098,9 @@ impl VerylWalker for Emitter {

/// Semantic action for non-terminal 'Identifier'
fn identifier(&mut self, arg: &Identifier) {
self.veryl_token(&emitting_identifier(arg));
let text = emitting_identifier(arg);
self.veryl_token(&text);
self.push_resolved_identifier(&text.to_string());
}

/// Semantic action for non-terminal 'HierarchicalIdentifier'
Expand Down Expand Up @@ -1166,26 +1181,37 @@ impl VerylWalker for Emitter {
let context: SymbolContext = self.into();
let text = symbol_string(arg.identifier(), &symbol.found, &context);
self.veryl_token(&arg.identifier().replace(&text));
self.push_resolved_identifier(&text);
} else if !path.is_resolvable() {
// emit literal by generics
let text = path.base_path(0).0[0].to_string();
self.veryl_token(&arg.identifier().replace(&text));
self.push_resolved_identifier(&text);
}
}

/// Semantic action for non-terminal 'ExpressionIdentifier'
fn expression_identifier(&mut self, arg: &ExpressionIdentifier) {
self.resolved_identifier.push("".to_string());
self.scoped_identifier(&arg.scoped_identifier);
for x in &arg.expression_identifier_list {
self.select(&x.select);
}
for _x in &arg.expression_identifier_list {
self.push_resolved_identifier("[0]");
}
for x in &arg.expression_identifier_list0 {
self.dot(&x.dot);
self.push_resolved_identifier(".");
self.identifier(&x.identifier);
for x in &x.expression_identifier_list0_list {
self.select(&x.select);
}
for _x in &x.expression_identifier_list0_list {
self.push_resolved_identifier("[0]");
}
}
self.resolved_identifier.pop();
}

/// Semantic action for non-terminal 'Expression'
Expand Down
2 changes: 1 addition & 1 deletion testcases/map/testcases/sv/28_msblsb.sv.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

38 changes: 34 additions & 4 deletions testcases/sv/28_msblsb.sv
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module veryl_testcase_Module28 (
module veryl_testcase_Module28A (
input logic [30-1:0][40-1:0] c
);
localparam int unsigned WIDTH0 = 10;
Expand All @@ -10,10 +10,40 @@ module veryl_testcase_Module28 (
always_comb b = 1;

logic _x;
always_comb _x = a[((10) - 1)][((20) - 1):0 + 1];
always_comb _x = a[($size(a, 1) - 1)][($size(a, 2) - 1):0 + 1];
logic _y;
always_comb _y = b[((WIDTH0 + 10) - 1) - 3][((WIDTH1) - 1) + 5:0];
always_comb _y = b[($size(b, 1) - 1) - 3][($size(b, 2) - 1) + 5:0];
logic _z;
always_comb _z = c[((30) - 1)][((40) - 1)];
always_comb _z = c[($size(c, 1) - 1)][($size(c, 2) - 1)];
endmodule

package veryl_testcase___Package28A__Package28B_B;
typedef struct packed {
logic [veryl_testcase_Package28B::B-1:0] a;
} StructA;
endpackage

package veryl_testcase_Package28B;
localparam int unsigned B = 2;
endpackage

package veryl_testcase_Package28C;
localparam int unsigned W = 2;
localparam int unsigned N = 3;
localparam bit [N-1:0][W-1:0] C = 0;
endpackage

module veryl_testcase_ModuleB;
veryl_testcase___Package28A__Package28B_B::StructA a ;
always_comb a.a = 0;

logic _w;
always_comb _w = a[($bits(a) - 1)];
logic _x;
always_comb _x = a.a[($size(a.a, 1) - 1)];
logic _y;
always_comb _y = veryl_testcase_Package28C::C[($size(veryl_testcase_Package28C::C, 1) - 1)];
logic _z;
always_comb _z = veryl_testcase_Package28C::C[0][($size(veryl_testcase_Package28C::C, 2) - 1)];
endmodule
//# sourceMappingURL=../map/testcases/sv/28_msblsb.sv.map
28 changes: 27 additions & 1 deletion testcases/veryl/28_msblsb.veryl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module Module28 (
module Module28A (
c: input logic<30, 40>,
) {
const WIDTH0: u32 = 10;
Expand All @@ -11,3 +11,29 @@ module Module28 (
let _y: logic = b[msb - 3][msb + 5:lsb];
let _z: logic = c[msb][msb];
}

package Package28A::<W: const> {
struct StructA {
a: logic<W>,
}
}

package Package28B {
const B: u32 = 2;
}

package Package28C {
const W: u32 = 2;
const N: u32 = 3;
const C: bit<N, W> = 0;
}

module ModuleB {
var a : Package28A::<Package28B::B>::StructA;
assign a.a = 0;

let _w: logic = a[msb];
let _x: logic = a.a[msb];
let _y: logic = Package28C::C[msb];
let _z: logic = Package28C::C[0][msb];
}
Loading