From b7e65fc0172f7281e96a46b351881648741257a9 Mon Sep 17 00:00:00 2001 From: Taichi Ishitani Date: Mon, 26 Aug 2024 16:49:13 +0900 Subject: [PATCH] add 'enum_encoding' attribute (refs: veryl-lang/veryl#907) --- crates/analyzer/src/analyzer_error.rs | 45 +++++- crates/analyzer/src/attribute.rs | 48 +++++++ .../analyzer/src/handlers/check_attribute.rs | 7 + crates/analyzer/src/handlers/check_enum.rs | 10 +- .../src/handlers/create_symbol_table.rs | 129 +++++++++++++----- crates/analyzer/src/symbol.rs | 14 ++ crates/analyzer/src/tests.rs | 81 ++++++++++- crates/emitter/src/emitter.rs | 76 +++++------ .../map/testcases/sv/09_struct_enum.sv.map | 2 +- testcases/sv/09_struct_enum.sv | 36 ++++- testcases/veryl/09_struct_enum.veryl | 39 +++++- 11 files changed, 388 insertions(+), 99 deletions(-) diff --git a/crates/analyzer/src/analyzer_error.rs b/crates/analyzer/src/analyzer_error.rs index 6b0be519..9140fad7 100644 --- a/crates/analyzer/src/analyzer_error.rs +++ b/crates/analyzer/src/analyzer_error.rs @@ -597,6 +597,16 @@ pub enum AnalyzerError { error_location: SourceSpan, }, + #[diagnostic(severity(Error), code(invalid_enum_encoding), help(""), url(""))] + #[error("{identifier} is not valid enum encoding")] + InvalidEnumEncoding { + identifier: String, + #[source_code] + input: NamedSource, + #[label("Error location")] + error_location: SourceSpan, + }, + #[diagnostic( severity(Error), code(too_large_enum_variant), @@ -620,7 +630,7 @@ pub enum AnalyzerError { help(""), url("") )] - #[error("The implicit value of enum variant {identifier} cannot be evaluated")] + #[error("The value of enum variant {identifier} cannot be evaluated")] UnevaluatableEnumVariant { identifier: String, #[source_code] @@ -629,6 +639,17 @@ pub enum AnalyzerError { error_location: SourceSpan, }, + #[diagnostic(severity(Error), code(invalid_enum_variant_value), help(""), url(""))] + #[error("The value of enum variant {identifier} is not encoded value by {encoding}")] + InvalidEnumVariant { + identifier: String, + encoding: String, + #[source_code] + input: NamedSource, + #[label("Error location")] + error_location: SourceSpan, + }, + #[diagnostic( severity(Error), code(too_large_number), @@ -1333,6 +1354,14 @@ impl AnalyzerError { } } + pub fn invalid_enum_encoding(identifier: &str, source: &str, token: &TokenRange) -> Self { + AnalyzerError::InvalidEnumEncoding { + identifier: identifier.to_string(), + input: AnalyzerError::named_source(source, token), + error_location: token.into(), + } + } + pub fn too_large_enum_variant( identifier: &str, value: isize, @@ -1357,6 +1386,20 @@ impl AnalyzerError { } } + pub fn invalid_enum_variant_value( + identifier: &str, + encoding: &str, + source: &str, + token: &TokenRange, + ) -> Self { + AnalyzerError::InvalidEnumVariant { + identifier: identifier.to_string(), + encoding: encoding.to_string(), + input: AnalyzerError::named_source(source, token), + error_location: token.into(), + } + } + pub fn too_large_number(width: usize, source: &str, token: &TokenRange) -> Self { AnalyzerError::TooLargeNumber { width, diff --git a/crates/analyzer/src/attribute.rs b/crates/analyzer/src/attribute.rs index 61c62055..ec26d695 100644 --- a/crates/analyzer/src/attribute.rs +++ b/crates/analyzer/src/attribute.rs @@ -9,6 +9,7 @@ pub enum Attribute { Ifndef(StrId), Sv(StrId), Allow(AllowItem), + EnumEncoding(EnumEncodingItem), EnumMemberPrefix(StrId), Test(Token, Option), } @@ -20,6 +21,7 @@ impl fmt::Display for Attribute { Attribute::Ifndef(x) => format!("ifndef({})", x), Attribute::Sv(x) => format!("sv(\"{}\")", x), Attribute::Allow(x) => format!("allow({})", x), + Attribute::EnumEncoding(x) => format!("enum_encoding({})", x), Attribute::EnumMemberPrefix(x) => format!("enum_member_prefix({})", x), Attribute::Test(x, _) => format!("test({})", x.text), }; @@ -32,6 +34,7 @@ pub enum AttributeError { UnknownAttribute, MismatchArgs(&'static str), InvalidAllow(StrId), + InvalidEnumEncoding(StrId), } fn get_arg_ident( @@ -82,6 +85,10 @@ struct Pattern { pub missing_port: StrId, pub missing_reset_statement: StrId, pub unused_variable: StrId, + pub enum_encoding: StrId, + pub sequential: StrId, + pub onehot: StrId, + pub gray: StrId, pub enum_member_prefix: StrId, pub test: StrId, } @@ -96,6 +103,10 @@ impl Pattern { missing_port: resource_table::insert_str("missing_port"), missing_reset_statement: resource_table::insert_str("missing_reset_statement"), unused_variable: resource_table::insert_str("unused_variable"), + enum_encoding: resource_table::insert_str("enum_encoding"), + sequential: resource_table::insert_str("sequential"), + onehot: resource_table::insert_str("onehot"), + gray: resource_table::insert_str("gray"), enum_member_prefix: resource_table::insert_str("enum_member_prefix"), test: resource_table::insert_str("test"), } @@ -149,6 +160,24 @@ impl TryFrom<&veryl_parser::veryl_grammar_trait::Attribute> for Attribute { Err(AttributeError::MismatchArgs("allowable rule")) } } + x if x == pat.enum_encoding => { + let arg = get_arg_ident(&value.attribute_opt, 0); + + if let Some(arg) = arg { + match arg.text { + x if x == pat.sequential => { + Ok(Attribute::EnumEncoding(EnumEncodingItem::Sequential)) + } + x if x == pat.onehot => { + Ok(Attribute::EnumEncoding(EnumEncodingItem::OneHot)) + } + x if x == pat.gray => Ok(Attribute::EnumEncoding(EnumEncodingItem::Gray)), + _ => Err(AttributeError::InvalidEnumEncoding(arg.text)), + } + } else { + Err(AttributeError::MismatchArgs("enum encoding rule")) + } + } x if x == pat.enum_member_prefix => { let arg = get_arg_ident(&value.attribute_opt, 0); @@ -190,3 +219,22 @@ impl fmt::Display for AllowItem { text.fmt(f) } } + +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] +pub enum EnumEncodingItem { + #[default] + Sequential, + OneHot, + Gray, +} + +impl fmt::Display for EnumEncodingItem { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let text = match self { + EnumEncodingItem::Sequential => "sequential", + EnumEncodingItem::OneHot => "one_hot", + EnumEncodingItem::Gray => "gray", + }; + text.fmt(f) + } +} diff --git a/crates/analyzer/src/handlers/check_attribute.rs b/crates/analyzer/src/handlers/check_attribute.rs index 41024ad8..2c2393c0 100644 --- a/crates/analyzer/src/handlers/check_attribute.rs +++ b/crates/analyzer/src/handlers/check_attribute.rs @@ -62,6 +62,13 @@ impl<'a> VerylGrammarTrait for CheckAttribute<'a> { &arg.identifier.as_ref().into(), )); } + crate::attribute::AttributeError::InvalidEnumEncoding(x) => { + self.errors.push(AnalyzerError::invalid_enum_encoding( + &x.to_string(), + self.text, + &arg.identifier.as_ref().into(), + )); + } } } } diff --git a/crates/analyzer/src/handlers/check_enum.rs b/crates/analyzer/src/handlers/check_enum.rs index 12a84a79..363fe8fa 100644 --- a/crates/analyzer/src/handlers/check_enum.rs +++ b/crates/analyzer/src/handlers/check_enum.rs @@ -1,6 +1,6 @@ use crate::analyzer_error::AnalyzerError; use crate::evaluator::Evaluator; -use crate::symbol::{EnumMemberValue, SymbolKind}; +use crate::symbol::SymbolKind; use crate::symbol_table; use veryl_parser::veryl_grammar_trait::*; use veryl_parser::veryl_walker::{Handler, HandlerPoint}; @@ -54,13 +54,7 @@ impl<'a> VerylGrammarTrait for CheckEnum<'a> { for id in r#enum.members { let member_symbol = symbol_table::get(id).unwrap(); if let SymbolKind::EnumMember(member) = member_symbol.kind { - let member_value = match member.value { - EnumMemberValue::ExplicitValue(_expression, evaluated) => { - evaluated.unwrap_or(0) - } - EnumMemberValue::ImplicitValue(x) => x, - }; - + let member_value = member.value.value().unwrap_or(0); if calc_width(member_value) > width { self.errors.push(AnalyzerError::too_large_enum_variant( &member_symbol.token.to_string(), diff --git a/crates/analyzer/src/handlers/create_symbol_table.rs b/crates/analyzer/src/handlers/create_symbol_table.rs index 2b973778..f56d4ac2 100644 --- a/crates/analyzer/src/handlers/create_symbol_table.rs +++ b/crates/analyzer/src/handlers/create_symbol_table.rs @@ -1,6 +1,6 @@ use crate::analyzer_error::AnalyzerError; -use crate::attribute::AllowItem; use crate::attribute::Attribute as Attr; +use crate::attribute::{AllowItem, EnumEncodingItem}; use crate::attribute_table; use crate::evaluator::Evaluated; use crate::evaluator::Evaluator; @@ -43,7 +43,9 @@ pub struct CreateSymbolTable<'a> { anonymous_namespace: usize, attribute_lines: HashSet, struct_or_union: Option, + enum_encoding: EnumEncodingItem, enum_member_prefix: Option, + enum_member_width: usize, enum_member_value: Option, enum_members: Vec>, struct_union_members: Vec>, @@ -68,6 +70,10 @@ enum StructOrUnion { InUnion, } +fn calc_width(value: usize) -> usize { + (usize::BITS - value.leading_zeros()) as usize +} + impl<'a> CreateSymbolTable<'a> { pub fn new(text: &'a str, build_opt: &'a Build) -> Self { Self { @@ -270,6 +276,72 @@ impl<'a> CreateSymbolTable<'a> { self.exist_clock_without_domain = true; } } + + fn evaluate_enum_value(&mut self, arg: &EnumItem) -> EnumMemberValue { + if let Some(ref x) = arg.enum_item_opt { + let evaluated = Evaluator::new().expression(&x.expression); + if let Evaluated::Fixed { value, .. } = evaluated { + let valid_variant = match self.enum_encoding { + EnumEncodingItem::OneHot => value.count_ones() == 1, + EnumEncodingItem::Gray => { + if let Some(expected) = self.enum_variant_next_value() { + (value as usize) == expected + } else { + true + } + } + _ => true, + }; + if !valid_variant { + self.errors.push(AnalyzerError::invalid_enum_variant_value( + &arg.identifier.identifier_token.to_string(), + &self.enum_encoding.to_string(), + self.text, + &arg.identifier.as_ref().into(), + )); + } + + EnumMemberValue::ExplicitValue(*x.expression.clone(), Some(value as usize)) + } else if self.enum_encoding == EnumEncodingItem::Sequential { + EnumMemberValue::ExplicitValue(*x.expression.clone(), None) + } else { + self.errors.push(AnalyzerError::unevaluatable_enum_variant( + &arg.identifier.identifier_token.to_string(), + self.text, + &arg.identifier.as_ref().into(), + )); + EnumMemberValue::UnevaluableValue + } + } else if let Some(value) = self.enum_variant_next_value() { + EnumMemberValue::ImplicitValue(value) + } else { + self.errors.push(AnalyzerError::unevaluatable_enum_variant( + &arg.identifier.identifier_token.to_string(), + self.text, + &arg.identifier.as_ref().into(), + )); + EnumMemberValue::UnevaluableValue + } + } + + fn enum_variant_next_value(&mut self) -> Option { + if let Some(value) = &self.enum_member_value { + if let Some(value) = value.value() { + match self.enum_encoding { + EnumEncodingItem::Sequential => Some(value + 1), + EnumEncodingItem::OneHot => Some(value << 1), + EnumEncodingItem::Gray => Some(((value + 1) >> 1) ^ (value + 1)), + } + } else { + None + } + } else { + match self.enum_encoding { + EnumEncodingItem::OneHot => Some(1), + _ => Some(0), + } + } + } } impl<'a> Handler for CreateSymbolTable<'a> { @@ -586,14 +658,19 @@ impl<'a> VerylGrammarTrait for CreateSymbolTable<'a> { // default prefix self.enum_member_prefix = Some(arg.identifier.identifier_token.to_string()); - // reset enum value + // reset enum encoding/width/value + self.enum_encoding = EnumEncodingItem::Sequential; + self.enum_member_width = 1; self.enum_member_value = None; - // overridden prefix by attribute let attrs = attribute_table::get(&arg.r#enum.enum_token.token); for attr in attrs { if let Attr::EnumMemberPrefix(x) = attr { + // overridden prefix by attribute self.enum_member_prefix = Some(x.to_string()); + } else if let Attr::EnumEncoding(x) = attr { + // overridden encoding by attribute + self.enum_encoding = x; } } } @@ -606,7 +683,18 @@ impl<'a> VerylGrammarTrait for CreateSymbolTable<'a> { .enum_declaration_opt .as_ref() .map(|x| x.scalar_type.as_ref().into()); - let property = EnumProperty { r#type, members }; + let width = if let Some(x) = r#type.clone() { + Evaluator::new().type_width(x).unwrap_or(0) + } else { + calc_width(members.len() - 1).max(self.enum_member_width) + }; + + let property = EnumProperty { + r#type, + width, + members, + encoding: self.enum_encoding, + }; let kind = SymbolKind::Enum(property); self.insert_symbol(&arg.identifier.identifier_token.token, kind, false); } @@ -616,35 +704,7 @@ impl<'a> VerylGrammarTrait for CreateSymbolTable<'a> { fn enum_item(&mut self, arg: &EnumItem) -> Result<(), ParolError> { if let HandlerPoint::Before = self.point { - let value = if let Some(ref x) = arg.enum_item_opt { - let mut evaluator = Evaluator::new(); - let evaluated = evaluator.expression(&x.expression); - if let Evaluated::Fixed { value, .. } = evaluated { - EnumMemberValue::ExplicitValue(*x.expression.clone(), Some(value as usize)) - } else { - EnumMemberValue::ExplicitValue(*x.expression.clone(), None) - } - } else if let Some(ref x) = self.enum_member_value { - let previous_value = match x { - EnumMemberValue::ExplicitValue(_expression, evaluated) => { - if let Some(value) = evaluated { - value - } else { - let name = arg.identifier.identifier_token.to_string(); - self.errors.push(AnalyzerError::unevaluatable_enum_variant( - &name, - self.text, - &arg.identifier.as_ref().into(), - )); - return Ok(()); - } - } - EnumMemberValue::ImplicitValue(value) => value, - }; - EnumMemberValue::ImplicitValue(previous_value + 1) - } else { - EnumMemberValue::ImplicitValue(0) - }; + let value = self.evaluate_enum_value(arg); let prefix = self.enum_member_prefix.clone().unwrap(); let property = EnumMemberProperty { value: value.clone(), @@ -667,6 +727,9 @@ impl<'a> VerylGrammarTrait for CreateSymbolTable<'a> { self.namespace.push(namespace); } + self.enum_member_width = self + .enum_member_width + .max(calc_width(value.value().unwrap_or(0))); self.enum_member_value = Some(value); } Ok(()) diff --git a/crates/analyzer/src/symbol.rs b/crates/analyzer/src/symbol.rs index 3cfd5794..7cc55440 100644 --- a/crates/analyzer/src/symbol.rs +++ b/crates/analyzer/src/symbol.rs @@ -1,3 +1,4 @@ +use crate::attribute::EnumEncodingItem; use crate::evaluator::{Evaluated, Evaluator}; use crate::namespace::Namespace; use crate::symbol_path::{GenericSymbolPath, SymbolPath}; @@ -1000,13 +1001,26 @@ pub struct TypeDefProperty { #[derive(Debug, Clone)] pub struct EnumProperty { pub r#type: Option, + pub width: usize, pub members: Vec, + pub encoding: EnumEncodingItem, } #[derive(Debug, Clone)] pub enum EnumMemberValue { ImplicitValue(usize), ExplicitValue(syntax_tree::Expression, Option), + UnevaluableValue, +} + +impl EnumMemberValue { + pub fn value(&self) -> Option { + match self { + EnumMemberValue::ImplicitValue(value) => Some(*value), + EnumMemberValue::ExplicitValue(_expression, evaluated) => *evaluated, + EnumMemberValue::UnevaluableValue => None, + } + } } #[derive(Debug, Clone)] diff --git a/crates/analyzer/src/tests.rs b/crates/analyzer/src/tests.rs index 78c9d89d..69a714f7 100644 --- a/crates/analyzer/src/tests.rs +++ b/crates/analyzer/src/tests.rs @@ -1415,7 +1415,86 @@ fn unevaluatable_enum_variant() { assert!(matches!( errors[0], AnalyzerError::UnevaluatableEnumVariant { .. } - )) + )); + + let code = r#" + module ModuleC { + #[enum_encoding(onehot)] + enum EnumA: logic<2> { + A = 2'bx1, + } + } + "#; + + let errors = analyze(code); + assert!(matches!( + errors[0], + AnalyzerError::UnevaluatableEnumVariant { .. } + )); + + let code = r#" + module ModuleD { + #[enum_encoding(gray)] + enum EnumA: logic<2> { + A = 2'bx0, + } + } + "#; + + let errors = analyze(code); + assert!(matches!( + errors[0], + AnalyzerError::UnevaluatableEnumVariant { .. } + )); +} + +#[test] +fn invalid_enum_variant() { + let code = r#" + module ModuleA { + #[enum_encoding(onehot)] + enum EnumA{ + A = 0, + } + } + "#; + + let errors = analyze(code); + assert!(matches!( + errors[0], + AnalyzerError::InvalidEnumVariant { .. } + )); + + let code = r#" + module ModuleB { + #[enum_encoding(onehot)] + enum EnumA{ + A = 3, + } + } + "#; + + let errors = analyze(code); + assert!(matches!( + errors[0], + AnalyzerError::InvalidEnumVariant { .. } + )); + + let code = r#" + module ModuleC { + #[enum_encoding(gray)] + enum EnumA{ + A, + B = 3, + } + } + "#; + + let errors = analyze(code); + assert!(matches!( + errors[0], + AnalyzerError::InvalidEnumVariant { .. } + )); } #[test] diff --git a/crates/emitter/src/emitter.rs b/crates/emitter/src/emitter.rs index 30eac9fa..a5032742 100644 --- a/crates/emitter/src/emitter.rs +++ b/crates/emitter/src/emitter.rs @@ -1,11 +1,10 @@ use crate::aligner::{Aligner, Location}; use std::fs; use std::path::Path; -use veryl_analyzer::attribute::Attribute as Attr; -use veryl_analyzer::attribute_table; +use veryl_analyzer::attribute::EnumEncodingItem; use veryl_analyzer::evaluator::{Evaluated, Evaluator}; use veryl_analyzer::namespace::Namespace; -use veryl_analyzer::symbol::{EnumMemberValue, TypeModifier as SymTypeModifier}; +use veryl_analyzer::symbol::TypeModifier as SymTypeModifier; use veryl_analyzer::symbol::{GenericMap, Symbol, SymbolId, SymbolKind, TypeKind}; use veryl_analyzer::symbol_path::{GenericSymbolPath, SymbolPath}; use veryl_analyzer::symbol_table; @@ -53,7 +52,8 @@ pub struct Emitter { default_reset: Option, reset_signal: Option, default_block: Option, - enum_member_prefix: Option, + enum_width: usize, + emit_enum_implicit_valiant: bool, file_scope_import: Vec, attribute: Vec, assignment_lefthand_side: Option, @@ -87,7 +87,8 @@ impl Default for Emitter { default_reset: None, reset_signal: None, default_block: None, - enum_member_prefix: None, + enum_width: 0, + emit_enum_implicit_valiant: false, file_scope_import: Vec::new(), attribute: Vec::new(), assignment_lefthand_side: None, @@ -681,35 +682,6 @@ impl Emitter { FunctionItem::Statement(x) => self.statement(&x.statement), }; } - - fn default_enum_type(&mut self, arg: &EnumDeclaration) { - if let Ok(enum_symbol) = symbol_table::resolve(arg.identifier.as_ref()) { - if let SymbolKind::Enum(r#enum) = enum_symbol.found.kind { - let mut max_value = r#enum.members.len() - 1; - - for id in r#enum.members { - let member_symbol = symbol_table::get(id).unwrap(); - if let SymbolKind::EnumMember(member) = member_symbol.kind { - match member.value { - EnumMemberValue::ExplicitValue(_expression, evaluated) => { - max_value = max_value.max(evaluated.unwrap_or(0)); - } - EnumMemberValue::ImplicitValue(value) => { - max_value = max_value.max(value); - } - } - } - } - - let width = if max_value == 0 { - 1 - } else { - usize::BITS - max_value.leading_zeros() - }; - self.str(&format!("logic [{}-1:0]", width)); - } - } - } } fn is_let_statement(arg: &Statement) -> bool { @@ -2358,12 +2330,15 @@ impl VerylWalker for Emitter { /// Semantic action for non-terminal 'EnumDeclaration' fn enum_declaration(&mut self, arg: &EnumDeclaration) { - self.enum_member_prefix = Some(arg.identifier.identifier_token.to_string()); - for attr in &attribute_table::get(&arg.r#enum.enum_token.token) { - if let Attr::EnumMemberPrefix(x) = attr { - self.enum_member_prefix = Some(x.to_string()); - } + let enum_symbol = symbol_table::resolve(arg.identifier.as_ref()).unwrap(); + if let SymbolKind::Enum(r#enum) = enum_symbol.found.kind { + self.enum_width = r#enum.width; + self.emit_enum_implicit_valiant = matches!( + r#enum.encoding, + EnumEncodingItem::OneHot | EnumEncodingItem::Gray + ); } + self.token( &arg.r#enum .enum_token @@ -2373,7 +2348,7 @@ impl VerylWalker for Emitter { if let Some(ref x) = arg.enum_declaration_opt { self.scalar_type(&x.scalar_type); } else { - self.default_enum_type(arg); + self.str(&format!("logic [{}-1:0]", self.enum_width)); } self.space(1); self.token_will_push(&arg.l_brace.l_brace_token); @@ -2385,7 +2360,6 @@ impl VerylWalker for Emitter { self.identifier(&arg.identifier); self.str(";"); self.token(&arg.r_brace.r_brace_token.replace("")); - self.enum_member_prefix = None; } /// Semantic action for non-terminal 'EnumList' @@ -2419,13 +2393,29 @@ impl VerylWalker for Emitter { /// Semantic action for non-terminal 'EnumItem' fn enum_item(&mut self, arg: &EnumItem) { - let prefix = format!("{}_", self.enum_member_prefix.clone().unwrap()); - self.token(&arg.identifier.identifier_token.append(&Some(prefix), &None)); + let member_symbol = symbol_table::resolve(arg.identifier.as_ref()).unwrap(); + let (prefix, value) = if let SymbolKind::EnumMember(member) = member_symbol.found.kind { + (member.prefix, member.value) + } else { + unreachable!(); + }; + + self.token( + &arg.identifier + .identifier_token + .append(&Some(format!("{}_", prefix)), &None), + ); if let Some(ref x) = arg.enum_item_opt { self.space(1); self.equ(&x.equ); self.space(1); self.expression(&x.expression); + } else if self.emit_enum_implicit_valiant { + self.str(&format!( + " = {}'d{}", + self.enum_width, + value.value().unwrap_or(0), + )); } } diff --git a/testcases/map/testcases/sv/09_struct_enum.sv.map b/testcases/map/testcases/sv/09_struct_enum.sv.map index d003a031..75cb2333 100644 --- a/testcases/map/testcases/sv/09_struct_enum.sv.map +++ b/testcases/map/testcases/sv/09_struct_enum.sv.map @@ -1 +1 @@ -{"version":3,"file":"09_struct_enum.sv.map","sources":["../../../veryl/09_struct_enum.veryl"],"names":["","module","Module09",";","typedef struct packed","{","logic","[","10","]","a","aa","int unsigned","aaa","A","typedef enum","2","B_X","=","1",",","B_Y","B_Z","B","C_X","C_Y","3","C_Z","C","D_X","D","FOO_E_0","FOO_E_1","E","b","c","d","e","f","always_comb",".","endmodule"],"mappings":"AAAAA,AAAAC,sBAAOC,QAASC;;IAEZC,sBAASC;QACAC,aAAKC,CAACC,MAAEC,EAAbC,GAAcP;QACTG,aAAKC,CAACC,MAAEC,EAAbE,GAAcR;QACTS,sBAALC,GAAcV;MAHXW,EAIPd;;;IAGAe,aAAQT,MAAKC,CAACS,KAACP,EAAEJ;QACbY,IAAEC,EAAEC,CAACC;QACLC,IAAEH,EAAEF,CAACI;QACLE,GAACtB;MAHAuB,EAILvB;;IAEAe,2BAAOV;QACHmB,IAAEN,EAAEF,CAACI;QACLK,IAAEP,EAAEQ,CAACN;QACLO,GAAC3B;MAHA4B,EAIL5B;;IAEAe,2BAAOV;QACHwB,GAAC7B;MADA8B,EAEL9B;;IAGAe,aAAQT,MAAMD;QACV0B,OAAGX;QACHY,OAAGhC;MAFFiC,EAGLjC;;IAEOc,MAAHJ,CAAQP;IACLoB,MAAHW,CAAQ/B;IACLyB,MAAHO,CAAQhC;IACL2B,MAAHM,CAAQjC;IACL8B,MAAHI,CAAQlC;IACLG,MAAHgC,CAAQnC;;IAEZoC,YAAO7B,CAAC8B,CAAC9B,IAAIQ,EAAEC,CAAChB;IAChBoC,YAAO7B,CAAC8B,CAAC7B,IAAIO,EAAEC,CAAChB;IAChBoC,YAAO7B,CAAC8B,CAAC3B,IAAIK,EAAEC,CAAChB;IAChBoC,YAAOL,MAAMhB,EAAED,GAAId;IACnBoC,YAAOJ,MAAMjB,EAAEM,GAAIrB;IACnBoC,YAAOH,MAAMlB,EAAEW,GAAI1B;IACnBoC,YAAOF,MAAMnB,EAAEa,OAAM5B;IACrBoC,YAAOD,MAAMpB,EAAER,CAAC8B,CAAC9B,CAACP;AACtBsC"} \ No newline at end of file +{"version":3,"file":"09_struct_enum.sv.map","sources":["../../../veryl/09_struct_enum.veryl"],"names":["","module","Module09",";","typedef struct packed","{","logic","[","10","]","a","aa","int unsigned","aaa","A","typedef enum","2","B_X","=","1",",","B_Y","B_Z","B","C_X","C_Y","3","C_Z","C","D_X","D","E_X","E_Y","E_Z","E","F_X","F_Y","F_Z","F","G_X","G_Y","G_Z","G","FOO_H_0","FOO_H_1","H","b","c","d","e","f","g","h","i","always_comb",".","endmodule"],"mappings":"AAAAA,AAAAC,sBAAOC,QAASC;;IAEZC,sBAASC;QACAC,aAAKC,CAACC,MAAEC,EAAbC,GAAcP;QACTG,aAAKC,CAACC,MAAEC,EAAbE,GAAcR;QACTS,sBAALC,GAAcV;MAHXW,EAIPd;;;IAGAe,aAAQT,MAAKC,CAACS,KAACP,EAAEJ;QACbY,IAAEC,EAAEC,CAACC;QACLC,IAAEH,EAAEF,CAACI;QACLE,GAACtB;MAHAuB,EAILvB;;IAEAe,2BAAOV;QACHmB,IAAEN,EAAEF,CAACI;QACLK,IAAEP,EAAEQ,CAACN;QACLO,GAAC3B;MAHA4B,EAIL5B;;IAEAe,2BAAOV;QACHwB,GAAC7B;MADA8B,EAEL9B;;IAGAe,2BAAOV;QACH0B,GAACX;QACDY,GAACZ;QACDa,GAACjC;MAHAkC,EAILlC;;IAGAe,2BAAOV;QACH8B,UAACf;QACDgB,UAAChB;QACDiB,UAACrC;MAHAsC,EAILtC;;IAGAe,2BAAOV;QACHkC,UAACnB;QACDoB,UAACpB;QACDqB,UAACzC;MAHA0C,EAIL1C;;IAGAe,aAAQT,MAAMD;QACVsC,OAAGvB;QACHwB,OAAG5C;MAFF6C,EAGL7C;;IAEOc,MAAHJ,CAAQP;IACLoB,MAAHuB,CAAQ3C;IACLyB,MAAHmB,CAAQ5C;IACL2B,MAAHkB,CAAQ7C;IACL+B,MAAHe,CAAQ9C;IACLmC,MAAHY,CAAQ/C;IACLuC,MAAHS,CAAQhD;IACL0C,MAAHO,CAAQjD;IACLG,MAAH+C,CAAQlD;;IAEZmD,YAAO5C,CAAC6C,CAAC7C,IAAIQ,EAAEC,CAAChB;IAChBmD,YAAO5C,CAAC6C,CAAC5C,IAAIO,EAAEC,CAAChB;IAChBmD,YAAO5C,CAAC6C,CAAC1C,IAAIK,EAAEC,CAAChB;IAChBmD,YAAOR,MAAM5B,EAAED,GAAId;IACnBmD,YAAOP,MAAM7B,EAAEM,GAAIrB;IACnBmD,YAAON,MAAM9B,EAAEW,GAAI1B;IACnBmD,YAAOL,MAAM/B,EAAEa,GAAI5B;IACnBmD,YAAOJ,MAAMhC,EAAEiB,GAAIhC;IACnBmD,YAAOH,MAAMjC,EAAEqB,GAAIpC;IACnBmD,YAAOF,MAAMlC,EAAEyB,OAAMxC;IACrBmD,YAAOD,MAAMnC,EAAER,CAAC6C,CAAC7C,CAACP;AACtBqD"} \ No newline at end of file diff --git a/testcases/sv/09_struct_enum.sv b/testcases/sv/09_struct_enum.sv index 43ee1924..c7d69a04 100644 --- a/testcases/sv/09_struct_enum.sv +++ b/testcases/sv/09_struct_enum.sv @@ -23,17 +23,38 @@ module veryl_testcase_Module09; D_X } D; - typedef enum logic { - FOO_E_0, - FOO_E_1 + typedef enum logic [2-1:0] { + E_X, + E_Y, + E_Z } E; + typedef enum logic [3-1:0] { + F_X = 3'd1, + F_Y = 3'd2, + F_Z = 3'd4 + } F; + + typedef enum logic [2-1:0] { + G_X = 2'd0, + G_Y = 2'd1, + G_Z = 2'd3 + } G; + + typedef enum logic { + FOO_H_0, + FOO_H_1 + } H; + A a; B b; C c; D d; E e; - logic f; + F f; + G g; + H h; + logic i; always_comb a.a = 1; always_comb a.aa = 1; @@ -41,7 +62,10 @@ module veryl_testcase_Module09; always_comb b = B_X; always_comb c = C_X; always_comb d = D_X; - always_comb e = FOO_E_0; - always_comb f = a.a; + always_comb e = E_X; + always_comb f = F_X; + always_comb g = G_X; + always_comb h = FOO_H_0; + always_comb i = a.a; endmodule //# sourceMappingURL=../map/testcases/sv/09_struct_enum.sv.map diff --git a/testcases/veryl/09_struct_enum.veryl b/testcases/veryl/09_struct_enum.veryl index 911cdec3..d7fafd88 100644 --- a/testcases/veryl/09_struct_enum.veryl +++ b/testcases/veryl/09_struct_enum.veryl @@ -23,10 +23,31 @@ module Module09 { X, } + #[enum_encoding(sequential)] + enum E { + X, + Y, + Z, + } + + #[enum_encoding(onehot)] + enum F { + X, + Y, + Z, + } + + #[enum_encoding(gray)] + enum G { + X, + Y, + Z, + } + #[enum_member_prefix(FOO)] - enum E: logic { - E_0, - E_1, + enum H: logic { + H_0, + H_1, } var a: A ; @@ -34,7 +55,10 @@ module Module09 { var c: C ; var d: D ; var e: E ; - var f: logic; + var f: F ; + var g: G ; + var h: H ; + var i: logic; assign a.a = 1; assign a.aa = 1; @@ -42,6 +66,9 @@ module Module09 { assign b = B::X; assign c = C::X; assign d = D::X; - assign e = E::E_0; - assign f = a.a; + assign e = E::X; + assign f = F::X; + assign g = G::X; + assign h = H::H_0; + assign i = a.a; }