Skip to content

Commit

Permalink
Schedule compaction (#1722)
Browse files Browse the repository at this point in the history
* added schedule compaction pass

* debug

* fmt

* changed test cases and added schedule-compaction to default pipeline

* addressed comments

* fmt

* debug

* debug

* changed the group enable to static par

* allowed non-enable control and recalculated latency

* add schedule-compaction to default pass

* restored invoke-memory.futil

* fixed bug

* fmt

* restore pass ordering

* debug

* fmt and fix test cases

* fix test cases

* fix test cases
  • Loading branch information
paili0628 authored Oct 12, 2023
1 parent cc78fcb commit fb9add4
Show file tree
Hide file tree
Showing 27 changed files with 550 additions and 121 deletions.
3 changes: 3 additions & 0 deletions calyx-frontend/src/attribute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ pub enum NumAttr {
#[strum(serialize = "promote_static")]
/// Promote the group or control to static with the annotated latency
PromoteStatic,
#[strum(serialize = "compactable")]
/// suggest that the current static seq block is compactable
Compactable,
}
impl From<NumAttr> for Attribute {
fn from(attr: NumAttr) -> Self {
Expand Down
88 changes: 86 additions & 2 deletions calyx-opt/src/analysis/control_order.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,28 @@ impl<const BETTER_ERR: bool> ControlOrder<BETTER_ERR> {
let cell = cr.borrow();
match cell.prototype {
// Ignore constants and _this
ir::CellType::Constant { .. }
| ir::CellType::ThisComponent => None,
ir::CellType::Constant { .. } => None,
ir::CellType::ThisComponent => None,
_ => Some(cell.name()),
}
})
.unique()
}

fn get_cells_static_seq(
ports: Vec<RRC<ir::Port>>,
) -> impl Iterator<Item = ir::Id> {
ports
.into_iter()
.filter_map(|p| {
let cr = p.borrow().cell_parent();
let cell = cr.borrow();
match cell.prototype {
// Ignore constants and _this
ir::CellType::Constant { .. } => None,
ir::CellType::ThisComponent => {
Some(ir::Id::new("this_comp"))
}
_ => Some(cell.name()),
}
})
Expand Down Expand Up @@ -123,4 +143,68 @@ impl<const BETTER_ERR: bool> ControlOrder<BETTER_ERR> {
Err(Error::misc(format!("No possible sequential ordering. Control programs exhibit data race:\n{}", msg)))
}
}

// returns a graph of dependency for input programs
// input control programs are considered to have data dependency if:
// 1. subsequent program writes to cells that previous program reads from
// 2. subsequent program writes to cells that previous program writes to
// 3. subsequent program reads from cells that previous program writes to
pub fn get_dependency_graph_static_seq(
stmts: impl Iterator<Item = ir::StaticControl>,
dependency: &mut HashMap<NodeIndex, Vec<NodeIndex>>,
latency_map: &mut HashMap<NodeIndex, u64>,
) -> DiGraph<Option<ir::StaticControl>, ()> {
// Directed graph where edges means that a control program must be run before.
let mut gr: DiGraph<Option<ir::StaticControl>, ()> = DiGraph::new();

// Mapping name of cell to all the indices that read or write to it.
let mut reads: HashMap<ir::Id, Vec<NodeIndex>> = HashMap::default();
let mut writes: HashMap<ir::Id, Vec<NodeIndex>> = HashMap::default();

for c in stmts {
let (port_reads, port_writes) =
ReadWriteSet::control_port_read_write_set_static(&c);
let r_cells = Self::get_cells_static_seq(port_reads);
let w_cells = Self::get_cells_static_seq(port_writes);
let latency = c.get_latency();
let idx = gr.add_node(Some(c));
dependency.insert(idx, Vec::new());
latency_map.insert(idx, latency);

for cell in r_cells {
if let Some(wr_idxs) = writes.get(&cell) {
for wr_idx in wr_idxs {
if !wr_idx.eq(&idx) {
gr.add_edge(*wr_idx, idx, ());
dependency.entry(idx).or_default().push(*wr_idx);
}
}
}
reads.entry(cell).or_default().push(idx);
}

for cell in w_cells {
if let Some(wr_idxs) = writes.get(&cell) {
for wr_idx in wr_idxs {
if !wr_idx.eq(&idx) {
gr.add_edge(*wr_idx, idx, ());
dependency.entry(idx).or_default().push(*wr_idx);
}
}
}

if let Some(r_idxs) = reads.get(&cell) {
for r_idx in r_idxs {
if !r_idx.eq(&idx) {
gr.add_edge(*r_idx, idx, ());
dependency.entry(idx).or_default().push(*r_idx);
}
}
}

writes.entry(cell).or_default().push(idx);
}
}
gr
}
}
52 changes: 44 additions & 8 deletions calyx-opt/src/analysis/read_write_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,11 +165,30 @@ impl ReadWriteSet {
ir::StaticControl::Invoke(ir::StaticInvoke {
inputs,
outputs,
ref_cells,
..
}) => {
let inps = inputs.iter().map(|(_, p)| p).cloned();
let outs = outputs.iter().map(|(_, p)| p).cloned();
(inps.collect(), outs.collect())
let mut inps: Vec<RRC<ir::Port>> =
inputs.iter().map(|(_, p)| p).cloned().collect();
let mut outs: Vec<RRC<ir::Port>> =
outputs.iter().map(|(_, p)| p).cloned().collect();
for (_, cell) in ref_cells.iter() {
for port in cell.borrow().ports.iter() {
match port.borrow().direction {
ir::Direction::Input => {
outs.push(Rc::clone(port));
}
ir::Direction::Output => {
inps.push(Rc::clone(port));
}
_ => {
outs.push(Rc::clone(port));
inps.push(Rc::clone(port));
}
}
}
}
(inps, outs)
}
}
}
Expand All @@ -190,22 +209,39 @@ impl ReadWriteSet {
inputs,
outputs,
comb_group,
ref_cells,
..
}) => {
let inps = inputs.iter().map(|(_, p)| p).cloned();
let outs = outputs.iter().map(|(_, p)| p).cloned();
let mut r: Vec<RRC<ir::Port>> = inps.collect();
let mut w: Vec<RRC<ir::Port>> = outs.collect();

for (_, cell) in ref_cells {
for port in cell.borrow().ports.iter() {
match port.borrow().direction {
ir::Direction::Input => {
w.push(Rc::clone(port));
}
ir::Direction::Output => {
r.push(Rc::clone(port));
}
_ => {
w.push(Rc::clone(port));
r.push(Rc::clone(port));
}
}
}
}
match comb_group {
Some(cgr) => {
let cg = cgr.borrow();
let assigns = cg.assignments.iter();
let reads = Self::port_read_set(assigns.clone());
let writes = Self::port_write_set(assigns);
(
reads.chain(inps).collect(),
writes.chain(outs).collect(),
)
(reads.chain(r).collect(), writes.chain(w).collect())
}
None => (inps.collect(), outs.collect()),
None => (r, w),
}
}
ir::Control::Seq(ir::Seq { stmts, .. })
Expand Down
10 changes: 6 additions & 4 deletions calyx-opt/src/default_passes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ use crate::passes::{
DeadAssignmentRemoval, DeadCellRemoval, DeadGroupRemoval, DiscoverExternal,
Externalize, GoInsertion, GroupToInvoke, GroupToSeq, HoleInliner,
InferShare, LowerGuards, MergeAssign, Papercut, ParToSeq,
RegisterUnsharing, RemoveIds, ResetInsertion, SimplifyStaticGuards,
SimplifyWithControl, StaticInliner, StaticPromotion, SynthesisPapercut,
TopDownCompileControl, TopDownStaticTiming, UnrollBounded, WellFormed,
WireInliner, WrapMain,
RegisterUnsharing, RemoveIds, ResetInsertion, ScheduleCompaction,
SimplifyStaticGuards, SimplifyWithControl, StaticInliner, StaticPromotion,
SynthesisPapercut, TopDownCompileControl, TopDownStaticTiming,
UnrollBounded, WellFormed, WireInliner, WrapMain,
};
use crate::traversal::Named;
use crate::{pass_manager::PassManager, register_alias};
Expand All @@ -36,6 +36,7 @@ impl PassManager {
pm.register_pass::<GroupToSeq>()?;
pm.register_pass::<InferShare>()?;
pm.register_pass::<CellShare>()?;
pm.register_pass::<ScheduleCompaction>()?;
pm.register_pass::<StaticPromotion>()?;
pm.register_pass::<AttributePromotion>()?;
pm.register_pass::<SimplifyStaticGuards>()?;
Expand Down Expand Up @@ -93,6 +94,7 @@ impl PassManager {
CompileInvoke, // creates dead comb groups
AttributePromotion,
StaticPromotion,
ScheduleCompaction,
CompileRepeat,
DeadGroupRemoval, // Since previous passes potentially create dead groups
CollapseControl,
Expand Down
8 changes: 6 additions & 2 deletions calyx-opt/src/passes/compile_invoke.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,11 +128,11 @@ impl CompileInvoke {
///
/// Since this pass eliminates all ref cells in post order, we expect that
/// invoked component already had all of its ref cells removed.
fn ref_cells_to_ports(
fn ref_cells_to_ports<T>(
&mut self,
inv_cell: RRC<ir::Cell>,
ref_cells: impl Iterator<Item = (ir::Id, ir::RRC<ir::Cell>)>,
) -> Vec<ir::Assignment<ir::Nothing>> {
) -> Vec<ir::Assignment<T>> {
let inv_comp = inv_cell.borrow().type_name().unwrap();
let mut assigns = Vec::new();
for (ref_cell_name, cell) in ref_cells {
Expand Down Expand Up @@ -361,6 +361,10 @@ impl Visitor for CompileInvoke {

let invoke_group = builder.add_static_group("static_invoke", s.latency);

invoke_group.borrow_mut().assignments.extend(
self.ref_cells_to_ports(Rc::clone(&s.comp), s.ref_cells.drain(..)),
);

// comp.go = 1'd1;
structure!(builder;
let one = constant(1, 1);
Expand Down
2 changes: 2 additions & 0 deletions calyx-opt/src/passes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ mod par_to_seq;
mod register_unsharing;
mod remove_ids;
mod reset_insertion;
mod schedule_compaction;
mod simplify_static_guards;
mod static_inliner;
mod static_promotion;
Expand Down Expand Up @@ -73,6 +74,7 @@ pub use par_to_seq::ParToSeq;
pub use register_unsharing::RegisterUnsharing;
pub use remove_ids::RemoveIds;
pub use reset_insertion::ResetInsertion;
pub use schedule_compaction::ScheduleCompaction;
pub use simplify_static_guards::SimplifyStaticGuards;
pub use simplify_with_control::SimplifyWithControl;
pub use static_inliner::StaticInliner;
Expand Down
Loading

0 comments on commit fb9add4

Please sign in to comment.