calyx 0.1.1

Intermediate Representation for Hardware Accelerator Generation
Documentation
use super::{Attributes, Cell, GetAttributes, Group, Id, Port, RRC};

/// Data for the `seq` control statement.
#[derive(Debug)]
pub struct Seq {
    /// List of `Control` statements to run in sequence.
    pub stmts: Vec<Control>,
    /// Attributes attached to this control statement.
    pub attributes: Attributes,
}

/// Data for the `par` control statement.
#[derive(Debug)]
pub struct Par {
    /// List of `Control` statements to run in parallel.
    pub stmts: Vec<Control>,
    /// Attributes attached to this control statement.
    pub attributes: Attributes,
}

/// Data for the `if` control statement.
#[derive(Debug)]
pub struct If {
    /// Port that connects the conditional check.
    pub port: RRC<Port>,

    /// Group that makes the signal on the conditional port valid.
    pub cond: RRC<Group>,

    /// Control for the true branch.
    pub tbranch: Box<Control>,

    /// Control for the true branch.
    pub fbranch: Box<Control>,

    /// Attributes attached to this control statement.
    pub attributes: Attributes,
}

/// Data for the `if` control statement.
#[derive(Debug)]
pub struct While {
    /// Port that connects the conditional check.
    pub port: RRC<Port>,

    /// Group that makes the signal on the conditional port valid.
    pub cond: RRC<Group>,

    /// Control for the loop body.
    pub body: Box<Control>,
    /// Attributes attached to this control statement.
    pub attributes: Attributes,
}

/// Data for the `enable` control statement.
#[derive(Debug)]
pub struct Enable {
    /// List of components to run.
    pub group: RRC<Group>,
    /// Attributes attached to this control statement.
    pub attributes: Attributes,
}

type PortMap = Vec<(Id, RRC<Port>)>;

/// Data for an `invoke` control statement.
#[derive(Debug)]
pub struct Invoke {
    /// Cell that is being invoked.
    pub comp: RRC<Cell>,
    /// Mapping from name of input ports in `comp` to the port connected to it.
    pub inputs: PortMap,
    /// Mapping from name of output ports in `comp` to the port connected to it.
    pub outputs: PortMap,
    /// Attributes attached to this control statement.
    pub attributes: Attributes,
}

/// Data for the `empty` control statement.
#[derive(Debug)]
pub struct Empty {}

/// Control AST nodes.
#[derive(Debug)]
pub enum Control {
    /// Represents sequential composition of control statements.
    Seq(Seq),
    /// Represents parallel composition of control statements.
    Par(Par),
    /// Standard imperative if statement
    If(If),
    /// Standard imperative while statement
    While(While),
    /// Invoke a sub-component with the given port assignments
    Invoke(Invoke),
    /// Runs the control for a list of subcomponents.
    Enable(Enable),
    /// Control statement that does nothing.
    Empty(Empty),
}

impl GetAttributes for Control {
    fn get_mut_attributes(&mut self) -> Option<&mut Attributes> {
        match self {
            Self::Seq(Seq { attributes, .. })
            | Self::Par(Par { attributes, .. })
            | Self::If(If { attributes, .. })
            | Self::While(While { attributes, .. })
            | Self::Invoke(Invoke { attributes, .. })
            | Self::Enable(Enable { attributes, .. }) => Some(attributes),
            Self::Empty(..) => None,
        }
    }

    fn get_attributes(&self) -> Option<&Attributes> {
        match self {
            Self::Seq(Seq { attributes, .. })
            | Self::Par(Par { attributes, .. })
            | Self::If(If { attributes, .. })
            | Self::While(While { attributes, .. })
            | Self::Invoke(Invoke { attributes, .. })
            | Self::Enable(Enable { attributes, .. }) => Some(attributes),
            Self::Empty(..) => None,
        }
    }
}

impl Control {
    // ================ Constructor methods ================
    /// Convience constructor for empty.
    pub fn empty() -> Self {
        Control::Empty(Empty {})
    }

    /// Convience constructor for seq.
    pub fn seq(stmts: Vec<Control>) -> Self {
        Control::Seq(Seq {
            stmts,
            attributes: Attributes::default(),
        })
    }

    /// Convience constructor for par.
    pub fn par(stmts: Vec<Control>) -> Self {
        Control::Par(Par {
            stmts,
            attributes: Attributes::default(),
        })
    }

    /// Convience constructor for enable.
    pub fn enable(group: RRC<Group>) -> Self {
        Control::Enable(Enable {
            group,
            attributes: Attributes::default(),
        })
    }

    /// Convience constructor for invoke.
    pub fn invoke(comp: RRC<Cell>, inputs: PortMap, outputs: PortMap) -> Self {
        Control::Invoke(Invoke {
            comp,
            inputs,
            outputs,
            attributes: Attributes::default(),
        })
    }

    /// Convience constructor for if
    pub fn if_(
        port: RRC<Port>,
        cond: RRC<Group>,
        tbranch: Box<Control>,
        fbranch: Box<Control>,
    ) -> Self {
        Control::If(If {
            port,
            cond,
            tbranch,
            fbranch,
            attributes: Attributes::default(),
        })
    }

    /// Convience constructor for while
    pub fn while_(
        port: RRC<Port>,
        cond: RRC<Group>,
        body: Box<Control>,
    ) -> Self {
        Control::While(While {
            port,
            cond,
            body,
            attributes: Attributes::default(),
        })
    }
}