1use crate::*;
15use nom::{bytes::complete::tag, multi::many0, IResult};
16use nom_tracable::tracable_parser;
17
18#[tracable_parser]
19pub(crate) fn process(input: Span) -> IResult<Span, (String, Process)> {
20 let (input, _) = many0(characters::sep)(input)?;
21 let (input, attributes) = many0(attribute::attr_stmt)(input)?;
22 let (input, id) = process_stmt(input)?;
23 let (input, assignments) = many0(assign_stmt)(input)?;
24 let (input, switches) = many0(switch::switch)(input)?;
25 let (input, syncs) = many0(crate::sync::sync)(input)?;
26 let (input, _) = process_end_stmt(input)?;
27 Ok((
28 input,
29 (
30 id,
31 Process {
32 attributes: attributes.into_iter().collect(),
33 assignments,
34 switches,
35 syncs,
36 },
37 ),
38 ))
39}
40
41pub(crate) fn process_stmt(input: Span) -> IResult<Span, String> {
43 let (input, _) = tag("process")(input)?;
44 let (input, _) = characters::sep(input)?;
45 let (input, id) = identifier::id(input)?;
46 let (input, _) = characters::eol(input)?;
47 Ok((input, id.erease()))
48}
49pub(crate) fn process_end_stmt(input: Span) -> IResult<Span, &str> {
51 let (input, _) = tag("end")(input)?;
52 let (input, _) = characters::eol(input)?;
53 Ok((input, ""))
54}
55
56pub(crate) fn assign_stmt(input: Span) -> IResult<Span, (SigSpec, SigSpec)> {
58 let (input, _) = tag("assign")(input)?;
59 let (input, _) = characters::sep(input)?;
60 let (input, dest) = sigspec::sigspec(input)?;
61 let (input, _) = characters::sep(input)?;
62 let (input, src) = sigspec::sigspec(input)?;
63 let (input, _) = characters::eol(input)?;
64 Ok((input, (dest, src)))
65}
66
67#[cfg(test)]
68mod tests {
69 use super::*;
70 use indoc::indoc;
71 use pretty_assertions::assert_eq;
72 #[test]
73 fn test_process() {
74 let input = indoc! {r#"
75 process $flatten\ctrl.$proc$serv_ctrl.v:0$702
76 switch 1'0
77 case
78 end
79 sync always
80 sync init
81 end
82 "#};
83 let (_input, process) = process(Span::new_extra(input, Default::default())).unwrap();
84 assert_eq!(
85 process,
86 (
87 "flatten\\ctrl.$proc$serv_ctrl.v:0$702".to_string(),
88 Process {
89 attributes: HashMap::new(),
90 assignments: vec![],
91 switches: vec![Switch {
92 attributes: HashMap::new(),
93 switch_on_sigspec: SigSpec::Constant(Constant::Value(vec!['0'])),
94 cases: vec![Case {
95 attributes: HashMap::new(),
96 compare_against: None,
97 case_bodies: vec![],
98 }]
99 }],
100 syncs: vec![
101 sync::sync(Span::new_extra("sync always\n", Default::default()))
102 .unwrap()
103 .1,
104 sync::sync(Span::new_extra("sync init\n", Default::default()))
105 .unwrap()
106 .1
107 ]
108 }
109 )
110 );
111 }
112
113 #[test]
114 fn test_process_multiple_switch_in_process() {
115 let input = indoc! {r#"
116 attribute \src "serv_bufreg.v:35.4-44.7"
117 process $flatten\bufreg.$proc$serv_bufreg.v:35$710
118 assign { } { }
119 assign $flatten\bufreg.$0\data[29:0] \bufreg.data
120 assign $flatten\bufreg.$0\lsb[1:0] \bufreg.lsb
121 assign $flatten\bufreg.$0\c_r[0:0] $flatten\bufreg.$and$serv_bufreg.v:37$711_Y
122 attribute \src "serv_bufreg.v:39.7-40.62"
123 switch \bufreg.i_en
124 case 1'1
125 assign $flatten\bufreg.$0\data[29:0] { $flatten\bufreg.$ternary$serv_bufreg.v:40$713_Y \bufreg.data [29:1] }
126 case
127 end
128 attribute \src "serv_bufreg.v:42.7-43.39"
129 switch $flatten\bufreg.$ternary$serv_bufreg.v:42$715_Y
130 case 1'1
131 assign $flatten\bufreg.$0\lsb[1:0] { $flatten\bufreg.$ternary$serv_bufreg.v:43$716_Y \bufreg.lsb [1] }
132 case
133 end
134 sync posedge \bufreg.i_clk
135 update \bufreg.c_r $flatten\bufreg.$0\c_r[0:0]
136 update \bufreg.data $flatten\bufreg.$0\data[29:0]
137 update \bufreg.lsb $flatten\bufreg.$0\lsb[1:0]
138 end
139 "#};
140 let (_input, process) = process(Span::new_extra(input, Default::default())).unwrap();
141 assert_eq!(process.0, "flatten\\bufreg.$proc$serv_bufreg.v:35$710");
142 assert_eq!(process.1.attributes.len(), 1);
143 }
144 #[test]
145 fn test_proc_stmt() {
146 let vectors = vec![
147 ("process \\dynports\n", "dynports"),
148 ("process \\top\n", "top"),
149 ("process \\src\n", "src"),
150 ];
151 for (input, expected) in vectors {
152 let span = Span::new_extra(input, Default::default());
153 let ret = process_stmt(span).unwrap();
154 assert_eq!(ret.1, expected);
155 }
156 }
157 #[test]
158 fn test_proc_end_stmt() {
159 let vectors = vec![("end\n", "")];
160 for input in vectors {
161 let span = Span::new_extra(input.0, Default::default());
162 let ret = process_end_stmt(span).unwrap();
163 assert_eq!(ret.1, input.1);
164 }
165 }
166
167 #[test]
168 fn test_assign_stmt() {
169 let vectors = vec![(
170 indoc! {r#"
171 assign $flatten\bufreg2.$0\dat[31:0] $flatten\bufreg2.$ternary$serv_bufreg2.v:62$80_Y
172 "#},
173 (
174 SigSpec::WireId("flatten\\bufreg2.$0\\dat[31:0]".to_string()),
175 SigSpec::WireId("flatten\\bufreg2.$ternary$serv_bufreg2.v:62$80_Y".to_string()),
176 ),
177 )];
178 for (input, expected) in vectors {
179 let span = Span::new_extra(input, Default::default());
180 let ret = assign_stmt(span).unwrap();
181 assert_eq!(ret.1, expected);
182 }
183 }
184}