1 /************************************************************************
2 ************************************************************************
3 FAUST compiler
4 Copyright (C) 2003-2018 GRAME, Centre National de Creation Musicale
5 ---------------------------------------------------------------------
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 ************************************************************************
20 ************************************************************************/
21
22 #include "compile_sched.hh"
23 #include "floats.hh"
24 #include "ppsig.hh"
25
compileMultiSignal(Tree L)26 void SchedulerCompiler::compileMultiSignal(Tree L)
27 {
28 // contextor recursivness(0);
29 L = prepare(L); // optimize, share and annotate expression
30
31 for (int i = 0; i < fClass->inputs(); i++) {
32 fClass->addZone3(subst("$1* input$0 = &input[$0][fIndex];", T(i), xfloat()));
33 }
34 for (int i = 0; i < fClass->outputs(); i++) {
35 fClass->addZone3(subst("$1* output$0 = &output[$0][fIndex];", T(i), xfloat()));
36 }
37
38 fClass->addSharedDecl("fullcount");
39 fClass->addSharedDecl("input");
40 fClass->addSharedDecl("output");
41
42 for (int i = 0; isList(L); L = tl(L), i++) {
43 Tree sig = hd(L);
44 fClass->openLoop("count");
45 fClass->addExecCode(Statement("", subst("output$0[i] = $2$1;", T(i), CS(sig), xcast())));
46 fClass->closeLoop(sig);
47 }
48
49 // Build tasks list
50 fClass->buildTasksList();
51
52 generateUserInterfaceTree(prepareUserInterfaceTree(fUIRoot), true);
53 generateMacroInterfaceTree("", prepareUserInterfaceTree(fUIRoot));
54 if (fDescription) {
55 fDescription->ui(prepareUserInterfaceTree(fUIRoot));
56 }
57 }
58
59 /**
60 * Generate the code for a (short) delay line
61 * @param k the c++ class where the delay line will be placed.
62 * @param l the loop where the code will be placed.
63 * @param tname the name of the C++ type (float or int)
64 * @param dlname the name of the delay line (vector) to be used.
65 * @param delay the maximum delay
66 * @param cexp the content of the signal as a C++ expression
67 */
vectorLoop(const string & tname,const string & vecname,const string & cexp,const string & ccs)68 void SchedulerCompiler::vectorLoop(const string& tname, const string& vecname, const string& cexp, const string& ccs)
69 {
70 // -- declare the vector
71 fClass->addSharedDecl(vecname);
72
73 // -- variables moved as class fields...
74 fClass->addDeclCode(subst("$0 \t$1[$2];", tname, vecname, T(gGlobal->gVecSize)));
75
76 // -- compute the new samples
77 fClass->addExecCode(Statement(ccs, subst("$0[i] = $1;", vecname, cexp)));
78 }
79
80 /**
81 * Generate the code for a (short) delay line
82 * @param k the c++ class where the delay line will be placed.
83 * @param l the loop where the code will be placed.
84 * @param tname the name of the C++ type (float or int)
85 * @param dlname the name of the delay line (vector) to be used.
86 * @param delay the maximum delay
87 * @param cexp the content of the signal as a C++ expression
88 */
dlineLoop(const string & tname,const string & dlname,int delay,const string & cexp,const string & ccs)89 void SchedulerCompiler::dlineLoop(const string& tname, const string& dlname, int delay, const string& cexp,
90 const string& ccs)
91 {
92 if (delay < gGlobal->gMaxCopyDelay) {
93 // Implementation of a copy based delayline
94
95 // create names for temporary and permanent storage
96 string buf = subst("$0_tmp", dlname);
97 string pmem = subst("$0_perm", dlname);
98
99 // constraints delay size to be multiple of 4
100 delay = (delay + 3) & -4;
101
102 // allocate permanent storage for delayed samples
103 string dsize = T(delay);
104 fClass->addDeclCode(subst("$0 \t$1[$2];", tname, pmem, dsize));
105
106 // init permanent memory
107 fClass->addClearCode(subst("for (int i=0; i<$1; i++) $0[i]=0;", pmem, dsize));
108
109 // compute method
110
111 // -- declare a buffer and a "shifted" vector
112 fClass->addSharedDecl(buf);
113
114 // -- variables moved as class fields...
115 fClass->addDeclCode(subst("$0 \t$1[$2+$3];", tname, buf, T(gGlobal->gVecSize), dsize));
116
117 fClass->addFirstPrivateDecl(dlname);
118 fClass->addZone2(subst("$0* \t$1 = &$2[$3];", tname, dlname, buf, dsize));
119
120 // -- copy the stored samples to the delay line
121 fClass->addPreCode(Statement(ccs, subst("for (int i=0; i<$2; i++) $0[i]=$1[i];", buf, pmem, dsize)));
122
123 // -- compute the new samples
124 fClass->addExecCode(Statement(ccs, subst("$0[i] = $1;", dlname, cexp)));
125
126 // -- copy back to stored samples
127 fClass->addPostCode(Statement(ccs, subst("for (int i=0; i<$2; i++) $0[i]=$1[count+i];", pmem, buf, dsize)));
128
129 } else {
130 // Implementation of a ring-buffer delayline
131
132 // the size should be large enough and aligned on a power of two
133 delay = pow2limit(delay + gGlobal->gVecSize);
134 string dsize = T(delay);
135 string mask = T(delay - 1);
136
137 // create names for temporary and permanent storage
138 string idx = subst("$0_idx", dlname);
139 string idx_save = subst("$0_idx_save", dlname);
140
141 // allocate permanent storage for delayed samples
142 fClass->addDeclCode(subst("$0 \t$1[$2];", tname, dlname, dsize));
143 fClass->addDeclCode(subst("int \t$0;", idx));
144 fClass->addDeclCode(subst("int \t$0;", idx_save));
145
146 // init permanent memory
147 fClass->addClearCode(subst("for (int i=0; i<$1; i++) $0[i]=0;", dlname, dsize));
148 fClass->addClearCode(subst("$0 = 0;", idx));
149 fClass->addClearCode(subst("$0 = 0;", idx_save));
150
151 // -- update index
152 fClass->addPreCode(Statement(ccs, subst("$0 = ($0+$1)&$2;", idx, idx_save, mask)));
153
154 // -- compute the new samples
155 fClass->addExecCode(Statement(ccs, subst("$0[($2+i)&$3] = $1;", dlname, cexp, idx, mask)));
156
157 // -- save index
158 fClass->addPostCode(Statement(ccs, subst("$0 = count;", idx_save)));
159 }
160 }
161