1 /************************************************************************
2 ************************************************************************
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.
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.
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 ************************************************************************/
24 #include "compile_sched.hh"
30 void SchedulerCompiler::compileMultiSignal (Tree L
)
32 //contextor recursivness(0);
33 L
= prepare(L
); // optimize, share and annotate expression
35 for (int i
= 0; i
< fClass
->inputs(); i
++) {
36 fClass
->addZone3(subst("$1* input$0 = &input[$0][fIndex];", T(i
), xfloat()));
38 for (int i
= 0; i
< fClass
->outputs(); i
++) {
39 fClass
->addZone3(subst("$1* output$0 = &output[$0][fIndex];", T(i
), xfloat()));
42 fClass
->addSharedDecl("fullcount");
43 fClass
->addSharedDecl("input");
44 fClass
->addSharedDecl("output");
46 for (int i
= 0; isList(L
); L
= tl(L
), i
++) {
48 fClass
->openLoop("count");
49 fClass
->addExecCode(subst("output$0[i] = $2$1;", T(i
), CS(sig
), xcast()));
50 fClass
->closeLoop(sig
);
54 fClass
->buildTasksList();
56 generateUserInterfaceTree(prepareUserInterfaceTree(fUIRoot
));
57 generateMacroInterfaceTree("", prepareUserInterfaceTree(fUIRoot
));
59 fDescription
->ui(prepareUserInterfaceTree(fUIRoot
));
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
73 void SchedulerCompiler::vectorLoop (const string
& tname
, const string
& vecname
, const string
& cexp
)
75 // -- declare the vector
76 fClass
->addSharedDecl(vecname
);
78 // -- variables moved as class fields...
79 fClass
->addDeclCode(subst("$0 \t$1[$2];", tname
, vecname
, T(gVecSize
)));
81 // -- compute the new samples
82 fClass
->addExecCode(subst("$0[i] = $1;", vecname
, cexp
));
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
95 void SchedulerCompiler::dlineLoop (const string
& tname
, const string
& dlname
, int delay
, const string
& cexp
)
97 if (delay
< gMaxCopyDelay
) {
99 // Implementation of a copy based delayline
101 // create names for temporary and permanent storage
102 string buf
= subst("$0_tmp", dlname
);
103 string pmem
= subst("$0_perm", dlname
);
105 // constraints delay size to be multiple of 4
106 delay
= (delay
+3)&-4;
108 // allocate permanent storage for delayed samples
109 string dsize
= T(delay
);
110 fClass
->addDeclCode(subst("$0 \t$1[$2];", tname
, pmem
, dsize
));
112 // init permanent memory
113 fClass
->addInitCode(subst("for (int i=0; i<$1; i++) $0[i]=0;", pmem
, dsize
));
117 // -- declare a buffer and a "shifted" vector
118 fClass
->addSharedDecl(buf
);
120 // -- variables moved as class fields...
121 fClass
->addDeclCode(subst("$0 \t$1[$2+$3];", tname
, buf
, T(gVecSize
), dsize
));
123 fClass
->addFirstPrivateDecl(dlname
);
124 fClass
->addZone2(subst("$0* \t$1 = &$2[$3];", tname
, dlname
, buf
, dsize
));
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
));
129 // -- compute the new samples
130 fClass
->addExecCode(subst("$0[i] = $1;", dlname
, cexp
));
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
));
137 // Implementation of a ring-buffer delayline
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);
144 // create names for temporary and permanent storage
145 string idx
= subst("$0_idx", dlname
);
146 string idx_save
= subst("$0_idx_save", dlname
);
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
));
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
));
159 fClass
->addPreCode(subst("$0 = ($0+$1)&$2;", idx
, idx_save
, mask
));
161 // -- compute the new samples
162 fClass
->addExecCode(subst("$0[($2+i)&$3] = $1;", dlname
, cexp
, idx
, mask
));
165 fClass
->addPostCode(subst("$0 = count;", idx_save
));