Compare commits
3 commits
b7ec623bfa
...
b63676d0ca
Author | SHA1 | Date | |
---|---|---|---|
|
b63676d0ca | ||
|
7005fa3330 | ||
|
2ab8428062 |
8
Cargo.lock
generated
8
Cargo.lock
generated
|
@ -543,9 +543,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.83"
|
||||
version = "1.0.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b33eb56c327dec362a9e55b3ad14f9d2f0904fb5a5b03b513ab5465399e9f43"
|
||||
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
@ -647,9 +647,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.66"
|
||||
version = "2.0.93"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5"
|
||||
checksum = "9c786062daee0d6db1132800e623df74274a0a87322d8e183338e01b3d98d058"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
|
|
@ -37,7 +37,7 @@ quote = "1.0.36"
|
|||
serde = { version = "1.0.202", features = ["derive"] }
|
||||
serde_json = { version = "1.0.117", features = ["preserve_order"] }
|
||||
sha2 = "0.10.8"
|
||||
syn = { version = "2.0.66", features = ["full", "fold", "visit", "extra-traits"] }
|
||||
syn = { version = "2.0.93", features = ["full", "fold", "visit", "extra-traits"] }
|
||||
tempfile = "3.10.1"
|
||||
thiserror = "1.0.61"
|
||||
trybuild = "1.0"
|
||||
|
|
|
@ -66,6 +66,7 @@ mod kw {
|
|||
};
|
||||
}
|
||||
|
||||
custom_keyword!(__evaluated_cfgs);
|
||||
custom_keyword!(all);
|
||||
custom_keyword!(any);
|
||||
custom_keyword!(cfg);
|
||||
|
@ -1022,6 +1023,12 @@ pub(crate) struct Cfg {
|
|||
trailing_comma: Option<Token![,]>,
|
||||
}
|
||||
|
||||
impl Cfg {
|
||||
fn parse_meta(meta: &Meta) -> syn::Result<Self> {
|
||||
syn::parse2(meta.to_token_stream())
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for Cfg {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
let Self {
|
||||
|
@ -1068,6 +1075,9 @@ impl CfgAttr {
|
|||
trailing_comma: None,
|
||||
}
|
||||
}
|
||||
fn parse_meta(meta: &Meta) -> syn::Result<Self> {
|
||||
syn::parse2(meta.to_token_stream())
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for CfgAttr {
|
||||
|
@ -1105,6 +1115,16 @@ pub(crate) struct Cfgs<T> {
|
|||
pub(crate) cfgs_list: Vec<Cfg>,
|
||||
}
|
||||
|
||||
impl<T> Default for Cfgs<T> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
bracket: Default::default(),
|
||||
cfgs_map: Default::default(),
|
||||
cfgs_list: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Cfgs<T> {
|
||||
fn insert_cfg(&mut self, cfg: Cfg, value: T) {
|
||||
match self.cfgs_map.entry(cfg) {
|
||||
|
@ -1125,10 +1145,11 @@ impl Parse for Cfgs<bool> {
|
|||
let mut cfgs_list = Vec::new();
|
||||
for CfgAndValue {
|
||||
cfg,
|
||||
eq_token: _,
|
||||
eq_token,
|
||||
value,
|
||||
} in contents.call(Punctuated::<CfgAndValue, Token![,]>::parse_terminated)?
|
||||
{
|
||||
let _ = eq_token;
|
||||
match cfgs_map.entry(cfg) {
|
||||
Entry::Occupied(_) => {}
|
||||
Entry::Vacant(entry) => {
|
||||
|
@ -1184,7 +1205,44 @@ impl ToTokens for Cfgs<()> {
|
|||
}
|
||||
}
|
||||
|
||||
fn handle_top_level_attr(item: Item) -> syn::Result<TokenStream> {
|
||||
fn hdl_main(
|
||||
kw: impl CustomToken,
|
||||
attr: TokenStream,
|
||||
item: TokenStream,
|
||||
) -> syn::Result<TokenStream> {
|
||||
let (evaluated_cfgs, attr): (_, TokenStream) = Parser::parse2(
|
||||
|input: ParseStream| {
|
||||
if input.peek(Bracket) && input.peek2(kw::__evaluated_cfgs) {
|
||||
let cfgs = input.parse()?;
|
||||
let _: kw::__evaluated_cfgs = input.parse()?;
|
||||
Ok((Some(cfgs), input.parse()?))
|
||||
} else {
|
||||
Ok((None, input.parse()?))
|
||||
}
|
||||
},
|
||||
attr,
|
||||
)?;
|
||||
let cfgs = if let Some(cfgs) = evaluated_cfgs {
|
||||
cfgs
|
||||
} else {
|
||||
let cfgs = process_cfg::collect_cfgs(syn::parse2(item.clone())?)?;
|
||||
if cfgs.cfgs_list.is_empty() {
|
||||
Cfgs::default()
|
||||
} else {
|
||||
let key = kw::__evaluated_cfgs::default();
|
||||
return Ok(quote! {
|
||||
::fayalite::__cfg_expansion_helper! {
|
||||
[]
|
||||
#cfgs
|
||||
#[::fayalite::#kw:(#key #attr)] { #item }
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
let item = syn::parse2(quote! { #[#kw(#attr)] #item })?;
|
||||
let Some(item) = process_cfg::process_cfgs(item, cfgs)? else {
|
||||
return Ok(TokenStream::new());
|
||||
};
|
||||
match item {
|
||||
Item::Enum(item) => hdl_enum::hdl_enum(item),
|
||||
Item::Struct(item) => hdl_bundle::hdl_bundle(item),
|
||||
|
@ -1197,39 +1255,10 @@ fn handle_top_level_attr(item: Item) -> syn::Result<TokenStream> {
|
|||
}
|
||||
}
|
||||
|
||||
fn generate_cfg_expansion_tokens(input: TokenStream) -> syn::Result<TokenStream> {
|
||||
let item = syn::parse2::<Item>(input)?;
|
||||
let cfgs = process_cfg::collect_cfgs(item.clone())?;
|
||||
Ok(quote! {
|
||||
::fayalite::__cfg_expansion_helper! {
|
||||
[]
|
||||
#cfgs
|
||||
::fayalite::__after_cfg_expansion { #item }
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn hdl_module(attr: TokenStream, item: TokenStream) -> syn::Result<TokenStream> {
|
||||
let kw = kw::hdl_module::default();
|
||||
generate_cfg_expansion_tokens(quote! { #[#kw(#attr)] #item })
|
||||
hdl_main(kw::hdl_module::default(), attr, item)
|
||||
}
|
||||
|
||||
pub fn hdl_attr(attr: TokenStream, item: TokenStream) -> syn::Result<TokenStream> {
|
||||
let kw = kw::hdl::default();
|
||||
generate_cfg_expansion_tokens(quote! { #[#kw(#attr)] #item })
|
||||
}
|
||||
|
||||
pub fn after_cfg_expansion(input: TokenStream) -> syn::Result<TokenStream> {
|
||||
syn::parse::Parser::parse2(
|
||||
|input: ParseStream| -> syn::Result<TokenStream> {
|
||||
let cfgs = input.parse()?;
|
||||
let item = input.parse()?;
|
||||
let item = process_cfg::process_cfgs(item, cfgs)?;
|
||||
Ok(item
|
||||
.map(handle_top_level_attr)
|
||||
.transpose()?
|
||||
.unwrap_or_default())
|
||||
},
|
||||
input,
|
||||
)
|
||||
hdl_main(kw::hdl::default(), attr, item)
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -27,12 +27,3 @@ pub fn hdl(
|
|||
Err(err) => err.into_compile_error().into(),
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[proc_macro]
|
||||
pub fn __after_cfg_expansion(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
match fayalite_proc_macros_impl::after_cfg_expansion(input.into()) {
|
||||
Ok(retval) => retval.into(),
|
||||
Err(err) => err.into_compile_error().into(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ use std::{env, fs, path::Path};
|
|||
fn main() {
|
||||
println!("cargo::rustc-check-cfg=cfg(todo)");
|
||||
println!("cargo::rustc-check-cfg=cfg(cfg_false_for_tests)");
|
||||
println!("cargo::rustc-check-cfg=cfg(cfg_true_for_tests)");
|
||||
println!("cargo::rustc-cfg=cfg_true_for_tests");
|
||||
let path = "visit_types.json";
|
||||
println!("cargo::rerun-if-changed={path}");
|
||||
|
|
|
@ -22,7 +22,7 @@ macro_rules! __cfg_expansion_helper {
|
|||
$cfg:ident($($expr:tt)*),
|
||||
$($unevaluated_cfgs:ident($($unevaluated_exprs:tt)*),)*
|
||||
]
|
||||
$after_evaluation:path {$($after_evaluation_args:tt)*}
|
||||
#[$after_evaluation:path:($($after_evaluation_attr_args:tt)*)] {$($after_evaluation_args:tt)*}
|
||||
) => {
|
||||
#[$cfg($($expr)*)]
|
||||
$crate::__cfg_expansion_helper! {
|
||||
|
@ -33,7 +33,7 @@ macro_rules! __cfg_expansion_helper {
|
|||
[
|
||||
$($unevaluated_cfgs($($unevaluated_exprs)*),)*
|
||||
]
|
||||
$after_evaluation {$($after_evaluation_args)*}
|
||||
#[$after_evaluation:($($after_evaluation_attr_args)*)] {$($after_evaluation_args)*}
|
||||
}
|
||||
#[$cfg(not($($expr)*))]
|
||||
$crate::__cfg_expansion_helper! {
|
||||
|
@ -44,7 +44,7 @@ macro_rules! __cfg_expansion_helper {
|
|||
[
|
||||
$($unevaluated_cfgs($($unevaluated_exprs)*),)*
|
||||
]
|
||||
$after_evaluation {$($after_evaluation_args)*}
|
||||
#[$after_evaluation:($($after_evaluation_attr_args)*)] {$($after_evaluation_args)*}
|
||||
}
|
||||
};
|
||||
(
|
||||
|
@ -52,14 +52,12 @@ macro_rules! __cfg_expansion_helper {
|
|||
$($evaluated_cfgs:ident($($evaluated_exprs:tt)*) = $evaluated_results:ident,)*
|
||||
]
|
||||
[]
|
||||
$after_evaluation:path {$($after_evaluation_args:tt)*}
|
||||
#[$after_evaluation:path:($($after_evaluation_attr_args:tt)*)] {$($after_evaluation_args:tt)*}
|
||||
) => {
|
||||
$after_evaluation! {
|
||||
[
|
||||
$($evaluated_cfgs($($evaluated_exprs)*) = $evaluated_results,)*
|
||||
]
|
||||
$($after_evaluation_args)*
|
||||
}
|
||||
#[$after_evaluation([
|
||||
$($evaluated_cfgs($($evaluated_exprs)*) = $evaluated_results,)*
|
||||
] $($after_evaluation_attr_args)*)]
|
||||
$($after_evaluation_args)*
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -75,9 +73,6 @@ pub use fayalite_proc_macros::hdl_module;
|
|||
#[doc(inline)]
|
||||
pub use fayalite_proc_macros::hdl;
|
||||
|
||||
#[doc(hidden)]
|
||||
pub use fayalite_proc_macros::__after_cfg_expansion;
|
||||
|
||||
/// struct used as a placeholder when applying defaults
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
||||
pub struct __;
|
||||
|
|
|
@ -4289,7 +4289,7 @@ circuit check_deduce_resets:
|
|||
}
|
||||
|
||||
#[hdl_module(outline_generated)]
|
||||
pub fn check_cfgs<#[cfg(cfg_false_for_tests)] A, #[cfg(cfg_true_for_tests)] B>(
|
||||
pub fn check_cfgs<#[cfg(cfg_false_for_tests)] A: Type, #[cfg(cfg_true_for_tests)] B: Type>(
|
||||
#[cfg(cfg_false_for_tests)] a: A,
|
||||
#[cfg(cfg_true_for_tests)] b: B,
|
||||
) {
|
||||
|
@ -4313,52 +4313,34 @@ pub fn check_cfgs<#[cfg(cfg_false_for_tests)] A, #[cfg(cfg_true_for_tests)] B>(
|
|||
#[hdl]
|
||||
let o_a: A = m.output(a);
|
||||
connect(o_a, w.a.cast_bits_to(a));
|
||||
connect(w.a, i_a.cast_to_bits(UInt::new_static()));
|
||||
connect_any(w.a, i_a.cast_to_bits());
|
||||
}
|
||||
#[cfg(cfg_true_for_tests)]
|
||||
{
|
||||
#[hdl]
|
||||
let o_a: B = m.output(b);
|
||||
let o_b: B = m.output(b);
|
||||
connect(o_b, w.b.cast_bits_to(b));
|
||||
connect(w.b, i_b.cast_to_bits(UInt::new_static()));
|
||||
connect_any(w.b, i_b.cast_to_bits());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cfgs() {
|
||||
let _n = SourceLocation::normalize_files_for_tests();
|
||||
let m = check_cfgs(UInt::<8>);
|
||||
let m = check_cfgs(UInt[8]);
|
||||
dbg!(m);
|
||||
#[rustfmt::skip] // work around https://github.com/rust-lang/rustfmt/issues/6161
|
||||
assert_export_firrtl! {
|
||||
m =>
|
||||
options: ExportOptions {
|
||||
simplify_enums: None,
|
||||
..ExportOptions::default()
|
||||
},
|
||||
"/test/check_deduce_resets.fir": r"FIRRTL version 3.2.0
|
||||
circuit check_deduce_resets:
|
||||
type Ty0 = {clk: Clock, rst: Reset}
|
||||
type Ty1 = {|A: Reset, B: AsyncReset, C: UInt<1>|}
|
||||
module check_deduce_resets: @[module-XXXXXXXXXX.rs 1:1]
|
||||
input cd: Ty0 @[module-XXXXXXXXXX.rs 2:1]
|
||||
input u8_in: UInt<8> @[module-XXXXXXXXXX.rs 4:1]
|
||||
output u8_out: UInt<8> @[module-XXXXXXXXXX.rs 6:1]
|
||||
input enum_in: Ty1 @[module-XXXXXXXXXX.rs 8:1]
|
||||
output enum_out: Ty1 @[module-XXXXXXXXXX.rs 9:1]
|
||||
output reset_out: Reset @[module-XXXXXXXXXX.rs 10:1]
|
||||
regreset my_reg: UInt<8>, cd.clk, cd.rst, UInt<8>(0h0) @[module-XXXXXXXXXX.rs 3:1]
|
||||
connect my_reg, u8_in @[module-XXXXXXXXXX.rs 5:1]
|
||||
connect u8_out, my_reg @[module-XXXXXXXXXX.rs 7:1]
|
||||
connect reset_out, cd.rst @[module-XXXXXXXXXX.rs 11:1]
|
||||
match enum_in: @[module-XXXXXXXXXX.rs 12:1]
|
||||
A(_match_arm_value):
|
||||
connect enum_out, {|A: Reset, B: AsyncReset, C: UInt<1>|}(A, cd.rst) @[module-XXXXXXXXXX.rs 13:1]
|
||||
connect reset_out, _match_arm_value @[module-XXXXXXXXXX.rs 14:1]
|
||||
B(_match_arm_value_1):
|
||||
connect enum_out, {|A: Reset, B: AsyncReset, C: UInt<1>|}(B, _match_arm_value_1) @[module-XXXXXXXXXX.rs 15:1]
|
||||
C(_match_arm_value_2):
|
||||
connect enum_out, {|A: Reset, B: AsyncReset, C: UInt<1>|}(C, _match_arm_value_2) @[module-XXXXXXXXXX.rs 16:1]
|
||||
"/test/check_cfgs.fir": r"FIRRTL version 3.2.0
|
||||
circuit check_cfgs:
|
||||
type Ty0 = {b: UInt<8>}
|
||||
module check_cfgs: @[module-XXXXXXXXXX.rs 1:1]
|
||||
input i_b: UInt<8> @[module-XXXXXXXXXX.rs 2:1]
|
||||
output o_b: UInt<8> @[module-XXXXXXXXXX.rs 4:1]
|
||||
wire w: Ty0 @[module-XXXXXXXXXX.rs 3:1]
|
||||
connect o_b, w.b @[module-XXXXXXXXXX.rs 5:1]
|
||||
connect w.b, i_b @[module-XXXXXXXXXX.rs 6:1]
|
||||
",
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue