|
|
**Warning:** this project is quite recent, and the provided API is immature and might change somehow.
|
|
|
|
|
|
## Configuration
|
|
|
|
|
|
The configuration of QECE is managed through a `DynamicVar` named `QeceContext`, which wrap a `QeceConfig` class aggregating the different configuration aspects in the project (sources are in `src/main/scala/QeceContext.scala`).
|
|
|
|
|
|
Different helpers are available to load and update this variable (you can take a look at the **scaladoc** for both `QeceContext` and `QeceConfig`), so you can easily modify the default configuration.
|
|
|
More specifically, some helpers are based on functional programming, exposing functions to modify the different aspects of the configuration: for example, you can use `val customConfig = QeceContext.copy(parallel = _.copy(numThread = 8))` to update the `ParallelConfig` with a new level of parallelism, without modifying the other default values.
|
|
|
|
|
|
**Warning:** If you aim at defining your own entry points in QECE - as the API is currently quite open - do not forget to wrap your calls with the right `withValue(myConfig)` to use an actually updated version of the `QeceContext`, or the default configuration will be used.
|
|
|
Otherwise, the entry points of the API are managing this aspect for you.
|
|
|
|
|
|
## Entry Points
|
|
|
|
|
|
Currently, two main entry points are available in the library, for both **exploration** and **estimation** features.
|
|
|
|
|
|
### Exploration
|
|
|
|
|
|
#### Annotating your modules
|
|
|
|
|
|
The first thing to do run an exploration is to annotate the explored design with its design space.
|
|
|
<br/>
|
|
|
To do so, your chisel `Module` must implement the `qece.exploration.utils.WithExplorable` trait, and each parameter must be annotated with a set of possible values, using the annotations defined in `qece.exploration.annotations`.
|
|
|
|
|
|
For example, we can define a `DummyModule` as follow:
|
|
|
```
|
|
|
class DummyModule(
|
|
|
@pow2(1, 5) bitWidth: Int,
|
|
|
@linear(2, 5) unitNumber: Int
|
|
|
) extends MultiIOModule with WithExplorable
|
|
|
```
|
|
|
|
|
|
**N.B.:** For now, the parameters can only take integer values.
|
|
|
However, it can easily be mapped to any countable set of value.
|
|
|
|
|
|
#### Running explorations
|
|
|
|
|
|
The real entry point of QECE is based on the `StrategyBuilder` class (sources in `src/main/scala/exploration/strategies/StrategyBuilder`).
|
|
|
<br/>
|
|
|
It is a simple wrapper around the available basic strategies, which includes an user defined `QeceConfiguration` to easily override the default configuration.
|
|
|
|
|
|
Once you have defined your own `customConfig` (as shown above), you can call `val builder = StrategyBuilder(customConfig)` to create your custom `StrategyBuilder`.
|
|
|
|
|
|
The builder itself allows to compose sequential exploration steps, which are methods of the builder.
|
|
|
For each method, you can specify different parameters (including the `TransformSeq` to run), and you can redefine the parallelism level by specifying the `numThread` parameter for each step.
|
|
|
For example, a simple strategy operating on the previously defined `DummyModule` (to find the design using the more DSP units but still fitting the target board) could be:
|
|
|
```
|
|
|
val builder = StrategyBuilder(customConfig).withPath("dummyExploration")
|
|
|
val strategy = builder.buildStrategy(
|
|
|
builder.compose(
|
|
|
builder.prune[DummyModule](
|
|
|
tfs = TransformSeq.resources,
|
|
|
func = m => m("%dsp") > 1.0
|
|
|
),
|
|
|
builder.sort[DummyModule](
|
|
|
tfs = TransformSeq.synthesis,
|
|
|
func = _("%realDSP"),
|
|
|
cmp = (_ > _),
|
|
|
numThread = 4
|
|
|
)
|
|
|
)
|
|
|
)
|
|
|
strategy.explore[DummyModule]
|
|
|
strategy.writeBack("myResults.csv")
|
|
|
```
|
|
|
|
|
|
**N.B.:** You can use the helper `withPath(targetPath: String)` to specify the file emission path for the current exploration
|
|
|
|
|
|
### Estimation
|
|
|
|
|
|
The **estimation** of digital designs is mainly used in the **exploration** feature, and might be difficult to integrate on its own.
|
|
|
|
|
|
However, if you want to use it, consider implementing the `qece.estimation.WithTransform` trait, using the `estimate[T: TypeTag](transforms: TransformSeq, config: QeceConfig)(point: Point)` method to run the selected estimation transforms on a given implementation (represented as a `Point`)
|
|
|
|
|
|
### Defining your own transforms and strategies
|
|
|
|
|
|
At the moment of this writing, the only way to define your own estimation transforms and basic exploration strategies is to clone this project, and integrate your code in it.
|
|
|
<br/>
|
|
|
As this solution is quite incompatible with the goal of this project, we are working on a way to externally define your custom operations, and integrate them in the API.
|
|
|
<br/>
|
|
|
However, if you think that your custom transform/strategy would benefit to other users, do not hesitate to create a merge request !
|
|
|
|
|
|
**N.B.:** Some helpers are available for file usage and timing, in `src/main/scala/package.scala` and `src/main/scala/Utils.scala`.
|
|
|
Moreover, statistics helpers are available in `src/main/scala/estimation/qor`. |
|
|
\ No newline at end of file |