Skip to content

Commit

Permalink
Merge resource sharing and minimize regs (#444)
Browse files Browse the repository at this point in the history
* add test for minimize regs rewriting conditions

* changing trait bounds + improved doc comments

* add `sharing_component.rs` to abstract common details between minimize-regs and
resource-sharing. fixes #442

* documentation + clippy fixes

* [fud] Errors in Fud prints out STDOUT

* Attempt to serialize workflows (#432)

* Give @external semantics for verilog backend (#430)

* Give @external semantics for verilog backend

@external(1) on a memory makes the backend generate code to initialize
memories and dump out their final states. Every other memory is ignored.
Fud is stricter about what memories it expects in the inputs and
outputs.

* fmt

* relay memories are external

* fmt

* line nonsense

* more reformat

* more test fixing

* Tests

* Commas are the worst

* undo change to pow test

Co-authored-by: cgyurgyik <gyurgyikcp@gmail.com>

* unify mod and div implements (#433)

* remove std_ prefix from math library (#431)

* remove std_ prefix from math library

* update test

* update relay impl

* Add prefix and suffix to Relay components.

* Add arity only.

* Remove re.

Co-authored-by: Chris Gyurgyik <37983775+cgyurgyik@users.noreply.github.com>
Co-authored-by: cgyurgyik <gyurgyikcp@gmail.com>

* Test Language Tutorial examples (#436)

* Test Language Tutorial examples

* update doc link

* add data.json

* link to calyx files

* [docs] Tutorial for memory by reference. (#441)

* Tutorial for memory by reference.

* Update english

* runt

* Use mod output.

* Update Summary.

* rename.

* Fix test.

* [obvious] Change table to columns.

* [obvious] Small grammatical changes.

* [obvious] Fix typo.

* Parser tweaks (#443)

* added check to ensure literal values are representable in the given bitwidth

* added a few tests

* fix edge case

* fix my formatting crimes

* appease clippy

* formatting, again

* fixed condition register test, removed rename swap

Co-authored-by: Rachit Nigam <rachit.nigam12@gmail.com>
Co-authored-by: cgyurgyik <gyurgyikcp@gmail.com>
Co-authored-by: Chris Gyurgyik <37983775+cgyurgyik@users.noreply.github.com>
Co-authored-by: Griffin Berlstein <griffin@berlste.in>
  • Loading branch information
5 people authored Mar 23, 2021
1 parent 2750bb4 commit 5f3c1f2
Show file tree
Hide file tree
Showing 11 changed files with 462 additions and 298 deletions.
10 changes: 8 additions & 2 deletions calyx/src/analysis/graph_coloring.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ use crate::utils::{Idx, WeightGraph};
use std::{collections::HashMap, hash::Hash};

/// Defines a greedy graph coloring algorithm over a generic conflict graph.
pub struct GraphColoring<T: Eq + Hash + Clone> {
pub struct GraphColoring<T> {
graph: WeightGraph<T>,
}

impl<T, C> From<C> for GraphColoring<T>
where
T: Eq + Hash + Clone,
T: Hash + Eq,
C: Iterator<Item = T>,
{
fn from(nodes: C) -> Self {
Expand Down Expand Up @@ -89,3 +89,9 @@ where
.collect()
}
}

impl<T: Eq + Hash + ToString + Clone> ToString for GraphColoring<T> {
fn to_string(&self) -> String {
self.graph.to_string()
}
}
3 changes: 2 additions & 1 deletion calyx/src/analysis/schedule_conflicts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ impl ScheduleConflicts {
.collect()
}

/// Returns a vector containing all conflict edges in this graph.
/// Returns an iterator containing all conflict edges,
/// `(src group: ir::Id, dst group: ir::Id)`, in this graph.
pub fn all_conflicts(&self) -> ConflictIterator<'_> {
let iter =
self.graph
Expand Down
2 changes: 1 addition & 1 deletion calyx/src/ir/structure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ impl Eq for Port {}
pub type Binding = SmallVec<[(Id, u64); 5]>;

/// The type for a Cell
#[derive(Debug)]
#[derive(Debug, PartialEq, Eq)]
pub enum CellType {
/// Cell constructed using a primitive definition
Primitive {
Expand Down
137 changes: 43 additions & 94 deletions calyx/src/passes/minimize_regs.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
use super::sharing_components::ShareComponents;
use crate::{
analysis::{GraphColoring, LiveRangeAnalysis, ScheduleConflicts},
ir::{
self,
traversal::{Named, Visitor},
LibrarySignatures,
},
analysis::{GraphColoring, LiveRangeAnalysis},
ir::{self, traversal::Named},
};
use ir::traversal::{Action, VisResult};
use itertools::Itertools;

/// Given a `LiveRangeAnalysis` that specifies the registers alive at each
/// group, minimize the registers used for each component.
Expand All @@ -23,7 +18,10 @@ use itertools::Itertools;
/// This pass only renames uses of registers. `DeadCellRemoval` should be run after this
/// to actually remove the register definitions.
#[derive(Default)]
pub struct MinimizeRegs;
pub struct MinimizeRegs {
live: LiveRangeAnalysis,
rewrites: Vec<(ir::RRC<ir::Cell>, ir::RRC<ir::Cell>)>,
}

impl Named for MinimizeRegs {
fn name() -> &'static str {
Expand All @@ -34,99 +32,50 @@ impl Named for MinimizeRegs {
}
}

impl Visitor for MinimizeRegs {
fn start(
impl ShareComponents for MinimizeRegs {
fn initialize(
&mut self,
comp: &mut ir::Component,
sigs: &LibrarySignatures,
) -> VisResult {
let registers = comp.cells.iter().filter_map(|cell_ref| {
let cell = cell_ref.borrow();
if let Some(name) = cell.type_name() {
if name == "std_reg" {
return Some((
cell.get_paramter("width").unwrap(),
cell.name.clone(),
));
}
}
None
});
comp: &ir::Component,
_sigs: &ir::LibrarySignatures,
) {
self.live = LiveRangeAnalysis::new(&comp, &*comp.control.borrow());
}

let mut graph: GraphColoring<ir::Id> =
GraphColoring::from(registers.clone().map(|(_, name)| name));
fn lookup_group_conflicts(&self, group_name: &ir::Id) -> Vec<ir::Id> {
self.live.get(group_name).iter().cloned().collect()
}

let live = LiveRangeAnalysis::new(&comp, &*comp.control.borrow());
let par_conflicts = ScheduleConflicts::from(&*comp.control.borrow());
fn cell_filter(
&self,
cell: &ir::Cell,
_sigs: &ir::LibrarySignatures,
) -> bool {
if let Some(name) = cell.type_name() {
name == "std_reg"
} else {
false
}
}

fn custom_conflicts(
&self,
comp: &ir::Component,
graph: &mut GraphColoring<ir::Id>,
) {
for group in &comp.groups {
// Conflict edges between all things alive at the same time.
let conflicts = live.get(&group.borrow().name);
let conflicts = self.live.get(&group.borrow().name);
graph.insert_conflicts(conflicts.iter());
}
}

// Conflict edges between all groups that are enabled in parallel.
par_conflicts
.all_conflicts()
.into_grouping_map_by(|(g1, _)| g1.clone())
.fold(vec![], |mut acc, _, (_, conf_group)| {
acc.extend(live.get(&conf_group));
acc
})
.into_iter()
.for_each(|(group, confs)| {
let conflicts = live.get(&group);
confs
.into_iter()
// This unique call saves a lot of time!
.unique()
.for_each(|par_conflict| {
for conflict_here in conflicts {
if conflict_here != par_conflict {
graph.insert_conflict(
&conflict_here,
&par_conflict,
);
}
}
})
});

// add constraints so that registers of different sizes can't be shared
registers
.tuple_combinations()
.for_each(|((w1, c1), (w2, c2))| {
if w1 != w2 {
graph.insert_conflict(&c1, &c2);
}
});

// used a sorted ordering to perform coloring
let ordering = live.get_all().sorted();
let coloring: Vec<_> = graph
.color_greedy_with(ordering)
.into_iter()
.filter(|(a, b)| a != b)
.map(|(a, b)| {
(comp.find_cell(&a).unwrap(), comp.find_cell(&b).unwrap())
})
.collect();

// apply the coloring as a renaming of registers for both groups
// and continuous assignments
let builder = ir::Builder::from(comp, sigs, false);
for group_ref in &builder.component.groups {
let mut group = group_ref.borrow_mut();
let mut assigns: Vec<_> = group.assignments.drain(..).collect();
builder.rename_port_uses(&coloring, &mut assigns);
group.assignments = assigns;
}

let mut assigns: Vec<_> =
builder.component.continuous_assignments.drain(..).collect();
builder.rename_port_uses(&coloring, &mut assigns);
builder.component.continuous_assignments = assigns;
fn set_rewrites(
&mut self,
rewrites: Vec<(ir::RRC<ir::Cell>, ir::RRC<ir::Cell>)>,
) {
self.rewrites = rewrites;
}

Ok(Action::Stop)
fn get_rewrites(&self) -> &[(ir::RRC<ir::Cell>, ir::RRC<ir::Cell>)] {
&self.rewrites
}
}
1 change: 1 addition & 0 deletions calyx/src/passes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ mod merge_assign;
mod minimize_regs;
mod papercut;
mod resource_sharing;
mod sharing_components;
mod simplify_guards;
mod static_timing;
mod synthesis_papercut;
Expand Down
Loading

0 comments on commit 5f3c1f2

Please sign in to comment.