pub mod suite;
pub mod veryl_sim;
pub mod veryl_sv;
#[path = "../fixtures/veryl_std.rs"]
#[allow(dead_code)]
pub mod veryl_std;
#[allow(dead_code)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Frontend {
Veryl,
Sv,
}
macro_rules! all_backends {
(@with_ignore native; (); { $($item:tt)* }) => { $($item)* };
(@with_ignore native; (native $(, $rest:ident)*); { $($item:tt)* }) => {
#[ignore]
$($item)*
};
(@with_ignore native; ($first:ident $(, $rest:ident)*); { $($item:tt)* }) => {
all_backends!(@with_ignore native; ($($rest),*); { $($item)* });
};
(@with_ignore cranelift; (); { $($item:tt)* }) => { $($item)* };
(@with_ignore cranelift; (cranelift $(, $rest:ident)*); { $($item:tt)* }) => {
#[ignore]
$($item)*
};
(@with_ignore cranelift; ($first:ident $(, $rest:ident)*); { $($item:tt)* }) => {
all_backends!(@with_ignore cranelift; ($($rest),*); { $($item)* });
};
(@with_ignore wasm; (); { $($item:tt)* }) => { $($item)* };
(@with_ignore wasm; (wasm $(, $rest:ident)*); { $($item:tt)* }) => {
#[ignore]
$($item)*
};
(@with_ignore wasm; ($first:ident $(, $rest:ident)*); { $($item:tt)* }) => {
all_backends!(@with_ignore wasm; ($($rest),*); { $($item)* });
};
(@with_ignore sv; (); { $($item:tt)* }) => { $($item)* };
(@with_ignore sv; (sv $(, $rest:ident)*); { $($item:tt)* }) => {
#[ignore]
$($item)*
};
(@with_ignore sv; ($first:ident $(, $rest:ident)*); { $($item:tt)* }) => {
all_backends!(@with_ignore sv; ($($rest),*); { $($item)* });
};
(@with_ignore veryl; (); { $($item:tt)* }) => { $($item)* };
(@with_ignore veryl; (veryl $(, $rest:ident)*); { $($item:tt)* }) => {
#[ignore]
$($item)*
};
(@with_ignore veryl; ($first:ident $(, $rest:ident)*); { $($item:tt)* }) => {
all_backends!(@with_ignore veryl; ($($rest),*); { $($item)* });
};
(@with_ignore interp; (); { $($item:tt)* }) => { $($item)* };
(@with_ignore interp; (interp $(, $rest:ident)*); { $($item:tt)* }) => {
#[ignore]
$($item)*
};
(@with_ignore interp; ($first:ident $(, $rest:ident)*); { $($item:tt)* }) => {
all_backends!(@with_ignore interp; ($($rest),*); { $($item)* });
};
(@sv_fn
$(#[$meta:meta])* fn $name:ident ($sim:ident)
ignore_list { $ignore_list:tt }
emit
setup { $($setup:tt)* }
build { $builder:expr }
body { $($body:tt)* }
) => {
all_backends!(@with_ignore sv; $ignore_list; {
#[cfg(feature = "systemverilog")]
#[test]
$(#[$meta])*
#[allow(unused_mut, unused_variables)]
fn sv() {
#[allow(dead_code)]
const FRONTEND: test_utils::Frontend = test_utils::Frontend::Sv;
$($setup)*
let __builder = { $builder };
let __emitted = test_utils::veryl_sv::emit_veryl_sources(__builder.sources());
let mut $sim = __builder
.into_sv_sources(__emitted.as_sv_sources())
.build()
.unwrap();
$($body)*
}
});
};
(@sv_fn
$(#[$meta:meta])* fn $name:ident ($sim:ident)
ignore_list { $ignore_list:tt }
skip
setup { $($setup:tt)* }
build { $builder:expr }
body { $($body:tt)* }
) => {};
(@veryl_fn
$(#[$meta:meta])* fn $name:ident ($sim:ident)
ignore_list { $ignore_list:tt }
emit
setup { $($setup:tt)* }
build { $builder:expr }
body { $($body:tt)* }
) => {
all_backends!(@with_ignore veryl; $ignore_list; {
#[test]
$(#[$meta])*
#[allow(unused_mut, unused_variables)]
fn veryl() {
#[allow(dead_code)]
const FRONTEND: test_utils::Frontend = test_utils::Frontend::Veryl;
$($setup)*
let __builder = { $builder };
let mut $sim = test_utils::veryl_sim::build_veryl_adapter(
__builder.sources(),
__builder.top(),
__builder.four_state_enabled(),
);
$($body)*
}
});
};
(@veryl_fn
$(#[$meta:meta])* fn $name:ident ($sim:ident)
ignore_list { $ignore_list:tt }
skip
setup { $($setup:tt)* }
build { $builder:expr }
body { $($body:tt)* }
) => {};
(@impl
$(#[$meta:meta])* fn $name:ident ($sim:ident)
ignore_list { $ignore_list:tt }
veryl_mode { $veryl_mode:ident }
sv_mode { $sv_mode:ident }
setup { $($setup:tt)* }
build { $builder:expr }
body { $($body:tt)* }
) => {
mod $name {
use super::*;
all_backends!(@with_ignore native; $ignore_list; {
#[test]
#[cfg(any(
target_arch = "x86_64",
target_arch = "aarch64"
))]
$(#[$meta])*
#[allow(unused_mut, unused_variables)]
fn native() {
#[allow(dead_code)]
const FRONTEND: test_utils::Frontend = test_utils::Frontend::Veryl;
$($setup)*
let mut $sim = { $builder }
.allow_always_ff_function_effects(true)
.build_native()
.unwrap();
$($body)*
}
});
all_backends!(@with_ignore native; $ignore_list; {
#[test]
#[cfg(any(
target_arch = "x86_64",
target_arch = "aarch64"
))]
$(#[$meta])*
#[allow(unused_mut, unused_variables)]
fn native_parallel() {
#[allow(dead_code)]
const FRONTEND: test_utils::Frontend = test_utils::Frontend::Veryl;
$($setup)*
let mut $sim = { $builder }
.allow_always_ff_function_effects(true)
.threads(4)
.parallel_partition(celox::ParallelPartition::Always)
.build_native()
.unwrap();
$($body)*
}
});
all_backends!(@with_ignore cranelift; $ignore_list; {
#[test]
$(#[$meta])*
#[allow(unused_mut, unused_variables)]
fn cranelift() {
#[allow(dead_code)]
const FRONTEND: test_utils::Frontend = test_utils::Frontend::Veryl;
$($setup)*
let mut $sim = { $builder }
.allow_always_ff_function_effects(true)
.build_cranelift()
.unwrap();
$($body)*
}
});
all_backends!(@with_ignore cranelift; $ignore_list; {
#[test]
$(#[$meta])*
#[allow(unused_mut, unused_variables)]
fn cranelift_parallel() {
#[allow(dead_code)]
const FRONTEND: test_utils::Frontend = test_utils::Frontend::Veryl;
$($setup)*
let mut $sim = { $builder }
.allow_always_ff_function_effects(true)
.threads(4)
.parallel_partition(celox::ParallelPartition::Always)
.build_cranelift()
.unwrap();
$($body)*
}
});
all_backends!(@with_ignore wasm; $ignore_list; {
#[test]
$(#[$meta])*
#[allow(unused_mut, unused_variables)]
fn wasm() {
#[allow(dead_code)]
const FRONTEND: test_utils::Frontend = test_utils::Frontend::Veryl;
$($setup)*
let mut $sim = { $builder }
.allow_always_ff_function_effects(true)
.build_wasm()
.unwrap();
$($body)*
}
});
all_backends!(@with_ignore interp; $ignore_list; {
#[test]
$(#[$meta])*
#[allow(unused_mut, unused_variables)]
fn interp() {
#[allow(dead_code)]
const FRONTEND: test_utils::Frontend = test_utils::Frontend::Veryl;
$($setup)*
let mut $sim = { $builder }
.allow_always_ff_function_effects(true)
.build_interpreter()
.unwrap();
$($body)*
}
});
all_backends!(@sv_fn
$(#[$meta])* fn $name ($sim)
ignore_list { $ignore_list }
$sv_mode
setup { $($setup)* }
build { $builder }
body { $($body)* }
);
all_backends!(@veryl_fn
$(#[$meta])* fn $name ($sim)
ignore_list { $ignore_list }
$veryl_mode
setup { $($setup)* }
build { $builder }
body { $($body)* }
);
}
};
(@dispatch
$(#[$meta:meta])* fn $name:ident ($sim:ident)
{ $($body:tt)* }
) => {
all_backends!(@parse [$(#[$meta])*] $name $sim emit emit () { $($body)* });
};
(@parse [$(#[$meta:meta])*] $name:ident $sim:ident $veryl:ident $sv:ident $ignore:tt
{ @omit_veryl; $($rest:tt)* }
) => {
all_backends!(@parse [$(#[$meta])*] $name $sim skip $sv $ignore { $($rest)* });
};
(@parse [$(#[$meta:meta])*] $name:ident $sim:ident $veryl:ident $sv:ident $ignore:tt
{ @omit_sv; $($rest:tt)* }
) => {
all_backends!(@parse [$(#[$meta])*] $name $sim $veryl skip $ignore { $($rest)* });
};
(@parse [$(#[$meta:meta])*] $name:ident $sim:ident $veryl:ident $sv:ident $old:tt
{ @ignore_on $ignore_list:tt; $($rest:tt)* }
) => {
all_backends!(@parse [$(#[$meta])*] $name $sim $veryl $sv $ignore_list { $($rest)* });
};
(@parse [$(#[$meta:meta])*] $name:ident $sim:ident $veryl:ident $sv:ident $ignore:tt
{ @case $case:literal; }
) => {
all_backends!(@case_impl $(#[$meta])* fn $name $ignore $veryl $sv $case);
};
(@parse [$(#[$meta:meta])*] $name:ident $sim:ident $veryl:ident $sv:ident $ignore:tt
{ @setup { $($setup:tt)* } @build $builder:expr; $($body:tt)* }
) => {
all_backends!(@impl
$(#[$meta])* fn $name ($sim)
ignore_list { $ignore }
veryl_mode { $veryl }
sv_mode { $sv }
setup { $($setup)* }
build { $builder }
body { $($body)* }
);
};
(@parse [$(#[$meta:meta])*] $name:ident $sim:ident $veryl:ident $sv:ident $ignore:tt
{ @build $builder:expr; $($body:tt)* }
) => {
all_backends!(@impl
$(#[$meta])* fn $name ($sim)
ignore_list { $ignore }
veryl_mode { $veryl }
sv_mode { $sv }
setup { }
build { $builder }
body { $($body)* }
);
};
(@case_impl $(#[$meta:meta])* fn $name:ident
$ignore_list:tt $veryl:ident $sv:ident $case:literal
) => {
mod $name {
use super::*;
all_backends!(@with_ignore native; $ignore_list; {
#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
#[test]
$(#[$meta])*
fn native() {
test_utils::suite::run_case($case, "native");
}
});
all_backends!(@with_ignore native; $ignore_list; {
#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
#[test]
$(#[$meta])*
fn native_parallel() {
test_utils::suite::run_case($case, "native-parallel");
}
});
all_backends!(@with_ignore cranelift; $ignore_list; {
#[test]
$(#[$meta])*
fn cranelift() {
test_utils::suite::run_case($case, "cranelift");
}
});
all_backends!(@with_ignore cranelift; $ignore_list; {
#[test]
$(#[$meta])*
fn cranelift_parallel() {
test_utils::suite::run_case($case, "cranelift-parallel");
}
});
all_backends!(@with_ignore wasm; $ignore_list; {
#[test]
$(#[$meta])*
fn wasm() {
test_utils::suite::run_case($case, "wasm");
}
});
all_backends!(@with_ignore interp; $ignore_list; {
#[test]
$(#[$meta])*
fn interp() {
test_utils::suite::run_case($case, "interp");
}
});
all_backends!(@case_sv $sv $ignore_list $(#[$meta])* $case);
all_backends!(@case_veryl $veryl $ignore_list $(#[$meta])* $case);
}
};
(@case_veryl emit $ignore_list:tt $(#[$meta:meta])* $case:literal) => {
all_backends!(@with_ignore veryl; $ignore_list; {
#[test]
$(#[$meta])*
fn veryl() {
test_utils::suite::run_case($case, "veryl");
}
});
};
(@case_veryl skip $ignore_list:tt $(#[$meta:meta])* $case:literal) => {};
(@case_sv emit $ignore_list:tt $(#[$meta:meta])* $case:literal) => {
all_backends!(@with_ignore sv; $ignore_list; {
#[cfg(feature = "systemverilog")]
#[test]
$(#[$meta])*
fn sv() {
test_utils::suite::run_case($case, "sv");
}
});
};
(@case_sv skip $ignore_list:tt $(#[$meta:meta])* $case:literal) => {};
($(
$(#[$meta:meta])*
fn $name:ident($sim:ident) $body:tt
)*) => {$(
all_backends!(@dispatch
$(#[$meta])* fn $name ($sim) $body
);
)*};
}