Skip to content

Commit 3a04f81

Browse files
Improvement to Python wrapper
Some small changes to Compute graph API to define structured datatype. Some small changes to take into account google colab new version numbers for the packages.
1 parent d760b35 commit 3a04f81

File tree

21 files changed

+120
-60
lines changed

21 files changed

+120
-60
lines changed

ComputeGraph/documentation/Generic.md

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Generic and functions bodes
1+
# Generic and functions nodes
22

33
The generic and function nodes are the basic nodes that you use to create other kind of nodes in the graph.
44

@@ -16,7 +16,7 @@ There are 3 other classes that can be used to create new nodes from functions:
1616
* `Binary`
1717
* `Dsp`
1818

19-
## Generic Nodes
19+
# Generic Nodes
2020

2121
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.
2222

@@ -38,7 +38,7 @@ class ProcessingNode(GenericNode):
3838

3939
See the [simple](../examples/simple/README.md) example for more explanation about how to define a new node.
4040

41-
### Methods
41+
## Methods
4242

4343
The constructor of the node is using the `addInput` and/or `addOutput` to define new IOs.
4444

@@ -66,16 +66,17 @@ def typeName(self):
6666

6767
This method defines the name of the C++ class implementing the wrapper for this node.
6868

69-
### Datatypes
69+
# Datatypes
7070

7171
Datatypes for the IOs are inheriting from `CGStaticType`.
7272

73-
Currently there are two classes defined:
73+
Currently there are 3 classes defined:
7474

7575
* `CType` for the standard CMSIS-DSP types
7676
* `CStructType` for a C struct
77+
* `PythonClassType` to create structured datatype for the Python scheduler
7778

78-
#### CType
79+
## CType
7980

8081
You create such a type with `CType(id)` where `id` is one of the constant coming from the Python wrapper:
8182

@@ -94,25 +95,28 @@ You create such a type with `CType(id)` where `id` is one of the constant coming
9495

9596
For instance, to define a `float32_t` type for an IO you can use `CType(F32)`
9697

97-
#### CStructType
98+
## CStructType
9899

99100
The constructor has the following definition
100101

101102
```python
102-
def __init__(self,name,python_name,size_in_bytes):
103+
def __init__(self,name,size_in_bytes):
103104
```
104105

105106
* `name` is the name of the C struct
106-
* `python_name` is the name of the Python class implementing this type (when you generate a Python schedule)
107-
* `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.
107+
* `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.
108108

109-
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.
109+
## PythonClassType
110110

111-
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.
111+
```python
112+
def __init__(self,python_name)
113+
```
114+
115+
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.
112116

113-
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.
117+
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 and they should be scalar values.
114118

115-
## Function and constant nodes
119+
# Function and constant nodes
116120

117121
A Compute graph C++ wrapper is useful when the software components you use have a state that needs to be initialized in the C++ constructor, and preserved between successive calls to the `run` method of the wrapper.
118122

ComputeGraph/documentation/PythonAPI.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Python APIs to describe the nodes and graph and generate the C++, Python or Grap
44

55
1. ## [Graph class](Graph.md)
66

7-
2. ## [Generic and function nodes](Generic.md)
7+
2. ## [Generic, function nodes and datatypes](Generic.md)
88

99
3. ## Scheduler
1010

ComputeGraph/examples/eventrecorder/main.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
#include CMSIS_device_header
1010
#include "cmsis_os2.h"
1111

12+
#if defined(RTE_Compiler_EventRecorder)
13+
#include "EventRecorder.h"
14+
#endif
1215

1316
void app_main (void *argument)
1417
{

ComputeGraph/examples/example3/AppNodes.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ using namespace std;
3232
#include <cstdio>
3333
#include "arm_math.h"
3434

35+
#include "cg_status.h"
36+
3537
#include "host/FileSink.h"
3638
#include "host/FileSource.h"
3739
#include "CFFT.h"

ComputeGraph/examples/example8/README.md

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,15 @@ This example is illustrating :
1111

1212
It is possible to use a custom datatype:
1313

14+
For the C++ version of the scheduler it would be:
15+
1416
```python
15-
complexType=CStructType("complex","MyComplex",8)
17+
complexType=CStructType("MyComplex",8)
1618
```
1719

18-
This is defining a new datatype that is mapped to the type `complex` in C/C++ and the class `MyComplex` in Python. The last argument is the size in bytes of the struct in C.
20+
This is defining a new datatype that is mapped to the type `complex` in C/C++.
21+
22+
The last argument is the size in bytes of the struct in C.
1923

2024
The type complex may be defined with:
2125

@@ -26,6 +30,15 @@ typedef struct {
2630
} complex;
2731
```
2832

33+
For the Python version of the scheduler:
34+
35+
```python
36+
complexType=PythonClassType("MyComplex")
37+
```
38+
39+
The class `MyComplex` is used in Python.
40+
41+
2942
**Note that:**
3043

3144
- The value **must have** value semantic in C/C++. So avoid classes

ComputeGraph/examples/example8/appnodes.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@
2323
# See the License for the specific language governing permissions and
2424
# limitations under the License.
2525
############################################
26-
from cmsisdsp.cg.static.nodes.simu import *
26+
from cmsisdsp.cg.nodes.simu import *
2727
from custom import *
28-
from cmsisdsp.cg.static.nodes.Duplicate import *
28+
from cmsisdsp.cg.nodes.Duplicate import *
2929

3030
class Sink(GenericSink):
3131
def __init__(self,inputSize,fifoin):

ComputeGraph/examples/example8/graph.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,13 @@ def typeName(self):
4242
# Modify the fields of the objects, or create a totally new
4343
# object.
4444

45-
complexType=CStructType("complex","MyComplex",8)
45+
GEN_PYTHON = False
46+
47+
48+
if GEN_PYTHON:
49+
complexType=PythonClassType("MyComplex")
50+
else:
51+
complexType=CStructType("complex",8)
4652

4753
src=Source("source",complexType,5)
4854
b=ProcessingNode("filter",complexType,7,5)
@@ -71,7 +77,6 @@ def typeName(self):
7177

7278
g.connect(b.ob,nd.i)
7379

74-
GEN_PYTHON = False
7580

7681
print("Generate graphviz and code")
7782

ComputeGraph/examples/example8/sched.py

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
import numpy as np
1212
import cmsisdsp as dsp
13-
from cmsisdsp.cg.static.nodes.simu import *
13+
from cmsisdsp.cg.nodes.simu import *
1414
from appnodes import *
1515
from custom import *
1616

@@ -102,22 +102,19 @@ def scheduler(someVariable):
102102
cgStaticError = dup0.run()
103103
if cgStaticError < 0:
104104
break
105-
cgStaticError = sc.run()
105+
cgStaticError = sa.run()
106106
if cgStaticError < 0:
107107
break
108108
cgStaticError = sb.run()
109109
if cgStaticError < 0:
110110
break
111-
cgStaticError = sa.run()
111+
cgStaticError = sc.run()
112112
if cgStaticError < 0:
113113
break
114114
cgStaticError = source.run()
115115
if cgStaticError < 0:
116116
break
117117
cgStaticError = filter.run()
118-
if cgStaticError < 0:
119-
break
120-
cgStaticError = source.run()
121118
if cgStaticError < 0:
122119
break
123120
cgStaticError = sd.run()
@@ -126,13 +123,16 @@ def scheduler(someVariable):
126123
cgStaticError = dup0.run()
127124
if cgStaticError < 0:
128125
break
129-
cgStaticError = sc.run()
126+
cgStaticError = sa.run()
130127
if cgStaticError < 0:
131128
break
132129
cgStaticError = sb.run()
133130
if cgStaticError < 0:
134131
break
135-
cgStaticError = sa.run()
132+
cgStaticError = sc.run()
133+
if cgStaticError < 0:
134+
break
135+
cgStaticError = source.run()
136136
if cgStaticError < 0:
137137
break
138138
cgStaticError = source.run()
@@ -147,22 +147,19 @@ def scheduler(someVariable):
147147
cgStaticError = dup0.run()
148148
if cgStaticError < 0:
149149
break
150-
cgStaticError = sc.run()
150+
cgStaticError = sa.run()
151151
if cgStaticError < 0:
152152
break
153153
cgStaticError = sb.run()
154154
if cgStaticError < 0:
155155
break
156-
cgStaticError = sa.run()
156+
cgStaticError = sc.run()
157157
if cgStaticError < 0:
158158
break
159159
cgStaticError = source.run()
160160
if cgStaticError < 0:
161161
break
162162
cgStaticError = filter.run()
163-
if cgStaticError < 0:
164-
break
165-
cgStaticError = source.run()
166163
if cgStaticError < 0:
167164
break
168165
cgStaticError = sd.run()
@@ -171,13 +168,16 @@ def scheduler(someVariable):
171168
cgStaticError = dup0.run()
172169
if cgStaticError < 0:
173170
break
174-
cgStaticError = sc.run()
171+
cgStaticError = sa.run()
175172
if cgStaticError < 0:
176173
break
177174
cgStaticError = sb.run()
178175
if cgStaticError < 0:
179176
break
180-
cgStaticError = sa.run()
177+
cgStaticError = sc.run()
178+
if cgStaticError < 0:
179+
break
180+
cgStaticError = source.run()
181181
if cgStaticError < 0:
182182
break
183183
cgStaticError = filter.run()
@@ -189,13 +189,13 @@ def scheduler(someVariable):
189189
cgStaticError = dup0.run()
190190
if cgStaticError < 0:
191191
break
192-
cgStaticError = sc.run()
192+
cgStaticError = sa.run()
193193
if cgStaticError < 0:
194194
break
195195
cgStaticError = sb.run()
196196
if cgStaticError < 0:
197197
break
198-
cgStaticError = sa.run()
198+
cgStaticError = sc.run()
199199
if cgStaticError < 0:
200200
break
201201

ComputeGraph/examples/example8/test.dot

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,38 +64,38 @@ source [label=<
6464

6565

6666

67-
source:i -> filter:i [label="complex(11)"
67+
source:i -> filter:i [label="MyComplex(11)"
6868
,headlabel=<<TABLE BORDER="0" CELLPADDING="2"><TR><TD><FONT COLOR="blue" POINT-SIZE="12.0" >7</FONT>
6969
</TD></TR></TABLE>>
7070
,taillabel=<<TABLE BORDER="0" CELLPADDING="2"><TR><TD><FONT COLOR="blue" POINT-SIZE="12.0" >5</FONT>
7171
</TD></TR></TABLE>>]
7272

73-
filter:ob -> sd:i [label="complex(5)"
73+
filter:ob -> sd:i [label="MyComplex(5)"
7474
,headlabel=<<TABLE BORDER="0" CELLPADDING="2"><TR><TD><FONT COLOR="blue" POINT-SIZE="12.0" >5</FONT>
7575
</TD></TR></TABLE>>
7676
,taillabel=<<TABLE BORDER="0" CELLPADDING="2"><TR><TD><FONT COLOR="blue" POINT-SIZE="12.0" >5</FONT>
7777
</TD></TR></TABLE>>]
7878

7979
filter:oa ->
80-
dup0 [label="complex(5)"
80+
dup0 [label="MyComplex(5)"
8181

8282
,taillabel=<<TABLE BORDER="0" CELLPADDING="2"><TR><TD><FONT COLOR="blue" POINT-SIZE="12.0" >5</FONT>
8383
</TD></TR></TABLE>>]
8484

8585

86-
dup0 -> sa:i [label="complex(5)"
86+
dup0 -> sa:i [label="MyComplex(5)"
8787
,headlabel=<<TABLE BORDER="0" CELLPADDING="2"><TR><TD><FONT COLOR="blue" POINT-SIZE="12.0" >5</FONT>
8888
</TD></TR></TABLE>>
8989
]
9090

9191

92-
dup0 -> sb:i [label="complex(5)"
92+
dup0 -> sb:i [label="MyComplex(5)"
9393
,headlabel=<<TABLE BORDER="0" CELLPADDING="2"><TR><TD><FONT COLOR="blue" POINT-SIZE="12.0" >5</FONT>
9494
</TD></TR></TABLE>>
9595
]
9696

9797

98-
dup0 -> sc:i [label="complex(5)"
98+
dup0 -> sc:i [label="MyComplex(5)"
9999
,headlabel=<<TABLE BORDER="0" CELLPADDING="2"><TR><TD><FONT COLOR="blue" POINT-SIZE="12.0" >5</FONT>
100100
</TD></TR></TABLE>>
101101
]

ComputeGraph/examples/simple/generated/scheduler.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ The support classes and code is covered by CMSIS-DSP license.
1313
#include "AppNodes.h"
1414
#include "scheduler.h"
1515

16+
1617
#if !defined(CHECKERROR)
1718
#define CHECKERROR if (cgStaticError < 0) \
1819
{\

ComputeGraph/examples/simple/generated/scheduler.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ extern "C"
1616
#endif
1717

1818

19+
1920
extern uint32_t scheduler(int *error);
2021

2122
#ifdef __cplusplus

ComputeGraph/tests/EventRecorder.log

48 Bytes
Binary file not shown.

ComputeGraph/tests/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Some tests to validate some parts of the Compute graph. They all rely on the CMS
88
* Create a complex graph containing all classes defined in `GenericNodes.h` (synchronous mode). Used to test that it builds and that there are no errors in the templates
99
* `cbuild "cprj\syncgraph.CommandLine+VHT-Corstone-300.cprj" `
1010
* `create_async.py`
11-
* Create a complex graph containing all classes defined in `GenericNodes.h` (ssynchronous mode). Used to test that it builds and that there are no errors in the templates
11+
* Create a complex graph containing all classes defined in `GenericNodes.h` (asynchronous mode). Used to test that it builds and that there are no errors in the templates
1212
* `cbuild "cprj\asyncgraph.CommandLine+VHT-Corstone-300.cprj" `
1313
* `create_fifobench_sync.py`
1414
* Create a graph with FFT / IFFT : the graph is decomposing a signal and rebuilding it. It is used to test the performance of different FIFOs implementations (synchronous mode)

ComputeGraph/tests/main_fifobench.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,11 @@ int main(void)
113113
cycleMeasurementStart();
114114
nbSched=scheduler(&error,input_buffer,output_buffer);
115115
cycleMeasurementStop();
116-
int32_t cycles = getCycles() - overhead;
116+
int32_t cycles = (getCycles() - overhead)/nbSched;
117117

118118
printf("Number of schedule iterations = %d\n\r",nbSched);
119119
printf("Error code = %d\n\r",error);
120-
printf("Cycles = %d\n\r",cycles);
120+
printf("Cycles per iteration = %d\n\r",cycles);
121121

122122

123123
#if defined(COMMAND_LINE)

PythonWrapper/build_linux/clean.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ rm -f CMakeCache.txt
22
rm -rf CMakeFiles
33
rm -f Makefile
44
rm -rf bin_dsp
5-
rm -f cmake_install.cmake
5+
rm -f cmake_install.cmake
6+
rm -rf dist

PythonWrapper/cmsisdsp_pkg/src/cmsisdsp_module.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,13 @@
2727
*/
2828
#ifndef CMSISMODULE_H
2929
#define CMSISMODULE_H
30-
#define NPY_NO_DEPRECATED_API NPY_1_21_API_VERSION
30+
#define NPY_NO_DEPRECATED_API NPY_1_22_API_VERSION
3131

3232
#include <numpy/numpyconfig.h>
3333

3434
// API version used on google colab
35-
#if (NPY_API_VERSION != 0x0000000E )
35+
// List on https://github.com/numpy/numpy/blob/main/numpy/core/include/numpy/numpyconfig.h
36+
#if (NPY_API_VERSION != 0x0000000F )
3637
#error("Error building with wrong NumPy API version")
3738
#endif
3839

0 commit comments

Comments
 (0)