calyx_opt/passes/
reset_insertion.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
use crate::traversal::{Action, Named, VisResult, Visitor};
use calyx_ir::{self as ir, LibrarySignatures};
use calyx_utils::Error;
use std::rc::Rc;

#[derive(Default)]
/// Adds assignments from a components `reset` port to every
/// component that contains an input `reset` port.
pub struct ResetInsertion;

impl Named for ResetInsertion {
    fn name() -> &'static str {
        "reset-insertion"
    }

    fn description() -> &'static str {
        "connect component reset to sub-component reset for applicable components"
    }
}

impl Visitor for ResetInsertion {
    fn start(
        &mut self,
        comp: &mut ir::Component,
        sigs: &LibrarySignatures,
        _comps: &[ir::Component],
    ) -> VisResult {
        let builder = ir::Builder::new(comp, sigs);
        let reset = builder
            .component
            .signature
            .borrow()
            .find_unique_with_attr(ir::BoolAttr::Reset)?;

        if let Some(reset) = reset {
            for cell_ref in builder.component.cells.iter() {
                let cell = cell_ref.borrow();
                if let Some(port) =
                    cell.find_unique_with_attr(ir::BoolAttr::Reset)?
                {
                    builder.component.continuous_assignments.push(
                        builder.build_assignment(
                            port,
                            Rc::clone(&reset),
                            ir::Guard::True,
                        ),
                    )
                }
            }
        } else {
            for cell_ref in builder.component.cells.iter() {
                let cell = cell_ref.borrow();
                if cell.find_unique_with_attr(ir::BoolAttr::Reset)?.is_some() {
                    return Err(Error::malformed_structure(format!(
                        "Cell `{}' in component `{}' has a reset port, \
                        but the component does not have a reset port.",
                        cell.name(),
                        builder.component.name
                    )));
                }
            }
        }

        // we don't need to traverse control
        Ok(Action::Stop)
    }
}