pub struct CellShare { /* private fields */ }
Expand description

Given a LiveRangeAnalysis that specifies the “share” and “state_share” cells alive at each group, minimizes the cells used for each component.

This works by constructing an interference graph for each alive “state_share” cell. If two cells are ever alive at the same time, then there is an edge between them in the interference graph. Additionally, if two cells are different prototypes, then there is an edge between them.

A greedy graph coloring algorithm on the interference graph is used to assign each cell a name.

By default, this pass will share a given cell as many times as possible. However, by passing a command line argument, we can limit the number of times a given cell is reused. The rationale behind this option is that, in certain cases, if you share a given component too much, the logic to determine when that component should be activated ends up being more expensive than just using a separate component. To pass this command line argument, you give three numbers: The number of times a given combinational component can be shared, the number of times a given register can be shared, and the number of times all other components can be shared. Generally we would want settings such that 1 < 2 < 3, since a given share of a 3) would save more hardware than a share of a 2), and a share of a 2) would save more hardware than a share of a 1). The exact command line syntax to use: if we had a file, “x.futil” and ran: cargo run x.futil -x cell-share:bounds=2,4,8, then we would only share a given combinational component at most twice, a given register at most 4 times, and all other components at most 8 times. If you wanted to do something with fud then run fud e ... -s calyx.flags " -x cell-share:bounds=2,4,8". Finally if you do not want to bound the sharing for a particular cell type, you can pass -1 as a bound. So for example if you passed -x cell-share:bounds=2,-1,3 this means that you will always share registers. Note: The no spaces are important. Also, if you pass the following flag: -x cell-share:print-share-freqs=file-name this pass will write a json to file-name. If want to print into stdout then just set the file-name to be “stdout” (you don’t need the quotes when you actually pass in the argument, so run -x cell-share:print-share-freqs=stdout), and if you want to print to stderr then just set the file-name to be “stderr”. The json will map an integer (say n) to the number of cells in the new design (i.e., the design after sharing has been performed) that were shared exactly n times. So the key n = 2 will be mapped to the number of cells in the new design that are shared exactly twice.

Other flags: print_par_timing: prints the par-timing-map calyx_2020: shares using the Calyx 2020 settings: unlimited sharing of combinational components and registers, but no sharing of anything else

This pass only renames uses of cells. crate::passes::DeadCellRemoval should be run after this to actually remove the definitions.

Trait Implementations

Construct the visitor using information from the Context
Clear the data stored in the visitor. Called before traversing the next component by [ir::traversal::Visitor]. Read more
The name of a pass. Is used for identifying passes.
A short description of the pass.
Set of options that can be passed to the pass. The options contains a tuple of the option name and a description. Read more

The algorithm that runs is:

  • instantiate conflict graph using all component cells that satisfy cell_filter
  • use [ScheduleConflicts] to find groups/invokes that run in parallel with each other
  • for each tuple combination of cells that return true on cell_filter(), c1 and c2
  • first determine if their live ranges overlap. If so, then insert a conflict between c1 and c2
  • if c1 and c2 don’t have overlapping live ranges, check if c1 and c2 are ever live at within the same par block, and they are live at different children of the par block. If the parent par is not static, then add a conflict. If the parent par is static, then we can use the static_par_timing analysis to check whether the cells’ liveness actually overlaps.
  • perform graph coloring using self.ordering to define the order of the greedy coloring
  • use coloring to rewrite group assignments, continuous assignments, and conditional ports.
Executed before the traversal begins.
Precondition for this pass to run on the program. If this function returns None, the pass triggers. Otherwise it aborts and logs the string as the reason. Read more
Transform the ir::Context before visiting the components.
Transform the ir::Context after visiting the components.
Define the iteration order in which components should be visited
Define the traversal over a component. Calls Visitor::start, visits each control node, and finally calls Visitor::finish. Read more
Run the visitor on a given program ir::Context. The function mutably borrows the control program in each component and traverses it. Read more
Build a Default implementation of this pass and call Visitor::do_pass using it. Read more
Executed after the traversal ends. This method is always invoked regardless of the Action returned from the children. Read more
Executed before visiting the children of a ir::Seq node.
Executed after visiting the children of a ir::Seq node.
Executed before visiting the children of a ir::Par node.
Executed after visiting the children of a ir::Par node.
Executed before visiting the children of a ir::If node.
Executed after visiting the children of a ir::If node.
Executed before visiting the children of a ir::While node.
Executed after visiting the children of a ir::While node.
Executed before visiting the children of a ir::Repeat node.
Executed after visiting the children of a ir::Repeat node.
Executed before visiting the contents of an ir::StaticControl node.
Executed after visiting the conetnts of an ir::StaticControl node.
Executed at an ir::Enable node.
Executed at an ir::StaticEnable node.
Executed before visiting the children of a ir::StaticIf node.
Executed after visiting the children of a ir::StaticIf node.
Executed before visiting the children of a ir::StaticRepeat node.
Executed after visiting the children of a ir::StaticRepeat node.
Executed at an ir::Invoke node.
Executed at a ir::StaticInvoke node.
Executed at an ir::Empty node.

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.