Improvements to the compute graph documentation.

pull/103/head
Christophe Favergeon 3 years ago
parent 1d9e38adca
commit 9ec82e87fc

@ -12,11 +12,11 @@
3. ### [Examples](examples/README.md)
4. ### [Python API](documentation/PythonAPI.md)
4. ### [Python API for creating graphs and schedulers](documentation/PythonAPI.md)
5. ### [C++ Default nodes](documentation/CPPNodes.md)
5. ### [C++ default nodes for C++ schedulers](documentation/CPPNodes.md)
6. ### [Python default nodes](documentation/PythonNodes.md)
6. ### [Python default nodes for Python schedulers](documentation/PythonNodes.md)
7. ### [Memory optimizations](documentation/Memory.md)

@ -1,4 +1,4 @@
# C Code generation
# C++ Code generation
## API
@ -21,12 +21,18 @@ 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`).
For instance:
For instance, with:
```Python
conf.cOptionalArgs=["int someVariable"]
```
The API of the generated scheduler function would be:
```C++
uint32_t scheduler(int *error,int someVariable)
```
### codeArray (default = True)
When true, the scheduling is defined as an array. Otherwise, a list of function calls is generated.

@ -4,7 +4,7 @@
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.
As consequence, the definition for those classes is always included.
### FIFO
@ -82,7 +82,7 @@ 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 :
This implementation is a bit more heavy and is providing implementations of following function :
```C++
bool willUnderflowWith(int nb) const;
@ -92,7 +92,7 @@ int nbSamplesInFIFO() const;
### Nodes
Nodes are inheriting from the virtual class:
All nodes are inheriting from the virtual class `NodeBase`:
```C++
class NodeBase
@ -269,7 +269,7 @@ class InterleavedStereoToMono;
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.
For specialization `float32_t` : The output is multiplied by `0.5f` for consistency with the fixed point version.
### MFCC
@ -317,7 +317,7 @@ The implementation is generic but will only build for a type `IN` having an addi
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.
This node will overlap input data by `overlap` samples and sum the common overlapping samples.
### SlidingBuffer
@ -443,9 +443,9 @@ 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.
It is reading text file with one float per line and generating a stream of float.
At the end of file, 0s are generated on the output indefinitely.
At the end of file, 0.0f are generated on the output indefinitely.
The constructor has an additional argument : the name/path of the input file:

@ -1,26 +1,26 @@
# Generic and functions nodes
# Description of the nodes
The generic and function nodes are the basic nodes that you use to create other kind of nodes in the graph.
There are 3 generic classes provided by the framework to be used to create new nodes :
There are 3 generic classes provided by the framework to be used to create new nodes.
To create a new kind of node, you inherit from one of those classes:
* `GenericSource`
* `GenericNode`
* `GenericSink`
They are defined in `cmsisdsp.cg.scheduler`
They are defined in `cmsisdsp.cg.scheduler`.
There are 3 other classes that can be used to create new nodes from functions:
There are 3 other classes that can be used to create new nodes from functions. A function has no state and a C++ wrapper is not required. In this case, the tool is generating code for calling the function directly rather than using a C++ wrapper.
* `Unary`
* `Binary`
* `Dsp`
* `Unary` (unary operators like `negate`, `inverse` ...)
* `Binary` (binary operators like `add`, `mul` ...)
* `Dsp` (Some CMSIS-DSP function either binary or unary)
# Generic Nodes
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.
When you define a new kind of node, it must inherit from one of those classes. Those classes are providing the methods `addInput` and/or `addOutput` to define new inputs / outputs.
A new kind of node is generally defined as:
@ -36,6 +36,20 @@ class ProcessingNode(GenericNode):
return "ProcessingNode"
```
The method `typeName` from the parent class must be overridden and provide the name of the `C++` wrapper to be used for this node.
The object constructor is defining the inputs / outputs : number of samples and datatype.
The object constructor is also defining the name used to identity this node in the generated code (so it must be a valid C variable name).
`GenericSink` is only providing the `addInput` function.
`GenericSource` is only providing the `addOutput` function
`GenericNode` is providing both.
You can use each function as much as you want to create several inputs and / or several outputs for a node.
See the [simple](../examples/simple/README.md) example for more explanation about how to define a new node.
## Methods
@ -46,7 +60,7 @@ The constructor of the node is using the `addInput` and/or `addOutput` to define
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
* `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
@ -54,7 +68,7 @@ def addInput(self,name,theType,theLength):
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
* `name` is the name of the output. 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
@ -70,9 +84,9 @@ This method defines the name of the C++ class implementing the wrapper for this
Datatypes for the IOs are inheriting from `CGStaticType`.
Currently there are 3 classes defined:
Currently there are 3 classes defined in the project:
* `CType` for the standard CMSIS-DSP types
* `CType` for the standard CMSIS-DSP types like `q15_t`, `float32_t` ...
* `CStructType` for a C struct
* `PythonClassType` to create structured datatype for the Python scheduler
@ -104,7 +118,7 @@ def __init__(self,name,size_in_bytes):
```
* `name` is the name of the C struct
* `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 including padding.
* `size_in_bytes` is the size of the C struct. It should take into account padding. It is used when the compute graph memory optimization is used since size of the datatype is needed.
## PythonClassType
@ -125,9 +139,17 @@ Most CMSIS-DSP functions have no state. The compute graph framework is providing
This feature is relying on the nodes:
* `Unary`
* To use an unary operator like `negate`, `inverse` ...
* `Binary`
* To use a binary operator like `add`, `mul` ...
* `Dsp`
* Should detect if the CMSIS-DSP operator is unary or binary and use the datatype to compute the name of the function. In practice, only a subset of CMSIS-DSP function is supported so you should use `Unary` or `Binary` nodes
* `Constant`
* Special node to be used **only** with function nodes when some arguments cannot be connected to a FIFO. For instance, with `arm_scale_f32` the scaling factor is a scalar value and a FIFO cannot be connected to this argument. The function is a binary operator but between a stream and a scalar.
All of this is explained in detail in the [simple example with CMSIS-DSP](../examples/simpledsp/README.md).

@ -1,4 +1,4 @@
# API of the Graph Class
# Adding nodes to the graph
## Creating a connection
@ -13,13 +13,14 @@ Typically this method is used as:
```python
the_graph = Graph()
# Connect the source output to the processing node input
# Connect the source output to the processing node input and add this directed
# edge to the object the_graph
the_graph.connect(src.o,processing.i)
```
There are two optional arguments:
There are two optional arguments for the `connect` function:
* `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>`
* `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). 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`).
```python
@ -55,3 +56,7 @@ Class used for FIFO by default. Can also be customized for each connection (`con
Prefix used to generate the duplicate node classes like `Duplicate2`, `Duplicate3` ...
Those nodes are inserted automatically to implement one-to-many connections.
If you need to connect an output to more than 3 nodes, you'll have to create the `Duplicate` nodes.

@ -1,24 +1,28 @@
# Python API
Python APIs to describe the nodes and graph and generate the C++, Python or Graphviz code.
When you describe a graph and generate a scheduler there are 4 mandatory steps and one optional one:
1. ## [Graph class](Graph.md)
* Describing the nodes
* Adding the nodes to the graph
* Computing the schedule
* Generating the C++ and/or Python scheduler implementation
* Optional : Generating a graphviz `.dot` file with the graphical representation of the graph
2. ## [Generic, function nodes and datatypes](Generic.md)
1. ## [Description of the nodes](Generic.md)
3. ## Scheduler
2. ## [Adding nodes to the graph](Graph.md)
1. ### [Schedule computation](SchedOptions.md)
3. ## [Schedule computation](SchedOptions.md)
2. ### Code generation
4. ## Code generation
1. #### [C++ Code generation](CCodeGen.md)
1. #### [C++ Code generation](CCodeGen.md)
2. #### [Python code generation](PythonGen.md)
2. #### [Python code generation](PythonGen.md)
3. #### [Graphviz representation](GraphvizGen.md)
4. #### [Common options](CodegenOptions.md)
3. #### [Graphviz representation](GraphvizGen.md)
4. #### [Common options](CodegenOptions.md)

@ -1,5 +1,9 @@
# Python Nodes and classes
Python implementation of the nodes to be run from a Python scheduler.
You don't need this if you're only working with C++ schedulers.
(DOCUMENTATION TO BE WRITTEN)
## Mandatory classes

Loading…
Cancel
Save