prjunnamed_pattern/
lib.rs1pub trait Pattern<Target> {
2 type Capture;
3
4 fn execute(&self, design: &dyn DesignDyn, target: &Target) -> Option<Self::Capture>;
5}
6
7#[macro_export]
8macro_rules! netlist_match {
9 { [ $($rule:tt)* ] $($rest:tt)* } => {
10 |design: &dyn $crate::DesignDyn, target: &prjunnamed_netlist::Value| {
11 $crate::netlist_match! { @TOP@ design target [ $($rule)* ] $($rest)* }
12 }
13 };
14 { @TOP@ $design:ident $target:ident $($rest:tt)* } => {
15 {
16 if $target.len() > 0 {
17 use $crate::{Pattern, DesignDyn};
18 let design = $crate::CellCollector::new($design);
19 $crate::netlist_match! { @RULE@ design $target $($rest)* }
20 } else {
21 None
22 }
23 }
24 };
25 { @RULE@ $design:ident $target:ident } => { None };
26 { @RULE@ $design:ident $target:ident [ $($pat:tt)+ ] $( if $gexpr:expr )? => $result:expr; $($rest:tt)* } => {
27 {
28 'block: {
29 $design.clear();
30 let pattern = $crate::netlist_match!( @NEW@ [ $($pat)+ ] );
31 match pattern.execute(&$design, $target) {
32 Some($crate::netlist_match!( @PAT@ [ $($pat)+ ] )) => {
33 let _guard = $design.inner().use_metadata_from(&$design.cells());
34 $( if $gexpr )? {
35 if cfg!(feature = "trace") {
36 eprintln!(">match {} => {}",
37 stringify!([ $($pat)* ] $( if $gexpr )?).replace("\n", " "),
38 $design.inner().display_value(&*$target)
39 );
40 }
41 break 'block Some($result.into())
42 }
43 }
44 _ => ()
45 }
46 $crate::netlist_match! { @RULE@ $design $target $($rest)* }
47 }
48 }
49 };
50 { @RULE@ $design:ident $target:ident [ $($pat:tt)+ ] if let $gpat:pat = $gexpr:expr => $result:expr; $($rest:tt)* } => {
51 {
52 'block: {
53 $design.clear();
54 let pattern = $crate::netlist_match!( @NEW@ [ $($pat)+ ] );
55 match pattern.execute(&$design, $target) {
56 Some($crate::netlist_match!( @PAT@ [ $($pat)+ ] )) => {
57 let _guard = $design.inner().use_metadata_from(&$design.cells());
58 if let $gpat = $gexpr {
59 if cfg!(feature = "trace") {
60 eprintln!(">match {} => {}",
61 stringify!([ $($pat)* ] if let $gpat = $gexpr).replace("\n", " "),
62 $design.inner().display_value(&*$target)
63 );
64 }
65 break 'block Some($result.into())
66 }
67 }
68 _ => ()
69 }
70 $crate::netlist_match! { @RULE@ $design $target $($rest)* }
71 }
72 }
73 };
74 ( @NEW@ [ $pat:ident $( @ $cap:ident )? $( ( $($exparg:tt)+ ) )* $( [ $($patarg:tt)+ ] )* ] ) => {
75 $pat::new( $( $($exparg)+, )* $( $crate::netlist_match!( @NEW@ [ $($patarg)+ ] ) ),*)
76 };
77 ( @PAT@ [ $pat:ident $( ( $($exparg:tt)+ ) )* $( [ $($patarg:tt)+ ] )* ] ) => {
78 (_, $( $crate::netlist_match!( @PAT@ [ $($patarg)+ ] ) ),*)
79 };
80 ( @PAT@ [ $pat:ident @ $cap:ident $( ( $($exparg:tt)+ ) )* $( [ $($patarg:tt)+ ] )* ] ) => {
81 ($cap, $( $crate::netlist_match!( @PAT@ [ $($patarg)+ ] ) ),*)
82 };
83}
84
85#[macro_export]
86macro_rules! netlist_replace {
87 { [ $($rule:tt)* ] $($rest:tt)* } => {
88 |design: &dyn $crate::DesignDyn, target: &prjunnamed_netlist::Value| -> bool {
89 $crate::netlist_replace! { @TOP@ design target [ $($rule)* ] $($rest)* }
90 }
91 };
92 { @TOP@ $design:ident $target:ident $($rest:tt)* } => {
93 let result: Option<Value> = $crate::netlist_match! { @TOP@ $design $target $($rest)* };
94 if let Some(replace) = result {
95 #[allow(unexpected_cfgs)]
96 if cfg!(feature = "trace") {
97 eprintln!(">replace => {}",
98 $design.inner().display_value(&prjunnamed_netlist::Value::from(replace.clone()))
99 );
100 }
101 $design.inner().replace_value($target, &replace);
102 true
103 } else {
104 false
105 }
106 };
107}
108
109#[macro_export]
110macro_rules! assert_netlist {
111 ( $design:expr , $check:expr $( , $( $assertarg:tt)+ )? ) => {
112 {
113 $design.apply();
114 let check = $check;
115 let mut matches = $design.iter_cells().all(|cell_ref| {
116 if let prjunnamed_netlist::Cell::Output(_name, value) = &*cell_ref.get() {
117 check(&$design, value).unwrap_or(false)
118 } else {
119 true
120 }
121 });
122 if !matches {
123 eprintln!("{}", $design);
124 }
125 assert!(matches $( , $( $assertarg )+ )?);
126 }
127 };
128}
129
130mod traits;
131mod simple;
132mod bitwise;
133mod shift;
134mod arithmetic;
135
136pub use traits::{NetOrValue, DesignDyn, CellCollector};
137
138pub mod patterns {
139 pub use crate::simple::*;
140 pub use crate::bitwise::*;
141 pub use crate::shift::*;
142 pub use crate::arithmetic::*;
143}