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 #ifndef _INSTRUCTION_COMPILER_H
23 #define _INSTRUCTION_COMPILER_H
24 
25 #include <list>
26 #include <map>
27 #include <set>
28 #include <string>
29 #include <vector>
30 
31 #include "Text.hh"
32 #include "code_container.hh"
33 #include "garbageable.hh"
34 #include "global.hh"
35 #include "instructions.hh"
36 #include "dcond.hh"
37 #include "old_occurences.hh"
38 #include "property.hh"
39 
40 #define _DNF_ 1
41 
42 using namespace std;
43 
44 typedef ValueInst* InstType;
45 
46 class InstructionsCompiler : public virtual Garbageable {
47    protected:
48     CodeContainer* fContainer;
49 
50     property<ValueInst*>            fCompileProperty;
51     property<string>                fVectorProperty;
52     property<pair<string, string>>  fStaticInitProperty;
53     property<pair<string, string>>  fInstanceInitProperty;
54     property<string>                fTableProperty;
55 
56     map<Tree, Tree> fConditionProperty;  // used with the new X,Y:enable --> sigControl(X*Y,Y>0) primitive
57 
58     Tree                            fSharingKey;
59     old_OccMarkup*                  fOccMarkup;
60 
61     // Ensure IOTA base fixed delays are computed once
62     std::map<int, std::string> fIOTATable;
63 
64     Tree         fUIRoot;
65     Description* fDescription;
66 
67     /*
68      -dlt <N> : threshold between 'mask' and 'select' based ring-buffer delay line model.
69      'mask' delay-lines use the next power-of-two value size and a mask (faster but use more memory)
70      'select' delay-line use N+1 and use select to wrap the read/write indexes (use less memory but slower)
71     */
72 
73     bool fHasIota;
74 
75     void getTypedNames(::Type t, const string& prefix, Typed::VarType& ctype, string& vname);
76 
77     bool     getCompiledExpression(Tree sig, InstType& cexp);
78     InstType setCompiledExpression(Tree sig, const InstType& cexp);
79 
80     void setVectorNameProperty(Tree sig, const string& vecname);
81     bool getVectorNameProperty(Tree sig, string& vecname);
82 
83     void setTableNameProperty(Tree sig, const string& vecname);
84     bool getTableNameProperty(Tree sig, string& vecname);
85 
86     // Redefined by RustInstructionsCompiler
87     virtual StatementInst* generateInitArray(const string& vname, Typed::VarType ctype, int delay);
88     virtual StatementInst* generateCopyArray(const string& vname, int index_from, int index_to);
89     virtual StatementInst* generateCopyArray(const string& vname_to, const string& vname_from, int size);
90 
91     // Redefined in InterpreterInstructionsCompiler
92     virtual StatementInst* generateShiftArray(const string& vname, int delay);
93 
94     ValueInst* generateButtonAux(Tree sig, Tree path, const string& name);
95     ValueInst* generateSliderAux(Tree sig, Tree path, Tree cur, Tree min, Tree max, Tree step, const string& name);
96     ValueInst* generateBargraphAux(Tree sig, Tree path, Tree min, Tree max, ValueInst* exp, const string& name);
97 
98     // wrapper functions to access code container
pushInitMethod(StatementInst * inst)99     StatementInst* pushInitMethod(StatementInst* inst) { return fContainer->pushInitMethod(inst); }
pushResetUIInstructions(StatementInst * inst)100     StatementInst* pushResetUIInstructions(StatementInst* inst) { return fContainer->pushResetUIInstructions(inst); }
pushClearMethod(StatementInst * inst)101     StatementInst* pushClearMethod(StatementInst* inst) { return fContainer->pushClearMethod(inst); }
pushPostInitMethod(StatementInst * inst)102     StatementInst* pushPostInitMethod(StatementInst* inst) { return fContainer->pushPostInitMethod(inst); }
pushPreInitMethod(StatementInst * inst)103     StatementInst* pushPreInitMethod(StatementInst* inst) { return fContainer->pushPreInitMethod(inst); }
pushDestroyMethod(StatementInst * inst)104     StatementInst* pushDestroyMethod(StatementInst* inst) { return fContainer->pushDestroyMethod(inst); }
pushStaticInitMethod(StatementInst * inst)105     StatementInst* pushStaticInitMethod(StatementInst* inst) { return fContainer->pushStaticInitMethod(inst); }
pushPostStaticInitMethod(StatementInst * inst)106     StatementInst* pushPostStaticInitMethod(StatementInst* inst) { return fContainer->pushPostStaticInitMethod(inst); }
pushStaticDestroyMethod(StatementInst * inst)107     StatementInst* pushStaticDestroyMethod(StatementInst* inst) { return fContainer->pushStaticDestroyMethod(inst); }
pushComputeBlockMethod(StatementInst * inst)108     StatementInst* pushComputeBlockMethod(StatementInst* inst) { return fContainer->pushComputeBlockMethod(inst); }
pushPostComputeBlockMethod(StatementInst * inst)109     StatementInst* pushPostComputeBlockMethod(StatementInst* inst)
110     {
111         return fContainer->pushPostComputeBlockMethod(inst);
112     }
pushUserInterfaceMethod(StatementInst * inst)113     StatementInst* pushUserInterfaceMethod(StatementInst* inst) { return fContainer->pushUserInterfaceMethod(inst); }
114 
pushDeclare(StatementInst * inst)115     StatementInst* pushDeclare(StatementInst* inst) { return fContainer->pushDeclare(inst); }
pushGlobalDeclare(StatementInst * inst)116     StatementInst* pushGlobalDeclare(StatementInst* inst) { return fContainer->pushGlobalDeclare(inst); }
pushExtGlobalDeclare(StatementInst * inst)117     StatementInst* pushExtGlobalDeclare(StatementInst* inst) { return fContainer->pushExtGlobalDeclare(inst); }
118 
pushPreComputeDSPMethod(StatementInst * inst)119     StatementInst* pushPreComputeDSPMethod(StatementInst* inst) { return fContainer->pushPreComputeDSPMethod(inst); }
pushComputeDSPMethod(StatementInst * inst)120     StatementInst* pushComputeDSPMethod(StatementInst* inst) { return fContainer->pushComputeDSPMethod(inst); }
pushPostComputeDSPMethod(StatementInst * inst)121     StatementInst* pushPostComputeDSPMethod(StatementInst* inst) { return fContainer->pushPostComputeDSPMethod(inst); }
122 
123     void ensureIotaCode();
124 
pow2limit(int x)125     int pow2limit(int x)
126     {
127         int n = 2;
128         while (n < x) {
129             n = 2 * n;
130         }
131         return n;
132     }
133 
ispowerof2(int x)134     bool ispowerof2(int x)
135     {
136         /* First x in the below expression is for the case when x is 0 */
137         return x && (!(x&(x-1)));
138     }
139 
140     CodeContainer* signal2Container(const string& name, Tree sig);
141 
142     int  getSharingCount(Tree sig);
143     void setSharingCount(Tree sig, int count);
144     void sharingAnalysis(Tree t);
145     void sharingAnnotation(int vctxt, Tree sig);
146 
getCurrentLoopIndex()147     FIRIndex getCurrentLoopIndex() { return FIRIndex(fContainer->getCurLoop()->getLoopIndex()); }
148 
149     void declareWaveform(Tree sig, string& vname, int& size);
150 
151     // Enable/control
152     void conditionAnnotation(Tree l);
153     void conditionAnnotation(Tree t, Tree nc);
154     void conditionStatistics(Tree l);
155 
156     ValueInst* cnf2code(Tree cc);
157     ValueInst* or2code(Tree oc);
158 
159     ValueInst* dnf2code(Tree cc);
160     ValueInst* and2code(Tree oc);
161 
162     ValueInst* getConditionCode(Tree sig);
163 
164    public:
165     InstructionsCompiler(CodeContainer* container);
166 
~InstructionsCompiler()167     virtual ~InstructionsCompiler() {}
168 
169     virtual ValueInst* CS(Tree sig);
170 
171     virtual void compileMultiSignal(Tree sig);
172     virtual void compileSingleSignal(Tree sig);
173 
174     virtual ValueInst* generateVariableStore(Tree sig, ValueInst* inst);
175     virtual ValueInst* generateCacheCode(Tree sig, ValueInst* inst);
176     virtual ValueInst* forceCacheCode(Tree sig, ValueInst* inst);
177 
178     // Code generation
179     virtual ValueInst* generateCode(Tree sig);
180 
181     virtual ValueInst* generateXtended(Tree sig);
182     virtual ValueInst* generateDelay(Tree sig, Tree arg, Tree size);
183     virtual ValueInst* generatePrefix(Tree sig, Tree x, Tree e);
184     virtual ValueInst* generateIota(Tree sig, Tree arg);
185     virtual ValueInst* generateBinOp(Tree sig, int opcode, Tree arg1, Tree arg2);
186 
187     virtual ValueInst* generateFFun(Tree sig, Tree ff, Tree largs);
188     virtual ValueInst* generateWaveform(Tree sig);
189 
190     virtual ValueInst* generateInput(Tree sig, int idx);
191 
192     virtual ValueInst* generateTable(Tree sig, Tree tsize, Tree content);
193     virtual ValueInst* generateStaticTable(Tree sig, Tree tsize, Tree content);
194     virtual ValueInst* generateWRTbl(Tree sig, Tree tbl, Tree idx, Tree data);
195     virtual ValueInst* generateRDTbl(Tree sig, Tree tbl, Tree idx);
196     virtual ValueInst* generateSigGen(Tree sig, Tree content);
197     virtual ValueInst* generateStaticSigGen(Tree sig, Tree content);
198 
199     virtual ValueInst* generateSelect2(Tree sig, Tree sel, Tree s1, Tree s2);
200 
201     virtual ValueInst* generateRecProj(Tree sig, Tree exp, int i);
202     virtual ValueInst* generateRec(Tree sig, Tree var, Tree le, int index = -1);
203 
204     virtual ValueInst* generateIntCast(Tree sig, Tree x);
205     virtual ValueInst* generateFloatCast(Tree sig, Tree x);
206 
207     virtual ValueInst* generateButton(Tree sig, Tree label);
208     virtual ValueInst* generateCheckbox(Tree sig, Tree label);
209     virtual ValueInst* generateVSlider(Tree sig, Tree label, Tree cur, Tree min, Tree max, Tree step);
210     virtual ValueInst* generateHSlider(Tree sig, Tree label, Tree cur, Tree min, Tree max, Tree step);
211     virtual ValueInst* generateNumEntry(Tree sig, Tree label, Tree cur, Tree min, Tree max, Tree step);
212 
213     virtual ValueInst* generateVBargraph(Tree sig, Tree label, Tree min, Tree max, ValueInst* exp);
214     virtual ValueInst* generateHBargraph(Tree sig, Tree label, Tree min, Tree max, ValueInst* exp);
215 
216     virtual ValueInst* generateSoundfile(Tree sig, Tree label);
217     virtual ValueInst* generateSoundfileLength(Tree sig, ValueInst* sf, ValueInst* part);
218     virtual ValueInst* generateSoundfileRate(Tree sig, ValueInst* sf, ValueInst* part);
219     virtual ValueInst* generateSoundfileBuffer(Tree sig, ValueInst* sf, ValueInst* x, ValueInst* y, ValueInst* z);
220 
221     virtual ValueInst* generateIntNumber(Tree sig, int num);
222     virtual ValueInst* generateRealNumber(Tree sig, double num);
223     virtual ValueInst* generateFConst(Tree sig, Tree type, const string& file, const string& name);
224     virtual ValueInst* generateFVar(Tree sig, Tree type, const string& file, const string& name);
225 
226     virtual ValueInst* generateDelayVec(Tree sig, ValueInst* exp, Typed::VarType ctype, const string& vname, int mxd);
227     virtual ValueInst* generateDelayLine(ValueInst* exp, Typed::VarType ctype, const string& vname, int mxd,
228                                          Address::AccessType& var_access, ValueInst* ccs);
229 
230     virtual ValueInst* generateControl(Tree sig, Tree x, Tree y);
231 
232     // UI hierachy description
233     void addUIWidget(Tree path, Tree widget);
234     Tree prepareUserInterfaceTree(Tree t);
235     void generateUserInterfaceTree(Tree t, bool root = false);
236     void generateUserInterfaceElements(Tree elements);
237     void generateWidgetCode(Tree fulllabel, Tree varname, Tree sig);
238 
239     void generateMacroInterfaceTree(const string& pathname, Tree t);
240     void generateMacroInterfaceElements(const string& pathname, Tree elements);
241     void generateWidgetMacro(const string& pathname, Tree fulllabel, Tree varname, Tree sig);
242 
setDescription(Description * descr)243     void         setDescription(Description* descr) { fDescription = descr; }
getDescription()244     Description* getDescription() { return fDescription; }
245 
246     Tree prepare(Tree LS);
247     Tree prepare2(Tree L0);
248 
249 };
250 
251 #endif
252