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)]
|
||||
#[derive(PartialEq, Eq)]
|
||||
#[derive(PartialEq, Eq, Clone, Copy)]
|
||||
pub struct TestBackendPrivate {
|
||||
pub module_var_name: &'static str,
|
||||
pub included_fields: &'static [&'static str],
|
||||
}
|
||||
|
||||
impl Default for TestBackendPrivate {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
module_var_name: "m",
|
||||
included_fields: &[],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2407,7 +2409,11 @@ impl fmt::Debug for TestBackend {
|
|||
files,
|
||||
error_after,
|
||||
options,
|
||||
__private: TestBackendPrivate { module_var_name },
|
||||
__private:
|
||||
TestBackendPrivate {
|
||||
module_var_name,
|
||||
included_fields,
|
||||
},
|
||||
} = self;
|
||||
writeln!(
|
||||
f,
|
||||
|
@ -2415,14 +2421,43 @@ impl fmt::Debug for TestBackend {
|
|||
)?;
|
||||
writeln!(f, " assert_export_firrtl! {{")?;
|
||||
writeln!(f, " {module_var_name} =>")?;
|
||||
for (file, content) in files {
|
||||
writeln!(f, " {file:?}: {:?},", DebugAsRawString(content))?;
|
||||
}
|
||||
if *error_after != Option::default() {
|
||||
if *error_after != Option::default() || included_fields.contains(&"error_after") {
|
||||
writeln!(f, " error_after: {error_after:?},")?;
|
||||
}
|
||||
if *options != ExportOptions::default() {
|
||||
writeln!(f, " options: {options:?},")?;
|
||||
if *options != ExportOptions::default() || included_fields.contains(&"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, " }};")
|
||||
}
|
||||
|
@ -2507,6 +2542,7 @@ fn export_impl(
|
|||
let ExportOptions {
|
||||
simplify_memories: do_simplify_memories,
|
||||
simplify_enums: do_simplify_enums,
|
||||
__private: _,
|
||||
} = options;
|
||||
if let Some(kind) = do_simplify_enums {
|
||||
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)]
|
||||
#[non_exhaustive]
|
||||
pub struct ExportOptions {
|
||||
#[clap(long = "no-simplify-memories", action = clap::ArgAction::SetFalse)]
|
||||
pub simplify_memories: bool,
|
||||
#[clap(long, value_parser = OptionSimplifyEnumsKindValueParser, default_value = OptionSimplifyEnumsKindValueParser::NONE_NAME)]
|
||||
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 {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.write_str("ExportOptions {")?;
|
||||
if f.alternate() {
|
||||
f.write_str("\n")?;
|
||||
self.debug_fmt(f, |_| false)
|
||||
}
|
||||
}
|
||||
|
||||
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 comma_sep = if f.alternate() { ",\n " } else { ", " };
|
||||
let default = ExportOptions::default();
|
||||
if self.simplify_memories != default.simplify_memories {
|
||||
write!(f, "{sep}simplify_memories: {:?}", self.simplify_memories)?;
|
||||
if simplify_memories != default.simplify_memories
|
||||
|| force_include_field("simplify_memories")
|
||||
{
|
||||
write!(f, "{sep}simplify_memories: {:?}", simplify_memories)?;
|
||||
sep = comma_sep;
|
||||
}
|
||||
if self.simplify_enums != default.simplify_enums {
|
||||
write!(f, "{sep}simplify_enums: {:?}", self.simplify_enums)?;
|
||||
if simplify_enums != default.simplify_enums || force_include_field("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;
|
||||
}
|
||||
write!(
|
||||
|
@ -2612,6 +2689,7 @@ impl Default for ExportOptions {
|
|||
Self {
|
||||
simplify_memories: true,
|
||||
simplify_enums: None,
|
||||
__private: ExportOptionsPrivate(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2630,7 +2708,17 @@ pub fn export<T: BundleType, B: FileBackendTrait>(
|
|||
#[doc(hidden)]
|
||||
#[track_caller]
|
||||
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 {
|
||||
panic!(
|
||||
"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 {
|
||||
{
|
||||
$m:ident =>
|
||||
$($file_name:literal: $file_contents:literal,)*
|
||||
$($field:ident: $value:expr,)*
|
||||
@parsed_fields($($field_strings:expr,)*)
|
||||
$($file_name:literal: $file_contents:literal,)*
|
||||
} => {
|
||||
$crate::firrtl::assert_export_firrtl_impl(
|
||||
&$m,
|
||||
$crate::firrtl::TestBackend {
|
||||
$($field: $value,)*
|
||||
files: $crate::firrtl::make_test_expected_files(&[
|
||||
$(($file_name, $file_contents),)*
|
||||
]),
|
||||
$($field: $value,)*
|
||||
__private: $crate::firrtl::TestBackendPrivate {
|
||||
module_var_name: stringify!($m),
|
||||
included_fields: &[$($field_strings,)*],
|
||||
},
|
||||
..<$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