diff --git a/ARM.CMSIS-DSP.pdsc b/ARM.CMSIS-DSP.pdsc index 18afa622..6864687d 100644 --- a/ARM.CMSIS-DSP.pdsc +++ b/ARM.CMSIS-DSP.pdsc @@ -105,12 +105,12 @@ - - CMSIS-DSP Compute Graph - Static Flow + + CMSIS-DSP Compute Graph - - - + + + diff --git a/ComputeGraph/README.md b/ComputeGraph/README.md index 7d802a95..da38aefb 100644 --- a/ComputeGraph/README.md +++ b/ComputeGraph/README.md @@ -49,7 +49,7 @@ The CMSIS-DSP Compute Graph Tools are a set of Python scripts and C++ classes wi - The Python script will generate a C++ implementation of the static schedule - The Python script can also generate a Python implementation of the static schedule (for use with the CMSIS-DSP Python wrapper) - +(There is no FIFO underflow or overflow due to the scheduling. If there are not enough cycles to run the processing, the real-time will be broken and the solution won't work But this problem is independent from the scheduling itself. ) ## Why it is useful @@ -93,6 +93,10 @@ The schedule is (the size of the FIFOs after the execution of the node displayed At the end, both FIFOs are empty so the schedule can be run again : it is periodic ! +The latest version of the compute graph also supports dynamic scheduling. + +![supported_configs](documentation/supported_configs.png) + ## How to use the static scheduler generator First, you must install the `CMSIS-DSP` PythonWrapper: @@ -130,6 +134,8 @@ Example 7 is communicating with OpenModelica. The Modelica model (PythonTest) in Example 8 is showing how to define a new custom datatype for the IOs of the nodes. Example 8 is also demonstrating a new feature where an IO can be connected up to 3 inputs and the static scheduler will automatically generate duplicate nodes. + + ## Frequently asked questions: There is a [FAQ](FAQ.md) document. @@ -181,10 +187,60 @@ The drawback of cyclo static scheduling is that the schedule length is increased Since schedule tend to be bigger with cyclo static scheduling, a new code generation mode has been introduced and is enabled by default : now instead of having a sequence of function calls, the schedule is coded by an array of number and there is a switch / case to select the function to be called. +## Dynamic Data Flow + +Versions of the compute graph corresponding to CMSIS-DSP Version >= 1.14.4 and Python wrapper version >= 1.10.0 are supporting a new dynamic / asynchronous mode. + + With a dynamic flow, the flow of data is potentially changing at each execution. The IOs can generate or consume a different amount of data at each execution of their node (including no data). + +This can be useful for sample oriented use cases where not all samples are available but a processing must nevertheless take place each time a subset of samples is available (samples could come from sensors). + +With a dynamic flow and scheduling, there is no more any way to ensure that there won't be FIFO underflow of overflow due to scheduling. As consequence, the nodes must be able to check for this problem and decide what to do. + +* A sink may decide to generate fake data in case of FIFO underflow +* A source may decide to skip some data in case of FIFO overflow +* Another node may decide to do nothing and skip the execution +* Another node may decide to raise an error. + +With dynamic scheduling, a node must implement the function `prepareForRunning` and decide what to do. + +3 error / status codes are reserved for this. They are defined in the header `cg_status.h`. This header is not included by default, but if you define you own error codes, they should be coherent with `cg_status` and use the same values for the 3 status / error codes which are used in dynamic mode: + +* `CG_SUCCESS` = 0 : Node can execute +* `CG_SKIP_EXECUTION` = -5 : Node will skip the execution +* `CG_BUFFER_ERROR` = -6 : Unrecoverable error due to FIFO underflow / overflow (only raised in pure function like CMSIS-DSP ones called directly) + +Any other returned value will stop the execution. + +The dynamic mode (also named asynchronous), is enabled with option : `asynchronous` + +The system will still compute a scheduling and FIFO sizes as if the flow was static. We can see the static flow as an average of the dynamic flow. In dynamic mode, the FIFOs may need to be bigger than the ones computed in static mode. The static estimation is giving a first idea of what the size of the FIFOs should be. The size can be increased by specifying a percent increase with option `FIFOIncrease`. + +For pure compute functions (like CMSIS-DSP ones), which are not packaged into a C++ class, there is no way to customize the decision logic in case of a problem with FIFO. There is a global option : `asyncDefaultSkip`. + +When `true`, a pure function that cannot run will just skip the execution. With `false`, the execution will stop. For any other decision algorithm, the pure function needs to be packaged in a C++ class. + +`Duplicate` nodes are skipping the execution in case of problems with FIFOs. If it is not the wanted behavior, you can either: + +* Replace the Duplicate class by a custom one by changing the class name with option `duplicateNodeClassName` on the graph. +* Don't use the automatic duplication feature and introduce your duplicate nodes in the compute graph + +When you don't want to generate or consume data in a node, just don't call the functions `getReadBuffer` or `getWriteBuffer` for your IOs. + ## Options Several options and be used to control the schedule generation. Some options are used by the scheduling algorithm and other options are used by the code generator: +### Options for the graph + +#### 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` ... + ### Options for the scheduling #### memoryOptimization (default = False) @@ -235,6 +291,8 @@ Prefix to add before the FIFO buffer definition. Those buffers are not static an Another possibility would be to make the buffer static by redefining the macro `CG_BEFORE_BUFFER` + + #### Options for C Code Generation only ##### cOptionalArgs (default = "") @@ -289,6 +347,30 @@ By default, the scheduler function is callable from C. When false, it is a stand 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) + +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. + +A synchronous schedule is used as start and should describe the average case. + +This implies `codeArray` and `switchCase`. This disables `memoryOptimizations`. + +Synchronous FIFOs that are just buffers will be considered as FIFOs in asynchronous mode. + +##### FIFOIncrease (default 0) + +In case of asynchronous scheduling, the FIFOs may need to be bigger than what is computed assuming a 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` + +##### 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. + +If another error recovery is needed, the function must be packaged into a C++ class to implement a `prepareForRun` function. + + + #### Options for Python code generation only ##### pyOptionalArgs (default = "") diff --git a/ComputeGraph/cg/static/nodes/README.md b/ComputeGraph/cg/nodes/README.md similarity index 100% rename from ComputeGraph/cg/static/nodes/README.md rename to ComputeGraph/cg/nodes/README.md diff --git a/ComputeGraph/cg/static/nodes/cpp/CFFT.h b/ComputeGraph/cg/nodes/cpp/CFFT.h similarity index 81% rename from ComputeGraph/cg/static/nodes/cpp/CFFT.h rename to ComputeGraph/cg/nodes/cpp/CFFT.h index 59ad9737..2359b04a 100644 --- a/ComputeGraph/cg/static/nodes/cpp/CFFT.h +++ b/ComputeGraph/cg/nodes/cpp/CFFT.h @@ -45,6 +45,18 @@ public: status=arm_cfft_init_f32(&sfft,inputSize>>1); }; + int prepareForRunning() override + { + if (this->willOverflow() || + this->willUnderflow() + ) + { + return(CG_SKIP_EXECUTION_ID_CODE); // Skip execution + } + + return(0); + }; + int run(){ float32_t *a=this->getReadBuffer(); float32_t *b=this->getWriteBuffer(); @@ -72,6 +84,18 @@ public: status=arm_cfft_init_f16(&sfft,inputSize>>1); }; + int prepareForRunning() override + { + if (this->willOverflow() || + this->willUnderflow() + ) + { + return(CG_SKIP_EXECUTION_ID_CODE); // Skip execution + } + + return(0); + }; + int run(){ float16_t *a=this->getReadBuffer(); float16_t *b=this->getWriteBuffer(); @@ -98,6 +122,18 @@ public: status=arm_cfft_init_q15(&sfft,inputSize>>1); }; + int prepareForRunning() override + { + if (this->willOverflow() || + this->willUnderflow() + ) + { + return(CG_SKIP_EXECUTION_ID_CODE); // Skip execution + } + + return(0); + }; + int run(){ q15_t *a=this->getReadBuffer(); q15_t *b=this->getWriteBuffer(); diff --git a/ComputeGraph/cg/static/nodes/cpp/ICFFT.h b/ComputeGraph/cg/nodes/cpp/ICFFT.h similarity index 81% rename from ComputeGraph/cg/static/nodes/cpp/ICFFT.h rename to ComputeGraph/cg/nodes/cpp/ICFFT.h index dfcdee84..01f1f2ba 100644 --- a/ComputeGraph/cg/static/nodes/cpp/ICFFT.h +++ b/ComputeGraph/cg/nodes/cpp/ICFFT.h @@ -45,6 +45,18 @@ public: status=arm_cfft_init_f32(&sifft,inputSize>>1); }; + int prepareForRunning() override + { + if (this->willOverflow() || + this->willUnderflow() + ) + { + return(CG_SKIP_EXECUTION_ID_CODE); // Skip execution + } + + return(0); + }; + int run(){ float32_t *a=this->getReadBuffer(); float32_t *b=this->getWriteBuffer(); @@ -72,6 +84,18 @@ public: status=arm_cfft_init_f16(&sifft,inputSize>>1); }; + int prepareForRunning() override + { + if (this->willOverflow() || + this->willUnderflow() + ) + { + return(CG_SKIP_EXECUTION_ID_CODE); // Skip execution + } + + return(0); + }; + int run(){ float16_t *a=this->getReadBuffer(); float16_t *b=this->getWriteBuffer(); @@ -99,6 +123,18 @@ public: status=arm_cfft_init_q15(&sifft,inputSize>>1); }; + int prepareForRunning() override + { + if (this->willOverflow() || + this->willUnderflow() + ) + { + return(CG_SKIP_EXECUTION_ID_CODE); // Skip execution + } + + return(0); + }; + int run(){ q15_t *a=this->getReadBuffer(); q15_t *b=this->getWriteBuffer(); diff --git a/ComputeGraph/cg/static/nodes/cpp/InterleavedStereoToMono.h b/ComputeGraph/cg/nodes/cpp/InterleavedStereoToMono.h similarity index 79% rename from ComputeGraph/cg/static/nodes/cpp/InterleavedStereoToMono.h rename to ComputeGraph/cg/nodes/cpp/InterleavedStereoToMono.h index 9d3a4726..6bec929a 100644 --- a/ComputeGraph/cg/static/nodes/cpp/InterleavedStereoToMono.h +++ b/ComputeGraph/cg/nodes/cpp/InterleavedStereoToMono.h @@ -40,7 +40,18 @@ public: InterleavedStereoToMono(FIFOBase &src,FIFOBase &dst): GenericNode(src,dst){}; - + int prepareForRunning() override + { + if (this->willOverflow() || + this->willUnderflow() + ) + { + return(CG_SKIP_EXECUTION_ID_CODE); // Skip execution + } + + return(0); + }; + int run(){ q15_t *a=this->getReadBuffer(); q15_t *b=this->getWriteBuffer(); @@ -60,7 +71,18 @@ public: InterleavedStereoToMono(FIFOBase &src,FIFOBase &dst): GenericNode(src,dst){}; - + int prepareForRunning() override + { + if (this->willOverflow() || + this->willUnderflow() + ) + { + return(CG_SKIP_EXECUTION_ID_CODE); // Skip execution + } + + return(0); + }; + int run(){ q31_t *a=this->getReadBuffer(); q31_t *b=this->getWriteBuffer(); @@ -80,7 +102,18 @@ public: InterleavedStereoToMono(FIFOBase &src,FIFOBase &dst): GenericNode(src,dst){}; - + int prepareForRunning() override + { + if (this->willOverflow() || + this->willUnderflow() + ) + { + return(CG_SKIP_EXECUTION_ID_CODE); // Skip execution + } + + return(0); + }; + int run(){ float32_t *a=this->getReadBuffer(); float32_t *b=this->getWriteBuffer(); diff --git a/ComputeGraph/cg/static/nodes/cpp/MFCC.h b/ComputeGraph/cg/nodes/cpp/MFCC.h similarity index 81% rename from ComputeGraph/cg/static/nodes/cpp/MFCC.h rename to ComputeGraph/cg/nodes/cpp/MFCC.h index 15ee1229..21c37d08 100644 --- a/ComputeGraph/cg/static/nodes/cpp/MFCC.h +++ b/ComputeGraph/cg/nodes/cpp/MFCC.h @@ -58,6 +58,18 @@ public: #endif }; + int prepareForRunning() override + { + if (this->willOverflow() || + this->willUnderflow() + ) + { + return(CG_SKIP_EXECUTION_ID_CODE); // Skip execution + } + + return(0); + }; + int run(){ float32_t *a=this->getReadBuffer(); float32_t *b=this->getWriteBuffer(); @@ -88,6 +100,18 @@ public: #endif }; + int prepareForRunning() override + { + if (this->willOverflow() || + this->willUnderflow() + ) + { + return(CG_SKIP_EXECUTION_ID_CODE); // Skip execution + } + + return(0); + }; + int run(){ float16_t *a=this->getReadBuffer(); float16_t *b=this->getWriteBuffer(); @@ -114,6 +138,18 @@ public: memory.resize(2*inputSize); }; + int prepareForRunning() override + { + if (this->willOverflow() || + this->willUnderflow() + ) + { + return(CG_SKIP_EXECUTION_ID_CODE); // Skip execution + } + + return(0); + }; + int run(){ q31_t *a=this->getReadBuffer(); q31_t *b=this->getWriteBuffer(); @@ -139,6 +175,18 @@ public: memory.resize(2*inputSize); }; + int prepareForRunning() override + { + if (this->willOverflow() || + this->willUnderflow() + ) + { + return(CG_SKIP_EXECUTION_ID_CODE); // Skip execution + } + + return(0); + }; + int run(){ q15_t *a=this->getReadBuffer(); q15_t *b=this->getWriteBuffer(); diff --git a/ComputeGraph/cg/static/nodes/cpp/NullSink.h b/ComputeGraph/cg/nodes/cpp/NullSink.h similarity index 87% rename from ComputeGraph/cg/static/nodes/cpp/NullSink.h rename to ComputeGraph/cg/nodes/cpp/NullSink.h index 5188c24e..57d9592c 100644 --- a/ComputeGraph/cg/static/nodes/cpp/NullSink.h +++ b/ComputeGraph/cg/nodes/cpp/NullSink.h @@ -35,6 +35,17 @@ class NullSink: public GenericSink public: NullSink(FIFOBase &src):GenericSink(src){}; + int prepareForRunning() override + { + if (this->willUnderflow() + ) + { + return(CG_SKIP_EXECUTION_ID_CODE); // Skip execution + } + + return(0); + }; + int run() { IN *b=this->getReadBuffer(); diff --git a/ComputeGraph/cg/static/nodes/cpp/OverlapAndAdd.h b/ComputeGraph/cg/nodes/cpp/OverlapAndAdd.h similarity index 91% rename from ComputeGraph/cg/static/nodes/cpp/OverlapAndAdd.h rename to ComputeGraph/cg/nodes/cpp/OverlapAndAdd.h index e59a521d..1c20769a 100644 --- a/ComputeGraph/cg/static/nodes/cpp/OverlapAndAdd.h +++ b/ComputeGraph/cg/nodes/cpp/OverlapAndAdd.h @@ -40,6 +40,18 @@ public: memory.resize(overlap); }; + int prepareForRunning() override + { + if (this->willOverflow() || + this->willUnderflow() + ) + { + return(CG_SKIP_EXECUTION_ID_CODE); // Skip execution + } + + return(0); + }; + int run(){ int i; IN *a=this->getReadBuffer(); diff --git a/ComputeGraph/cg/static/nodes/cpp/SlidingBuffer.h b/ComputeGraph/cg/nodes/cpp/SlidingBuffer.h similarity index 88% rename from ComputeGraph/cg/static/nodes/cpp/SlidingBuffer.h rename to ComputeGraph/cg/nodes/cpp/SlidingBuffer.h index a9c1c338..ff1d833c 100644 --- a/ComputeGraph/cg/static/nodes/cpp/SlidingBuffer.h +++ b/ComputeGraph/cg/nodes/cpp/SlidingBuffer.h @@ -40,6 +40,18 @@ public: memory.resize(overlap); }; + int prepareForRunning() override + { + if (this->willOverflow() || + this->willUnderflow() + ) + { + return(CG_SKIP_EXECUTION_ID_CODE); // Skip execution + } + + return(0); + }; + int run(){ IN *a=this->getReadBuffer(); IN *b=this->getWriteBuffer(); diff --git a/ComputeGraph/cg/static/nodes/cpp/StreamingNodes/CMSIS_RTOS/RingPrivate.h b/ComputeGraph/cg/nodes/cpp/StreamingNodes/CMSIS_RTOS/RingPrivate.h similarity index 100% rename from ComputeGraph/cg/static/nodes/cpp/StreamingNodes/CMSIS_RTOS/RingPrivate.h rename to ComputeGraph/cg/nodes/cpp/StreamingNodes/CMSIS_RTOS/RingPrivate.h diff --git a/ComputeGraph/cg/static/nodes/cpp/StreamingNodes/CMSIS_RTOS/SchedEvents.h b/ComputeGraph/cg/nodes/cpp/StreamingNodes/CMSIS_RTOS/SchedEvents.h similarity index 100% rename from ComputeGraph/cg/static/nodes/cpp/StreamingNodes/CMSIS_RTOS/SchedEvents.h rename to ComputeGraph/cg/nodes/cpp/StreamingNodes/CMSIS_RTOS/SchedEvents.h diff --git a/ComputeGraph/cg/static/nodes/cpp/StreamingNodes/Config/AudioConfig.h b/ComputeGraph/cg/nodes/cpp/StreamingNodes/Config/AudioConfig.h similarity index 100% rename from ComputeGraph/cg/static/nodes/cpp/StreamingNodes/Config/AudioConfig.h rename to ComputeGraph/cg/nodes/cpp/StreamingNodes/Config/AudioConfig.h diff --git a/ComputeGraph/cg/static/nodes/cpp/StreamingNodes/Config/RingConfig.h b/ComputeGraph/cg/nodes/cpp/StreamingNodes/Config/RingConfig.h similarity index 100% rename from ComputeGraph/cg/static/nodes/cpp/StreamingNodes/Config/RingConfig.h rename to ComputeGraph/cg/nodes/cpp/StreamingNodes/Config/RingConfig.h diff --git a/ComputeGraph/cg/static/nodes/cpp/StreamingNodes/Config/VideoConfig.h b/ComputeGraph/cg/nodes/cpp/StreamingNodes/Config/VideoConfig.h similarity index 100% rename from ComputeGraph/cg/static/nodes/cpp/StreamingNodes/Config/VideoConfig.h rename to ComputeGraph/cg/nodes/cpp/StreamingNodes/Config/VideoConfig.h diff --git a/ComputeGraph/cg/static/nodes/cpp/StreamingNodes/README.md b/ComputeGraph/cg/nodes/cpp/StreamingNodes/README.md similarity index 94% rename from ComputeGraph/cg/static/nodes/cpp/StreamingNodes/README.md rename to ComputeGraph/cg/nodes/cpp/StreamingNodes/README.md index 866c6aa8..e894ca39 100644 --- a/ComputeGraph/cg/static/nodes/cpp/StreamingNodes/README.md +++ b/ComputeGraph/cg/nodes/cpp/StreamingNodes/README.md @@ -10,6 +10,8 @@ Those files are kept because they are used in the AVH-SystemModeling example. But there are simpler way to interface the compute graph to an audio interrupt. +Those nodes are considered as deprecated. Don't use them. + ## RingBuffer It is a way to connect the compute graph with static flow to an audio source or sink. diff --git a/ComputeGraph/cg/static/nodes/cpp/StreamingNodes/RingBuffer/RingBuffer.cpp b/ComputeGraph/cg/nodes/cpp/StreamingNodes/RingBuffer/RingBuffer.cpp similarity index 100% rename from ComputeGraph/cg/static/nodes/cpp/StreamingNodes/RingBuffer/RingBuffer.cpp rename to ComputeGraph/cg/nodes/cpp/StreamingNodes/RingBuffer/RingBuffer.cpp diff --git a/ComputeGraph/cg/static/nodes/cpp/StreamingNodes/RingBuffer/RingBuffer.h b/ComputeGraph/cg/nodes/cpp/StreamingNodes/RingBuffer/RingBuffer.h similarity index 100% rename from ComputeGraph/cg/static/nodes/cpp/StreamingNodes/RingBuffer/RingBuffer.h rename to ComputeGraph/cg/nodes/cpp/StreamingNodes/RingBuffer/RingBuffer.h diff --git a/ComputeGraph/cg/static/nodes/cpp/StreamingNodes/RingBuffer/RingInit.cpp b/ComputeGraph/cg/nodes/cpp/StreamingNodes/RingBuffer/RingInit.cpp similarity index 100% rename from ComputeGraph/cg/static/nodes/cpp/StreamingNodes/RingBuffer/RingInit.cpp rename to ComputeGraph/cg/nodes/cpp/StreamingNodes/RingBuffer/RingInit.cpp diff --git a/ComputeGraph/cg/static/nodes/cpp/StreamingNodes/RingBuffer/RingInit.h b/ComputeGraph/cg/nodes/cpp/StreamingNodes/RingBuffer/RingInit.h similarity index 100% rename from ComputeGraph/cg/static/nodes/cpp/StreamingNodes/RingBuffer/RingInit.h rename to ComputeGraph/cg/nodes/cpp/StreamingNodes/RingBuffer/RingInit.h diff --git a/ComputeGraph/cg/static/nodes/cpp/StreamingNodes/VHT/audio/AudioInterrupt.cpp b/ComputeGraph/cg/nodes/cpp/StreamingNodes/VHT/audio/AudioInterrupt.cpp similarity index 100% rename from ComputeGraph/cg/static/nodes/cpp/StreamingNodes/VHT/audio/AudioInterrupt.cpp rename to ComputeGraph/cg/nodes/cpp/StreamingNodes/VHT/audio/AudioInterrupt.cpp diff --git a/ComputeGraph/cg/static/nodes/cpp/StreamingNodes/VHT/audio/audio_drv.c b/ComputeGraph/cg/nodes/cpp/StreamingNodes/VHT/audio/audio_drv.c similarity index 100% rename from ComputeGraph/cg/static/nodes/cpp/StreamingNodes/VHT/audio/audio_drv.c rename to ComputeGraph/cg/nodes/cpp/StreamingNodes/VHT/audio/audio_drv.c diff --git a/ComputeGraph/cg/static/nodes/cpp/StreamingNodes/VHT/audio/audio_drv.h b/ComputeGraph/cg/nodes/cpp/StreamingNodes/VHT/audio/audio_drv.h similarity index 100% rename from ComputeGraph/cg/static/nodes/cpp/StreamingNodes/VHT/audio/audio_drv.h rename to ComputeGraph/cg/nodes/cpp/StreamingNodes/VHT/audio/audio_drv.h diff --git a/ComputeGraph/cg/static/nodes/cpp/StreamingNodes/VHT/video/VideoInterrupt.cpp b/ComputeGraph/cg/nodes/cpp/StreamingNodes/VHT/video/VideoInterrupt.cpp similarity index 100% rename from ComputeGraph/cg/static/nodes/cpp/StreamingNodes/VHT/video/VideoInterrupt.cpp rename to ComputeGraph/cg/nodes/cpp/StreamingNodes/VHT/video/VideoInterrupt.cpp diff --git a/ComputeGraph/cg/static/nodes/cpp/StreamingNodes/VHT/video/video_drv.c b/ComputeGraph/cg/nodes/cpp/StreamingNodes/VHT/video/video_drv.c similarity index 100% rename from ComputeGraph/cg/static/nodes/cpp/StreamingNodes/VHT/video/video_drv.c rename to ComputeGraph/cg/nodes/cpp/StreamingNodes/VHT/video/video_drv.c diff --git a/ComputeGraph/cg/static/nodes/cpp/StreamingNodes/VHT/video/video_drv.h b/ComputeGraph/cg/nodes/cpp/StreamingNodes/VHT/video/video_drv.h similarity index 100% rename from ComputeGraph/cg/static/nodes/cpp/StreamingNodes/VHT/video/video_drv.h rename to ComputeGraph/cg/nodes/cpp/StreamingNodes/VHT/video/video_drv.h diff --git a/ComputeGraph/cg/static/nodes/cpp/StreamingSink.h b/ComputeGraph/cg/nodes/cpp/StreamingSink.h similarity index 88% rename from ComputeGraph/cg/static/nodes/cpp/StreamingSink.h rename to ComputeGraph/cg/nodes/cpp/StreamingSink.h index 7dca9701..3765fbcb 100644 --- a/ComputeGraph/cg/static/nodes/cpp/StreamingSink.h +++ b/ComputeGraph/cg/nodes/cpp/StreamingSink.h @@ -30,7 +30,7 @@ #include "RingBuffer.h" - +/* This is deprecated. Don't use it */ template class StreamingSink: public GenericSink { @@ -38,6 +38,17 @@ public: StreamingSink(FIFOBase &src,ring_config_t *config): GenericSink(src),mConfig(config){}; + int prepareForRunning() override + { + if (this->willUnderflow() + ) + { + return(CG_SKIP_EXECUTION_ID_CODE); // Skip execution + } + + return(0); + }; + int run() { IN *b=this->getReadBuffer(); diff --git a/ComputeGraph/cg/static/nodes/cpp/StreamingSource.h b/ComputeGraph/cg/nodes/cpp/StreamingSource.h similarity index 89% rename from ComputeGraph/cg/static/nodes/cpp/StreamingSource.h rename to ComputeGraph/cg/nodes/cpp/StreamingSource.h index d52b4b60..343b36b3 100644 --- a/ComputeGraph/cg/static/nodes/cpp/StreamingSource.h +++ b/ComputeGraph/cg/nodes/cpp/StreamingSource.h @@ -30,7 +30,7 @@ #include "RingBuffer.h" - +/* This is deprecated. Don't use it */ template class StreamingSource: public GenericSource { @@ -38,6 +38,17 @@ public: StreamingSource(FIFOBase &dst,ring_config_t *config): GenericSource(dst),mConfig(config){}; + int prepareForRunning() override + { + if (this->willUnderflow() + ) + { + return(CG_SKIP_EXECUTION_ID_CODE); // Skip execution + } + + return(0); + }; + int run(){ OUT *b=this->getWriteBuffer(); /* diff --git a/ComputeGraph/cg/static/nodes/cpp/ToComplex.h b/ComputeGraph/cg/nodes/cpp/ToComplex.h similarity index 88% rename from ComputeGraph/cg/static/nodes/cpp/ToComplex.h rename to ComputeGraph/cg/nodes/cpp/ToComplex.h index 392bb8ae..e048416a 100644 --- a/ComputeGraph/cg/static/nodes/cpp/ToComplex.h +++ b/ComputeGraph/cg/nodes/cpp/ToComplex.h @@ -44,6 +44,18 @@ public: ToComplex(FIFOBase &src,FIFOBase &dst):GenericNode(src,dst){ }; + int prepareForRunning() override + { + if (this->willOverflow() || + this->willUnderflow() + ) + { + return(CG_SKIP_EXECUTION_ID_CODE); // Skip execution + } + + return(0); + }; + int run(){ IN *a=this->getReadBuffer(); IN *b=this->getWriteBuffer(); diff --git a/ComputeGraph/cg/static/nodes/cpp/ToReal.h b/ComputeGraph/cg/nodes/cpp/ToReal.h similarity index 87% rename from ComputeGraph/cg/static/nodes/cpp/ToReal.h rename to ComputeGraph/cg/nodes/cpp/ToReal.h index 82f03309..4dd26ea9 100644 --- a/ComputeGraph/cg/static/nodes/cpp/ToReal.h +++ b/ComputeGraph/cg/nodes/cpp/ToReal.h @@ -43,6 +43,18 @@ public: ToReal(FIFOBase &src,FIFOBase &dst):GenericNode(src,dst){ }; + int prepareForRunning() override + { + if (this->willOverflow() || + this->willUnderflow() + ) + { + return(CG_SKIP_EXECUTION_ID_CODE); // Skip execution + } + + return(0); + }; + int run(){ IN *a=this->getReadBuffer(); IN *b=this->getWriteBuffer(); diff --git a/ComputeGraph/cg/static/nodes/cpp/Unzip.h b/ComputeGraph/cg/nodes/cpp/Unzip.h similarity index 87% rename from ComputeGraph/cg/static/nodes/cpp/Unzip.h rename to ComputeGraph/cg/nodes/cpp/Unzip.h index 93d110fd..e49b3292 100644 --- a/ComputeGraph/cg/static/nodes/cpp/Unzip.h +++ b/ComputeGraph/cg/nodes/cpp/Unzip.h @@ -46,6 +46,19 @@ public: Unzip(FIFOBase &src,FIFOBase &dst1,FIFOBase &dst2): GenericNode12(src,dst1,dst2){}; + int prepareForRunning() override + { + if (this->willOverflow1() || + this->willOverflow2() || + this->willUnderflow() + ) + { + return(CG_SKIP_EXECUTION_ID_CODE); // Skip execution + } + + return(0); + }; + /* 2*outputSize1 == 2*outSize2 == inputSize */ diff --git a/ComputeGraph/cg/static/nodes/cpp/Zip.h b/ComputeGraph/cg/nodes/cpp/Zip.h similarity index 86% rename from ComputeGraph/cg/static/nodes/cpp/Zip.h rename to ComputeGraph/cg/nodes/cpp/Zip.h index 1aa513a6..6447c075 100644 --- a/ComputeGraph/cg/static/nodes/cpp/Zip.h +++ b/ComputeGraph/cg/nodes/cpp/Zip.h @@ -39,6 +39,18 @@ public: Zip(FIFOBase &src1,FIFOBase &src2,FIFOBase &dst): GenericNode21(src1,src2,dst){}; + int prepareForRunning() override + { + if (this->willOverflow() || + this->willUnderflow1() || + this->willUnderflow2() + ) + { + return(CG_SKIP_EXECUTION_ID_CODE); // Skip execution + } + + return(0); + }; int run(){ IN *a1=this->getReadBuffer1(); diff --git a/ComputeGraph/cg/static/nodes/cpp/host/FileSink.h b/ComputeGraph/cg/nodes/cpp/host/FileSink.h similarity index 87% rename from ComputeGraph/cg/static/nodes/cpp/host/FileSink.h rename to ComputeGraph/cg/nodes/cpp/host/FileSink.h index 9ac317f1..bda7c34d 100644 --- a/ComputeGraph/cg/static/nodes/cpp/host/FileSink.h +++ b/ComputeGraph/cg/nodes/cpp/host/FileSink.h @@ -35,6 +35,17 @@ class FileSink: public GenericSink public: FileSink(FIFOBase &src, std::string name):GenericSink(src),output(name){}; + int prepareForRunning() override + { + if (this->willUnderflow() + ) + { + return(CG_SKIP_EXECUTION_ID_CODE); // Skip execution + } + + return(0); + }; + int run() { IN *b=this->getReadBuffer(); diff --git a/ComputeGraph/cg/static/nodes/cpp/host/FileSource.h b/ComputeGraph/cg/nodes/cpp/host/FileSource.h similarity index 91% rename from ComputeGraph/cg/static/nodes/cpp/host/FileSource.h rename to ComputeGraph/cg/nodes/cpp/host/FileSource.h index b275ee2d..70252791 100644 --- a/ComputeGraph/cg/static/nodes/cpp/host/FileSource.h +++ b/ComputeGraph/cg/nodes/cpp/host/FileSource.h @@ -46,6 +46,17 @@ public: }; + int prepareForRunning() override + { + if (this->willOverflow() + ) + { + return(CG_SKIP_EXECUTION_ID_CODE); // Skip execution + } + + return(0); + }; + int run(){ string str; int i; diff --git a/ComputeGraph/cg/static/src/GenericNodes.h b/ComputeGraph/cg/src/GenericNodes.h similarity index 56% rename from ComputeGraph/cg/static/src/GenericNodes.h rename to ComputeGraph/cg/src/GenericNodes.h index ff28f74c..f73464ba 100644 --- a/ComputeGraph/cg/static/src/GenericNodes.h +++ b/ComputeGraph/cg/src/GenericNodes.h @@ -1,6 +1,6 @@ /* ---------------------------------------------------------------------- * Project: CMSIS DSP Library - * Title: Sched.h + * Title: GenericNodes.h * Description: C++ support templates for the compute graph with static scheduler * * $Date: 29 July 2021 @@ -9,7 +9,7 @@ * Target Processor: Cortex-M and Cortex-A cores * -------------------------------------------------------------------- */ /* - * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. + * Copyright (C) 2010-2022 ARM Limited or its affiliates. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -31,10 +31,20 @@ #include +/* +Defined in cg_status.h by default but user +may want to use a different header to define the +error codes of the application +*/ +#define CG_SKIP_EXECUTION_ID_CODE (-5) +#define CG_BUFFER_ERROR_ID_CODE (-6) + // FIFOS #ifdef DEBUGSCHED +#include + template struct debugtype{ typedef T type; @@ -55,23 +65,29 @@ class FIFOBase{ public: virtual T* getWriteBuffer(int nb)=0; virtual T* getReadBuffer(int nb)=0; + virtual bool willUnderflowWith(int nb)=0; + virtual bool willOverflowWith(int nb)=0; + }; +template +class FIFO; -template -class FIFO: public FIFOBase +/* Real FIFO, Synchronous */ +template +class FIFO: public FIFOBase { public: FIFO(T *buffer,int delay=0):mBuffer(buffer),readPos(0),writePos(delay) {}; FIFO(uint8_t *buffer,int delay=0):mBuffer((T*)buffer),readPos(0),writePos(delay) {}; + /* Not used in synchronous mode */ + bool willUnderflowWith(int nb) override {return false;}; + bool willOverflowWith(int nb) override {return false;}; + T * getWriteBuffer(int nb) override { - if (isArray==1) - { - return(mBuffer); - } - + T *ret; if (readPos > 0) { @@ -87,24 +103,148 @@ class FIFO: public FIFOBase T* getReadBuffer(int nb) override { - if (isArray==1) + + T *ret = mBuffer + readPos; + readPos += nb; + return(ret); + } + + #ifdef DEBUGSCHED + void dump() + { + int nb=0; + std::cout << std::endl; + for(int i=0; i < length ; i++) { - return(mBuffer); + std::cout << (typename Debug::type)mBuffer[i] << " "; + nb++; + if (nb == 10) + { + nb=0; + std::cout << std::endl; + } } + std::cout << std::endl; + std::cout << std::endl; + } + #endif + + protected: + T *mBuffer; + int readPos,writePos; +}; + +/* Buffer, Synchronous */ +template +class FIFO: public FIFOBase +{ + public: + FIFO(T *buffer,int delay=0):mBuffer(buffer),readPos(0),writePos(delay) {}; + FIFO(uint8_t *buffer,int delay=0):mBuffer((T*)buffer),readPos(0),writePos(delay) {}; + + bool willUnderflowWith(int nb) override {return false;}; + bool willOverflowWith(int nb) override {return false;}; + + T * getWriteBuffer(int nb) override + { + return(mBuffer); + }; + + T* getReadBuffer(int nb) override + { + return(mBuffer); + } + + #ifdef DEBUGSCHED + void dump() + { + int nb=0; + std::cout << std::endl; + for(int i=0; i < length ; i++) + { + std::cout << (typename Debug::type)mBuffer[i] << " "; + nb++; + if (nb == 10) + { + nb=0; + std::cout << std::endl; + } + } + std::cout << std::endl; + std::cout << std::endl; + } + #endif + + protected: + T *mBuffer; + int readPos,writePos; +}; + +/* Real FIFO, Asynchronous */ +template +class FIFO: public FIFOBase +{ + public: + FIFO(T *buffer,int delay=0):mBuffer(buffer),readPos(0),writePos(delay),nbSamples(delay) {}; + FIFO(uint8_t *buffer,int delay=0):mBuffer((T*)buffer),readPos(0),writePos(delay),nbSamples(delay) {}; + + /* + + Check for overflow must have been done + before using this function + + */ + T * getWriteBuffer(int nb) override + { + T *ret; + if (readPos > 0) + { + memcpy((void*)mBuffer,(void*)(mBuffer+readPos),(writePos-readPos)*sizeof(T)); + writePos -= readPos; + readPos = 0; + } + + ret = mBuffer + writePos; + writePos += nb; + nbSamples += nb; + return(ret); + }; + + /* + + Check for undeflow must have been done + before using this function + + */ + T* getReadBuffer(int nb) override + { + T *ret = mBuffer + readPos; readPos += nb; + nbSamples -= nb; return(ret); } + bool willUnderflowWith(int nb) override + { + return((nbSamples - nb)<0); + } + + bool willOverflowWith(int nb) override + { + return((nbSamples + nb)>length); + } + #ifdef DEBUGSCHED void dump() { int nb=0; std::cout << std::endl; + std::cout << "FIFO nb samples = " << nbSamples << std::endl; for(int i=0; i < length ; i++) { - std::cout << (Debug::type)mBuffer[i] << " "; + std::cout << (typename Debug::type)mBuffer[i] << " "; nb++; if (nb == 10) { @@ -120,6 +260,7 @@ class FIFO: public FIFOBase protected: T *mBuffer; int readPos,writePos; + int nbSamples; }; // GENERIC NODES @@ -128,6 +269,7 @@ class NodeBase { public: virtual int run()=0; + virtual int prepareForRunning()=0; }; template @@ -140,6 +282,9 @@ protected: OUT * getWriteBuffer(int nb = outputSize){return mDst.getWriteBuffer(nb);}; IN * getReadBuffer(int nb = inputSize){return mSrc.getReadBuffer(nb);}; + bool willOverflow(int nb = outputSize){return mDst.willOverflowWith(nb);}; + bool willUnderflow(int nb = inputSize){return mSrc.willUnderflowWith(nb);}; + private: FIFOBase &mSrc; FIFOBase &mDst; @@ -157,6 +302,11 @@ protected: OUT2 * getWriteBuffer2(int nb=output2Size){return mDst2.getWriteBuffer(nb);}; IN * getReadBuffer(int nb=inputSize){return mSrc.getReadBuffer(nb);}; + bool willOverflow1(int nb = output1Size){return mDst1.willOverflowWith(nb);}; + bool willOverflow2(int nb = output2Size){return mDst2.willOverflowWith(nb);}; + + bool willUnderflow(int nb = inputSize){return mSrc.willUnderflowWith(nb);}; + private: FIFOBase &mSrc; FIFOBase &mDst1; @@ -184,6 +334,12 @@ protected: IN * getReadBuffer(int nb=inputSize){return mSrc.getReadBuffer(nb);}; + bool willOverflow1(int nb = output1Size){return mDst1.willOverflowWith(nb);}; + bool willOverflow2(int nb = output2Size){return mDst2.willOverflowWith(nb);}; + bool willOverflow3(int nb = output3Size){return mDst3.willOverflowWith(nb);}; + + bool willUnderflow(int nb = inputSize){return mSrc.willUnderflowWith(nb);}; + private: FIFOBase &mSrc; FIFOBase &mDst1; @@ -205,6 +361,10 @@ protected: IN1 * getReadBuffer1(int nb=input1Size){return mSrc1.getReadBuffer(nb);}; IN2 * getReadBuffer2(int nb=input2Size){return mSrc2.getReadBuffer(nb);}; + bool willOverflow(int nb = outputSize){return mDst.willOverflowWith(nb);}; + bool willUnderflow1(int nb = input1Size){return mSrc1.willUnderflowWith(nb);}; + bool willUnderflow2(int nb = input2Size){return mSrc2.willUnderflowWith(nb);}; + private: FIFOBase &mSrc1; FIFOBase &mSrc2; @@ -222,6 +382,8 @@ public: protected: OUT * getWriteBuffer(int nb=outputSize){return mDst.getWriteBuffer(nb);}; + bool willOverflow(int nb = outputSize){return mDst.willOverflowWith(nb);}; + private: FIFOBase &mDst; }; @@ -235,6 +397,8 @@ public: protected: IN * getReadBuffer(int nb=inputSize){return mSrc.getReadBuffer(nb);}; + bool willUnderflow(int nb = inputSize){return mSrc.willUnderflowWith(nb);}; + private: FIFOBase &mSrc; }; @@ -253,7 +417,19 @@ public: Duplicate2(FIFOBase &src,FIFOBase &dst1,FIFOBase &dst2): GenericNode12(src,dst1,dst2){}; - int run(){ + int prepareForRunning() override + { + if (this->willUnderflow() || + this->willOverflow1() || + this->willOverflow2()) + { + return(CG_SKIP_EXECUTION_ID_CODE); // Skip execution + } + + return(0); + }; + + int run() override { IN *a=this->getReadBuffer(); IN *b1=this->getWriteBuffer1(); IN *b2=this->getWriteBuffer2(); @@ -293,7 +469,21 @@ public: IN,inputSize, IN,inputSize>(src,dst1,dst2,dst3){}; - int run(){ + int prepareForRunning() override + { + if (this->willUnderflow() || + this->willOverflow1() || + this->willOverflow2() || + this->willOverflow3() + ) + { + return(CG_SKIP_EXECUTION_ID_CODE); // Skip execution + } + + return(0); + }; + + int run() override { IN *a=this->getReadBuffer(); IN *b1=this->getWriteBuffer1(); IN *b2=this->getWriteBuffer2(); diff --git a/ComputeGraph/cg/src/cg_status.h b/ComputeGraph/cg/src/cg_status.h new file mode 100644 index 00000000..430dc437 --- /dev/null +++ b/ComputeGraph/cg/src/cg_status.h @@ -0,0 +1,17 @@ +#ifndef _CG_STATUS_H_ + + + typedef enum + { + CG_SUCCESS = 0, /**< No error */ + CG_BUFFER_UNDERFLOW = -1, /**< FIFO underflow */ + CG_BUFFER_OVERFLOW = -2, /**< FIFO overflow */ + CG_MEMORY_ALLOCATION_FAILURE = -3, /**< Memory allocation failure */ + CG_INIT_FAILURE = -4, /**< Node initialization failure */ + CG_SKIP_EXECUTION = -5, /**< Skip node execution (asynchronous mode) */ + CG_BUFFER_ERROR = -6, /**< Stop execution due to FIFO overflow or underflow (asynchronous mode for pure function) */ + } cg_status; + + + +#endif /* _CG_STATUS_H_ */ \ No newline at end of file diff --git a/ComputeGraph/documentation/supported_configs.png b/ComputeGraph/documentation/supported_configs.png new file mode 100644 index 00000000..d1b536ec Binary files /dev/null and b/ComputeGraph/documentation/supported_configs.png differ diff --git a/ComputeGraph/examples/CMakeLists.txt b/ComputeGraph/examples/CMakeLists.txt index 7b7f529d..06f30c0c 100644 --- a/ComputeGraph/examples/CMakeLists.txt +++ b/ComputeGraph/examples/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required (VERSION 3.14) +cmake_minimum_required (VERSION 3.15) include(CMakePrintHelpers) set(Python_FIND_REGISTRY "LAST") @@ -26,13 +26,33 @@ function(sdf TARGET) target_sources(${TARGET} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/generated/scheduler.cpp) endfunction() -set(CGSTATICDIR ${CMAKE_CURRENT_SOURCE_DIR}/../cg/static) +function(sdfpython TARGET) + 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 + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/test.dot + VERBATIM + ) + endif() + + add_custom_command(OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/sched.py + ${CMAKE_CURRENT_SOURCE_DIR}/test.dot + COMMAND ${Python_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/graph.py + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/graph.py + VERBATIM + ) +endfunction() + +set(CGDIR ${CMAKE_CURRENT_SOURCE_DIR}/../cg) set(DSP ${CMAKE_CURRENT_SOURCE_DIR}/../..) function(add_sdf_dir TARGET) - target_include_directories(${TARGET} PRIVATE ${CGSTATICDIR}/src) - target_include_directories(${TARGET} PRIVATE ${CGSTATICDIR}/nodes/cpp) + target_include_directories(${TARGET} PRIVATE ${CGDIR}/src) + target_include_directories(${TARGET} PRIVATE ${CGDIR}/nodes/cpp) target_include_directories(${TARGET} PRIVATE ${CMSISCORE}) target_include_directories(${TARGET} PRIVATE ${DSP}/Include) endfunction() @@ -52,3 +72,9 @@ add_subdirectory(example3 bin_example3) add_subdirectory(example6 bin_example6) add_subdirectory(example8 bin_example8) add_subdirectory(example9 bin_example9) +add_subdirectory(example10 bin_example10) + +# Python examples +add_subdirectory(example4 bin_example4) +add_subdirectory(example5 bin_example5) +add_subdirectory(example7 bin_example7) diff --git a/ComputeGraph/examples/example1/AppNodes.h b/ComputeGraph/examples/example1/AppNodes.h index 1bdd4c45..653d5e82 100644 --- a/ComputeGraph/examples/example1/AppNodes.h +++ b/ComputeGraph/examples/example1/AppNodes.h @@ -36,6 +36,17 @@ class Sink: public GenericSink public: Sink(FIFOBase &src):GenericSink(src){}; + int prepareForRunning() override + { + if (this->willUnderflow() + ) + { + return(CG_SKIP_EXECUTION_ID_CODE); // Skip execution + } + + return(0); + }; + int run() { IN *b=this->getReadBuffer(); @@ -55,6 +66,17 @@ class Source: GenericSource public: Source(FIFOBase &dst):GenericSource(dst),mCounter(0){}; + int prepareForRunning() override + { + if (this->willOverflow() + ) + { + return(CG_SKIP_EXECUTION_ID_CODE); // Skip execution + } + + return(0); + }; + int run(){ OUT *b=this->getWriteBuffer(); @@ -76,6 +98,18 @@ class ProcessingNode: public GenericNode public: ProcessingNode(FIFOBase &src,FIFOBase &dst,int,const char*,int):GenericNode(src,dst){}; + int prepareForRunning() override + { + if (this->willOverflow() || + this->willUnderflow() + ) + { + return(CG_SKIP_EXECUTION_ID_CODE); // Skip execution + } + + return(0); + }; + int run(){ printf("ProcessingNode\n"); IN *a=this->getReadBuffer(); diff --git a/ComputeGraph/examples/example1/generated/scheduler.cpp b/ComputeGraph/examples/example1/generated/scheduler.cpp index e3825ee0..0fcded00 100644 --- a/ComputeGraph/examples/example1/generated/scheduler.cpp +++ b/ComputeGraph/examples/example1/generated/scheduler.cpp @@ -72,6 +72,7 @@ The support classes and code is covered by CMSIS-DSP license. CG_AFTER_INCLUDES + /* Description of the scheduling. @@ -111,8 +112,8 @@ uint32_t scheduler(int *error,int someVariable) /* Create FIFOs objects */ - FIFO fifo0(buf1); - FIFO fifo1(buf2); + FIFO fifo0(buf1); + FIFO fifo1(buf2); CG_BEFORE_NODE_INIT; /* @@ -131,6 +132,7 @@ uint32_t scheduler(int *error,int someVariable) for(unsigned long id=0 ; id < 17; id++) { CG_BEFORE_NODE_EXECUTION; + switch(schedule[id]) { case 0: diff --git a/ComputeGraph/examples/example1/graph.py b/ComputeGraph/examples/example1/graph.py index 29cd45fc..d4242c0f 100644 --- a/ComputeGraph/examples/example1/graph.py +++ b/ComputeGraph/examples/example1/graph.py @@ -1,4 +1,4 @@ -from cmsisdsp.cg.static.scheduler import * +from cmsisdsp.cg.scheduler import * ### Define new types of Nodes diff --git a/ComputeGraph/examples/example10/AppNodes.h b/ComputeGraph/examples/example10/AppNodes.h new file mode 100644 index 00000000..e588337c --- /dev/null +++ b/ComputeGraph/examples/example10/AppNodes.h @@ -0,0 +1,195 @@ +/* ---------------------------------------------------------------------- + * 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 +#include + +static int count=0; + +template +class SourceOdd; + +template +class SourceEven; + +template<> +class SourceOdd: public GenericSource +{ +public: + SourceOdd(FIFOBase &dst): + GenericSource(dst){}; + + int prepareForRunning() override + { + if (this->willOverflow()) + { + return(CG_SKIP_EXECUTION_ID_CODE); // Skip execution + } + + return(0); + }; + + int run() override{ + if (count & 1) + { + int16_t *b=this->getWriteBuffer(); + b[0] = count; + } + return(0); + }; + + + +}; + +template<> +class SourceEven: public GenericSource +{ +public: + SourceEven(FIFOBase &dst): + GenericSource(dst){}; + + int prepareForRunning() override + { + if (this->willOverflow()) + { + return(CG_SKIP_EXECUTION_ID_CODE); // Skip execution + } + + return(0); + }; + + int run() override{ + if (!(count & 1)) + { + int16_t *b=this->getWriteBuffer(); + b[0] = count; + } + return(0); + }; + + +}; + +template +class ProcessingOddEven; + +template<> +class ProcessingOddEven: +public GenericNode21 +{ +public: + ProcessingOddEven(FIFOBase &srcOdd, + FIFOBase &srcEven, + FIFOBase &dst): + GenericNode21(srcOdd,srcEven,dst){}; + + int prepareForRunning() override + { + if (this->willOverflow()) + { + return(CG_SKIP_EXECUTION_ID_CODE); + } + return(0); + }; + + int run() override{ + int16_t oddVal=0; + int16_t evenVal=0; + if (!this->willUnderflow1()) + { + int16_t *odd=this->getReadBuffer1(); + oddVal=odd[0]; + } + + if (!this->willUnderflow2()) + { + int16_t *even=this->getReadBuffer2(); + evenVal=even[0]; + } + + int16_t *dst=this->getWriteBuffer(); + + dst[0] = (evenVal + oddVal); + + return(0); + }; + +}; + +template +class SinkAsync; + +template +class SinkAsync: +public GenericSink +{ +public: + SinkAsync(FIFOBase &src): + GenericSink(src){ + }; + + int prepareForRunning() override + { + if (this->willUnderflow()) + { + return(CG_SKIP_EXECUTION_ID_CODE); // Skip execution + } + + return(0); + }; + + int run() override + { + int16_t *b=this->getReadBuffer(); + for(int i=0;i fifo0(buf1); + FIFO fifo1(buf2); + FIFO fifo2(buf3); + FIFO fifo3(buf4); + FIFO fifo4(buf5); + FIFO fifo5(buf6); + + CG_BEFORE_NODE_INIT; + /* + Create node objects + */ + Duplicate2 dup0(fifo3,fifo4,fifo5); + ProcessingOddEven proc(fifo0,fifo1,fifo2); + SinkAsync sinka(fifo4); + SinkAsync sinkb(fifo5); + SourceEven sourceEven(fifo1); + SourceOdd sourceOdd(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 < 7; id++) + { + CG_BEFORE_NODE_EXECUTION; + + cgStaticError = 0; + switch(schedule[id]) + { + case 0: + { + + bool canRun=true; + canRun &= !fifo2.willUnderflowWith(1); + canRun &= !fifo3.willOverflowWith(1); + + if (!canRun) + { + cgStaticError = CG_SKIP_EXECUTION_ID_CODE; + } + else + { + cgStaticError = 0; + } + } + break; + + case 1: + { + cgStaticError = dup0.prepareForRunning(); + } + break; + + case 2: + { + cgStaticError = proc.prepareForRunning(); + } + break; + + case 3: + { + cgStaticError = sinka.prepareForRunning(); + } + break; + + case 4: + { + cgStaticError = sinkb.prepareForRunning(); + } + break; + + case 5: + { + cgStaticError = sourceEven.prepareForRunning(); + } + break; + + case 6: + { + cgStaticError = sourceOdd.prepareForRunning(); + } + break; + + default: + break; + } + + if (cgStaticError == CG_SKIP_EXECUTION_ID_CODE) + continue; + + CHECKERROR; + + switch(schedule[id]) + { + case 0: + { + + { + + int16_t* i0; + int16_t* o1; + i0=fifo2.getReadBuffer(1); + o1=fifo3.getWriteBuffer(1); + compute(i0,o1,1); + cgStaticError = 0; + } + } + break; + + case 1: + { + cgStaticError = dup0.run(); + } + break; + + case 2: + { + cgStaticError = proc.run(); + } + break; + + case 3: + { + cgStaticError = sinka.run(); + } + break; + + case 4: + { + cgStaticError = sinkb.run(); + } + break; + + case 5: + { + cgStaticError = sourceEven.run(); + } + break; + + case 6: + { + cgStaticError = sourceOdd.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/example10/generated/scheduler.h b/ComputeGraph/examples/example10/generated/scheduler.h new file mode 100644 index 00000000..d98d9e63 --- /dev/null +++ b/ComputeGraph/examples/example10/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/example10/graph.py b/ComputeGraph/examples/example10/graph.py new file mode 100644 index 00000000..83371029 --- /dev/null +++ b/ComputeGraph/examples/example10/graph.py @@ -0,0 +1,132 @@ +from cmsisdsp.cg.scheduler import * + +### Define new types of Nodes + + + +class SinkAsync(GenericSink): + def __init__(self,name,theType,inLength): + GenericSink.__init__(self,name) + self.addInput("i",theType,inLength) + + @property + def typeName(self): + return "SinkAsync" + +class SourceOdd(GenericSource): + def __init__(self,name,theType,inLength): + GenericSource.__init__(self,name) + self.addOutput("o",theType,inLength) + + @property + def typeName(self): + return "SourceOdd" + +class SourceEven(GenericSource): + def __init__(self,name,theType,inLength): + GenericSource.__init__(self,name) + self.addOutput("o",theType,inLength) + + @property + def typeName(self): + return "SourceEven" + +class ProcessingOddEven(GenericNode): + def __init__(self,name,theType,inLength,outLength): + GenericNode.__init__(self,name) + self.addInput("ia",theType,inLength) + self.addInput("ib",theType,inLength) + self.addOutput("o",theType,outLength) + + @property + def typeName(self): + return "ProcessingOddEven" + + + +### Define nodes +dataType=CType(SINT16) +odd=SourceOdd("sourceOdd",dataType,1) +even=SourceEven("sourceEven",dataType,1) + +proc=ProcessingOddEven("proc",dataType,1,1) +comp=Unary("compute",dataType,1) + +sinka=SinkAsync("sinka",dataType,1) +sinkb=SinkAsync("sinkb",dataType,1) + +g = Graph() + +# Option to customize the default class +# to use for Duplicate and FIFO +# FIFO class can also be changed in the connect +# function to change the class for a specific +# connection +g.defaultFIFOClass = "FIFO" +g.duplicateNodeClassName = "Duplicate" + +g.connect(odd.o,proc.ia) +g.connect(even.o,proc.ib) + +g.connect(proc.o,comp.i) +g.connect(comp.o,sinka.i) +g.connect(comp.o,sinkb.i) + + +print("Generate graphviz and code") + +conf=Configuration() +conf.debugLimit=10 +conf.cOptionalArgs="" + +# It is disabled in asynchronous mode +# since the schedule has no mor any reason to +# be periodic and thus the FIFO content can +# overlap several executions of the schedule +conf.memoryOptimization=True + +conf.codeArray = True +conf.switchCase = True + +# Asynchronous mode enable. It implies +# switchCase and codeArray true +conf.asynchronous = True + +# Increase size of synchronous FIFOs by 100% +# for the asynchronous case (so 2 samples +# instead of 1 in this example) +conf.FIFOIncrease = 100 # percent + + +#conf.displayFIFOSizes=True +# Prefix for global FIFO buffers +#conf.prefix="sched1" + +#conf.dumpSchedule = True +sched = g.computeSchedule(config=conf) +#print(sched.schedule) +print("Schedule length = %d" % sched.scheduleLength) +print("Memory usage %d bytes" % sched.memory) +# + + +#conf.postCustomCName = "post.h" +#conf.CAPI = True +#conf.prefix="global" +#conf.dumpFIFO = True +#conf.CMSISDSP = False +#conf.codeArray = False +#conf.switchCase = False + +# For pure functions (like CMSIS-DSP) which are not +# packaged in a C++ class, we have to decide of the +# asynchronous policy. What must be done in case of +# FIFO overflow or underflow. +# By default, the execution is skipped. +conf.asyncDefaultSkip = True + +sched.ccode("./generated",conf) + +with open("test.dot","w") as f: + sched.graphviz(f) + diff --git a/ComputeGraph/examples/example10/main.cpp b/ComputeGraph/examples/example10/main.cpp new file mode 100644 index 00000000..a1fd4028 --- /dev/null +++ b/ComputeGraph/examples/example10/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/example10/test.dot b/ComputeGraph/examples/example10/test.dot new file mode 100644 index 00000000..490fa64b --- /dev/null +++ b/ComputeGraph/examples/example10/test.dot @@ -0,0 +1,104 @@ + + + + +digraph structs { + node [shape=plaintext] + rankdir=LR + edge [arrowsize=0.5] + fontname="times" + + +compute1 [label=< + + + + +
compute
(Function)
>]; + +dup0 [shape=point,label=dup0] + + +proc [label=< + + + + + + + + + + + + +
iaproc
(ProcessingOddEven)
o
ib
>]; + +sinka [label=< + + + + +
sinka
(SinkAsync)
>]; + +sinkb [label=< + + + + +
sinkb
(SinkAsync)
>]; + +sourceEven [label=< + + + + +
sourceEven
(SourceEven)
>]; + +sourceOdd [label=< + + + + +
sourceOdd
(SourceOdd)
>]; + + + +sourceOdd:i -> proc:ia [label="s16(2)" +,headlabel=<
1 +
> +,taillabel=<
1 +
>] + +sourceEven:i -> proc:ib [label="s16(2)" +,headlabel=<
1 +
> +,taillabel=<
1 +
>] + +proc:o -> compute1:i [label="s16(2)" +,headlabel=<
1 +
> +,taillabel=<
1 +
>] + +compute1:i -> +dup0 [label="s16(2)" + +,taillabel=<
1 +
>] + + +dup0 -> sinka:i [label="s16(2)" +,headlabel=<
1 +
> +] + + +dup0 -> sinkb:i [label="s16(2)" +,headlabel=<
1 +
> +] + + +} diff --git a/ComputeGraph/examples/example10/test.pdf b/ComputeGraph/examples/example10/test.pdf new file mode 100644 index 00000000..b5508a12 Binary files /dev/null and b/ComputeGraph/examples/example10/test.pdf differ diff --git a/ComputeGraph/examples/example2/AppNodes.h b/ComputeGraph/examples/example2/AppNodes.h index 9841f3df..28f1a430 100644 --- a/ComputeGraph/examples/example2/AppNodes.h +++ b/ComputeGraph/examples/example2/AppNodes.h @@ -39,6 +39,17 @@ class TFLite: public GenericSink public: TFLite(FIFOBase &src):GenericSink(src){}; + int prepareForRunning() override + { + if (this->willUnderflow() + ) + { + return(CG_SKIP_EXECUTION_ID_CODE); // Skip execution + } + + return(0); + }; + int run() { IN *b=this->getReadBuffer(); @@ -58,6 +69,17 @@ class StereoSource: GenericSource public: StereoSource(FIFOBase &dst):GenericSource(dst),mCounter(0){}; + int prepareForRunning() override + { + if (this->willOverflow() + ) + { + return(CG_SKIP_EXECUTION_ID_CODE); // Skip execution + } + + return(0); + }; + int run(){ OUT *b=this->getWriteBuffer(); @@ -80,6 +102,18 @@ class MFCC: public GenericNode public: MFCC(FIFOBase &src,FIFOBase &dst):GenericNode(src,dst){}; + int prepareForRunning() override + { + if (this->willOverflow() || + this->willUnderflow() + ) + { + return(CG_SKIP_EXECUTION_ID_CODE); // Skip execution + } + + return(0); + }; + int run(){ printf("MFCC\n"); IN *a=this->getReadBuffer(); diff --git a/ComputeGraph/examples/example2/generated/scheduler.cpp b/ComputeGraph/examples/example2/generated/scheduler.cpp index d2c9a19f..1cb16aff 100644 --- a/ComputeGraph/examples/example2/generated/scheduler.cpp +++ b/ComputeGraph/examples/example2/generated/scheduler.cpp @@ -72,6 +72,7 @@ The support classes and code is covered by CMSIS-DSP license. CG_AFTER_INCLUDES + /* Description of the scheduling. @@ -153,15 +154,15 @@ uint32_t scheduler(int *error,int opt1,int opt2) /* Create FIFOs objects */ - FIFO fifo0(buf1,10); - FIFO fifo1(buf2); - FIFO fifo2(buf3); - FIFO fifo3(buf4); - FIFO fifo4(buf5); - FIFO fifo5(buf6); - FIFO fifo6(buf7); - FIFO fifo7(buf8); - FIFO fifo8(buf9); + FIFO fifo0(buf1,10); + FIFO fifo1(buf2); + FIFO fifo2(buf3); + FIFO fifo3(buf4); + FIFO fifo4(buf5); + FIFO fifo5(buf6); + FIFO fifo6(buf7); + FIFO fifo7(buf8); + FIFO fifo8(buf9); CG_BEFORE_NODE_INIT; /* @@ -183,6 +184,7 @@ uint32_t scheduler(int *error,int opt1,int opt2) for(unsigned long id=0 ; id < 302; id++) { CG_BEFORE_NODE_EXECUTION; + switch(schedule[id]) { case 0: @@ -193,42 +195,48 @@ uint32_t scheduler(int *error,int opt1,int opt2) case 1: { - { - float32_t* i0; - float32_t* i1; - float32_t* o2; - i0=fifo3.getReadBuffer(160); - i1=fifo4.getReadBuffer(160); - o2=fifo5.getWriteBuffer(160); - arm_add_f32(i0,i1,o2,160); - cgStaticError = 0; -} + + { + + float32_t* i0; + float32_t* i1; + float32_t* o2; + i0=fifo3.getReadBuffer(160); + i1=fifo4.getReadBuffer(160); + o2=fifo5.getWriteBuffer(160); + arm_add_f32(i0,i1,o2,160); + cgStaticError = 0; + } } break; case 2: { - { - float32_t* i0; - float32_t* o2; - i0=fifo1.getReadBuffer(160); - o2=fifo3.getWriteBuffer(160); - arm_scale_f32(i0,HALF,o2,160); - cgStaticError = 0; -} + + { + + float32_t* i0; + float32_t* o2; + i0=fifo1.getReadBuffer(160); + o2=fifo3.getWriteBuffer(160); + arm_scale_f32(i0,HALF,o2,160); + cgStaticError = 0; + } } break; case 3: { - { - float32_t* i0; - float32_t* o2; - i0=fifo2.getReadBuffer(160); - o2=fifo4.getWriteBuffer(160); - arm_scale_f32(i0,HALF,o2,160); - cgStaticError = 0; -} + + { + + float32_t* i0; + float32_t* o2; + i0=fifo2.getReadBuffer(160); + o2=fifo4.getWriteBuffer(160); + arm_scale_f32(i0,HALF,o2,160); + cgStaticError = 0; + } } break; diff --git a/ComputeGraph/examples/example2/graph.py b/ComputeGraph/examples/example2/graph.py index 9868d544..6127bcb4 100644 --- a/ComputeGraph/examples/example2/graph.py +++ b/ComputeGraph/examples/example2/graph.py @@ -1,4 +1,4 @@ -from cmsisdsp.cg.static.scheduler import * +from cmsisdsp.cg.scheduler import * AUDIO_INTERRUPT_LENGTH = 160 diff --git a/ComputeGraph/examples/example3/generated/scheduler.cpp b/ComputeGraph/examples/example3/generated/scheduler.cpp index 26710576..320a78ee 100644 --- a/ComputeGraph/examples/example3/generated/scheduler.cpp +++ b/ComputeGraph/examples/example3/generated/scheduler.cpp @@ -72,6 +72,7 @@ The support classes and code is covered by CMSIS-DSP license. CG_AFTER_INCLUDES + /* Description of the scheduling. @@ -141,14 +142,14 @@ uint32_t scheduler(int *error) /* Create FIFOs objects */ - FIFO fifo0(buf1); - FIFO fifo1(buf2); - FIFO fifo2(buf3); - FIFO fifo3(buf4); - FIFO fifo4(buf5); - FIFO fifo5(buf6); - FIFO fifo6(buf7); - FIFO fifo7(buf8); + FIFO fifo0(buf1); + FIFO fifo1(buf2); + FIFO fifo2(buf3); + FIFO fifo3(buf4); + FIFO fifo4(buf5); + FIFO fifo5(buf6); + FIFO fifo6(buf7); + FIFO fifo7(buf8); CG_BEFORE_NODE_INIT; /* @@ -172,18 +173,99 @@ uint32_t scheduler(int *error) for(unsigned long id=0 ; id < 25; id++) { CG_BEFORE_NODE_EXECUTION; + + cgStaticError = 0; switch(schedule[id]) { case 0: { - { - float32_t* i0; - float32_t* o2; - i0=fifo1.getReadBuffer(256); - o2=fifo2.getWriteBuffer(256); - arm_mult_f32(i0,HANN,o2,256); - cgStaticError = 0; -} + + bool canRun=true; + canRun &= !fifo1.willUnderflowWith(256); + canRun &= !fifo2.willOverflowWith(256); + + if (!canRun) + { + cgStaticError = CG_SKIP_EXECUTION_ID_CODE; + } + else + { + cgStaticError = 0; + } + } + break; + + case 1: + { + cgStaticError = audioOverlap.prepareForRunning(); + } + break; + + case 2: + { + cgStaticError = audioWin.prepareForRunning(); + } + break; + + case 3: + { + cgStaticError = cfft.prepareForRunning(); + } + break; + + case 4: + { + cgStaticError = icfft.prepareForRunning(); + } + break; + + case 5: + { + cgStaticError = sink.prepareForRunning(); + } + break; + + case 6: + { + cgStaticError = src.prepareForRunning(); + } + break; + + case 7: + { + cgStaticError = toCmplx.prepareForRunning(); + } + break; + + case 8: + { + cgStaticError = toReal.prepareForRunning(); + } + break; + + default: + break; + } + + if (cgStaticError == CG_SKIP_EXECUTION_ID_CODE) + continue; + + CHECKERROR; + + switch(schedule[id]) + { + case 0: + { + + { + + float32_t* i0; + float32_t* o2; + i0=fifo1.getReadBuffer(256); + o2=fifo2.getWriteBuffer(256); + arm_mult_f32(i0,HANN,o2,256); + cgStaticError = 0; + } } break; diff --git a/ComputeGraph/examples/example3/graph.py b/ComputeGraph/examples/example3/graph.py index 17600c54..b3edffe9 100644 --- a/ComputeGraph/examples/example3/graph.py +++ b/ComputeGraph/examples/example3/graph.py @@ -1,6 +1,6 @@ import numpy as np -from cmsisdsp.cg.static.scheduler import * +from cmsisdsp.cg.scheduler import * FS=16000 @@ -53,6 +53,7 @@ conf.debugLimit=40 #conf.memoryOptimization=True #conf.dumpSchedule = True + sched = g.computeSchedule(conf) #print(sched.schedule) print("Schedule length = %d" % sched.scheduleLength) diff --git a/ComputeGraph/examples/example4/CMakeLists.txt b/ComputeGraph/examples/example4/CMakeLists.txt new file mode 100644 index 00000000..b329c8a2 --- /dev/null +++ b/ComputeGraph/examples/example4/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required (VERSION 3.14) +include(CMakePrintHelpers) + +project(Example4) + + +add_custom_target(example4 ALL DEPENDS sched.py) + +sdfpython(example4) + diff --git a/ComputeGraph/examples/example4/appnodes.py b/ComputeGraph/examples/example4/appnodes.py index cd85148f..2e2a85fb 100644 --- a/ComputeGraph/examples/example4/appnodes.py +++ b/ComputeGraph/examples/example4/appnodes.py @@ -25,12 +25,12 @@ # See the License for the specific language governing permissions and # limitations under the License. ############################################ -from cmsisdsp.cg.static.nodes.simu import * +from cmsisdsp.cg.nodes.simu import * from custom import * -from cmsisdsp.cg.static.nodes.host.FileSink import * -from cmsisdsp.cg.static.nodes.host.FileSource import * -from cmsisdsp.cg.static.nodes.CFFT import * -from cmsisdsp.cg.static.nodes.ICFFT import * -from cmsisdsp.cg.static.nodes.ToComplex import * -from cmsisdsp.cg.static.nodes.ToReal import * +from cmsisdsp.cg.nodes.host.FileSink import * +from cmsisdsp.cg.nodes.host.FileSource import * +from cmsisdsp.cg.nodes.CFFT import * +from cmsisdsp.cg.nodes.ICFFT import * +from cmsisdsp.cg.nodes.ToComplex import * +from cmsisdsp.cg.nodes.ToReal import * diff --git a/ComputeGraph/examples/example4/graph.py b/ComputeGraph/examples/example4/graph.py index 17c70f8d..003e25fb 100644 --- a/ComputeGraph/examples/example4/graph.py +++ b/ComputeGraph/examples/example4/graph.py @@ -1,6 +1,6 @@ import numpy as np -from cmsisdsp.cg.static.scheduler import * +from cmsisdsp.cg.scheduler import * FS=16000 diff --git a/ComputeGraph/examples/example4/sched.py b/ComputeGraph/examples/example4/sched.py index 4fbeff85..17074b30 100644 --- a/ComputeGraph/examples/example4/sched.py +++ b/ComputeGraph/examples/example4/sched.py @@ -10,7 +10,7 @@ import sys import numpy as np import cmsisdsp as dsp -from cmsisdsp.cg.static.nodes.simu import * +from cmsisdsp.cg.nodes.simu import * from appnodes import * from custom import * diff --git a/ComputeGraph/examples/example5/CMakeLists.txt b/ComputeGraph/examples/example5/CMakeLists.txt new file mode 100644 index 00000000..bd0f4007 --- /dev/null +++ b/ComputeGraph/examples/example5/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required (VERSION 3.14) +include(CMakePrintHelpers) + +project(Example5) + + +add_custom_target(example5 ALL DEPENDS sched.py) + +sdfpython(example5) + diff --git a/ComputeGraph/examples/example5/appnodes.py b/ComputeGraph/examples/example5/appnodes.py index 51974c7b..c7f7667b 100644 --- a/ComputeGraph/examples/example5/appnodes.py +++ b/ComputeGraph/examples/example5/appnodes.py @@ -25,16 +25,16 @@ # See the License for the specific language governing permissions and # limitations under the License. ############################################ -from cmsisdsp.cg.static.nodes.simu import * +from cmsisdsp.cg.nodes.simu import * from custom import * # Host only nodes -from cmsisdsp.cg.static.nodes.host.NumpySink import * -from cmsisdsp.cg.static.nodes.host.WavSource import * +from cmsisdsp.cg.nodes.host.NumpySink import * +from cmsisdsp.cg.nodes.host.WavSource import * # Embedded nodes -from cmsisdsp.cg.static.nodes.StereoToMono import * -from cmsisdsp.cg.static.nodes.MFCC import * +from cmsisdsp.cg.nodes.InterleavedStereoToMono import * +from cmsisdsp.cg.nodes.MFCC import * diff --git a/ComputeGraph/examples/example5/graph.py b/ComputeGraph/examples/example5/graph.py index ad9f15d8..4e798db0 100644 --- a/ComputeGraph/examples/example5/graph.py +++ b/ComputeGraph/examples/example5/graph.py @@ -1,6 +1,6 @@ import numpy as np -from cmsisdsp.cg.static.scheduler import * +from cmsisdsp.cg.scheduler import * from sharedconfig import * diff --git a/ComputeGraph/examples/example5/sched.py b/ComputeGraph/examples/example5/sched.py index 3a96a154..c8673a90 100644 --- a/ComputeGraph/examples/example5/sched.py +++ b/ComputeGraph/examples/example5/sched.py @@ -10,7 +10,7 @@ import sys import numpy as np import cmsisdsp as dsp -from cmsisdsp.cg.static.nodes.simu import * +from cmsisdsp.cg.nodes.simu import * from appnodes import * from custom import * diff --git a/ComputeGraph/examples/example5/test.pdf b/ComputeGraph/examples/example5/test.pdf index ce5864fb..520728b3 100644 Binary files a/ComputeGraph/examples/example5/test.pdf and b/ComputeGraph/examples/example5/test.pdf differ diff --git a/ComputeGraph/examples/example6/generated/scheduler.cpp b/ComputeGraph/examples/example6/generated/scheduler.cpp index 008b55fe..665b95f3 100644 --- a/ComputeGraph/examples/example6/generated/scheduler.cpp +++ b/ComputeGraph/examples/example6/generated/scheduler.cpp @@ -72,6 +72,7 @@ The support classes and code is covered by CMSIS-DSP license. CG_AFTER_INCLUDES + /* Description of the scheduling. @@ -121,10 +122,10 @@ uint32_t scheduler(int *error,arm_mfcc_instance_f32 *mfccConfig) /* Create FIFOs objects */ - FIFO fifo0(buf1); - FIFO fifo1(buf2); - FIFO fifo2(buf3); - FIFO fifo3(buf4); + FIFO fifo0(buf1); + FIFO fifo1(buf2); + FIFO fifo2(buf3); + FIFO fifo3(buf4); CG_BEFORE_NODE_INIT; /* @@ -145,6 +146,7 @@ uint32_t scheduler(int *error,arm_mfcc_instance_f32 *mfccConfig) for(unsigned long id=0 ; id < 17; id++) { CG_BEFORE_NODE_EXECUTION; + switch(schedule[id]) { case 0: diff --git a/ComputeGraph/examples/example6/graph.py b/ComputeGraph/examples/example6/graph.py index 4ff9fb28..75170d7d 100644 --- a/ComputeGraph/examples/example6/graph.py +++ b/ComputeGraph/examples/example6/graph.py @@ -1,6 +1,6 @@ import numpy as np -from cmsisdsp.cg.static.scheduler import * +from cmsisdsp.cg.scheduler import * from sharedconfig import * diff --git a/ComputeGraph/examples/example7/CMakeLists.txt b/ComputeGraph/examples/example7/CMakeLists.txt new file mode 100644 index 00000000..b6c73287 --- /dev/null +++ b/ComputeGraph/examples/example7/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required (VERSION 3.14) +include(CMakePrintHelpers) + +project(Example7) + + +add_custom_target(example7 ALL DEPENDS sched.py) + +sdfpython(example7) + diff --git a/ComputeGraph/examples/example7/appnodes.py b/ComputeGraph/examples/example7/appnodes.py index 1bea427e..42fd62ea 100644 --- a/ComputeGraph/examples/example7/appnodes.py +++ b/ComputeGraph/examples/example7/appnodes.py @@ -25,17 +25,17 @@ # See the License for the specific language governing permissions and # limitations under the License. ############################################ -from cmsisdsp.cg.static.nodes.simu import * +from cmsisdsp.cg.nodes.simu import * from custom import * -from cmsisdsp.cg.static.nodes.host.FileSink import * -from cmsisdsp.cg.static.nodes.host.FileSource import * -from cmsisdsp.cg.static.nodes.CFFT import * -from cmsisdsp.cg.static.nodes.ICFFT import * -from cmsisdsp.cg.static.nodes.ToComplex import * -from cmsisdsp.cg.static.nodes.ToReal import * +from cmsisdsp.cg.nodes.host.FileSink import * +from cmsisdsp.cg.nodes.host.FileSource import * +from cmsisdsp.cg.nodes.CFFT import * +from cmsisdsp.cg.nodes.ICFFT import * +from cmsisdsp.cg.nodes.ToComplex import * +from cmsisdsp.cg.nodes.ToReal import * -from cmsisdsp.cg.static.nodes.host.VHTCGSTATIC import * +from cmsisdsp.cg.nodes.host.VHTCGSTATIC import * diff --git a/ComputeGraph/examples/example7/custom.py b/ComputeGraph/examples/example7/custom.py index 2a5a31bd..d7b673ca 100644 --- a/ComputeGraph/examples/example7/custom.py +++ b/ComputeGraph/examples/example7/custom.py @@ -1,4 +1,4 @@ -from cmsisdsp.cg.static.nodes.simu import * +from cmsisdsp.cg.nodes.simu import * import numpy as np import cmsisdsp as dsp diff --git a/ComputeGraph/examples/example7/graph.py b/ComputeGraph/examples/example7/graph.py index 47b1a7d9..93f45b9b 100644 --- a/ComputeGraph/examples/example7/graph.py +++ b/ComputeGraph/examples/example7/graph.py @@ -1,6 +1,6 @@ import numpy as np -from cmsisdsp.cg.static.scheduler import * +from cmsisdsp.cg.scheduler import * class Processing(GenericNode): diff --git a/ComputeGraph/examples/example7/sched.py b/ComputeGraph/examples/example7/sched.py index ca78473a..62cecbdf 100644 --- a/ComputeGraph/examples/example7/sched.py +++ b/ComputeGraph/examples/example7/sched.py @@ -10,7 +10,7 @@ import sys import numpy as np import cmsisdsp as dsp -from cmsisdsp.cg.static.nodes.simu import * +from cmsisdsp.cg.nodes.simu import * from appnodes import * from custom import * diff --git a/ComputeGraph/examples/example8/AppNodes.h b/ComputeGraph/examples/example8/AppNodes.h index f1ca45fa..d818ba65 100644 --- a/ComputeGraph/examples/example8/AppNodes.h +++ b/ComputeGraph/examples/example8/AppNodes.h @@ -36,6 +36,17 @@ class Sink: public GenericSink public: Sink(FIFOBase &src):GenericSink(src){}; + int prepareForRunning() override + { + if (this->willUnderflow() + ) + { + return(CG_SKIP_EXECUTION_ID_CODE); // Skip execution + } + + return(0); + }; + int run() { IN *b=this->getReadBuffer(); @@ -58,6 +69,17 @@ class Source: GenericSource public: Source(FIFOBase &dst):GenericSource(dst),mCounter(0){}; + int prepareForRunning() override + { + if (this->willOverflow() + ) + { + return(CG_SKIP_EXECUTION_ID_CODE); // Skip execution + } + + return(0); + }; + int run(){ complex *b=this->getWriteBuffer(); @@ -90,6 +112,19 @@ public: OUT1,outputSize1, OUT2,outputSize2>(src,dst1,dst2){}; + int prepareForRunning() override + { + if (this->willOverflow1() || + this->willOverflow2() || + this->willUnderflow() + ) + { + return(CG_SKIP_EXECUTION_ID_CODE); // Skip execution + } + + return(0); + }; + int run(){ printf("ProcessingNode\n"); IN *a=this->getReadBuffer(); diff --git a/ComputeGraph/examples/example8/generated/scheduler.cpp b/ComputeGraph/examples/example8/generated/scheduler.cpp index ff2ea63c..557475e1 100644 --- a/ComputeGraph/examples/example8/generated/scheduler.cpp +++ b/ComputeGraph/examples/example8/generated/scheduler.cpp @@ -72,6 +72,7 @@ The support classes and code is covered by CMSIS-DSP license. CG_AFTER_INCLUDES + /* Description of the scheduling. @@ -131,12 +132,12 @@ uint32_t scheduler(int *error,int someVariable) /* Create FIFOs objects */ - FIFO fifo0(buf1); - FIFO fifo1(buf2); - FIFO fifo2(buf3); - FIFO fifo3(buf4); - FIFO fifo4(buf5); - FIFO fifo5(buf6); + FIFO fifo0(buf1); + FIFO fifo1(buf2); + FIFO fifo2(buf3); + FIFO fifo3(buf4); + FIFO fifo4(buf5); + FIFO fifo5(buf6); CG_BEFORE_NODE_INIT; /* @@ -159,6 +160,7 @@ uint32_t scheduler(int *error,int someVariable) for(unsigned long id=0 ; id < 37; id++) { CG_BEFORE_NODE_EXECUTION; + switch(schedule[id]) { case 0: diff --git a/ComputeGraph/examples/example8/graph.py b/ComputeGraph/examples/example8/graph.py index 118c6db3..f88ccbf9 100644 --- a/ComputeGraph/examples/example8/graph.py +++ b/ComputeGraph/examples/example8/graph.py @@ -1,4 +1,4 @@ -from cmsisdsp.cg.static.scheduler import * +from cmsisdsp.cg.scheduler import * ### Define new types of Nodes diff --git a/ComputeGraph/examples/example9/AppNodes.h b/ComputeGraph/examples/example9/AppNodes.h index 53e311ac..b90c1a76 100644 --- a/ComputeGraph/examples/example9/AppNodes.h +++ b/ComputeGraph/examples/example9/AppNodes.h @@ -36,6 +36,17 @@ class Sink: public GenericSink public: Sink(FIFOBase &src):GenericSink(src){}; + int prepareForRunning() override + { + if (this->willUnderflow() + ) + { + return(CG_SKIP_EXECUTION_ID_CODE); // Skip execution + } + + return(0); + }; + int run() { IN *b=this->getReadBuffer(); @@ -55,6 +66,17 @@ class Source: GenericSource public: Source(FIFOBase &dst):GenericSource(dst),mCounter(0){}; + int prepareForRunning() override + { + if (this->willOverflow() + ) + { + return(CG_SKIP_EXECUTION_ID_CODE); // Skip execution + } + + return(0); + }; + int run(){ OUT *b=this->getWriteBuffer(); @@ -91,6 +113,19 @@ public: float32_t,inputSize, float32_t,inputSize>(src1,src2,dst){}; + int prepareForRunning() override + { + if (this->willOverflow() || + this->willUnderflow1() || + this->willUnderflow2() + ) + { + return(CG_SKIP_EXECUTION_ID_CODE); // Skip execution + } + + return(0); + }; + int run(){ printf("ProcessingNode\n"); float32_t *a=this->getReadBuffer1(); diff --git a/ComputeGraph/examples/example9/generated/scheduler.cpp b/ComputeGraph/examples/example9/generated/scheduler.cpp index 48d4b8bc..d82d6848 100644 --- a/ComputeGraph/examples/example9/generated/scheduler.cpp +++ b/ComputeGraph/examples/example9/generated/scheduler.cpp @@ -72,6 +72,7 @@ The support classes and code is covered by CMSIS-DSP license. CG_AFTER_INCLUDES + /* Description of the scheduling. @@ -121,10 +122,10 @@ uint32_t scheduler(int *error,int someVariable) /* Create FIFOs objects */ - FIFO fifo0(buf1); - FIFO fifo1(buf2); - FIFO fifo2(buf3); - FIFO fifo3(buf4,5); + FIFO fifo0(buf1); + FIFO fifo1(buf2); + FIFO fifo2(buf3); + FIFO fifo3(buf4,5); CG_BEFORE_NODE_INIT; /* @@ -144,6 +145,7 @@ uint32_t scheduler(int *error,int someVariable) for(unsigned long id=0 ; id < 4; id++) { CG_BEFORE_NODE_EXECUTION; + switch(schedule[id]) { case 0: diff --git a/ComputeGraph/examples/example9/graph.py b/ComputeGraph/examples/example9/graph.py index 7aa824b0..4094058a 100644 --- a/ComputeGraph/examples/example9/graph.py +++ b/ComputeGraph/examples/example9/graph.py @@ -1,4 +1,4 @@ -from cmsisdsp.cg.static.scheduler import * +from cmsisdsp.cg.scheduler import * ### Define new types of Nodes diff --git a/MANIFEST.in b/MANIFEST.in index ce69175a..5e742107 100755 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -2,6 +2,6 @@ include PythonWrapper_README.md recursive-include Include *.h recursive-include PrivateInclude *.h recursive-include PythonWrapper/cmsisdsp_pkg/src *.h -include cmsisdsp/cg/static/scheduler/templates/* +include cmsisdsp/cg/scheduler/templates/* include Source/DistanceFunctions/arm_boolean_distance_template.h diff --git a/cmsisdsp/__init__.py b/cmsisdsp/__init__.py index 277cc25b..970b6bdc 100755 --- a/cmsisdsp/__init__.py +++ b/cmsisdsp/__init__.py @@ -20,7 +20,7 @@ from cmsisdsp_window import * __version__ = cmsisdsp.version.__version__ # CMSIS-DSP Version used to build the wrapper -cmsis_dsp_version="1.15.0" +cmsis_dsp_version="1.14.4" # CMSIS-DSP Commit hash used to build the wrapper diff --git a/cmsisdsp/cg/static/nodes/CFFT.py b/cmsisdsp/cg/nodes/CFFT.py similarity index 95% rename from cmsisdsp/cg/static/nodes/CFFT.py rename to cmsisdsp/cg/nodes/CFFT.py index 082ffaed..fc710b03 100644 --- a/cmsisdsp/cg/static/nodes/CFFT.py +++ b/cmsisdsp/cg/nodes/CFFT.py @@ -9,7 +9,7 @@ # Target Processor: Cortex-M and Cortex-A cores # -------------------------------------------------------------------- */ # -# Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. +# Copyright (C) 2010-2023 ARM Limited or its affiliates. All rights reserved. # # SPDX-License-Identifier: Apache-2.0 # diff --git a/cmsisdsp/cg/static/nodes/Duplicate.py b/cmsisdsp/cg/nodes/Duplicate.py similarity index 95% rename from cmsisdsp/cg/static/nodes/Duplicate.py rename to cmsisdsp/cg/nodes/Duplicate.py index ab86284c..aa977999 100644 --- a/cmsisdsp/cg/static/nodes/Duplicate.py +++ b/cmsisdsp/cg/nodes/Duplicate.py @@ -8,7 +8,7 @@ # Target Processor: Cortex-M and Cortex-A cores # -------------------------------------------------------------------- */ # -# Copyright (C) 2010-2022 ARM Limited or its affiliates. All rights reserved. +# Copyright (C) 2010-2023 ARM Limited or its affiliates. All rights reserved. # # SPDX-License-Identifier: Apache-2.0 # diff --git a/cmsisdsp/cg/static/nodes/ICFFT.py b/cmsisdsp/cg/nodes/ICFFT.py similarity index 95% rename from cmsisdsp/cg/static/nodes/ICFFT.py rename to cmsisdsp/cg/nodes/ICFFT.py index 81a30e3c..575b1b22 100644 --- a/cmsisdsp/cg/static/nodes/ICFFT.py +++ b/cmsisdsp/cg/nodes/ICFFT.py @@ -9,7 +9,7 @@ # Target Processor: Cortex-M and Cortex-A cores # -------------------------------------------------------------------- */ # -# Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. +# Copyright (C) 2010-2023 ARM Limited or its affiliates. All rights reserved. # # SPDX-License-Identifier: Apache-2.0 # diff --git a/cmsisdsp/cg/static/nodes/InterleavedStereoToMono.py b/cmsisdsp/cg/nodes/InterleavedStereoToMono.py similarity index 95% rename from cmsisdsp/cg/static/nodes/InterleavedStereoToMono.py rename to cmsisdsp/cg/nodes/InterleavedStereoToMono.py index 20a5bae1..10e9d126 100644 --- a/cmsisdsp/cg/static/nodes/InterleavedStereoToMono.py +++ b/cmsisdsp/cg/nodes/InterleavedStereoToMono.py @@ -9,7 +9,7 @@ # Target Processor: Cortex-M and Cortex-A cores # -------------------------------------------------------------------- */ # -# Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. +# Copyright (C) 2010-2023 ARM Limited or its affiliates. All rights reserved. # # SPDX-License-Identifier: Apache-2.0 # diff --git a/cmsisdsp/cg/static/nodes/MFCC.py b/cmsisdsp/cg/nodes/MFCC.py similarity index 95% rename from cmsisdsp/cg/static/nodes/MFCC.py rename to cmsisdsp/cg/nodes/MFCC.py index cace21b3..e90f2345 100644 --- a/cmsisdsp/cg/static/nodes/MFCC.py +++ b/cmsisdsp/cg/nodes/MFCC.py @@ -9,7 +9,7 @@ # Target Processor: Cortex-M and Cortex-A cores # -------------------------------------------------------------------- */ # -# Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. +# Copyright (C) 2010-2023 ARM Limited or its affiliates. All rights reserved. # # SPDX-License-Identifier: Apache-2.0 # diff --git a/cmsisdsp/cg/static/nodes/NullSink.py b/cmsisdsp/cg/nodes/NullSink.py similarity index 94% rename from cmsisdsp/cg/static/nodes/NullSink.py rename to cmsisdsp/cg/nodes/NullSink.py index 71055484..27133448 100644 --- a/cmsisdsp/cg/static/nodes/NullSink.py +++ b/cmsisdsp/cg/nodes/NullSink.py @@ -9,7 +9,7 @@ # Target Processor: Cortex-M and Cortex-A cores # -------------------------------------------------------------------- */ # -# Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. +# Copyright (C) 2010-2023 ARM Limited or its affiliates. All rights reserved. # # SPDX-License-Identifier: Apache-2.0 # diff --git a/cmsisdsp/cg/static/nodes/ToComplex.py b/cmsisdsp/cg/nodes/ToComplex.py similarity index 94% rename from cmsisdsp/cg/static/nodes/ToComplex.py rename to cmsisdsp/cg/nodes/ToComplex.py index 9a22923c..d8d696e1 100644 --- a/cmsisdsp/cg/static/nodes/ToComplex.py +++ b/cmsisdsp/cg/nodes/ToComplex.py @@ -9,7 +9,7 @@ # Target Processor: Cortex-M and Cortex-A cores # -------------------------------------------------------------------- */ # -# Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. +# Copyright (C) 2010-2023 ARM Limited or its affiliates. All rights reserved. # # SPDX-License-Identifier: Apache-2.0 # diff --git a/cmsisdsp/cg/static/nodes/ToReal.py b/cmsisdsp/cg/nodes/ToReal.py similarity index 94% rename from cmsisdsp/cg/static/nodes/ToReal.py rename to cmsisdsp/cg/nodes/ToReal.py index d379a700..9a65ac61 100644 --- a/cmsisdsp/cg/static/nodes/ToReal.py +++ b/cmsisdsp/cg/nodes/ToReal.py @@ -9,7 +9,7 @@ # Target Processor: Cortex-M and Cortex-A cores # -------------------------------------------------------------------- */ # -# Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. +# Copyright (C) 2010-2023 ARM Limited or its affiliates. All rights reserved. # # SPDX-License-Identifier: Apache-2.0 # diff --git a/cmsisdsp/cg/static/nodes/Unzip.py b/cmsisdsp/cg/nodes/Unzip.py similarity index 94% rename from cmsisdsp/cg/static/nodes/Unzip.py rename to cmsisdsp/cg/nodes/Unzip.py index 1fdf0497..f3f98395 100644 --- a/cmsisdsp/cg/static/nodes/Unzip.py +++ b/cmsisdsp/cg/nodes/Unzip.py @@ -9,7 +9,7 @@ # Target Processor: Cortex-M and Cortex-A cores # -------------------------------------------------------------------- */ # -# Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. +# Copyright (C) 2010-2023 ARM Limited or its affiliates. All rights reserved. # # SPDX-License-Identifier: Apache-2.0 # diff --git a/cmsisdsp/cg/static/nodes/Zip.py b/cmsisdsp/cg/nodes/Zip.py similarity index 95% rename from cmsisdsp/cg/static/nodes/Zip.py rename to cmsisdsp/cg/nodes/Zip.py index a7147baa..dedfa023 100644 --- a/cmsisdsp/cg/static/nodes/Zip.py +++ b/cmsisdsp/cg/nodes/Zip.py @@ -9,7 +9,7 @@ # Target Processor: Cortex-M and Cortex-A cores # -------------------------------------------------------------------- */ # -# Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. +# Copyright (C) 2010-2023 ARM Limited or its affiliates. All rights reserved. # # SPDX-License-Identifier: Apache-2.0 # diff --git a/cmsisdsp/cg/static/nodes/__init__.py b/cmsisdsp/cg/nodes/__init__.py similarity index 90% rename from cmsisdsp/cg/static/nodes/__init__.py rename to cmsisdsp/cg/nodes/__init__.py index ac29b6d4..a6459239 100644 --- a/cmsisdsp/cg/static/nodes/__init__.py +++ b/cmsisdsp/cg/nodes/__init__.py @@ -1,7 +1,7 @@ ########################################### # Project: CMSIS DSP Library # Title: __init__.py -# Description: CG static flow module +# Description: CG default nodes # # $Date: 30 August 2021 # $Revision: V1.10.0 @@ -9,7 +9,7 @@ # Target Processor: Cortex-M and Cortex-A cores # -------------------------------------------------------------------- */ # -# Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. +# Copyright (C) 2010-2023 ARM Limited or its affiliates. All rights reserved. # # SPDX-License-Identifier: Apache-2.0 # diff --git a/cmsisdsp/cg/static/nodes/host/FileSink.py b/cmsisdsp/cg/nodes/host/FileSink.py similarity index 95% rename from cmsisdsp/cg/static/nodes/host/FileSink.py rename to cmsisdsp/cg/nodes/host/FileSink.py index f9b0b752..612fd282 100644 --- a/cmsisdsp/cg/static/nodes/host/FileSink.py +++ b/cmsisdsp/cg/nodes/host/FileSink.py @@ -9,7 +9,7 @@ # Target Processor: Cortex-M and Cortex-A cores # -------------------------------------------------------------------- */ # -# Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. +# Copyright (C) 2010-2023 ARM Limited or its affiliates. All rights reserved. # # SPDX-License-Identifier: Apache-2.0 # diff --git a/cmsisdsp/cg/static/nodes/host/FileSource.py b/cmsisdsp/cg/nodes/host/FileSource.py similarity index 94% rename from cmsisdsp/cg/static/nodes/host/FileSource.py rename to cmsisdsp/cg/nodes/host/FileSource.py index 18b41039..348684e3 100644 --- a/cmsisdsp/cg/static/nodes/host/FileSource.py +++ b/cmsisdsp/cg/nodes/host/FileSource.py @@ -9,7 +9,7 @@ # Target Processor: Cortex-M and Cortex-A cores # -------------------------------------------------------------------- */ # -# Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. +# Copyright (C) 2010-2023 ARM Limited or its affiliates. All rights reserved. # # SPDX-License-Identifier: Apache-2.0 # diff --git a/cmsisdsp/cg/static/nodes/host/NumpySink.py b/cmsisdsp/cg/nodes/host/NumpySink.py similarity index 95% rename from cmsisdsp/cg/static/nodes/host/NumpySink.py rename to cmsisdsp/cg/nodes/host/NumpySink.py index 5283a306..c69eacde 100644 --- a/cmsisdsp/cg/static/nodes/host/NumpySink.py +++ b/cmsisdsp/cg/nodes/host/NumpySink.py @@ -9,7 +9,7 @@ # Target Processor: Cortex-M and Cortex-A cores # -------------------------------------------------------------------- */ # -# Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. +# Copyright (C) 2010-2023 ARM Limited or its affiliates. All rights reserved. # # SPDX-License-Identifier: Apache-2.0 # diff --git a/cmsisdsp/cg/static/nodes/host/VHT.py b/cmsisdsp/cg/nodes/host/VHT.py similarity index 98% rename from cmsisdsp/cg/static/nodes/host/VHT.py rename to cmsisdsp/cg/nodes/host/VHT.py index d3c10c23..102d7d1e 100644 --- a/cmsisdsp/cg/static/nodes/host/VHT.py +++ b/cmsisdsp/cg/nodes/host/VHT.py @@ -1,7 +1,7 @@ from multiprocessing import Process,Semaphore import multiprocessing as mp import socket -import cmsisdsp.cg.static.nodes.host.message as msg +import cmsisdsp.cg.nodes.host.message as msg HOST = '127.0.0.1' # The remote host PORT = 50007 diff --git a/cmsisdsp/cg/static/nodes/host/VHTCGSTATIC.py b/cmsisdsp/cg/nodes/host/VHTCGSTATIC.py similarity index 100% rename from cmsisdsp/cg/static/nodes/host/VHTCGSTATIC.py rename to cmsisdsp/cg/nodes/host/VHTCGSTATIC.py diff --git a/cmsisdsp/cg/static/nodes/host/WavSink.py b/cmsisdsp/cg/nodes/host/WavSink.py similarity index 95% rename from cmsisdsp/cg/static/nodes/host/WavSink.py rename to cmsisdsp/cg/nodes/host/WavSink.py index cae8ed34..2ba6519c 100644 --- a/cmsisdsp/cg/static/nodes/host/WavSink.py +++ b/cmsisdsp/cg/nodes/host/WavSink.py @@ -9,7 +9,7 @@ # Target Processor: Cortex-M and Cortex-A cores # -------------------------------------------------------------------- */ # -# Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. +# Copyright (C) 2010-2023 ARM Limited or its affiliates. All rights reserved. # # SPDX-License-Identifier: Apache-2.0 # diff --git a/cmsisdsp/cg/static/nodes/host/WavSource.py b/cmsisdsp/cg/nodes/host/WavSource.py similarity index 100% rename from cmsisdsp/cg/static/nodes/host/WavSource.py rename to cmsisdsp/cg/nodes/host/WavSource.py diff --git a/cmsisdsp/cg/static/nodes/host/__init__.py b/cmsisdsp/cg/nodes/host/__init__.py similarity index 100% rename from cmsisdsp/cg/static/nodes/host/__init__.py rename to cmsisdsp/cg/nodes/host/__init__.py diff --git a/cmsisdsp/cg/static/nodes/host/message.py b/cmsisdsp/cg/nodes/host/message.py similarity index 98% rename from cmsisdsp/cg/static/nodes/host/message.py rename to cmsisdsp/cg/nodes/host/message.py index 25df7d16..f7c77704 100644 --- a/cmsisdsp/cg/static/nodes/host/message.py +++ b/cmsisdsp/cg/nodes/host/message.py @@ -107,7 +107,7 @@ def getBufferMsg(conn,nbBytes): data = receiveBytes(conn,nbBytes) return(data) -# Stop the server when the end of the static scheduling has been reached. +# Stop the server when the end of the scheduling has been reached. # It is to make it easier to end the demo. # Only the VHT client has to be killed. # Client -> Server diff --git a/cmsisdsp/cg/static/nodes/simu.py b/cmsisdsp/cg/nodes/simu.py similarity index 99% rename from cmsisdsp/cg/static/nodes/simu.py rename to cmsisdsp/cg/nodes/simu.py index 4e1387f3..5afef587 100644 --- a/cmsisdsp/cg/static/nodes/simu.py +++ b/cmsisdsp/cg/nodes/simu.py @@ -9,7 +9,7 @@ # Target Processor: Cortex-M and Cortex-A cores # -------------------------------------------------------------------- */ # -# Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. +# Copyright (C) 2010-2023 ARM Limited or its affiliates. All rights reserved. # # SPDX-License-Identifier: Apache-2.0 # diff --git a/cmsisdsp/cg/static/scheduler/__init__.py b/cmsisdsp/cg/scheduler/__init__.py similarity index 100% rename from cmsisdsp/cg/static/scheduler/__init__.py rename to cmsisdsp/cg/scheduler/__init__.py diff --git a/cmsisdsp/cg/static/scheduler/ccode.py b/cmsisdsp/cg/scheduler/ccode.py similarity index 89% rename from cmsisdsp/cg/static/scheduler/ccode.py rename to cmsisdsp/cg/scheduler/ccode.py index b0851530..00cccfce 100644 --- a/cmsisdsp/cg/static/scheduler/ccode.py +++ b/cmsisdsp/cg/scheduler/ccode.py @@ -1,7 +1,7 @@ ########################################### # Project: CMSIS DSP Library # Title: ccode.py -# Description: C++ code generator for static scheduler +# Description: C++ code generator for scheduler # # $Date: 29 July 2021 # $Revision: V1.10.0 @@ -34,13 +34,19 @@ def gencode(sched,directory,config): env = Environment( - loader=PackageLoader("cmsisdsp.cg.static.scheduler"), + loader=PackageLoader("cmsisdsp.cg.scheduler"), autoescape=select_autoescape(), trim_blocks=True ) schedDescription="" + # Asychronous implies code array and switchCase + if config.asynchronous: + config.codeArray = True + config.switchCase = True + config.memoryOptimization = False + if config.codeArray: if config.switchCase: ctemplate = env.get_template("codeSwitch.cpp") diff --git a/cmsisdsp/cg/static/scheduler/config.py b/cmsisdsp/cg/scheduler/config.py similarity index 85% rename from cmsisdsp/cg/static/scheduler/config.py rename to cmsisdsp/cg/scheduler/config.py index 197e808c..04558a02 100644 --- a/cmsisdsp/cg/static/scheduler/config.py +++ b/cmsisdsp/cg/scheduler/config.py @@ -123,6 +123,26 @@ class Configuration: # By default arm_math.h is included self.CMSISDSP = True + # Asynchronous scheduling using + # synchronous as first start + # It implies switchCase and codeArray + # It disables memory optimizations + # Also FIFO cannot be used any more as just + # buffers. + self.asynchronous = False + + # Increase in percent of the FIFOs. + # Used in asynchronous mode + # where the FIFOs may need to be bigger + # than what is computed assuming a + # synchronous scheduling. + self.FIFOIncrease = 0 + + # Default asynchronous more for pure functions + # like CMSIS-DSP + self.asyncDefaultSkip = True + + @property def debug(self): return (self.debugLimit > 0) diff --git a/cmsisdsp/cg/static/scheduler/description.py b/cmsisdsp/cg/scheduler/description.py similarity index 95% rename from cmsisdsp/cg/static/scheduler/description.py rename to cmsisdsp/cg/scheduler/description.py index 600f773e..2f81515e 100644 --- a/cmsisdsp/cg/static/scheduler/description.py +++ b/cmsisdsp/cg/scheduler/description.py @@ -9,7 +9,7 @@ # Target Processor: Cortex-M and Cortex-A cores # -------------------------------------------------------------------- */ # -# Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. +# Copyright (C) 2010-2023 ARM Limited or its affiliates. All rights reserved. # # SPDX-License-Identifier: Apache-2.0 # @@ -29,12 +29,14 @@ import networkx as nx import numpy as np +import math + from sympy import Matrix from sympy.core.numbers import ilcm,igcd -import cmsisdsp.cg.static.scheduler.graphviz -import cmsisdsp.cg.static.scheduler.ccode -import cmsisdsp.cg.static.scheduler.pythoncode +import cmsisdsp.cg.scheduler.graphviz +import cmsisdsp.cg.scheduler.ccode +import cmsisdsp.cg.scheduler.pythoncode from .node import * from .config import * @@ -72,7 +74,7 @@ class FifoBuffer: class FIFODesc: """A FIFO connecting two nodes""" - def __init__(self,fifoid): + def __init__(self,fifoid,fifoClass): # The FIFO is in fact just an array self.isArray=False # FIFO length @@ -90,7 +92,7 @@ class FIFODesc: self.dst = None # FIFO delay self.delay=0 - self.fifoClass = "FIFO" + self.fifoClass = fifoClass # Used for liveliness analysis # To share buffers between FIFO in memory optimization @@ -177,6 +179,13 @@ class Graph(): # (prioritizing the scheduling of nodes # close to the graph output) self._topologicalSort=[] + self.defaultFIFOClass = "FIFO" + + # Prefix used to generate the class names + # of the duplicate nodes like Duplicate2, + # Duplicate3 ... + self.duplicateNodeClassName = "Duplicate" + def computeTopologicalSortOfNodes(self): remaining = self._sortedNodes.copy() @@ -213,7 +222,7 @@ class Graph(): #print(self._topologicalSort) - def connectDup(self,destination,outputIO,theId,fifoClass="FIFO"): + def connectDup(self,destination,outputIO,theId): if (destination[theId][1]!=0): self.connectWithDelay(outputIO,destination[theId][0],destination[theId][1],dupAllowed=False,fifoClass=destination[theId][2]) else: @@ -261,10 +270,10 @@ class Graph(): # We create a duplicate node if len(fifo)==2: - dup = Duplicate2("dup%d" % dupNb,theType,inputSize) + dup = Duplicate2("dup%d" % dupNb,theType,inputSize,className=self.duplicateNodeClassName) if len(fifo)==3: - dup = Duplicate3("dup%d" % dupNb,theType,inputSize) + dup = Duplicate3("dup%d" % dupNb,theType,inputSize,className=self.duplicateNodeClassName) #print(dup) @@ -289,7 +298,7 @@ class Graph(): nodea = f[0] nodeb = f[1] - fifoClass = "FIFO" + fifoClass = self.defaultFIFOClass if (nodea,nodeb) in self._FIFOClasses: fifoClass = self._FIFOClasses[(nodea,nodeb)] @@ -342,7 +351,9 @@ class Graph(): - def connect(self,nodea,nodeb,dupAllowed=True,fifoClass="FIFO"): + def connect(self,nodea,nodeb,dupAllowed=True,fifoClass=None): + if fifoClass is None: + fifoClass = self.defaultFIFOClass # When connecting to a constant node we do nothing # since there is no FIFO in this case # and it does not participate to the scheduling. @@ -370,7 +381,9 @@ class Graph(): else: raise IncompatibleIO - def connectWithDelay(self,nodea,nodeb,delay,dupAllowed=True,fifoClass="FIFO"): + def connectWithDelay(self,nodea,nodeb,delay,dupAllowed=True,fifoClass=None): + if fifoClass is None: + fifoClass = self.defaultFIFOClass # We cannot connect with delay to a constant node if (isinstance(nodea,Constant)): raise CannotDelayConstantError @@ -392,7 +405,10 @@ class Graph(): """Initialize FIFOs datastructure""" for fifo in allFIFOs: edge = self._sortedEdges[fifo.fifoID] - fifo.length = fifoLengths[fifo.fifoID] + if config.asynchronous: + fifo.length = int(math.ceil(fifoLengths[fifo.fifoID] * (1.0 + 1.0*config.FIFOIncrease/100))) + else: + fifo.length = fifoLengths[fifo.fifoID] src,dst = edge if edge in self._FIFOClasses: fifoClass = self._FIFOClasses[edge] @@ -404,7 +420,8 @@ class Graph(): # potentially be shared with other FIFOs workign as arrays if src.nbSamples == dst.nbSamples: if fifo.delay==0: - fifo.isArray = True + if not config.asynchronous: + fifo.isArray = True fifo.theType = src.theType #fifo.dump() @@ -415,7 +432,11 @@ class Graph(): # Compute a graph describing when FIFOs are used at the same time # Then use graph coloring to allocate buffer to those FIFOs. # Then size the buffer based on the longest FIFO using it - if config.memoryOptimization: + # Memory optimizations are disabled by the asynchronous mode + # because the execution is no more periodic. + # So anything deduced from a synchronous period + # can't be used. + if config.memoryOptimization and not config.asynchronous: G = nx.Graph() for fifo in allFIFOs: @@ -512,7 +533,7 @@ class Graph(): bufferID = bufferID + 1 for fifo in allFIFOs: # Use shared buffer if memory optimization - if fifo.isArray and config.memoryOptimization: + if fifo.isArray and (config.memoryOptimization and not config.asynchronous): fifo.buffer=allBuffers[fifo.sharedNB] fifo.bufferID=fifo.sharedNB # Create a new buffer for a real FIFO @@ -631,7 +652,7 @@ class Graph(): def evolutionVectorForNode(self,nodeID,test=True): """Return the evolution vector corresponding to a selected node""" - # For a simple static scheduling, the toplogy matrix T + # For a simple static scheduling, the topology matrix T # is enough. If we know which node is executed, we have # a node vector V where there is a 1 at the position of the # execute node. @@ -845,7 +866,7 @@ class Graph(): nbFIFOS = t.shape[0] allFIFOs = [] for i in range(nbFIFOS): - allFIFOs.append(FIFODesc(i)) + allFIFOs.append(FIFODesc(i,self.defaultFIFOClass)) # Normalization vector # For static scheduling it is @@ -1103,15 +1124,15 @@ class Schedule: def ccode(self,directory,config=Configuration()): """Write graphviz into file f""" - cmsisdsp.cg.static.scheduler.ccode.gencode(self,directory,config) + cmsisdsp.cg.scheduler.ccode.gencode(self,directory,config) def pythoncode(self,directory,config=Configuration()): """Write graphviz into file f""" - cmsisdsp.cg.static.scheduler.pythoncode.gencode(self,directory,config) + cmsisdsp.cg.scheduler.pythoncode.gencode(self,directory,config) def graphviz(self,f,config=Configuration()): """Write graphviz into file f""" - cmsisdsp.cg.static.scheduler.graphviz.gengraph(self,f,config) + cmsisdsp.cg.scheduler.graphviz.gengraph(self,f,config) diff --git a/cmsisdsp/cg/static/scheduler/graphviz.py b/cmsisdsp/cg/scheduler/graphviz.py similarity index 95% rename from cmsisdsp/cg/static/scheduler/graphviz.py rename to cmsisdsp/cg/scheduler/graphviz.py index 0924bac3..242b47f3 100644 --- a/cmsisdsp/cg/static/scheduler/graphviz.py +++ b/cmsisdsp/cg/scheduler/graphviz.py @@ -32,7 +32,7 @@ import os.path def gengraph(sched,f,config): env = Environment( - loader=PackageLoader("cmsisdsp.cg.static.scheduler"), + loader=PackageLoader("cmsisdsp.cg.scheduler"), autoescape=select_autoescape(), trim_blocks=True ) diff --git a/cmsisdsp/cg/static/scheduler/node.py b/cmsisdsp/cg/scheduler/node.py similarity index 92% rename from cmsisdsp/cg/static/scheduler/node.py rename to cmsisdsp/cg/scheduler/node.py index 3f20d969..97909947 100644 --- a/cmsisdsp/cg/static/scheduler/node.py +++ b/cmsisdsp/cg/scheduler/node.py @@ -37,6 +37,8 @@ from sympy.core.numbers import ilcm class NoFunctionArrayInPython(Exception): pass +class NoAsynchronousModeInPython(Exception): + pass def camelCase(st): output = ''.join(x for x in st.title() if x.isalnum()) @@ -579,6 +581,15 @@ class GenericNode(BaseNode): def __init__(self,name): BaseNode.__init__(self,name) + # Pure node is for instance a + # CMSIS-DSP function. + # It is not packaged into an object + # and the code is generated directly + self._isPureNode = False + + @property + def isPureNode(self): + return self._isPureNode @property def typeName(self): @@ -668,13 +679,14 @@ class GenericFunction(GenericNode): ENV = Environment( - loader=PackageLoader("cmsisdsp.cg.static.scheduler"), + loader=PackageLoader("cmsisdsp.cg.scheduler"), autoescape=select_autoescape(), lstrip_blocks=True, trim_blocks=True ) CTEMPLATE = ENV.get_template("cmsis.cpp") + CCHECKTEMPLATE = ENV.get_template("cmsisCheck.cpp") CNODETEMPLATE = ENV.get_template("cmsisNode.cpp") PYTEMPLATE = ENV.get_template("cmsis.py") @@ -690,6 +702,7 @@ class GenericFunction(GenericNode): self._hasState = False self._length = length self._nodeName = funcname + self._isPureNode = True GenericFunction.NODEID[funcname]=GenericFunction.NODEID[funcname]+1 @@ -836,14 +849,18 @@ class GenericFunction(GenericNode): def typeName(self): return "Function" - # To clean - def cRun(self,ctemplate=True,codeArray=False): + # Prepare for code generation. + # All those values are used in the + # code generation template + # They are both used for the run part + # and the prepareForRunning part + def _prepareForCodeGen(self,ctemplate=True): if ctemplate: theType=self._inputs[self.inputNames[0]].ctype else: theType=self._inputs[self.inputNames[0]].nptype # For cyclo static scheduling, nbSamples may be a list - # and in this case we are uding the mac value + # and in this case we are using the max value nbSamples = self._inputs[self.inputNames[0]].nbSamples if isinstance(nbSamples,int): theLen = self._inputs[self.inputNames[0]].nbSamples @@ -901,37 +918,65 @@ class GenericFunction(GenericNode): inArgsStr="".join(joinit(inargs,",")) outArgsStr="".join(joinit(outargs,",")) + return ({"theType" : theType, + "nb" : theLen, + "ptrs" : ptrs, + "args" : argsStr, + "inArgsStr" : inArgsStr, + "outArgsStr" :outArgsStr, + "inputs":inputs, + "outputs":outputs}) + + def cCheck(self,asyncDefaultSkip=True): + params = self._prepareForCodeGen(True) + result=Dsp.CCHECKTEMPLATE.render(func=self._nodeName, + theType = params["theType"], + nb = params["nb"], + ptrs = params["ptrs"], + args = params["args"], + inputs=params["inputs"], + outputs=params["outputs"], + node=self, + asyncDefaultSkip = asyncDefaultSkip + ) + return(result) + + + # To clean + def cRun(self,ctemplate=True,codeArray=False): + params = self._prepareForCodeGen(ctemplate) + if ctemplate: if codeArray: result=Dsp.CNODETEMPLATE.render(func=self._nodeName, - theType = theType, - nb = theLen, - ptrs = ptrs, - args = argsStr, - inputs=inputs, - outputs=outputs, + theType = params["theType"], + nb = params["nb"], + ptrs = params["ptrs"], + args = params["args"], + inputs=params["inputs"], + outputs=params["outputs"], node=self ) else: result=Dsp.CTEMPLATE.render(func=self._nodeName, - theType = theType, - nb = theLen, - ptrs = ptrs, - args = argsStr, - inputs=inputs, - outputs=outputs, + theType = params["theType"], + nb = params["nb"], + ptrs = params["ptrs"], + args = params["args"], + inputs=params["inputs"], + outputs=params["outputs"], node=self ) else: result=Dsp.PYTEMPLATE.render(func=self._nodeName, - theType = theType, - nb = theLen, - ptrs = ptrs, - args = argsStr, - inArgs= inArgsStr, - outArgs= outArgsStr, - inputs=inputs, - outputs=outputs, + theType = params["theType"], + nb = params["nb"], + ptrs = params["ptrs"], + args = params["args"], + inArgs= params["inArgsStr"], + outArgs= params["outArgsStr"], + inputs=params["inputs"], + outputs=params["outputs"], node=self ) return(result) diff --git a/cmsisdsp/cg/static/scheduler/pythoncode.py b/cmsisdsp/cg/scheduler/pythoncode.py similarity index 95% rename from cmsisdsp/cg/static/scheduler/pythoncode.py rename to cmsisdsp/cg/scheduler/pythoncode.py index 3430d234..9d0dddb0 100644 --- a/cmsisdsp/cg/static/scheduler/pythoncode.py +++ b/cmsisdsp/cg/scheduler/pythoncode.py @@ -33,7 +33,7 @@ from .config import * def gencode(sched,directory,config): env = Environment( - loader=PackageLoader("cmsisdsp.cg.static.scheduler"), + loader=PackageLoader("cmsisdsp.cg.scheduler"), autoescape=select_autoescape(), trim_blocks=True ) diff --git a/cmsisdsp/cg/static/scheduler/standard.py b/cmsisdsp/cg/scheduler/standard.py similarity index 95% rename from cmsisdsp/cg/static/scheduler/standard.py rename to cmsisdsp/cg/scheduler/standard.py index e5894256..844800c6 100644 --- a/cmsisdsp/cg/static/scheduler/standard.py +++ b/cmsisdsp/cg/scheduler/standard.py @@ -137,9 +137,11 @@ class MFCC(GenericNode): return "MFCC" class Duplicate2(GenericNode): - def __init__(self,name,theType,inLength): + def __init__(self,name,theType,inLength,className="Duplicate"): GenericNode.__init__(self,name) + self._className = className + self.addInput("i",theType,inLength) self.addOutput("oa",theType,inLength) self.addOutput("ob",theType,inLength) @@ -150,12 +152,14 @@ class Duplicate2(GenericNode): @property def typeName(self): - return "Duplicate2" + return ("%s2" % self._className) class Duplicate3(GenericNode): - def __init__(self,name,theType,inLength): + def __init__(self,name,theType,inLength,className="Duplicate"): GenericNode.__init__(self,name) + self._className = className + self.addInput("i",theType,inLength) self.addOutput("oa",theType,inLength) self.addOutput("ob",theType,inLength) @@ -167,7 +171,7 @@ class Duplicate3(GenericNode): @property def typeName(self): - return "Duplicate3" + return ("%s3" % self._className) ############################# # diff --git a/cmsisdsp/cg/scheduler/templates/cmsis.cpp b/cmsisdsp/cg/scheduler/templates/cmsis.cpp new file mode 100644 index 00000000..e378fc9e --- /dev/null +++ b/cmsisdsp/cg/scheduler/templates/cmsis.cpp @@ -0,0 +1,15 @@ + + { + +{% for ptr in ptrs %} + {{theType}}* {{ptr}}; +{% endfor %} +{% for ptr in inputs %} + {{ptr[0]}}={{ptr[1]}}.getReadBuffer({{nb}}); +{% endfor %} +{% for ptr in outputs %} + {{ptr[0]}}={{ptr[1]}}.getWriteBuffer({{nb}}); +{% endfor %} + {{func}}({{args}},{{nb}}); + cgStaticError = 0; + } \ No newline at end of file diff --git a/cmsisdsp/cg/static/scheduler/templates/cmsis.py b/cmsisdsp/cg/scheduler/templates/cmsis.py similarity index 100% rename from cmsisdsp/cg/static/scheduler/templates/cmsis.py rename to cmsisdsp/cg/scheduler/templates/cmsis.py diff --git a/cmsisdsp/cg/scheduler/templates/cmsisCheck.cpp b/cmsisdsp/cg/scheduler/templates/cmsisCheck.cpp new file mode 100644 index 00000000..052ebdd5 --- /dev/null +++ b/cmsisdsp/cg/scheduler/templates/cmsisCheck.cpp @@ -0,0 +1,21 @@ + + bool canRun=true; +{% for ptr in inputs %} + canRun &= !{{ptr[1]}}.willUnderflowWith({{nb}}); +{% endfor %} +{% for ptr in outputs %} + canRun &= !{{ptr[1]}}.willOverflowWith({{nb}}); +{% endfor %} + + if (!canRun) + { +{% if asyncDefaultSkip %} + cgStaticError = CG_SKIP_EXECUTION_ID_CODE; +{% else %} + cgStaticError = CG_BUFFER_ERROR_ID_CODE; +{%- endif %} + } + else + { + cgStaticError = 0; + } \ No newline at end of file diff --git a/cmsisdsp/cg/static/scheduler/templates/cmsisNode.cpp b/cmsisdsp/cg/scheduler/templates/cmsisNode.cpp similarity index 100% rename from cmsisdsp/cg/static/scheduler/templates/cmsisNode.cpp rename to cmsisdsp/cg/scheduler/templates/cmsisNode.cpp diff --git a/cmsisdsp/cg/static/scheduler/templates/code.cpp b/cmsisdsp/cg/scheduler/templates/code.cpp similarity index 100% rename from cmsisdsp/cg/static/scheduler/templates/code.cpp rename to cmsisdsp/cg/scheduler/templates/code.cpp diff --git a/cmsisdsp/cg/static/scheduler/templates/code.h b/cmsisdsp/cg/scheduler/templates/code.h similarity index 100% rename from cmsisdsp/cg/static/scheduler/templates/code.h rename to cmsisdsp/cg/scheduler/templates/code.h diff --git a/cmsisdsp/cg/static/scheduler/templates/code.py b/cmsisdsp/cg/scheduler/templates/code.py similarity index 96% rename from cmsisdsp/cg/static/scheduler/templates/code.py rename to cmsisdsp/cg/scheduler/templates/code.py index 1afcf57b..3ebf391a 100644 --- a/cmsisdsp/cg/static/scheduler/templates/code.py +++ b/cmsisdsp/cg/scheduler/templates/code.py @@ -10,7 +10,7 @@ import sys import numpy as np import cmsisdsp as dsp -from cmsisdsp.cg.static.nodes.simu import * +from cmsisdsp.cg.nodes.simu import * from {{config.appNodesPythonName}} import * from {{config.customPythonName}} import * diff --git a/cmsisdsp/cg/static/scheduler/templates/codeArray.cpp b/cmsisdsp/cg/scheduler/templates/codeArray.cpp similarity index 100% rename from cmsisdsp/cg/static/scheduler/templates/codeArray.cpp rename to cmsisdsp/cg/scheduler/templates/codeArray.cpp diff --git a/cmsisdsp/cg/static/scheduler/templates/codeSwitch.cpp b/cmsisdsp/cg/scheduler/templates/codeSwitch.cpp similarity index 52% rename from cmsisdsp/cg/static/scheduler/templates/codeSwitch.cpp rename to cmsisdsp/cg/scheduler/templates/codeSwitch.cpp index 551a83f9..494e3e78 100644 --- a/cmsisdsp/cg/static/scheduler/templates/codeSwitch.cpp +++ b/cmsisdsp/cg/scheduler/templates/codeSwitch.cpp @@ -31,12 +31,58 @@ static unsigned int schedule[{{schedLen}}]= EventRecord2 (Evt_Node, schedule[id], 0); {% endif -%} CG_BEFORE_NODE_EXECUTION; + + {% if config.asynchronous -%} + cgStaticError = 0; + switch(schedule[id]) + { + {% for nodeID in range(nbNodes) -%} + case {{nodeID}}: + { + {% if not nodes[nodeID].isPureNode -%} + cgStaticError = {{nodes[nodeID].nodeName}}.prepareForRunning(); + {%- else -%} + {{nodes[nodeID].cCheck(config.asyncDefaultSkip)}} + {%- endif %} + + } + break; + + {% endfor -%} + + default: + break; + } + + if (cgStaticError == CG_SKIP_EXECUTION_ID_CODE) + continue; + + {% if config.eventRecorder -%} + if (cgStaticError<0) + { + EventRecord2 (Evt_Error, cgStaticError, 0); + } + {% endif -%} + + CHECKERROR; + + {% endif -%} + switch(schedule[id]) { {% for nodeID in range(nbNodes) -%} case {{nodeID}}: { {{nodes[nodeID].cRun()}} + + {%- if config.dumpFIFO %} + {%- for fifoID in sched.outputFIFOs(nodes[nodeID]) %} + + std::cout << "{{nodes[nodeID].nodeName}}:{{fifoID[1]}}" << std::endl; + fifo{{fifoID[0]}}.dump(); + {%- endfor %} + {%- endif %} + } break; diff --git a/cmsisdsp/cg/static/scheduler/templates/commonc.cpp b/cmsisdsp/cg/scheduler/templates/commonc.cpp similarity index 85% rename from cmsisdsp/cg/static/scheduler/templates/commonc.cpp rename to cmsisdsp/cg/scheduler/templates/commonc.cpp index 1480f3eb..bef27552 100644 --- a/cmsisdsp/cg/static/scheduler/templates/commonc.cpp +++ b/cmsisdsp/cg/scheduler/templates/commonc.cpp @@ -31,6 +31,10 @@ CG_AFTER_INCLUDES {% if config.cOptionalArgs %},{{config.cOptionalArgs}}{% endif %} {% endmacro -%} +{% macro async() -%} +{% if config.asynchronous %}1{% else %}0{% endif %} +{% endmacro %} + {% block schedArray %} {% endblock %} @@ -66,9 +70,9 @@ uint32_t {{config.schedName}}(int *error{{optionalargs()}}) */ {% for id in range(nbFifos) %} {% if fifos[id].hasDelay %} - {{fifos[id].fifoClass}}<{{fifos[id].theType.ctype}},FIFOSIZE{{id}},{{fifos[id].isArrayAsInt}}> fifo{{id}}({{config.prefix}}buf{{fifos[id].buffer._bufferID}},{{fifos[id].delay}}); + {{fifos[id].fifoClass}}<{{fifos[id].theType.ctype}},FIFOSIZE{{id}},{{fifos[id].isArrayAsInt}},{{async()}}> fifo{{id}}({{config.prefix}}buf{{fifos[id].buffer._bufferID}},{{fifos[id].delay}}); {% else %} - {{fifos[id].fifoClass}}<{{fifos[id].theType.ctype}},FIFOSIZE{{id}},{{fifos[id].isArrayAsInt}}> fifo{{id}}({{config.prefix}}buf{{fifos[id].buffer._bufferID}}); + {{fifos[id].fifoClass}}<{{fifos[id].theType.ctype}},FIFOSIZE{{id}},{{fifos[id].isArrayAsInt}},{{async()}}> fifo{{id}}({{config.prefix}}buf{{fifos[id].buffer._bufferID}}); {% endif %} {% endfor %} diff --git a/cmsisdsp/cg/static/scheduler/templates/defineConfig.h b/cmsisdsp/cg/scheduler/templates/defineConfig.h similarity index 100% rename from cmsisdsp/cg/static/scheduler/templates/defineConfig.h rename to cmsisdsp/cg/scheduler/templates/defineConfig.h diff --git a/cmsisdsp/cg/static/scheduler/templates/dot_template.dot b/cmsisdsp/cg/scheduler/templates/dot_template.dot similarity index 100% rename from cmsisdsp/cg/static/scheduler/templates/dot_template.dot rename to cmsisdsp/cg/scheduler/templates/dot_template.dot diff --git a/cmsisdsp/cg/static/scheduler/templates/cmsis.cpp b/cmsisdsp/cg/static/scheduler/templates/cmsis.cpp deleted file mode 100644 index 99136fb0..00000000 --- a/cmsisdsp/cg/static/scheduler/templates/cmsis.cpp +++ /dev/null @@ -1,13 +0,0 @@ -{ -{% for ptr in ptrs %} - {{theType}}* {{ptr}}; -{% endfor %} -{% for ptr in inputs %} - {{ptr[0]}}={{ptr[1]}}.getReadBuffer({{nb}}); -{% endfor %} -{% for ptr in outputs %} - {{ptr[0]}}={{ptr[1]}}.getWriteBuffer({{nb}}); -{% endfor %} - {{func}}({{args}},{{nb}}); - cgStaticError = 0; -} \ No newline at end of file diff --git a/cmsisdsp/cg/static/types.py b/cmsisdsp/cg/types.py similarity index 100% rename from cmsisdsp/cg/static/types.py rename to cmsisdsp/cg/types.py diff --git a/setup.py b/setup.py index 7306d1b7..07bb6dcf 100644 --- a/setup.py +++ b/setup.py @@ -255,11 +255,11 @@ def build(): setup (name = 'cmsisdsp', version = main_ns['__version__'], packages=["cmsisdsp", - "cmsisdsp.cg.static", - "cmsisdsp.cg.static.nodes", - "cmsisdsp.cg.static.nodes.host", - "cmsisdsp.cg.static.scheduler", - "cmsisdsp.cg.static.scheduler.templates"], + "cmsisdsp.cg", + "cmsisdsp.cg.nodes", + "cmsisdsp.cg.nodes.host", + "cmsisdsp.cg.scheduler", + "cmsisdsp.cg.scheduler.templates"], description = 'CMSIS-DSP Python API', long_description=open("PythonWrapper_README.md").read(), long_description_content_type='text/markdown',