improve ExportOptions support in assert_export_firrtl!
This commit is contained in:
parent
186488a82e
commit
9d66fcc548
|
@ -2378,15 +2378,17 @@ impl FileBackendTrait for FileBackend {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[derive(PartialEq, Eq)]
|
#[derive(PartialEq, Eq, Clone, Copy)]
|
||||||
pub struct TestBackendPrivate {
|
pub struct TestBackendPrivate {
|
||||||
pub module_var_name: &'static str,
|
pub module_var_name: &'static str,
|
||||||
|
pub included_fields: &'static [&'static str],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for TestBackendPrivate {
|
impl Default for TestBackendPrivate {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
module_var_name: "m",
|
module_var_name: "m",
|
||||||
|
included_fields: &[],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2407,7 +2409,11 @@ impl fmt::Debug for TestBackend {
|
||||||
files,
|
files,
|
||||||
error_after,
|
error_after,
|
||||||
options,
|
options,
|
||||||
__private: TestBackendPrivate { module_var_name },
|
__private:
|
||||||
|
TestBackendPrivate {
|
||||||
|
module_var_name,
|
||||||
|
included_fields,
|
||||||
|
},
|
||||||
} = self;
|
} = self;
|
||||||
writeln!(
|
writeln!(
|
||||||
f,
|
f,
|
||||||
|
@ -2415,14 +2421,43 @@ impl fmt::Debug for TestBackend {
|
||||||
)?;
|
)?;
|
||||||
writeln!(f, " assert_export_firrtl! {{")?;
|
writeln!(f, " assert_export_firrtl! {{")?;
|
||||||
writeln!(f, " {module_var_name} =>")?;
|
writeln!(f, " {module_var_name} =>")?;
|
||||||
for (file, content) in files {
|
if *error_after != Option::default() || included_fields.contains(&"error_after") {
|
||||||
writeln!(f, " {file:?}: {:?},", DebugAsRawString(content))?;
|
|
||||||
}
|
|
||||||
if *error_after != Option::default() {
|
|
||||||
writeln!(f, " error_after: {error_after:?},")?;
|
writeln!(f, " error_after: {error_after:?},")?;
|
||||||
}
|
}
|
||||||
if *options != ExportOptions::default() {
|
if *options != ExportOptions::default() || included_fields.contains(&"options") {
|
||||||
writeln!(f, " options: {options:?},")?;
|
struct DebugWithForceIncludeFields<'a> {
|
||||||
|
options: ExportOptions,
|
||||||
|
included_fields: &'a [&'a str],
|
||||||
|
}
|
||||||
|
impl fmt::Debug for DebugWithForceIncludeFields<'_> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
self.options.debug_fmt(f, |field| {
|
||||||
|
self.included_fields.iter().any(|included_field| {
|
||||||
|
if let Some(("options", suffix)) = included_field.split_once(".") {
|
||||||
|
suffix == field
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let options_str = format!(
|
||||||
|
"{:#?}",
|
||||||
|
DebugWithForceIncludeFields {
|
||||||
|
options: *options,
|
||||||
|
included_fields
|
||||||
|
}
|
||||||
|
);
|
||||||
|
let mut sep = " options: ";
|
||||||
|
for line in options_str.lines() {
|
||||||
|
write!(f, "{sep}{line}")?;
|
||||||
|
sep = "\n ";
|
||||||
|
}
|
||||||
|
writeln!(f, ",")?;
|
||||||
|
}
|
||||||
|
for (file, content) in files {
|
||||||
|
writeln!(f, " {file:?}: {:?},", DebugAsRawString(content))?;
|
||||||
}
|
}
|
||||||
write!(f, " }};")
|
write!(f, " }};")
|
||||||
}
|
}
|
||||||
|
@ -2507,6 +2542,7 @@ fn export_impl(
|
||||||
let ExportOptions {
|
let ExportOptions {
|
||||||
simplify_memories: do_simplify_memories,
|
simplify_memories: do_simplify_memories,
|
||||||
simplify_enums: do_simplify_enums,
|
simplify_enums: do_simplify_enums,
|
||||||
|
__private: _,
|
||||||
} = options;
|
} = options;
|
||||||
if let Some(kind) = do_simplify_enums {
|
if let Some(kind) = do_simplify_enums {
|
||||||
top_module =
|
top_module =
|
||||||
|
@ -2573,30 +2609,71 @@ impl clap::builder::TypedValueParser for OptionSimplifyEnumsKindValueParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
|
pub struct ExportOptionsPrivate(());
|
||||||
|
|
||||||
#[derive(clap::Parser, Copy, Clone, PartialEq, Eq, Hash)]
|
#[derive(clap::Parser, Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
#[non_exhaustive]
|
|
||||||
pub struct ExportOptions {
|
pub struct ExportOptions {
|
||||||
#[clap(long = "no-simplify-memories", action = clap::ArgAction::SetFalse)]
|
#[clap(long = "no-simplify-memories", action = clap::ArgAction::SetFalse)]
|
||||||
pub simplify_memories: bool,
|
pub simplify_memories: bool,
|
||||||
#[clap(long, value_parser = OptionSimplifyEnumsKindValueParser, default_value = OptionSimplifyEnumsKindValueParser::NONE_NAME)]
|
#[clap(long, value_parser = OptionSimplifyEnumsKindValueParser, default_value = OptionSimplifyEnumsKindValueParser::NONE_NAME)]
|
||||||
pub simplify_enums: std::option::Option<SimplifyEnumsKind>,
|
pub simplify_enums: std::option::Option<SimplifyEnumsKind>,
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[clap(skip = ExportOptionsPrivate(()))]
|
||||||
|
/// `#[non_exhaustive]` except allowing struct update syntax
|
||||||
|
pub __private: ExportOptionsPrivate,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for ExportOptions {
|
impl fmt::Debug for ExportOptions {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
f.write_str("ExportOptions {")?;
|
self.debug_fmt(f, |_| false)
|
||||||
if f.alternate() {
|
|
||||||
f.write_str("\n")?;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ExportOptions {
|
||||||
|
fn debug_fmt(
|
||||||
|
&self,
|
||||||
|
f: &mut fmt::Formatter<'_>,
|
||||||
|
force_include_field: impl Fn(&str) -> bool,
|
||||||
|
) -> fmt::Result {
|
||||||
|
let Self {
|
||||||
|
simplify_memories,
|
||||||
|
simplify_enums,
|
||||||
|
__private: _,
|
||||||
|
} = *self;
|
||||||
|
f.write_str("ExportOptions {")?;
|
||||||
let mut sep = if f.alternate() { "\n " } else { " " };
|
let mut sep = if f.alternate() { "\n " } else { " " };
|
||||||
let comma_sep = if f.alternate() { ",\n " } else { ", " };
|
let comma_sep = if f.alternate() { ",\n " } else { ", " };
|
||||||
let default = ExportOptions::default();
|
let default = ExportOptions::default();
|
||||||
if self.simplify_memories != default.simplify_memories {
|
if simplify_memories != default.simplify_memories
|
||||||
write!(f, "{sep}simplify_memories: {:?}", self.simplify_memories)?;
|
|| force_include_field("simplify_memories")
|
||||||
|
{
|
||||||
|
write!(f, "{sep}simplify_memories: {:?}", simplify_memories)?;
|
||||||
sep = comma_sep;
|
sep = comma_sep;
|
||||||
}
|
}
|
||||||
if self.simplify_enums != default.simplify_enums {
|
if simplify_enums != default.simplify_enums || force_include_field("simplify_enums") {
|
||||||
write!(f, "{sep}simplify_enums: {:?}", self.simplify_enums)?;
|
write!(f, "{sep}simplify_enums: ")?;
|
||||||
|
macro_rules! debug_cases {
|
||||||
|
($($ident:ident $(($($args:tt)*))?,)*) => {
|
||||||
|
match simplify_enums {
|
||||||
|
// use more complex stringify to avoid the compiler inserting spaces
|
||||||
|
$($ident $(($($args)*))? => {
|
||||||
|
f.write_str(concat!(
|
||||||
|
stringify!($ident),
|
||||||
|
$("(",
|
||||||
|
$(stringify!($args),)*
|
||||||
|
")")?
|
||||||
|
))?;
|
||||||
|
})*
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
debug_cases! {
|
||||||
|
Some(SimplifyEnumsKind::SimplifyToEnumsWithNoBody),
|
||||||
|
Some(SimplifyEnumsKind::ReplaceWithBundleOfUInts),
|
||||||
|
Some(SimplifyEnumsKind::ReplaceWithUInt),
|
||||||
|
None,
|
||||||
|
}
|
||||||
sep = comma_sep;
|
sep = comma_sep;
|
||||||
}
|
}
|
||||||
write!(
|
write!(
|
||||||
|
@ -2612,6 +2689,7 @@ impl Default for ExportOptions {
|
||||||
Self {
|
Self {
|
||||||
simplify_memories: true,
|
simplify_memories: true,
|
||||||
simplify_enums: None,
|
simplify_enums: None,
|
||||||
|
__private: ExportOptionsPrivate(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2630,7 +2708,17 @@ pub fn export<T: BundleType, B: FileBackendTrait>(
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub fn assert_export_firrtl_impl<T: BundleType>(top_module: &Module<T>, expected: TestBackend) {
|
pub fn assert_export_firrtl_impl<T: BundleType>(top_module: &Module<T>, expected: TestBackend) {
|
||||||
let result = export(TestBackend::default(), top_module, expected.options).unwrap();
|
let result = export(
|
||||||
|
TestBackend {
|
||||||
|
files: BTreeMap::default(),
|
||||||
|
error_after: expected.error_after,
|
||||||
|
options: expected.options,
|
||||||
|
__private: expected.__private,
|
||||||
|
},
|
||||||
|
top_module,
|
||||||
|
expected.options,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
if result != expected {
|
if result != expected {
|
||||||
panic!(
|
panic!(
|
||||||
"assert_export_firrtl failed:\nyou can update the expected output by using:\n-------START-------\n{result:?}\n-------END-------"
|
"assert_export_firrtl failed:\nyou can update the expected output by using:\n-------START-------\n{result:?}\n-------END-------"
|
||||||
|
@ -2647,21 +2735,69 @@ pub fn make_test_expected_files(v: &[(&str, &str)]) -> BTreeMap<String, String>
|
||||||
macro_rules! assert_export_firrtl {
|
macro_rules! assert_export_firrtl {
|
||||||
{
|
{
|
||||||
$m:ident =>
|
$m:ident =>
|
||||||
$($file_name:literal: $file_contents:literal,)*
|
|
||||||
$($field:ident: $value:expr,)*
|
$($field:ident: $value:expr,)*
|
||||||
|
@parsed_fields($($field_strings:expr,)*)
|
||||||
|
$($file_name:literal: $file_contents:literal,)*
|
||||||
} => {
|
} => {
|
||||||
$crate::firrtl::assert_export_firrtl_impl(
|
$crate::firrtl::assert_export_firrtl_impl(
|
||||||
&$m,
|
&$m,
|
||||||
$crate::firrtl::TestBackend {
|
$crate::firrtl::TestBackend {
|
||||||
|
$($field: $value,)*
|
||||||
files: $crate::firrtl::make_test_expected_files(&[
|
files: $crate::firrtl::make_test_expected_files(&[
|
||||||
$(($file_name, $file_contents),)*
|
$(($file_name, $file_contents),)*
|
||||||
]),
|
]),
|
||||||
$($field: $value,)*
|
|
||||||
__private: $crate::firrtl::TestBackendPrivate {
|
__private: $crate::firrtl::TestBackendPrivate {
|
||||||
module_var_name: stringify!($m),
|
module_var_name: stringify!($m),
|
||||||
|
included_fields: &[$($field_strings,)*],
|
||||||
},
|
},
|
||||||
..<$crate::firrtl::TestBackend as $crate::__std::default::Default>::default()
|
..<$crate::firrtl::TestBackend as $crate::__std::default::Default>::default()
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
{
|
||||||
|
$m:ident =>
|
||||||
|
$($parsed_fields:ident: $parsed_field_values:expr,)*
|
||||||
|
@parsed_fields($($field_strings:expr,)*)
|
||||||
|
options: ExportOptions {
|
||||||
|
$($export_option_fields:ident: $parsed_export_option_field_values:expr,)*
|
||||||
|
..$export_option_default:expr
|
||||||
|
},
|
||||||
|
$($rest:tt)*
|
||||||
|
} => {
|
||||||
|
$crate::assert_export_firrtl!(
|
||||||
|
$m =>
|
||||||
|
$($parsed_fields: $parsed_field_values,)*
|
||||||
|
options: ExportOptions {
|
||||||
|
$($export_option_fields: $parsed_export_option_field_values,)*
|
||||||
|
..$export_option_default
|
||||||
|
},
|
||||||
|
@parsed_fields($($field_strings,)* "options", $(concat!("options.", stringify!($export_option_fields)),)*)
|
||||||
|
$($rest)*
|
||||||
|
);
|
||||||
|
};
|
||||||
|
{
|
||||||
|
$m:ident =>
|
||||||
|
$($parsed_fields:ident: $parsed_field_values:expr,)*
|
||||||
|
@parsed_fields($($field_strings:expr,)*)
|
||||||
|
$field:ident: $field_value:expr,
|
||||||
|
$($rest:tt)*
|
||||||
|
} => {
|
||||||
|
$crate::assert_export_firrtl!(
|
||||||
|
$m =>
|
||||||
|
$($parsed_fields: $parsed_field_values,)*
|
||||||
|
$field: $field_value,
|
||||||
|
@parsed_fields($($field_strings,)* stringify!($field),)
|
||||||
|
$($rest)*
|
||||||
|
);
|
||||||
|
};
|
||||||
|
{
|
||||||
|
$m:ident =>
|
||||||
|
$($rest:tt)*
|
||||||
|
} => {
|
||||||
|
$crate::assert_export_firrtl!(
|
||||||
|
$m =>
|
||||||
|
@parsed_fields()
|
||||||
|
$($rest)*
|
||||||
|
);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue