diff --git a/calyx-opt/src/passes/par_to_seq.rs b/calyx-opt/src/passes/par_to_seq.rs index a48c1ffb0..2c551fef8 100644 --- a/calyx-opt/src/passes/par_to_seq.rs +++ b/calyx-opt/src/passes/par_to_seq.rs @@ -1,11 +1,14 @@ use crate::analysis; -use crate::traversal::{Action, Named, VisResult, Visitor}; +use crate::traversal::{ + Action, ConstructVisitor, Named, ParseVal, PassOpt, VisResult, Visitor, +}; use calyx_ir::{self as ir, LibrarySignatures}; +use calyx_utils::CalyxResult; -#[derive(Default)] /// Transforms all `par` into `seq`. Uses [analysis::ControlOrder] to get a /// sequentialization of `par` such that the program still computes the same -/// value. When there is no such sequentialization, errors out. +/// value. When there is no such sequentialization, errors out unless the +/// `always_sequentialize` option is true. /// /// /// # Example @@ -21,7 +24,11 @@ use calyx_ir::{self as ir, LibrarySignatures}; /// ``` /// /// To remove uneccessarily nested `par` blocks, run collapse-control. -pub struct ParToSeq; +pub struct ParToSeq { + /// sequentializes without checking + /// NOTE: does not guarantee correctness on shared reads and writes + always_sequentialize: bool, +} impl Named for ParToSeq { fn name() -> &'static str { @@ -31,6 +38,32 @@ impl Named for ParToSeq { fn description() -> &'static str { "Transform `par` blocks to `seq`" } + + fn opts() -> Vec { + vec![PassOpt::new( + "always-sequentialize", + "Sequentializes the program without attempting to preserve dataflow dependencies.", + ParseVal::Bool(false), + PassOpt::parse_bool, + )] + } +} + +impl ConstructVisitor for ParToSeq { + fn from(ctx: &ir::Context) -> CalyxResult + where + Self: Sized + Named, + { + let opts = Self::get_opts(ctx); + + Ok(ParToSeq { + always_sequentialize: opts[&"always-sequentialize"].bool(), + }) + } + + fn clear_data(&mut self) { + /* All data can be transferred between components */ + } } impl Visitor for ParToSeq { @@ -42,9 +75,14 @@ impl Visitor for ParToSeq { _c: &LibrarySignatures, _comps: &[ir::Component], ) -> VisResult { - let total_order = - analysis::ControlOrder::::get_total_order(s.stmts.drain(..))?; - let par = ir::Control::seq(total_order); + let par = if self.always_sequentialize { + ir::Control::seq(s.stmts.drain(..).collect()) + } else { + let total_order = analysis::ControlOrder::::get_total_order( + s.stmts.drain(..), + )?; + ir::Control::seq(total_order) + }; Ok(Action::change(par)) } }