diff --git a/ComputeGraph/README.md b/ComputeGraph/README.md index 465f8b45..8e4c25a6 100644 --- a/ComputeGraph/README.md +++ b/ComputeGraph/README.md @@ -128,11 +128,11 @@ If you have declared new nodes in `graph.py` then you'll need to provide an impl More details and explanations can be found in the documentation for the examples. The first example is a deep dive giving all the details about the Python and C++ sides of the tool: -* [Example 1 : how to describe a simple graph](documentation/example1.md) -* [Example 2 : More complex example with delay and CMSIS-DSP](documentation/example2.md) -* [Example 3 : Working example with CMSIS-DSP and FFT](documentation/example3.md) -* [Example 4 : Same as example 3 but with the CMSIS-DSP Python wrapper](documentation/example4.md) -* [Example 10 : The asynchronous mode](documentation/example10.md) +* [Example 1 : how to describe a simple graph](documentation/examples/example1/README.md) +* [Example 2 : More complex example with delay and CMSIS-DSP](documentation/examples/example2/README.md) +* [Example 3 : Working example with CMSIS-DSP and FFT](documentation/examples/example3/README.md) +* [Example 4 : Same as example 3 but with the CMSIS-DSP Python wrapper](documentation/examples/example4/README.md) +* [Example 10 : The asynchronous mode](documentation/examples/example10/README.md) Examples 5 and 6 are showing how to use the CMSIS-DSP MFCC with a synchronous data flow. diff --git a/ComputeGraph/documentation/Options.md b/ComputeGraph/documentation/Options.md new file mode 100644 index 00000000..04893bcb --- /dev/null +++ b/ComputeGraph/documentation/Options.md @@ -0,0 +1 @@ +Options diff --git a/ComputeGraph/examples/CMakeLists.txt b/ComputeGraph/examples/CMakeLists.txt index bf876a19..7683e7b4 100644 --- a/ComputeGraph/examples/CMakeLists.txt +++ b/ComputeGraph/examples/CMakeLists.txt @@ -5,22 +5,22 @@ set(Python_FIND_REGISTRY "LAST") find_package (Python COMPONENTS Interpreter) -function(sdf TARGET) +function(sdf TARGET SCRIPT DOTNAME) if (DOT) add_custom_command(TARGET ${TARGET} PRE_BUILD - BYPRODUCTS ${CMAKE_CURRENT_SOURCE_DIR}/test.pdf - COMMAND ${DOT} -Tpdf -o ${CMAKE_CURRENT_SOURCE_DIR}/test.pdf ${CMAKE_CURRENT_SOURCE_DIR}/test.dot + BYPRODUCTS ${CMAKE_CURRENT_SOURCE_DIR}/${DOTNAME}.pdf + COMMAND ${DOT} -Tpdf -o ${CMAKE_CURRENT_SOURCE_DIR}/${DOTNAME}.pdf ${CMAKE_CURRENT_SOURCE_DIR}/${DOTNAME}.dot WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/test.dot + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${DOTNAME}.dot VERBATIM ) endif() add_custom_command(OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/generated/scheduler.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/test.dot - COMMAND ${Python_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/graph.py + ${CMAKE_CURRENT_SOURCE_DIR}/${DOTNAME}.dot + COMMAND ${Python_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/${SCRIPT} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/graph.py + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${SCRIPT} VERBATIM ) target_sources(${TARGET} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/generated/scheduler.cpp) @@ -73,6 +73,7 @@ add_subdirectory(example6 bin_example6) add_subdirectory(example8 bin_example8) add_subdirectory(example9 bin_example9) add_subdirectory(example10 bin_example10) +add_subdirectory(simple bin_simple) # Python examples add_subdirectory(example4 bin_example4) diff --git a/ComputeGraph/examples/example1/CMakeLists.txt b/ComputeGraph/examples/example1/CMakeLists.txt index 6a37dd49..5920cc73 100644 --- a/ComputeGraph/examples/example1/CMakeLists.txt +++ b/ComputeGraph/examples/example1/CMakeLists.txt @@ -6,7 +6,7 @@ project(Example1) add_executable(example1 main.cpp) -sdf(example1) +sdf(example1 graph.py test) add_sdf_dir(example1) target_include_directories(example1 PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/ComputeGraph/documentation/example1.md b/ComputeGraph/examples/example1/README.md similarity index 99% rename from ComputeGraph/documentation/example1.md rename to ComputeGraph/examples/example1/README.md index f677b17e..cf3443a6 100644 --- a/ComputeGraph/documentation/example1.md +++ b/ComputeGraph/examples/example1/README.md @@ -2,7 +2,7 @@ In this example we will see how to describe the following graph: -graph1 +graph1 The framework is coming with some default blocks. But for this example, we will create new blocks. The blocks that you to create need must be described with a simple Python class and a corresponding simple C++ class. diff --git a/ComputeGraph/documentation/graph1.PNG b/ComputeGraph/examples/example1/docassets/graph1.PNG similarity index 100% rename from ComputeGraph/documentation/graph1.PNG rename to ComputeGraph/examples/example1/docassets/graph1.PNG diff --git a/ComputeGraph/examples/example10/CMakeLists.txt b/ComputeGraph/examples/example10/CMakeLists.txt index 71e9157f..e138c3a2 100644 --- a/ComputeGraph/examples/example10/CMakeLists.txt +++ b/ComputeGraph/examples/example10/CMakeLists.txt @@ -6,7 +6,7 @@ project(Example10) add_executable(example10 main.cpp) -sdf(example10) +sdf(example10 graph.py test) add_sdf_dir(example10) target_include_directories(example10 PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/ComputeGraph/documentation/example10.md b/ComputeGraph/examples/example10/README.md similarity index 93% rename from ComputeGraph/documentation/example10.md rename to ComputeGraph/examples/example10/README.md index 015351d6..63addf96 100644 --- a/ComputeGraph/documentation/example10.md +++ b/ComputeGraph/examples/example10/README.md @@ -12,7 +12,7 @@ The FIFO sizes are doubled with: The graph implemented in this example is: -![graph10](graph10.png) +![graph10](docassets/graph10.png) There is a global iteration count corresponding to one execution of the schedule. diff --git a/ComputeGraph/documentation/graph10.png b/ComputeGraph/examples/example10/docassets/graph10.png similarity index 100% rename from ComputeGraph/documentation/graph10.png rename to ComputeGraph/examples/example10/docassets/graph10.png diff --git a/ComputeGraph/examples/example2/CMakeLists.txt b/ComputeGraph/examples/example2/CMakeLists.txt index 8f9fb524..d5167dd5 100644 --- a/ComputeGraph/examples/example2/CMakeLists.txt +++ b/ComputeGraph/examples/example2/CMakeLists.txt @@ -6,7 +6,7 @@ project(Example2) add_executable(example2 main.cpp) -sdf(example2) +sdf(example2 graph.py test) add_sdf_dir(example2) target_include_directories(example2 PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/ComputeGraph/documentation/example2.md b/ComputeGraph/examples/example2/README.md similarity index 99% rename from ComputeGraph/documentation/example2.md rename to ComputeGraph/examples/example2/README.md index 60a01830..a178c26a 100644 --- a/ComputeGraph/documentation/example2.md +++ b/ComputeGraph/examples/example2/README.md @@ -10,7 +10,7 @@ In this example. we are just analyzing a much more complex example to see some n The graph is: -![graph2](graph2.PNG) +![graph2](docassets/graph2.PNG) It is much more complex: diff --git a/ComputeGraph/documentation/graph2.PNG b/ComputeGraph/examples/example2/docassets/graph2.PNG similarity index 100% rename from ComputeGraph/documentation/graph2.PNG rename to ComputeGraph/examples/example2/docassets/graph2.PNG diff --git a/ComputeGraph/examples/example3/CMakeLists.txt b/ComputeGraph/examples/example3/CMakeLists.txt index 5b955c2b..9c647583 100644 --- a/ComputeGraph/examples/example3/CMakeLists.txt +++ b/ComputeGraph/examples/example3/CMakeLists.txt @@ -6,7 +6,7 @@ project(Example3) add_executable(example3 main.cpp custom.cpp) -sdf(example3) +sdf(example3 graph.py test) add_sdf_dir(example3) target_include_directories(example3 PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/ComputeGraph/documentation/example3.md b/ComputeGraph/examples/example3/README.md similarity index 99% rename from ComputeGraph/documentation/example3.md rename to ComputeGraph/examples/example3/README.md index 84293c69..fe3b7b79 100644 --- a/ComputeGraph/documentation/example3.md +++ b/ComputeGraph/examples/example3/README.md @@ -2,7 +2,7 @@ This example is implementing a working example with FFT. The graph is: -![graph3](graph3.PNG) +![graph3](docassets/graph3.PNG) The example is: diff --git a/ComputeGraph/documentation/graph3.PNG b/ComputeGraph/examples/example3/docassets/graph3.PNG similarity index 100% rename from ComputeGraph/documentation/graph3.PNG rename to ComputeGraph/examples/example3/docassets/graph3.PNG diff --git a/ComputeGraph/documentation/example4.md b/ComputeGraph/examples/example4/README.md similarity index 100% rename from ComputeGraph/documentation/example4.md rename to ComputeGraph/examples/example4/README.md diff --git a/ComputeGraph/examples/example6/CMakeLists.txt b/ComputeGraph/examples/example6/CMakeLists.txt index 1591cd23..9d53513a 100644 --- a/ComputeGraph/examples/example6/CMakeLists.txt +++ b/ComputeGraph/examples/example6/CMakeLists.txt @@ -6,7 +6,7 @@ project(Example6) add_executable(example6 main.cpp mfccConfigData.c) -sdf(example6) +sdf(example6 graph.py test) add_sdf_dir(example6) target_include_directories(example6 PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/ComputeGraph/examples/example8/CMakeLists.txt b/ComputeGraph/examples/example8/CMakeLists.txt index 83f7c875..8a9351ee 100644 --- a/ComputeGraph/examples/example8/CMakeLists.txt +++ b/ComputeGraph/examples/example8/CMakeLists.txt @@ -6,7 +6,7 @@ project(Example8) add_executable(example8 main.cpp) -sdf(example8) +sdf(example8 graph.py test) add_sdf_dir(example8) target_include_directories(example8 PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/ComputeGraph/examples/example9/CMakeLists.txt b/ComputeGraph/examples/example9/CMakeLists.txt index 85d8e90b..25d61df2 100644 --- a/ComputeGraph/examples/example9/CMakeLists.txt +++ b/ComputeGraph/examples/example9/CMakeLists.txt @@ -6,7 +6,7 @@ project(Example9) add_executable(example9 main.cpp) -sdf(example9) +sdf(example9 graph.py test) add_sdf_dir(example9) target_include_directories(example9 PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/ComputeGraph/examples/simple/AppNodes.h b/ComputeGraph/examples/simple/AppNodes.h new file mode 100644 index 00000000..f5f65c23 --- /dev/null +++ b/ComputeGraph/examples/simple/AppNodes.h @@ -0,0 +1,128 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: AppNodes.h + * Description: Application nodes for Example 1 + * + * $Date: 29 July 2021 + * $Revision: V1.10.0 + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ +/* + * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef _APPNODES_H_ +#define _APPNODES_H_ + +#include + +template +class Sink: public GenericSink +{ +public: + Sink(FIFOBase &src):GenericSink(src){}; + + int prepareForRunning() final + { + if (this->willUnderflow()) + { + return(CG_SKIP_EXECUTION_ID_CODE); // Skip execution + } + + return(0); + }; + + int run() final + { + IN *b=this->getReadBuffer(); + printf("Sink\n"); + for(int i=0;i +class Source: public GenericSource +{ +public: + Source(FIFOBase &dst):GenericSource(dst){}; + + int prepareForRunning() final + { + if (this->willOverflow()) + { + return(CG_SKIP_EXECUTION_ID_CODE); // Skip execution + } + + return(0); + }; + + int run() final{ + OUT *b=this->getWriteBuffer(); + + printf("Source\n"); + for(int i=0;i +class ProcessingNode; + + +template +class ProcessingNode: + public GenericNode +{ +public: + ProcessingNode(FIFOBase &src, + FIFOBase &dst):GenericNode(src,dst){}; + + int prepareForRunning() final + { + if (this->willOverflow() || + this->willUnderflow()) + { + return(CG_SKIP_EXECUTION_ID_CODE); // Skip execution + } + + return(0); + }; + + int run() final{ + printf("ProcessingNode\n"); + IN *a=this->getReadBuffer(); + IN *b=this->getWriteBuffer(); + for(int i=0;i +class Source; +``` + +The previous line is defining a new class template with two arguments: + +* A datatype `OUT` +* The number of samples `outputSize` + +This template can be used to implement different kind of `Source` classes : with different datatypes or number of samples. We can also (when it makes sense) define a `Source` implementation that can work with any datatype and any number of samples. + +You don't need to be knowledgeable in C++ template to start using them in the context of the compute graph. They are just here to define the plumbing. + +Now, when you have declared a C++ template, you need to implement it. There are two ways to do it: + +* You can define a generic implementation +* And/or you can define specialized implementations for specific datatypes or sizes. + +For the `Source` we have defined a generic implementation so we need (like in Python case) to inherit from `GenericSource`: + +```C++ +template +class Source: GenericSource +``` + +Then, like in the Python case, we need to define a constructor. But contrary to the Python case, here we are defining an implementation. The constructor is not defining the IOs. The IOs are coming from the `GenericSource` template and its arguments. + +```C++ +public: + Source(FIFOBase &dst):public GenericSource(dst){}; +``` + +Our `Source` has only one IO : the output. It needs the FIFO for this output. The first argument, `dst`, of the `Source` constructor is the FIFO. This FIFO is coming from the scheduler. + +We also need to initialize the `GenericSource` parent since we are inheriting from it. `GenericSource` constructor is called with the `FIFO` argument `dst`. + +The constructor is here doing nothing more than initializing the parent and the implementation is empty `{}` + + Then, the implementation needs to provide an entry point to be usable from the scheduler. It is the `run` function. As said before, since the algorithm is very simple it has been implemented in `run`. In general, `run` is just calling an external function with the buffers coming from the FIFOs. + +```C++ +int run() final { + OUT *b=this->getWriteBuffer(); + + printf("Source\n"); + for(int i=0;igetWriteBuffer(); +``` + +We get a pointer to be able to write in the output FIFO. This pointer has the datatype OUT coming from the template so can be anything. + +The code in the loop is casting an `int` (the loop index) into the `OUT` datatype. If it is not possible it won't typecheck and build. + +So, although we have not provided a specific implementation of the template, this template can only work with specific `OUT` datatypes. + +The return of the function is to inform the scheduler that no error occurred. In synchronous mode, errors (like underflow or overflow) cannot occur due to the scheduling but only because of a broken real time. So any error returned by a node will stop the scheduling. + +### The processing node + +It is similar but now we have one input and one output. The template is: + +```C++ +template +class ProcessingNode; +``` + +In this example we have decided to implement only a specific version of the processing node. We want to enforce the constraint that the output datatype must be equal to the input datatype and that the number of sample produced must be equal to the number of sample consumed. If it is not the case, it won't type check and the solution won't build. + +Remember from the Python definition that this constraint has not been enforced in the Python description of the processing node. + +Here is how we implement a specialized version of the template. + +First we define the arguments of the template. It is no more generic. We have to give all the arguments: + +```C++ +class ProcessingNode +``` + +This enforces that the `OUT` datatype is equal to the `IN` datatype since `IN` is used in both arguments. + +It also envorces that the input and output sizes are the same since `inputOutputSize` is used in the two arguments for the size. + +Since the arguments of the template are still not fully specified and there is some remaining degree of freedom, we need to continue to define some template parameters: + +```C++ +template +class ProcessingNode +``` + +And finally, like before, we inherit from `GenericNode` using the same template arguments: + +```C++ +template +class ProcessingNode: + public GenericNode +``` + +To be compared with the generic implementation: + +```C++ +template +class ProcessingNode: + public GenericNode +``` + +It is possible to have several specialization of the same class. + +One could also have another specialization like: + +```C++ +template +class ProcessingNode: + public GenericNode +``` + +Just working `q15_t` datatype + +The `run` function of the processing node has access to `getReadBuffer` and `getWriteBuffer` to access to the FIFO buffers. + +### The sink + +The definition of the `Sink` should be clear now: + +```C++ +template +class Sink: public GenericSink +{ +public: + Sink(FIFOBase &src):GenericSink(src){}; +``` + +## How to call the C++ scheduler + +The API to the scheduler is: + +```C +extern uint32_t scheduler(int *error); +``` + +It is a C API that can be used from C code. + +In case of error, the function is returning : + +* the number of schedule iterations computed since +* an error code. + +It is possible, from the Python script, to add arguments to this API when there is the need to pass additional information to the nodes. + +## How to build and run the example + +There is a very simple `Makefile` in the folder. It is for `MSVC` compiler on Windows but can be easily adapted. There are only 2 files to compile: + +* `generated/scheduler.cpp` +* `main.c` + +The directory to use for headers are: + +* `generated` +* `../../cg/src` +* `.` the current directory + +The headers required by the software are: + +* `generated/scheduler.h` + + * The is the C API to the scheduler function + +* `AppNodes.h` + + * `AppNodes.h` is where the implementation of the nodes is defined. This file could also just include nodes from a standard library. + +* `custom.h` + + * This is the first include in the `scheduler.cpp` and this file can contain whatever is needed or just be empty + * In this example, the datatype `float32_t` is defined in `custom.h` so that we don't needed to build the CMSIS-DSP for such a simple example + +* `GenericNodes.h` + + * It is coming from the `../../cg/src` folder. + * It provides the basic definitions needed by the framework like `GenericNode`, `GenericSink`,`GenericSource`, `FIFO` ... + + + + + diff --git a/ComputeGraph/examples/simple/create.py b/ComputeGraph/examples/simple/create.py new file mode 100644 index 00000000..a21923b9 --- /dev/null +++ b/ComputeGraph/examples/simple/create.py @@ -0,0 +1,31 @@ +# Include definition of the nodes +from nodes import * +# Include definition of the graph +from graph import * + +# Create a configuration object +conf=Configuration() +# The number of schedule iteration is limited to 1 +# to prevent the scheduling from running forever +# (which should be the case for a stream computation) +conf.debugLimit=1 +# Disable inclusion of CMSIS-DSP headers so that we don't have +# to recompile CMSIS-DSP for such a simple example +conf.CMSISDSP = False + +# Compute a static scheduling of the graph +# The size of FIFO is also computed +scheduling = the_graph.computeSchedule(config=conf) + +# Print some statistics about the compute schedule +# and the memory usage +print("Schedule length = %d" % scheduling.scheduleLength) +print("Memory usage %d bytes" % scheduling.memory) + +# Generate the C++ code for the static scheduler +scheduling.ccode("generated",conf) + +# Generate a graphviz representation of the graph +with open("simple.dot","w") as f: + scheduling.graphviz(f) + diff --git a/ComputeGraph/examples/simple/custom.h b/ComputeGraph/examples/simple/custom.h new file mode 100644 index 00000000..41b6c6ee --- /dev/null +++ b/ComputeGraph/examples/simple/custom.h @@ -0,0 +1,5 @@ +#ifndef _CUSTOM_H_ + +typedef float float32_t; + +#endif \ No newline at end of file diff --git a/ComputeGraph/examples/simple/docassets/simple.png b/ComputeGraph/examples/simple/docassets/simple.png new file mode 100644 index 00000000..eaa33fb4 Binary files /dev/null and b/ComputeGraph/examples/simple/docassets/simple.png differ diff --git a/ComputeGraph/examples/simple/generated/scheduler.cpp b/ComputeGraph/examples/simple/generated/scheduler.cpp new file mode 100644 index 00000000..139e2f96 --- /dev/null +++ b/ComputeGraph/examples/simple/generated/scheduler.cpp @@ -0,0 +1,170 @@ +/* + +Generated with CMSIS-DSP Compute Graph Scripts. +The generated code is not covered by CMSIS-DSP license. + +The support classes and code is covered by CMSIS-DSP license. + +*/ + + +#include "custom.h" +#include "GenericNodes.h" +#include "AppNodes.h" +#include "scheduler.h" + +#if !defined(CHECKERROR) +#define CHECKERROR if (cgStaticError < 0) \ + {\ + goto errorHandling;\ + } + +#endif + +#if !defined(CG_BEFORE_ITERATION) +#define CG_BEFORE_ITERATION +#endif + +#if !defined(CG_AFTER_ITERATION) +#define CG_AFTER_ITERATION +#endif + +#if !defined(CG_BEFORE_SCHEDULE) +#define CG_BEFORE_SCHEDULE +#endif + +#if !defined(CG_AFTER_SCHEDULE) +#define CG_AFTER_SCHEDULE +#endif + +#if !defined(CG_BEFORE_BUFFER) +#define CG_BEFORE_BUFFER +#endif + +#if !defined(CG_BEFORE_FIFO_BUFFERS) +#define CG_BEFORE_FIFO_BUFFERS +#endif + +#if !defined(CG_BEFORE_FIFO_INIT) +#define CG_BEFORE_FIFO_INIT +#endif + +#if !defined(CG_BEFORE_NODE_INIT) +#define CG_BEFORE_NODE_INIT +#endif + +#if !defined(CG_AFTER_INCLUDES) +#define CG_AFTER_INCLUDES +#endif + +#if !defined(CG_BEFORE_SCHEDULER_FUNCTION) +#define CG_BEFORE_SCHEDULER_FUNCTION +#endif + +#if !defined(CG_BEFORE_NODE_EXECUTION) +#define CG_BEFORE_NODE_EXECUTION +#endif + +#if !defined(CG_AFTER_NODE_EXECUTION) +#define CG_AFTER_NODE_EXECUTION +#endif + +CG_AFTER_INCLUDES + + +/* + +Description of the scheduling. + +*/ +static unsigned int schedule[19]= +{ +2,2,0,1,2,0,1,2,2,0,1,1,2,0,1,2,0,1,1, +}; + +CG_BEFORE_FIFO_BUFFERS +/*********** + +FIFO buffers + +************/ +#define FIFOSIZE0 11 +#define FIFOSIZE1 11 + +#define BUFFERSIZE1 11 +CG_BEFORE_BUFFER +float32_t buf1[BUFFERSIZE1]={0}; + +#define BUFFERSIZE2 11 +CG_BEFORE_BUFFER +float32_t buf2[BUFFERSIZE2]={0}; + + +CG_BEFORE_SCHEDULER_FUNCTION +uint32_t scheduler(int *error) +{ + int cgStaticError=0; + uint32_t nbSchedule=0; + int32_t debugCounter=1; + + CG_BEFORE_FIFO_INIT; + /* + Create FIFOs objects + */ + FIFO fifo0(buf1); + FIFO fifo1(buf2); + + CG_BEFORE_NODE_INIT; + /* + Create node objects + */ + ProcessingNode processing(fifo0,fifo1); + Sink sink(fifo1); + Source source(fifo0); + + /* Run several schedule iterations */ + CG_BEFORE_SCHEDULE; + while((cgStaticError==0) && (debugCounter > 0)) + { + /* Run a schedule iteration */ + CG_BEFORE_ITERATION; + for(unsigned long id=0 ; id < 19; id++) + { + CG_BEFORE_NODE_EXECUTION; + + switch(schedule[id]) + { + case 0: + { + cgStaticError = processing.run(); + } + break; + + case 1: + { + cgStaticError = sink.run(); + } + break; + + case 2: + { + cgStaticError = source.run(); + } + break; + + default: + break; + } + CG_AFTER_NODE_EXECUTION; + CHECKERROR; + } + debugCounter--; + CG_AFTER_ITERATION; + nbSchedule++; + } + +errorHandling: + CG_AFTER_SCHEDULE; + *error=cgStaticError; + return(nbSchedule); +} diff --git a/ComputeGraph/examples/simple/generated/scheduler.h b/ComputeGraph/examples/simple/generated/scheduler.h new file mode 100644 index 00000000..d98d9e63 --- /dev/null +++ b/ComputeGraph/examples/simple/generated/scheduler.h @@ -0,0 +1,26 @@ +/* + +Generated with CMSIS-DSP Compute Graph Scripts. +The generated code is not covered by CMSIS-DSP license. + +The support classes and code is covered by CMSIS-DSP license. + +*/ + +#ifndef _SCHEDULER_H_ +#define _SCHEDULER_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + + +extern uint32_t scheduler(int *error); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/ComputeGraph/examples/simple/graph.py b/ComputeGraph/examples/simple/graph.py new file mode 100644 index 00000000..ad116e11 --- /dev/null +++ b/ComputeGraph/examples/simple/graph.py @@ -0,0 +1,39 @@ +# Include definitions from the Python package to +# define datatype for the IOs and to have access to the +# Graph class +from cmsisdsp.cg.scheduler import * +# Include definition of the nodes +from nodes import * + +# Define the datatype we are using for all the IOs in this +# example +floatType=CType(F32) + +# Instantiate a Source node with a float datatype and +# working with packet of 5 samples (each execution of the +# source in the C code will generate 5 samples) +# "source" is the name of the C variable that will identify +# this node +src=Source("source",floatType,5) +# Instantiate a Processing node using a float data type for +# both the input and output. The number of samples consumed +# on the input and produced on the output is 7 each time +# the node is executed in the C code +# "processing" is the name of the C variable that will identify +# this node +processing=ProcessingNode("processing",floatType,7,7) +# Instantiate a Sink node with a float datatype and consuming +# 5 samples each time the node is executed in the C code +# "sink" is the name of the C variable that will identify +# this node +sink=Sink("sink",floatType,5) + +# Create a Graph object +the_graph = Graph() + +# Connect the source to the processing node +the_graph.connect(src.o,processing.i) +# Connect the processing node to the sink +the_graph.connect(processing.o,sink.i) + + diff --git a/ComputeGraph/examples/simple/main.cpp b/ComputeGraph/examples/simple/main.cpp new file mode 100644 index 00000000..a1fd4028 --- /dev/null +++ b/ComputeGraph/examples/simple/main.cpp @@ -0,0 +1,11 @@ +#include +#include +#include "scheduler.h" + +int main(int argc, char const *argv[]) +{ + int error; + printf("Start\n"); + uint32_t nbSched=scheduler(&error); + return 0; +} \ No newline at end of file diff --git a/ComputeGraph/examples/simple/main.obj b/ComputeGraph/examples/simple/main.obj new file mode 100644 index 00000000..05de417d Binary files /dev/null and b/ComputeGraph/examples/simple/main.obj differ diff --git a/ComputeGraph/examples/simple/nodes.py b/ComputeGraph/examples/simple/nodes.py new file mode 100644 index 00000000..6f5a5987 --- /dev/null +++ b/ComputeGraph/examples/simple/nodes.py @@ -0,0 +1,77 @@ +# Include definitions from the Python package +from cmsisdsp.cg.scheduler import GenericNode,GenericSink,GenericSource + +### Define new types of Nodes + +class ProcessingNode(GenericNode): + """ + Definition of a ProcessingNode for the graph + + Parameters + ---------- + name : str + Name of the C variable identifying this node + in the C code + theType : CGStaticType + The datatype for the input and output + inLength : int + The number of samples consumed by input + outLength : int + The number of samples produced on output + """ + 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): + """The name of the C++ class implementing this node""" + return "ProcessingNode" + +class Sink(GenericSink): + """ + Definition of a Sink node for the graph + + Parameters + ---------- + name : str + Name of the C variable identifying this node + in the C code + theType : CGStaticType + The datatype for the input + inLength : int + The number of samples consumed by input + """ + def __init__(self,name,theType,inLength): + GenericSink.__init__(self,name) + self.addInput("i",theType,inLength) + + @property + def typeName(self): + """The name of the C++ class implementing this node""" + return "Sink" + +class Source(GenericSource): + """ + Definition of a Source node for the graph + + Parameters + ---------- + name : str + Name of the C variable identifying this node + in the C code + theType : CGStaticType + The datatype for the output + outLength : int + The number of samples produced on output + """ + def __init__(self,name,theType,outLength): + GenericSource.__init__(self,name) + self.addOutput("o",theType,outLength) + + @property + def typeName(self): + """The name of the C++ class implementing this node""" + return "Source" + diff --git a/ComputeGraph/examples/simple/scheduler.obj b/ComputeGraph/examples/simple/scheduler.obj new file mode 100644 index 00000000..1b429716 Binary files /dev/null and b/ComputeGraph/examples/simple/scheduler.obj differ diff --git a/ComputeGraph/examples/simple/simple.dot b/ComputeGraph/examples/simple/simple.dot new file mode 100644 index 00000000..031c4181 --- /dev/null +++ b/ComputeGraph/examples/simple/simple.dot @@ -0,0 +1,48 @@ + + + + +digraph structs { + node [shape=plaintext] + rankdir=LR + edge [arrowsize=0.5] + fontname="times" + + +processing [label=< + + + + +
processing
(ProcessingNode)
>]; + +sink [label=< + + + + +
sink
(Sink)
>]; + +source [label=< + + + + +
source
(Source)
>]; + + + +source:i -> processing:i [label="f32(11)" +,headlabel=<
7 +
> +,taillabel=<
5 +
>] + +processing:i -> sink:i [label="f32(11)" +,headlabel=<
5 +
> +,taillabel=<
7 +
>] + + +} diff --git a/ComputeGraph/examples/simple/simple.exe b/ComputeGraph/examples/simple/simple.exe new file mode 100644 index 00000000..e4712075 Binary files /dev/null and b/ComputeGraph/examples/simple/simple.exe differ diff --git a/ComputeGraph/examples/simple/simple.ilk b/ComputeGraph/examples/simple/simple.ilk new file mode 100644 index 00000000..23f7f194 Binary files /dev/null and b/ComputeGraph/examples/simple/simple.ilk differ diff --git a/ComputeGraph/examples/simple/simple.pdb b/ComputeGraph/examples/simple/simple.pdb new file mode 100644 index 00000000..5bc7a223 Binary files /dev/null and b/ComputeGraph/examples/simple/simple.pdb differ diff --git a/ComputeGraph/examples/simple/simple.pdf b/ComputeGraph/examples/simple/simple.pdf new file mode 100644 index 00000000..19c89724 Binary files /dev/null and b/ComputeGraph/examples/simple/simple.pdf differ diff --git a/ComputeGraph/examples/simple/simple.png b/ComputeGraph/examples/simple/simple.png new file mode 100644 index 00000000..eaa33fb4 Binary files /dev/null and b/ComputeGraph/examples/simple/simple.png differ diff --git a/ComputeGraph/examples/simple/vc140.pdb b/ComputeGraph/examples/simple/vc140.pdb new file mode 100644 index 00000000..142c4bf9 Binary files /dev/null and b/ComputeGraph/examples/simple/vc140.pdb differ