1use std::collections::HashMap;
2
3use super::*;
4
5#[derive(Debug, Clone, SExpr)]
9pub enum RuleSignature {
10 #[pp(surrounded)]
11 Always {
12 inputs: Vec<ValueId>,
13 outputs: Vec<ValueId>,
14 },
15 Method {
16 inputs: Vec<ValueId>,
17 outputs: Vec<ValueId>,
18 side_effect: Option<bool>,
19 },
20}
21
22impl RuleSignature {
23 pub fn inputs(&self) -> impl Iterator<Item = ValueId> {
25 match self {
26 RuleSignature::Always { inputs, .. } => inputs.clone().into_iter(),
27 RuleSignature::Method { inputs, .. } => inputs.clone().into_iter(),
28 }
29 }
30 pub fn inputs_mut(&mut self) -> &mut Vec<ValueId> {
32 match self {
33 RuleSignature::Always { inputs, .. } => inputs,
34 RuleSignature::Method { inputs, .. } => inputs,
35 }
36 }
37 pub fn outputs(&self) -> impl Iterator<Item = ValueId> {
39 match self {
40 RuleSignature::Always { outputs, .. } => outputs.clone().into_iter(),
41 RuleSignature::Method { outputs, .. } => outputs.clone().into_iter(),
42 }
43 }
44 pub fn outputs_mut(&mut self) -> &mut Vec<ValueId> {
46 match self {
47 RuleSignature::Always { outputs, .. } => outputs,
48 RuleSignature::Method { outputs, .. } => outputs,
49 }
50 }
51
52 pub fn is_method(&self) -> bool {
53 matches!(self, RuleSignature::Method { .. })
54 }
55}
56
57#[derive(Debug, Clone, SExpr)]
61pub enum RuleTiming {
62 #[pp(surrounded)]
63 SingleCycle,
64 MultiCycle {
65 num_cycles: Option<u32>,
68 intv: TimingIntv,
69 },
70 FSM,
71 Pipeline,
72}
73
74impl RuleTiming {
75 pub fn interval(&self) -> TimingIntv {
76 match self {
77 RuleTiming::SingleCycle => TimingIntv::none(),
78 RuleTiming::MultiCycle {
79 num_cycles: _,
80 intv,
81 } => intv.clone(),
82 _ => unimplemented!(),
83 }
84 }
85}
86
87#[derive(Debug, Clone, SExpr)]
91pub struct Rule {
92 #[pp(open)]
93 #[pp(surrounded = "ext?")]
94 pub is_ext: bool,
95 #[pp(surrounded = "private?")]
96 pub is_private: bool,
97 #[pp(kw = "rule")]
98 pub name: String,
99 pub signature: RuleSignature,
100 pub timing: RuleTiming,
101 pub enable: Option<String>,
102 pub ready: Option<String>,
103 #[pp(list_ml)]
104 pub guard_ops: Vec<Op>,
105 #[pp(list_ml)]
106 #[pp(close)]
107 pub ops: Vec<Op>,
108 pub annotations: json::object::Object,
109}
110
111impl Rule {
112 pub fn is_ext(&self) -> bool {
114 self.is_ext
115 }
116
117 pub fn is_private(&self) -> bool {
119 self.is_private
120 }
121
122 pub fn set_private(&mut self, is_private: bool) {
124 self.is_private = is_private;
125 }
126
127 pub fn is_always(&self) -> bool {
129 matches!(self.signature, RuleSignature::Always { .. })
130 }
131
132 pub fn is_method(&self) -> bool {
134 matches!(self.signature, RuleSignature::Method { .. })
135 }
136
137 pub fn has_side_effect(&self) -> bool {
139 matches!(self.signature, RuleSignature::Method { side_effect, .. } if side_effect.unwrap_or(false))
140 }
141
142 pub fn set_side_effect(&mut self, se: bool) {
144 if let RuleSignature::Method { side_effect, .. } = &mut self.signature {
145 *side_effect = Some(se);
146 }
147 }
148
149 pub fn is_single_cycle(&self) -> bool {
151 matches!(self.timing, RuleTiming::SingleCycle)
152 }
153
154 pub fn guard(&self) -> impl Iterator<Item = &Op> {
156 self.guard_ops.iter()
157 }
158
159 pub fn guard_mut(&mut self) -> impl Iterator<Item = &mut Op> {
161 self.guard_ops.iter_mut()
162 }
163
164 pub fn ops(&self) -> impl Iterator<Item = &Op> {
166 self.ops.iter()
167 }
168
169 pub fn ops_mut(&mut self) -> impl Iterator<Item = &mut Op> {
171 self.ops.iter_mut()
172 }
173
174 pub fn name(&self) -> &str {
176 &self.name
177 }
178
179 pub fn new(name: String) -> Rule {
181 Rule {
182 is_ext: false,
183 is_private: false,
184 name,
185 signature: RuleSignature::Always {
186 inputs: vec![],
187 outputs: vec![],
188 },
189 timing: RuleTiming::SingleCycle,
190 guard_ops: vec![],
191 ops: vec![],
192 enable: None,
193 ready: None,
194 annotations: json::object::Object::new(),
195 }
196 }
197
198 pub fn always(
200 name: String,
201 inputs: Vec<ValueId>,
202 outputs: Vec<ValueId>,
203 guard_ops: Vec<Op>,
204 ops: Vec<Op>,
205 timing: RuleTiming,
206 ) -> Rule {
207 Rule {
208 is_ext: false,
209 is_private: false,
210 name,
211 signature: RuleSignature::Always { inputs, outputs },
212 guard_ops,
213 timing,
214 ops,
215 enable: None,
216 ready: None,
217 annotations: json::object::Object::new(),
218 }
219 }
220
221 pub fn method(
223 name: String,
224 inputs: Vec<ValueId>,
225 outputs: Vec<ValueId>,
226 side_effect: Option<bool>,
227 guard_ops: Vec<Op>,
228 ops: Vec<Op>,
229 timing: RuleTiming,
230 ) -> Rule {
231 Rule {
232 is_ext: false,
233 is_private: false,
234 name,
235 signature: RuleSignature::Method {
236 inputs,
237 outputs,
238 side_effect,
239 },
240 timing,
241 guard_ops,
242 ops,
243 enable: None,
244 ready: None,
245 annotations: json::object::Object::new(),
246 }
247 }
248
249 pub fn ext(
251 name: String,
252 inputs: Vec<ValueId>,
253 outputs: Vec<ValueId>,
254 enable: Option<String>,
255 ready: Option<String>,
256 side_effect: Option<bool>,
257 ) -> Rule {
258 Rule {
259 is_ext: true,
260 is_private: false,
261 name,
262 signature: RuleSignature::Method {
263 inputs,
264 outputs,
265 side_effect,
266 },
267 guard_ops: vec![],
268 timing: RuleTiming::SingleCycle,
269 ops: vec![],
270 enable,
271 ready,
272 annotations: json::object::Object::new(),
273 }
274 }
275
276 pub fn to_be_private(self) -> Rule {
278 Rule {
279 is_private: true,
280 ..self
281 }
282 }
283
284 pub fn span(&self) -> impl Iterator<Item = MySpan> + '_ {
286 self.annotations.iter().filter_map(|(k, v)| {
287 if k.ends_with("span") {
288 MySpan::from_json(v)
289 } else {
290 None
291 }
292 })
293 }
294
295 pub fn inputs(&self) -> Vec<ValueId> {
297 self.signature.inputs().collect()
298 }
299
300 pub fn inputs_mut(&mut self) -> &mut Vec<ValueId> {
302 self.signature.inputs_mut()
303 }
304
305 pub fn outputs(&self) -> Vec<ValueId> {
307 self.signature.outputs().collect()
308 }
309
310 pub fn outputs_mut(&mut self) -> &mut Vec<ValueId> {
312 self.signature.outputs_mut()
313 }
314
315 pub fn return_values(&self) -> Vec<ValueId> {
317 self
319 .ops
320 .last()
321 .map(|op| op.outputs().collect())
322 .unwrap_or_default()
323 }
324
325 pub fn replace_guard_op(&mut self, index: usize, new_ops: Vec<Op>) {
327 if index < self.guard_ops.len() {
328 self.guard_ops.splice(index..=index, new_ops);
329 } else {
330 panic!("Index out of bounds for guard_ops");
331 }
332 }
333
334 pub fn replace_op(&mut self, index: usize, new_ops: Vec<Op>) {
336 if index < self.ops.len() {
337 self.ops.splice(index + 1..=index + 1, new_ops);
338 } else {
339 panic!("Index out of bounds for ops");
340 }
341 }
342
343 pub fn replace_all_op_with_map(
345 &mut self,
346 replacements: &HashMap<ir::ValueId, ir::ValueId>,
347 ) {
348 for op in self.guard_mut() {
349 op.replace_value_with_map(replacements);
350 }
351
352 for op in self.ops_mut() {
353 op.replace_value_with_map(replacements);
354 }
355 }
356
357 pub fn remove_unused_op(&mut self) {
359 let mut indices_to_remove = vec![];
360
361 for (index, op) in self.guard_mut().enumerate() {
362 if let OpEnum::Assign(AssignOp { res, value }) = op.inner_mut() {
363 if res == value {
364 indices_to_remove.push(index);
365 }
366 } else {
367 op.remove_unused_op();
368 }
369 }
370
371 indices_to_remove.sort_unstable_by(|a, b| b.cmp(a));
372 for &index in &indices_to_remove {
373 self.guard_ops.remove(index);
374 }
375
376 indices_to_remove.clear();
377
378 for (index, op) in self.ops_mut().enumerate() {
379 if let OpEnum::Assign(AssignOp { res, value }) = op.inner_mut() {
380 if res == value {
381 indices_to_remove.push(index);
382 }
383 } else {
384 op.remove_unused_op();
385 }
386 }
387
388 indices_to_remove.sort_unstable_by(|a, b| b.cmp(a));
389
390 for &index in &indices_to_remove {
391 self.ops.remove(index);
392 }
393 }
394}
395
396#[derive(Debug, Clone, SExpr)]
401pub enum RuleRel {
402 #[pp(surrounded)]
403 Method {
404 rel: MethodRel,
405 lhs: Vec<InstRule>,
406 rhs: Vec<InstRule>,
407 },
408 Schedule(Vec<InstRule>),
409}
410
411impl RuleRel {
412 pub fn method(
414 rel: MethodRel,
415 lhs: Vec<InstRule>,
416 rhs: Vec<InstRule>,
417 ) -> RuleRel {
418 RuleRel::Method { rel, lhs, rhs }
419 }
420
421 pub fn schedule(inst_rules: Vec<InstRule>) -> RuleRel {
423 RuleRel::Schedule(inst_rules)
424 }
425}