Merge branch 'newtree'
[Faustine.git] / interpretor / preprocessor / faust-0.9.47mr3 / compiler / generator / compile_sched.cpp
1 /************************************************************************
2 ************************************************************************
3 FAUST compiler
4 Copyright (C) 2003-2004 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
23
24 #include "compile_sched.hh"
25 #include "floats.hh"
26 #include "ppsig.hh"
27
28 extern int gVecSize;
29
30 void SchedulerCompiler::compileMultiSignal (Tree L)
31 {
32 //contextor recursivness(0);
33 L = prepare(L); // optimize, share and annotate expression
34
35 for (int i = 0; i < fClass->inputs(); i++) {
36 fClass->addZone3(subst("$1* input$0 = &input[$0][fIndex];", T(i), xfloat()));
37 }
38 for (int i = 0; i < fClass->outputs(); i++) {
39 fClass->addZone3(subst("$1* output$0 = &output[$0][fIndex];", T(i), xfloat()));
40 }
41
42 fClass->addSharedDecl("fullcount");
43 fClass->addSharedDecl("input");
44 fClass->addSharedDecl("output");
45
46 for (int i = 0; isList(L); L = tl(L), i++) {
47 Tree sig = hd(L);
48 fClass->openLoop("count");
49 fClass->addExecCode(subst("output$0[i] = $2$1;", T(i), CS(sig), xcast()));
50 fClass->closeLoop(sig);
51 }
52
53 // Build tasks list
54 fClass->buildTasksList();
55
56 generateUserInterfaceTree(prepareUserInterfaceTree(fUIRoot));
57 generateMacroInterfaceTree("", prepareUserInterfaceTree(fUIRoot));
58 if (fDescription) {
59 fDescription->ui(prepareUserInterfaceTree(fUIRoot));
60 }
61 }
62
63
64 /**
65 * Generate the code for a (short) delay line
66 * @param k the c++ class where the delay line will be placed.
67 * @param l the loop where the code will be placed.
68 * @param tname the name of the C++ type (float or int)
69 * @param dlname the name of the delay line (vector) to be used.
70 * @param delay the maximum delay
71 * @param cexp the content of the signal as a C++ expression
72 */
73 void SchedulerCompiler::vectorLoop (const string& tname, const string& vecname, const string& cexp)
74 {
75 // -- declare the vector
76 fClass->addSharedDecl(vecname);
77
78 // -- variables moved as class fields...
79 fClass->addDeclCode(subst("$0 \t$1[$2];", tname, vecname, T(gVecSize)));
80
81 // -- compute the new samples
82 fClass->addExecCode(subst("$0[i] = $1;", vecname, cexp));
83 }
84
85
86 /**
87 * Generate the code for a (short) delay line
88 * @param k the c++ class where the delay line will be placed.
89 * @param l the loop where the code will be placed.
90 * @param tname the name of the C++ type (float or int)
91 * @param dlname the name of the delay line (vector) to be used.
92 * @param delay the maximum delay
93 * @param cexp the content of the signal as a C++ expression
94 */
95 void SchedulerCompiler::dlineLoop (const string& tname, const string& dlname, int delay, const string& cexp)
96 {
97 if (delay < gMaxCopyDelay) {
98
99 // Implementation of a copy based delayline
100
101 // create names for temporary and permanent storage
102 string buf = subst("$0_tmp", dlname);
103 string pmem= subst("$0_perm", dlname);
104
105 // constraints delay size to be multiple of 4
106 delay = (delay+3)&-4;
107
108 // allocate permanent storage for delayed samples
109 string dsize = T(delay);
110 fClass->addDeclCode(subst("$0 \t$1[$2];", tname, pmem, dsize));
111
112 // init permanent memory
113 fClass->addInitCode(subst("for (int i=0; i<$1; i++) $0[i]=0;", pmem, dsize));
114
115 // compute method
116
117 // -- declare a buffer and a "shifted" vector
118 fClass->addSharedDecl(buf);
119
120 // -- variables moved as class fields...
121 fClass->addDeclCode(subst("$0 \t$1[$2+$3];", tname, buf, T(gVecSize), dsize));
122
123 fClass->addFirstPrivateDecl(dlname);
124 fClass->addZone2(subst("$0* \t$1 = &$2[$3];", tname, dlname, buf, dsize));
125
126 // -- copy the stored samples to the delay line
127 fClass->addPreCode(subst("for (int i=0; i<$2; i++) $0[i]=$1[i];", buf, pmem, dsize));
128
129 // -- compute the new samples
130 fClass->addExecCode(subst("$0[i] = $1;", dlname, cexp));
131
132 // -- copy back to stored samples
133 fClass->addPostCode(subst("for (int i=0; i<$2; i++) $0[i]=$1[count+i];", pmem, buf, dsize));
134
135 } else {
136
137 // Implementation of a ring-buffer delayline
138
139 // the size should be large enough and aligned on a power of two
140 delay = pow2limit(delay + gVecSize);
141 string dsize = T(delay);
142 string mask = T(delay-1);
143
144 // create names for temporary and permanent storage
145 string idx = subst("$0_idx", dlname);
146 string idx_save = subst("$0_idx_save", dlname);
147
148 // allocate permanent storage for delayed samples
149 fClass->addDeclCode(subst("$0 \t$1[$2];", tname, dlname, dsize));
150 fClass->addDeclCode(subst("int \t$0;", idx));
151 fClass->addDeclCode(subst("int \t$0;", idx_save));
152
153 // init permanent memory
154 fClass->addInitCode(subst("for (int i=0; i<$1; i++) $0[i]=0;", dlname, dsize));
155 fClass->addInitCode(subst("$0 = 0;", idx));
156 fClass->addInitCode(subst("$0 = 0;", idx_save));
157
158 // -- update index
159 fClass->addPreCode(subst("$0 = ($0+$1)&$2;", idx, idx_save, mask));
160
161 // -- compute the new samples
162 fClass->addExecCode(subst("$0[($2+i)&$3] = $1;", dlname, cexp, idx, mask));
163
164 // -- save index
165 fClass->addPostCode(subst("$0 = count;", idx_save));
166 }
167 }