Reworked the compute graph top level documentation

Started to add documentation for Python APIs, C++ nodes
pull/94/head
Christophe Favergeon 3 years ago
parent 5a4b6064d1
commit 46a732c158

@ -93,6 +93,13 @@ class FIFO<T,length,0,0>: public FIFOBase<T>
T *ret;
if (readPos > 0)
{
/* This is re-aligning the read buffer.
Aligning buffer is better for vectorized code.
But it has an impact since more memcpy are
executed than required.
This is likely to be not so useful in practice
so a future version will optimize the memcpy usage
*/
memcpy((void*)mBuffer,(void*)(mBuffer+readPos),(writePos-readPos)*sizeof(T));
writePos -= readPos;
readPos = 0;

@ -1,12 +1,18 @@
#### Options for C Code Generation only
# Options for C Code Generation
##### cOptionalArgs (default = "")
## cOptionalArgs (default = "")
Optional arguments to pass to the C API of the scheduler function
It can either use a `string` or a list of `string` where an element is an argument of the function (and should be valid `C`).
##### codeArray (default = True)
For instance:
```Python
conf.cOptionalArgs=["int someVariable"]
```
## codeArray (default = True)
When true, the scheduling is defined as an array. Otherwise, a list of function calls is generated.
@ -14,13 +20,13 @@ A list of function call may be easier to read but if the schedule is long, it is
When `codeArray` is True, the option `switchCase`can also be used.
##### switchCase (default = True)
## switchCase (default = True)
`codeArray` must be true or this option is ignored.
When the schedule is encoded as an array, it can either be an array of function pointers (`switchCase` false) or an array of indexes for a state machine (`switchCase` true)
##### eventRecorder (default = False)
## eventRecorder (default = False)
Enable the generation of `CMSIS EventRecorder` intrumentation in the code. The CMSIS-DSP Pack is providing definition of 3 events:
@ -28,37 +34,37 @@ Enable the generation of `CMSIS EventRecorder` intrumentation in the code. The C
* Node execution
* Error
##### customCName (default = "custom.h")
## customCName (default = "custom.h")
Name of custom header in generated C code. If you use several scheduler, you may want to use different headers for each one.
##### postCustomCName (default = "")
## postCustomCName (default = "")
Name of custom header in generated C code coming after all of the other includes.
Name of custom header in generated C code coming after all of the other includes. By default none is used.
##### genericNodeCName (default = "GenericNodes.h")
## genericNodeCName (default = "GenericNodes.h")
Name of GenericNodes header in generated C code. If you use several scheduler, you may want to use different headers for each one.
##### appNodesCName (default = "AppNodes.h")
## appNodesCName (default = "AppNodes.h")
Name of AppNodes header in generated C code. If you use several scheduler, you may want to use different headers for each one.
##### schedulerCFileName (default = "scheduler")
## schedulerCFileName (default = "scheduler")
Name of scheduler cpp and header in generated C code. If you use several scheduler, you may want to use different headers for each one.
Name of scheduler `cpp` and header in generated C code. If you use several scheduler, you may want to use different headers for each one.
If the option is set to `xxx`, the names generated will be `xxx.cpp` and `xxx.h`
##### CAPI (default = True)
## CAPI (default = True)
By default, the scheduler function is callable from C. When false, it is a standard C++ API.
##### CMSISDSP (default = True)
## CMSISDSP (default = True)
If you don't use any of the datatypes or functions of the CMSIS-DSP, you don't need to include the `arm_math.h` in the scheduler file. This option can thus be set to `False`.
##### asynchronous (default = False)
## asynchronous (default = False)
When true, the scheduling is for a dynamic / asynchronous flow. A node may not always produce or consume the same amount of data. As consequence, a scheduling can fail. Each node needs to implement a `prepareForRunning` function to identify and recover from FIFO underflows and overflows.
@ -68,17 +74,17 @@ This implies `codeArray` and `switchCase`. This disables `memoryOptimizations`.
Synchronous FIFOs that are just buffers will be considered as FIFOs in asynchronous mode.
More info are available in the documentation for [this mode](Dynamic.md).
More info are available in the documentation for [this mode](../Async.md).
##### FIFOIncrease (default 0)
## FIFOIncrease (default 0)
In case of dynamic / asynchronous scheduling, the FIFOs may need to be bigger than what is computed assuming a static / synchronous scheduling. This option is used to increase the FIFO size. It represents a percent increase.
For instance, a value of 10 means the FIFO will have their size updated from `oldSize` to `1.1 * oldSize` which is ` (1 + 10%)* oldSize`
For instance, a value of `10` means the FIFO will have their size updated from `oldSize` to `1.1 * oldSize` which is ` (1 + 10%)* oldSize`
If the value is a `float` instead of an `int` it will be used as is. For instance, `1.1` would increase the size by `1.1` and be equivalent to the setting `10` (for 10 percent).
##### asyncDefaultSkip (default True)
## asyncDefaultSkip (default True)
Behavior of a pure function (like CMSIS-DSP) in asynchronous mode. When `True`, the execution is skipped if the function can't be executed. If `False`, an error is raised.

@ -1,54 +1,455 @@
# CPP Nodes and classes
(DOCUMENTATION TO BE WRITTEN)
## Mandatory classes
FIFO
Those classes are defined in `GenericNodes.h` a header that is always included by the scheduler.
As consequence, the definition for those classes is always included : that's the meaning of mandatory.
### FIFO
FIFO classes are inheriting from the virtual class `FIFOBase`:
```C++
template<typename T>
class FIFOBase{
public:
virtual T* getWriteBuffer(int nb)=0;
virtual T* getReadBuffer(int nb)=0;
virtual bool willUnderflowWith(int nb) const = 0;
virtual bool willOverflowWith(int nb) const = 0;
virtual int nbSamplesInFIFO() const = 0;
};
```
The functions `willUnderflowWith`, `willOverflowWith` and `nbSamplesInFIFO` are only used in asynchronous mode.
If you implement a FIFO for synchronous mode you only need to implement `getWriteBuffer` and `getReadBuffer`.
FIFO must be templates with a type defined as:
```C++
template<typename T, int length, int isArray=0, int isAsync = 0>
class FIFO;
```
* `T` is a C datatype that must have value semantic : standard C type like `float` or `struct`
* `length` is the length of the FIFO in **samples**
* `isArray` is set to 1 when the scheduler has identified that the FIFO is always used as a buffer. So it is possible to provide a more optimized implementation for this case
* `isAsync` is set to 1 for the asynchronous mode
If you implement you own FIFO class, it should come from a template with the same arguments. For instance:
```C++
template<typename T, int length, int isArray=0, int isAsync = 0>
class MyCustomFIFO;
```
and it should inherit from `FIFOBase<T>`.
`GenericNodes.h` is providing 3 default implementations. Their are specialization of the FIFO template:
#### FIFO for synchronous mode
```C++
template<typename T, int length>
class FIFO<T,length,0,0>: public FIFOBase<T>
```
#### Buffer for synchronous mode
In some case a FIFO is just used as a buffer. An optimized implementation for this case is provided
```C++
template<typename T, int length>
class FIFO<T,length,1,0>: public FIFOBase<T>
```
In this mode, the FIFO implementation is very light. For instance, for `getWriteBuffer` we have:
```C++
T * getWriteBuffer(int nb) const final
{
return(mBuffer);
};
```
#### FIFO for asynchronous mode
```C++
template<typename T, int length>
class FIFO<T,length,0,1>: public FIFOBase<T>
```
This implementation is a bit more heavy and is providing implementations of following function that is doing something useful :
```C++
bool willUnderflowWith(int nb) const;
bool willOverflowWith(int nb) const;
int nbSamplesInFIFO() const;
```
### Nodes
Nodes are inheriting from the virtual class:
```C++
class NodeBase
{
public:
virtual int run()=0;
virtual int prepareForRunning()=0;
};
```
`GenericNode`, `GenericSource` and `GenericSink` are providing accesses to the FIFOs for each IO. The goal of those wrappers is to define the IOs (number of IO, their type and length) and hide the API to the FIFOs.
There are different versions depending on the number of inputs and/or output. Other nodes of that kind can be created by the user if different IO configurations are required:
#### GenericNode
The template is:
```C++
template<typename IN, int inputSize,
typename OUT, int outputSize>
class GenericNode:public NodeBase
```
There is one input and one output.
GenericNode
The constructor is:
GenericNode12
```C++
GenericNode(FIFOBase<IN> &src,FIFOBase<OUT> &dst);
```
GenericNode13
It is taking the input and output FIFOs as argument. The real type of the FIFO is hidden since the type `FIFOBase` is used. So `GenericNode` can be used with any FIFO implementation.
GenericNode21
The main role of this `GenericNode` class is to provide functions to connect to the FIFOs.
GenericSource
The functions to access the FIFO buffers are:
GenericSink
```C++
OUT * getWriteBuffer(int nb = outputSize);
IN * getReadBuffer(int nb = inputSize);
```
Duplicate2
`getWriteBuffer` is getting a pointer to a buffer of length `nb` to write the output samples.
Duplicate3
`getReadBuffer` is getting a pointer to a buffer of length `nb` to read the input samples.
`nb` must be chosen so that there is no underflow / overflow. In synchronous mode, it will work by design if the length defined in the template argument is used. The template length is thus chosen as default value for `nb`.
This value may be changed in cyclo-static or asynchronous mode. In asynchronous mode, additional functions are provided to test for a possibility of underflow / overflow **before** getting a pointer to the buffer.
It is done with following function that are also provided by `GenericNode`:
```C++
bool willOverflow(int nb = outputSize);
bool willUnderflow(int nb = inputSize);
```
All of those functions introduced by `GenericNode` are doing nothing more than calling the underlying FIFO methods. But they hide those FIFOs from the user code. The FIFO can only be accessed through those APIs.
#### GenericNode12
Same as `GenericNode` but with two outputs.
```C++
template<typename IN, int inputSize,
typename OUT1, int output1Size
typename OUT2, int output2Size>
class GenericNode12:public NodeBase
```
It provides:
```C++
IN * getReadBuffer(int nb=inputSize);
OUT1 * getWriteBuffer1(int nb=output1Size);
OUT2 * getWriteBuffer2(int nb=output2Size);
bool willUnderflow(int nb = inputSize);
bool willOverflow1(int nb = output1Size);
bool willOverflow2(int nb = output2Size);
```
#### GenericNode13
Same but with 3 outputs.
#### GenericNode21
Same but with 2 inputs and 1 output.
#### GenericSource
Similar to a `GenericNode` but there is no inputs.
#### GenericSink
Similar to a `GenericNode` but there is no outputs.
#### Duplicate2
This node is duplicating its input to 2 outputs.
The template is:
```C++
template<typename IN, int inputSize,
typename OUT1,int output1Size,
typename OUT2,int output2Size>
class Duplicate2;
```
Only one specialization of this template makes sense : the output must have same type and same length as the input.
```C++
template<typename IN, int inputSize>
class Duplicate2<IN,inputSize,
IN,inputSize,
IN,inputSize> :
public GenericNode12<IN,inputSize,
IN,inputSize,
IN,inputSize>
```
#### Duplicate3
Similar to `Duplicate2` but with 3 outputs.
## Optional nodes
CFFT
Those nodes are not included by default. They can be found in `ComputeGraph/cg/nodes/cpp`
To use any of them you just need to include the header (for instance in your `AppNodes.h` file):
```C++
#include "CFFT.h"
```
### CFFT / CIFFT
Those nodes are for using the CMSIS-DSP FFT.
Template:
```C++
template<typename IN, int inputSize,
typename OUT,int outputSize>
class CFFT;
```
CIFFT
Specialization provided only for `float32_t`, `float16_t`,`q15_t`.
InterleavedStereoToMono
The wrapper is copying the input buffer before doing the FFT (since CMSIS-DSP FFT is modifying the input buffer). It is normally possible to modify the input buffer even if it is in the input FIFO.
MFCC
This implementation has made the choice of not touching the input FIFO with the cost of an additional copy.
NullSink
Other data types can be easily added based on the current provided example. The user can just implement other specializations.
OverlapAndAdd
`CIFFT` is defined with class `CIFFT`.
SlidingBuffer
### InterleavedStereoToMono
ToComplex
Deinterleave a stream of stereo samples to **one** stream of mono samples.
ToReal
Template:
Unzip
```C++
template<typename IN, int inputSize,
typename OUT,int outputSize>
class InterleavedStereoToMono;
```
Zip
For specialization `q15_t` and `q31_t`, the inputs are divided by 2 before being added to avoid any overflow.
For specialization `float32_t` : The output is multiplied by `0.5f` for consistency for the fixed point version.
### MFCC
Those nodes are for using the CMSIS-DSP MFCC.
Template:
```C++
template<typename IN, int inputSize,
typename OUT,int outputSize>
class MFCC;
```
Specializations provided for `float32_t`, `float16_t`, `q31_t` and `q15_t`.
The MFCC is requiring a temporary buffer. The wrappers are thus allocating a memory buffer during initialization of the node.
The buffer is allocated as a C++ vector. See the documentation of the MFCC in CMSIS-DSP to know more about the size of this buffer.
### NullSink
Template:
```C++
template<typename IN, int inputSize>
class NullSink: public GenericSink<IN, inputSize>
```
It is useful for development and debug. This node is doing nothing and just consuming its input.
### OverlapAndAdd
Template:
```c++
template<typename IN,int windowSize, int overlap>
class OverlapAdd: public GenericNode<IN,windowSize,IN,windowSize-overlap>
```
There are two sizes in the template arguments : `windowSize` and `overlap`.
From those size, the template is computing the number of samples consumed and produced by the node.
The implementation is generic but will only build for a type `IN` having an addition operator.
This node is using a little memory (C++ vector) of size `overlap` that is allocated during creation of the node.
This node will overlap input data by `overlap` samples and add the common overlapping samples.
### SlidingBuffer
Template:
```C++
template<typename IN,int windowSize, int overlap>
class SlidingBuffer: public GenericNode<IN,windowSize-overlap,IN,windowSize>
```
There are two sizes in the template arguments : `windowSize` and `overlap`.
For those size, the template is computing the number of samples consumed and produced by the node.
The implementation is generic and will work with all types.
This node is using a little memory (C++ vector) of size `overlap` allocated during creation of the node.
This node is moving a window on the input data with an overlap. The output data is the content of the window.
Note that this node is not doing any multiplication with window functions that can be found in signal processing literature. This multiplication has to be implemented in the compute graph in a separate node.
### ToComplex
Template:
```C++
template<typename IN, int inputSize,
typename OUT,int outputSize>
class ToComplex;
```
Convert a stream of reals a b c d ... to complexes a 0 b 0 c 0 d 0 ...
The implementation is generic and does not enforce the required size constraints.
### ToReal
Template:
```C++
template<typename IN, int inputSize,typename OUT,int outputSize>
class ToReal;
```
Convert a stream of complex a 0 b 0 c 0 ... to reals a b c ...
The implementation is generic and does not enforce the required size constraints.
### Unzip
Template:
```C++
template<typename IN, int inputSize,
typename OUT1,int output1Size,
typename OUT2,int output2Size>
class Unzip;
```
Unzip a stream a1 a2 b1 b2 c1 c2 ...
Into 2 streams:
a1 b1 c1 ...
a2 b2 c2 ...
The implementation is generic and does not enforce the required size constraints.
### Zip
Template:
```C++
template<typename IN1, int inputSize1,
typename IN2,int inputSize2,
typename OUT,int outputSize>
class Zip;
```
Transform two input streams:
a1 b1 c1 ...
a2 b2 c2 ...
into one output stream:
a1 a2 b1 b2 c1 c2 ...
The implementation is generic and does not enforce the required size constraints
### Host
FileSink
Those nodes are for host (Windows, Linux, Mac). They can be useful to experiment with a compute graph.
By default there is no nodes to read / write `.wav` files but you can easily add some if needed (`dr_wav.h` is a simple way to add `.wav` reading / writing and is freely available from the web).
#### FileSink
Template
```C++
template<typename IN, int inputSize>
class FileSink: public GenericSink<IN, inputSize>
```
Write the input samples to a file. The implementation is generic and use iostream for writing the datatype.
The constructor has an additional argument : the name/path of the output file:
```C++
FileSink(FIFOBase<IN> &src, std::string name)
```
#### FileSource
Template:
```C++
template<typename OUT,int outputSize> class FileSource;
```
There is only one specialization for the `float32_t` type.
It is reading text file with one float per file and generating a stream of float.
At the end of file, 0s are generated on the output indefinitely.
The constructor has an additional argument : the name/path of the input file:
FileSource
```C++
FileSource(FIFOBase<float32_t> &dst,std::string name)
```

@ -1,12 +1,14 @@
### Options for the code generator
# Options for the code generator
#### debugLimit (default = 0)
Global options for the code generators. There are specific options for the C, Python and Graphviz generators. They are described in different part of the documentation.
## debugLimit (default = 0)
When `debugLimit` is > 0, the number of iterations of the scheduling is limited to `debugLimit`. Otherwise, the scheduling is running forever or until an error has occured.
#### dumpFIFO (default = False)
## dumpFIFO (default = False)
When true, generate some code to dump the FIFO content at runtime. Only useful for debug.
When true, generate some code to dump the FIFO content at **runtime**. Only useful for debug.
In C++ code generation, it is only available when using the mode `codeArray == False`.
@ -16,11 +18,11 @@ When this mode is enabled, the first line of the scheduler file is :
and it also enable some debug code in `GenericNodes.h`
#### schedName (default = "scheduler")
## schedName (default = "scheduler")
Name of the scheduler function used in the generated code.
#### prefix (default = "")
## prefix (default = "")
Prefix to add before the FIFO buffer definitions. Those buffers are not static and are global. If you want to use several schedulers in your code, the buffer names used by each should be different.

@ -1 +1,103 @@
(DOCUMENTATION TO BE WRITTEN)
# Generic Nodes
The generic node classes are used to build new kind of nodes. There are 3 classes provided by the framework :
* `GenericSource`
* `GenericNode`
* `GenericSink`
They are defined in `cmsisdsp.cg.scheduler`
Any new kind of node must inherit from one of those classes. Those classes are providing the methods `addInput` and/or `addOutput` to define new IOs.
The method `typeName` from the parent class must be overridden.
A new kind of node is generally defined as:
```python
class ProcessingNode(GenericNode):
def __init__(self,name,theType,inLength,outLength):
GenericNode.__init__(self,name)
self.addInput("i",theType,inLength)
self.addOutput("o",theType,outLength)
@property
def typeName(self):
return "ProcessingNode"
```
See the [simple](../examples/simple/README.md) example for more explanation about how to define a new node.
## Methods
The constructor of the node is using the `addInput` and/or `addOutput` to define new IOs.
```python
def addInput(self,name,theType,theLength):
```
* `name` is the name of the input. It will becomes a property of the Python object so it must not conflict with existing properties. If `name` is, for instance, "i" then it can be accessed with `node.i` in the code
* `theType` is the datatype of the IO. It must inherit from `CGStaticType` (see below for more details about defining the types)
* `theLength` is the amount of **samples** consumed by this IO at each execution of the node
```python
def addOutput(self,name,theType,theLength):
```
* `name` is the name of the input. It will becomes a property of the Python object so it must not conflict with existing properties. If `name` is, for instance, "o" then it can be accessed with `node.o` in the code
* `theType` is the datatype of the IO. It must inherit from `CGStaticType` (see below for more details about defining the types)
* `theLength` is the amount of **samples** produced by this IO at each execution of the node
```python
@property
def typeName(self):
return "ProcessingNode"
```
This method defines the name of the C++ class implementing the wrapper for this node.
## Datatypes
Datatypes for the IOs are inheriting from `CGStaticType`.
Currently there are two classes defined:
* `CType` for the standard CMSIS-DSP types
* `CStructType` for a C struct
### CType
You create such a type with `CType(id)` where `id` is one of the constant coming from the Python wrapper:
* F64
* F32
* F16
* Q31
* Q15
* Q7
* UINT32
* UINT16
* UINT8
* SINT32
* SINT16
* SINT8
For instance, to define a `float32_t` type for an IO you can use `CType(F32)`
### CStructType
The constructor has the following definition
```python
def __init__(self,name,python_name,size_in_bytes):
```
* `name` is the name of the C struct
* `python_name` is the name of the Python class implementing this type (when you generate a Python schedule)
* `size_in_bytes` is the size of the struct. It should take into account padding. It is used in case of buffer sharing since the datatype of the shared buffer is `int8_t`. The Python script must be able to compute the size of those buffers and needs to know the size of the structure.
In Python, there is no `struct`. This datatype is mapped to an object. Object have reference type. Compute graph FIFOs are assuming a value type semantic.
As consequence, in Python side you should never copy those structs since it would copy the reference. You should instead copy the members of the struct.
If you don't plan on generating a Python scheduler, you can just use whatever name you want for the `python_name`. It will be ignored by the C++ code generation.

@ -1,42 +1,57 @@
### Options for the graph
# API of the Graph Class
Those options needs to be used on the graph object created with `Graph()`.
## Creating a connection
For instance :
Those methods must be applied to a graph object created with `Graph()`. The `Graph` class is defined inside `cmsisdsp.cg.scheduler` from the CMSIS-DSP Python wrapper.
```python
g = Graph()
g.defaultFIFOClass = "FIFO"
def connect(self,input_io,output_io,fifoClass=None,fifoScale = 1.0):
```
#### defaultFIFOClass (default = "FIFO")
Class used for FIFO by default. Can also be customized for each connection (`connect` of `connectWithDelay` call) with something like:
`g.connect(src.o,b.i,fifoClass="FIFOClassNameForThisConnection")`
Typically this method is used as:
#### duplicateNodeClassName(default="Duplicate")
```python
the_graph = Graph()
Prefix used to generate the duplicate node classes like `Duplicate2`, `Duplicate3` ...
# Connect the source output to the processing node input
the_graph.connect(src.o,processing.i)
```
There are two optional arguments:
* `fifoClass` : To use a different C++ class for implementing the connection between the two IOs. (it is also possible to change the FIFO class globally by setting an option on the graph. See below). Only the `FIFO` class is provided by default. Any new implementation must inherit from `FIFObase<T>`
* `fifoScale` : In asynchronous mode, it is a scaling factor to increase the length of the FIFO compared to what has been computed by the synchronous approximation. This setting can also be set globally using the scheduler options. `fifoScale` is overriding the global setting. It must be a `float` (not an `int`).
### Options for connections
```python
def connectWithDelay(self,input_io,output_io,delay,fifoClass=None,fifoScale=1.0):
```
It is now possible to write something like:
The only difference with the previous function is the `delay` argument. It could be used like:
```python
g.connect(src.o,b.i,fifoClass="FIFOSource")
the_graph.connect(src.o,processing.i, 10)
```
The `fifoClass` argument allows to choose a specific FIFO class in the generated C++ or Python.
The `delay` is the number of samples contained in the FIFO at start (initialized to zero). The FIFO length (computed by the scheduling) is generally bigger by this amount of sample. The result is that it is delaying the output by `delay` samples.
Only the `FIFO` class is provided by default. Any new implementation must inherit from `FIFObase<T>`
It is generally useful when the graph has some loops to make it schedulable.
There is also an option to set the scaling factor when used in asynchronous mode:
## Options for the graph
Those options needs to be used on the graph object created with `Graph()`.
For instance :
```python
g.connect(odd.o,debug.i,fifoScale=3.0)
g = Graph()
g.defaultFIFOClass = "FIFO"
```
When this option is set, it will be used (instead of the global setting). This must be a float.
### defaultFIFOClass (default = "FIFO")
Class used for FIFO by default. Can also be customized for each connection (`connect` of `connectWithDelay` call).
### duplicateNodeClassName(default="Duplicate")
Prefix used to generate the duplicate node classes like `Duplicate2`, `Duplicate3` ...

@ -1,11 +1,11 @@
### Options for the graphviz generator
# Options for the graphviz generator
#### horizontal (default = True)
## horizontal (default = True)
Horizontal or vertical layout for the graph.
#### displayFIFOBuf (default = False)
## displayFIFOBuf (default = False)
By default, the graph is displaying the FIFO sizes. If you want to know with FIFO variable is used in the code, you can set this option to true and the graph will display the FIFO variable names.
By default, the graph is displaying the FIFO sizes computed as result of the scheduling. If you want to know the FIFO variable names used in the code, you can set this option to true and the graph will display the FIFO variable names.

@ -1,18 +1,18 @@
#### Options for Python code generation only
# Options for Python code generation
##### pyOptionalArgs (default = "")
## pyOptionalArgs (default = "")
Optional arguments to pass to the Python version of the scheduler function
##### customPythonName (default = "custom")
## customPythonName (default = "custom")
Name of custom header in generated Python code. If you use several scheduler, you may want to use different headers for each one.
##### appNodesPythonName (default = "appnodes")
## appNodesPythonName (default = "appnodes")
Name of AppNodes header in generated Python code. If you use several scheduler, you may want to use different headers for each one.
##### schedulerPythonFileName (default = "sched")
## schedulerPythonFileName (default = "sched")
Name of scheduler file in generated Python code. If you use several scheduler, you may want to use different headers for each one.

@ -1,4 +1,4 @@
### Options for the scheduling
# Options for the scheduling
Those options needs to be used on a configuration objects passed as argument of the scheduling function. For instance:
@ -8,24 +8,24 @@ conf.debugLimit = 10
sched = g.computeSchedule(config = conf)
```
Note that the configuration object also contain options for the code generators.
Note that the configuration object also contain options for the code generators. They are described in different part of the documentation.
#### memoryOptimization (default = False)
## memoryOptimization (default = False)
When the amount of data written to a FIFO and read from the FIFO is the same, the FIFO is just an array. In this case, depending on the scheduling, the memory used by different arrays may be reused if those arrays are not needed at the same time.
This option is enabling an analysis to optimize the memory usage by merging some buffers when it is possible.
#### sinkPriority (default = True)
## sinkPriority (default = True)
Try to prioritize the scheduling of the sinks to minimize the latency between sources and sinks.
When this option is enabled, the tool may not be able to find a schedule in all cases. If it can't find a schedule, it will raise a `DeadLock` exception.
#### displayFIFOSizes (default = False)
## displayFIFOSizes (default = False)
During computation of the schedule, the evolution of the FIFO sizes is generated on `stdout`.
#### dumpSchedule (default = False)
## dumpSchedule (default = False)
During computation of the schedule, the human readable schedule is generated on `stdout`.

@ -19,7 +19,7 @@ cmake -DHOST=YES \
-G "Unix Makefiles" ..
```
The core include directory is `...CMSIS_5/Core` ...
The core include directory is something like `CMSIS_5/Core` ...
If cmake is successful, you can type `make` to build the examples. It will also build CMSIS-DSP for the host.
@ -49,10 +49,10 @@ python main.py
# List of examples
* [Simple example](simple/README.md) : How to get started
* [Example 1](example1/README.md) : Sample as the simple example but explaining how to add arguments to the scheduler API and node constructors
* [Example 1](example1/README.md) : Same as the simple example but explaining how to add arguments to the scheduler API and node constructors. This example is also giving a very detailed explanation of the C++ code generated for the scheduler
* [Example 2](example2/README.md) : Explain how to use CMSIS-DSP pure functions (no state) and add delay on the arcs of the graph. Explain some configuration options for the schedule generation.
* [Example 3 ](example3/README.md) : A full signal processing example with CMSIS-DSP using FFT and sliding windows and overlap and add node
* [Example 4](example4/README.md) : Same as examples 3 but where we generate a Python implementation rather than a C++ implementation. The resulting graph can be executed than to the CMSIS-DSP Python wrapper
* [Example 3](example3/README.md) : A full signal processing example with CMSIS-DSP using FFT and sliding windows and overlap and add node
* [Example 4](example4/README.md) : Same as example 3 but where we generate a Python implementation rather than a C++ implementation. The resulting graph can be executed thanks to the CMSIS-DSP Python wrapper
* [Example 5](example5/README.md) : Another pure Python example showing how to compute a sequence of Q15 MFCC and generate an animation (using also the CMSIS-DSP Python wrapper)
* [Example 6](example6/README.md) : Same as example 5 but with C++ code generation
* [Example 7](example7/README.md) : Pure Python example demonstrating a communication between the compute graph and OpenModelica to generate a Larsen effect

@ -4,7 +4,7 @@ Please refer to the [simple example](../simple/README.md) to have an overview of
* How to define new arguments for the C implementation of the nodes
* How to define new arguments for the C API of the scheduler function
* More detailed description of the generated C++ scheduler
* Detailed description of the generated C++ scheduler
The graph is is nearly the same as the one in the [simple example](../simple/README.md) but the processing node is just generating 5 samples in this example:

Loading…
Cancel
Save