diff --git a/.gitignore b/.gitignore index 04a72323..a3304d22 100644 --- a/.gitignore +++ b/.gitignore @@ -26,4 +26,5 @@ build Documentation/html/* Doxygen/history.txt Doxygen/dsp.dxy -__pycache__/ \ No newline at end of file +__pycache__/ +*.pyd diff --git a/SDFTools/examples/CMakeLists.txt b/SDFTools/examples/CMakeLists.txt index e0ac9db5..3a47beb1 100755 --- a/SDFTools/examples/CMakeLists.txt +++ b/SDFTools/examples/CMakeLists.txt @@ -50,3 +50,4 @@ add_subdirectory(example1 bin_example1) add_subdirectory(example2 bin_example2) add_subdirectory(example3 bin_example3) add_subdirectory(example6 bin_example6) +add_subdirectory(example8 bin_example8) diff --git a/SDFTools/examples/example8/AppNodes.h b/SDFTools/examples/example8/AppNodes.h new file mode 100644 index 00000000..2a967c73 --- /dev/null +++ b/SDFTools/examples/example8/AppNodes.h @@ -0,0 +1,93 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: AppNodes.h + * Description: Application nodes for Example 1 + * + * $Date: 29 July 2021 + * $Revision: V1.10.0 + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ +/* + * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef _APPNODES_H_ +#define _APPNODES_H_ + +#include + +template +class Sink: public GenericSink +{ +public: + Sink(FIFOBase &src):GenericSink(src){}; + + int run() + { + IN *b=this->getReadBuffer(); + printf("Sink\n"); + for(int i=0;i +class Source; + +template +class Source: GenericSource +{ +public: + Source(FIFOBase &dst):GenericSource(dst),mCounter(0){}; + + int run(){ + complex *b=this->getWriteBuffer(); + + printf("Source\n"); + for(int i=0;i +class ProcessingNode: public GenericNode +{ +public: + ProcessingNode(FIFOBase &src,FIFOBase &dst,int,const char*,int):GenericNode(src,dst){}; + + int run(){ + printf("ProcessingNode\n"); + IN *a=this->getReadBuffer(); + OUT *b=this->getWriteBuffer(); + b[0] =(OUT)a[3]; + return(0); + }; + +}; + +#endif \ No newline at end of file diff --git a/SDFTools/examples/example8/CMakeLists.txt b/SDFTools/examples/example8/CMakeLists.txt new file mode 100644 index 00000000..83f7c875 --- /dev/null +++ b/SDFTools/examples/example8/CMakeLists.txt @@ -0,0 +1,13 @@ +cmake_minimum_required (VERSION 3.14) +include(CMakePrintHelpers) + +project(Example8) + + +add_executable(example8 main.cpp) + +sdf(example8) +add_sdf_dir(example8) + +target_include_directories(example8 PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) +target_include_directories(example8 PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/generated) diff --git a/SDFTools/examples/example8/custom.h b/SDFTools/examples/example8/custom.h new file mode 100644 index 00000000..0ed497ee --- /dev/null +++ b/SDFTools/examples/example8/custom.h @@ -0,0 +1,20 @@ +#ifndef _CUSTOM_H_ + + +#ifdef __cplusplus +extern "C" +{ +#endif + +typedef struct { + float re; + float im; +} complex; + + +#ifdef __cplusplus +} +#endif + + +#endif \ No newline at end of file diff --git a/SDFTools/examples/example8/generated/scheduler.cpp b/SDFTools/examples/example8/generated/scheduler.cpp new file mode 100644 index 00000000..3b320e24 --- /dev/null +++ b/SDFTools/examples/example8/generated/scheduler.cpp @@ -0,0 +1,143 @@ +/* + +Generated with CMSIS-DSP SDF Scripts. +The generated code is not covered by CMSIS-DSP license. + +The support classes and code is covered by CMSIS-DSP license. + +*/ + + +#include "arm_math.h" +#include "custom.h" +#include "GenericNodes.h" +#include "AppNodes.h" +#include "scheduler.h" + +/*********** + +FIFO buffers + +************/ +#define FIFOSIZE0 11 +#define FIFOSIZE1 5 +#define FIFOSIZE2 5 +#define FIFOSIZE3 5 +#define FIFOSIZE4 5 + +#define BUFFERSIZE0 11 +complex buf0[BUFFERSIZE0]={0}; + +#define BUFFERSIZE1 5 +complex buf1[BUFFERSIZE1]={0}; + +#define BUFFERSIZE2 5 +complex buf2[BUFFERSIZE2]={0}; + +#define BUFFERSIZE3 5 +complex buf3[BUFFERSIZE3]={0}; + +#define BUFFERSIZE4 5 +complex buf4[BUFFERSIZE4]={0}; + + +uint32_t scheduler(int *error,int someVariable) +{ + int sdfError=0; + uint32_t nbSchedule=0; + int32_t debugCounter=1; + + /* + Create FIFOs objects + */ + FIFO fifo0(buf0); + FIFO fifo1(buf1); + FIFO fifo2(buf2); + FIFO fifo3(buf3); + FIFO fifo4(buf4); + + /* + Create node objects + */ + Duplicate3 dup(fifo1,fifo2,fifo3,fifo4); + ProcessingNode filter(fifo0,fifo1,4,"Test",someVariable); + Sink sa(fifo2); + Sink sb(fifo3); + Sink sc(fifo4); + Source source(fifo0); + + /* Run several schedule iterations */ + while((sdfError==0) && (debugCounter > 0)) + { + /* Run a schedule iteration */ + sdfError = source.run(); + CHECKERROR; + sdfError = source.run(); + CHECKERROR; + sdfError = filter.run(); + CHECKERROR; + sdfError = dup.run(); + CHECKERROR; + sdfError = sc.run(); + CHECKERROR; + sdfError = sb.run(); + CHECKERROR; + sdfError = sa.run(); + CHECKERROR; + sdfError = source.run(); + CHECKERROR; + sdfError = filter.run(); + CHECKERROR; + sdfError = source.run(); + CHECKERROR; + sdfError = dup.run(); + CHECKERROR; + sdfError = sc.run(); + CHECKERROR; + sdfError = sb.run(); + CHECKERROR; + sdfError = sa.run(); + CHECKERROR; + sdfError = source.run(); + CHECKERROR; + sdfError = filter.run(); + CHECKERROR; + sdfError = dup.run(); + CHECKERROR; + sdfError = sc.run(); + CHECKERROR; + sdfError = sb.run(); + CHECKERROR; + sdfError = sa.run(); + CHECKERROR; + sdfError = source.run(); + CHECKERROR; + sdfError = filter.run(); + CHECKERROR; + sdfError = source.run(); + CHECKERROR; + sdfError = dup.run(); + CHECKERROR; + sdfError = sc.run(); + CHECKERROR; + sdfError = sb.run(); + CHECKERROR; + sdfError = sa.run(); + CHECKERROR; + sdfError = filter.run(); + CHECKERROR; + sdfError = dup.run(); + CHECKERROR; + sdfError = sc.run(); + CHECKERROR; + sdfError = sb.run(); + CHECKERROR; + sdfError = sa.run(); + CHECKERROR; + + debugCounter--; + nbSchedule++; + } + *error=sdfError; + return(nbSchedule); +} diff --git a/SDFTools/examples/example8/generated/scheduler.h b/SDFTools/examples/example8/generated/scheduler.h new file mode 100644 index 00000000..7f544ec6 --- /dev/null +++ b/SDFTools/examples/example8/generated/scheduler.h @@ -0,0 +1,25 @@ +/* + +Generated with CMSIS-DSP SDF Scripts. +The generated code is not covered by CMSIS-DSP license. + +The support classes and code is covered by CMSIS-DSP license. + +*/ + +#ifndef _SCHED_H_ +#define _SCHED_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +extern uint32_t scheduler(int *error,int someVariable); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/SDFTools/examples/example8/graph.py b/SDFTools/examples/example8/graph.py new file mode 100644 index 00000000..ae39ba1e --- /dev/null +++ b/SDFTools/examples/example8/graph.py @@ -0,0 +1,79 @@ +from cmsisdsp.sdf.scheduler import * + +### Define new types of Nodes + +class Node(GenericNode): + def __init__(self,name,theType,inLength,outLength): + GenericNode.__init__(self,name) + self.addInput("i",theType,inLength) + self.addOutput("o",theType,outLength) + +class Sink(GenericSink): + def __init__(self,name,theType,inLength): + GenericSink.__init__(self,name) + self.addInput("i",theType,inLength) + + @property + def typeName(self): + return "Sink" + +class Source(GenericSource): + def __init__(self,name,theType,inLength): + GenericSource.__init__(self,name) + self.addOutput("o",theType,inLength) + + @property + def typeName(self): + return "Source" + +class ProcessingNode(Node): + @property + def typeName(self): + return "ProcessingNode" + + + +### Define nodes +complexType=CStructType("complex","Complex",8) + +src=Source("source",complexType,5) +b=ProcessingNode("filter",complexType,7,5) +b.addLiteralArg(4) +b.addLiteralArg("Test") +b.addVariableArg("someVariable") +na = Sink("sa",complexType,5) +nb = Sink("sb",complexType,5) +nc = Sink("sc",complexType,5) +dup=Duplicate3("dup",complexType,5) + +g = Graph() + +g.connect(src.o,b.i) +g.connect(b.o,dup.i) +g.connect(dup.oa,na.i) +g.connect(dup.ob,nb.i) +g.connect(dup.oc,nc.i) + + +print("Generate graphviz and code") + +conf=Configuration() +conf.debugLimit=1 +conf.cOptionalArgs="int someVariable" +#conf.displayFIFOSizes=True +# Prefix for global FIFO buffers +#conf.prefix="sched1" + +#print(g.nullVector()) +sched = g.computeSchedule() +#print(sched.schedule) +print("Schedule length = %d" % sched.scheduleLength) +print("Memory usage %d bytes" % sched.memory) +# + +#conf.codeArray=True +sched.ccode("generated",conf) + +with open("test.dot","w") as f: + sched.graphviz(f) + diff --git a/SDFTools/examples/example8/main.cpp b/SDFTools/examples/example8/main.cpp new file mode 100644 index 00000000..b0cb113f --- /dev/null +++ b/SDFTools/examples/example8/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,1); + return 0; +} \ No newline at end of file diff --git a/SDFTools/examples/example8/test.dot b/SDFTools/examples/example8/test.dot new file mode 100644 index 00000000..178f4722 --- /dev/null +++ b/SDFTools/examples/example8/test.dot @@ -0,0 +1,99 @@ + + + +digraph structs { + node [shape=plaintext] + rankdir=LR + edge [arrowsize=0.5] + fontname="times" + + + +dup [label=< + + + + + + + + + + + + + + + + +
idup
(Duplicate3)
oa
ob
oc
>]; + +filter [label=< + + + + +
filter
(ProcessingNode)
>]; + +sa [label=< + + + + +
sa
(Sink)
>]; + +sb [label=< + + + + +
sb
(Sink)
>]; + +sc [label=< + + + + +
sc
(Sink)
>]; + +source [label=< + + + + +
source
(Source)
>]; + + + +source:i -> filter:i [headlabel=< +
7 +
>,taillabel=< +
5 +
>,label="complex(11)"] + +filter:i -> dup:i [headlabel=< +
5 +
>,taillabel=< +
5 +
>,label="complex(5)"] + +dup:oa -> sa:i [headlabel=< +
5 +
>,taillabel=< +
5 +
>,label="complex(5)"] + +dup:ob -> sb:i [headlabel=< +
5 +
>,taillabel=< +
5 +
>,label="complex(5)"] + +dup:oc -> sc:i [headlabel=< +
5 +
>,taillabel=< +
5 +
>,label="complex(5)"] + + +} diff --git a/SDFTools/examples/example8/test.pdf b/SDFTools/examples/example8/test.pdf new file mode 100644 index 00000000..1d2051e5 Binary files /dev/null and b/SDFTools/examples/example8/test.pdf differ diff --git a/SDFTools/sdf/src/GenericNodes.h b/SDFTools/sdf/src/GenericNodes.h index a9e7fd12..12cba304 100755 --- a/SDFTools/sdf/src/GenericNodes.h +++ b/SDFTools/sdf/src/GenericNodes.h @@ -163,6 +163,35 @@ private: FIFOBase &mDst2; }; +template +class GenericNode13:public NodeBase +{ +public: + GenericNode13(FIFOBase &src, + FIFOBase &dst1, + FIFOBase &dst2, + FIFOBase &dst3 + ):mSrc(src), + mDst1(dst1),mDst2(dst2),mDst3(dst3){}; + +protected: + OUT1 * getWriteBuffer1(){return mDst1.getWriteBuffer(output1Size);}; + OUT2 * getWriteBuffer2(){return mDst2.getWriteBuffer(output2Size);}; + OUT3 * getWriteBuffer3(){return mDst3.getWriteBuffer(output3Size);}; + + IN * getReadBuffer(){return mSrc.getReadBuffer(inputSize);}; + +private: + FIFOBase &mSrc; + FIFOBase &mDst1; + FIFOBase &mDst2; + FIFOBase &mDst3; + +}; + template class GenericNode21:public NodeBase { @@ -287,6 +316,72 @@ protected: }; +template +class Duplicate2; + +template +class Duplicate2: public GenericNode12 +{ +public: + Duplicate2(FIFOBase &src,FIFOBase &dst1,FIFOBase &dst2): + GenericNode12(src,dst1,dst2){}; + + int run(){ + IN *a=this->getReadBuffer(); + IN *b1=this->getWriteBuffer1(); + IN *b2=this->getWriteBuffer2(); + for(int i = 0; i +class Duplicate3; + +template +class Duplicate3: + public GenericNode13 +{ +public: + Duplicate3(FIFOBase &src, + FIFOBase &dst1, + FIFOBase &dst2, + FIFOBase &dst3): + GenericNode13(src,dst1,dst2,dst2){}; + + int run(){ + IN *a=this->getReadBuffer(); + IN *b1=this->getWriteBuffer1(); + IN *b2=this->getWriteBuffer2(); + IN *b3=this->getWriteBuffer3(); + for(int i = 0; i