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 interpreter_dsp_aux_pe_h 23 #define interpreter_dsp_aux_pe_h 24 25 #include "interpreter_dsp_aux.h" 26 27 // Specialization using partial evaluation: making controllers constant and optimizing the code. 28 29 template <class REAL, int TRACE> 30 class interpreter_dsp_aux_pe : public interpreter_dsp_aux<REAL, TRACE> { 31 protected: 32 FBCBlockInstruction<REAL>* fStaticInitBlock; 33 FBCBlockInstruction<REAL>* fInitBlock; 34 FBCBlockInstruction<REAL>* fResetUIBlock; 35 FBCBlockInstruction<REAL>* fClearBlock; 36 FBCBlockInstruction<REAL>* fComputeBlock; 37 FBCBlockInstruction<REAL>* fComputeDSPBlock; 38 39 std::map<int, int> fIntMap; 40 std::map<int, REAL> fRealMap; 41 42 public: interpreter_dsp_aux_pe(interpreter_dsp_factory_aux<REAL,TRACE> * factory)43 interpreter_dsp_aux_pe(interpreter_dsp_factory_aux<REAL, TRACE>* factory) 44 { 45 std::cout << "interpreter_dsp_aux_pe\n"; 46 /* 47 if (this->fFactory->getMemoryManager()) { 48 this->fInputs = static_cast<T**>(this->fFactory->allocate(sizeof(T*) * this->fFactory->fNumInputs)); 49 this->fOutputs = static_cast<T**>(this->fFactory->allocate(sizeof(T*) * this->fFactory->fNumOutputs)); 50 } else { 51 this->fInputs = new T*[this->fFactory->fNumInputs]; 52 this->fOutputs = new T*[this->fFactory->fNumOutputs]; 53 } 54 */ 55 56 /* 57 fFactory->fStaticInitBlock->write(&std::cout, false); 58 fFactory->fInitBlock->write(&std::cout, false); 59 fFactory->fResetUIBlock->write(&std::cout, false); 60 fFactory->fClearBlock->write(&std::cout, false); 61 fFactory->fComputeBlock->write(&std::cout, false); 62 fFactory->fComputeDSPBlock->write(&std::cout, false); 63 std::cout << "size " << fFactory->fComputeDSPBlock->size() << std::endl; 64 */ 65 66 this->fFactory = factory; 67 this->fFBCExecutor = factory->createFBCExecutor(); 68 69 fStaticInitBlock = nullptr; 70 fInitBlock = nullptr; 71 fResetUIBlock = nullptr; 72 fClearBlock = nullptr; 73 fComputeBlock = nullptr; 74 fComputeDSPBlock = nullptr; 75 } 76 ~interpreter_dsp_aux_pe()77 virtual ~interpreter_dsp_aux_pe() 78 { 79 /* 80 if (this->fFactory->getMemoryManager()) { 81 this->fFactory->destroy(this->fInputs); 82 this->fFactory->destroy(this->fOutputs); 83 } else { 84 delete[] this->fInputs; 85 delete[] this->fOutputs; 86 } 87 */ 88 89 delete this->fStaticInitBlock; 90 delete this->fInitBlock; 91 delete this->fResetUIBlock; 92 delete this->fClearBlock; 93 delete this->fComputeBlock; 94 delete this->fComputeDSPBlock; 95 } 96 instanceConstants(int sample_rate)97 virtual void instanceConstants(int sample_rate) 98 { 99 // Store sample_rate in specialization fIntMap 100 fIntMap[this->fFactory->fSROffset] = sample_rate; 101 102 // Store sample_rate in 'fSampleate' variable at correct offset in fIntHeap 103 this->fFBCExecutor->setIntValue(this->fFactory->fSROffset, sample_rate); 104 105 // Execute state init instructions 106 this->fFBCExecutor->ExecuteBlock(this->fFactory->fInitBlock); 107 } 108 init(int sample_rate)109 virtual void init(int sample_rate) 110 { 111 this->fInitialized = true; 112 113 // Store sample_rate in specialization fIntMap 114 fIntMap[this->fFactory->fSROffset] = sample_rate; 115 116 // Store sample_rate in 'fSampleRate' variable at correct offset in fIntHeap 117 this->fFBCExecutor->setIntValue(this->fFactory->fSROffset, sample_rate); 118 119 this->classInit(sample_rate); 120 this->instanceInit(sample_rate); 121 122 // Propagate constant values stored in the code into the heap 123 this->fStaticInitBlock = 124 FBCInstructionOptimizer<T>::specialize2Heap(this->fFactory->fStaticInitBlock->copy(), fIntMap, fRealMap); 125 this->fInitBlock = 126 FBCInstructionOptimizer<T>::specialize2Heap(this->fFactory->fInitBlock->copy(), fIntMap, fRealMap); 127 this->fResetUIBlock = 128 FBCInstructionOptimizer<T>::specialize2Heap(this->fFactory->fResetUIBlock->copy(), fIntMap, fRealMap); 129 this->fClearBlock = 130 FBCInstructionOptimizer<T>::specialize2Heap(this->fFactory->fClearBlock->copy(), fIntMap, fRealMap); 131 132 // Suppress IOTA from fIntMap since we don't want specialization to use it 133 if (fIntMap.find(this->fFactory->fIOTAOffset) != fIntMap.end()) { 134 fIntMap.erase(fIntMap.find(this->fFactory->fIOTAOffset)); 135 } 136 137 // Freeze all controllers 138 this->fFactory->fUserInterfaceBlock->freezeDefaultValues(fRealMap); 139 140 // To test : unfreeze "freg, gate, gain" controllers 141 std::map<std::string, int>& map = this->fFactory->fUserInterfaceBlock->getPathMap(); 142 for (auto& it : map) { 143 if ((it.first.find("freq") != std::string::npos) || (it.first.find("gate") != std::string::npos) || 144 (it.first.find("gain") != std::string::npos)) { 145 this->fFactory->fUserInterfaceBlock->unFreezeValue(fRealMap, it.first); 146 } 147 } 148 // Keep button on 149 // this->fFactory->fUserInterfaceBlock->unFreezeValue(fRealMap, FBCInstruction::kAddButton); 150 151 // Specialization by partial evaluation 152 this->fComputeBlock = 153 FBCInstructionOptimizer<T>::specialize(this->fFactory->fComputeBlock->copy(), fIntMap, fRealMap); 154 155 #ifdef MACHINE 156 // LLVM JIT only works on unoptimized FBC 157 this->fComputeDSPBlock = this->fFactory->fComputeDSPBlock->copy(); 158 #else 159 this->fComputeDSPBlock = 160 FBCInstructionOptimizer<T>::optimizeBlock(this->fFactory->fComputeDSPBlock->copy(), 1, 4); 161 #endif 162 163 // To test C++ generation 164 // this->fComputeDSPBlock = this->fFactory->fComputeDSPBlock->copy(); 165 166 this->fComputeDSPBlock = FBCInstructionOptimizer<T>::specialize(this->fComputeDSPBlock, fIntMap, fRealMap); 167 168 #ifndef MACHINE 169 // // LLVM JIT only works on unoptimized FBC 170 this->fComputeBlock = FBCInstructionOptimizer<T>::optimizeBlock(this->fComputeBlock, 5, 6); 171 this->fComputeDSPBlock = FBCInstructionOptimizer<T>::optimizeBlock(this->fComputeDSPBlock, 5, 6); 172 #endif 173 174 /* 175 this->fStaticInitBlock->write(&std::cout, false); 176 this->fInitBlock->write(&std::cout, false); 177 this->fResetUIBlock->write(&std::cout, false); 178 this->fClearBlock->write(&std::cout, false); 179 this->fComputeBlock->write(&std::cout, false); 180 this->fComputeDSPBlock->write(&std::cout, false); 181 */ 182 /* 183 #ifdef MACHINE 184 FBCCPPGenerator<T> cpp_generator(this->fFactory); 185 cpp_generator.generateCode(std::cout, this->fComputeBlock, this->fComputeDSPBlock); 186 #endif 187 */ 188 } 189 compute(int count,FAUSTFLOAT ** inputs_aux,FAUSTFLOAT ** outputs_aux)190 virtual void compute(int count, FAUSTFLOAT** inputs_aux, FAUSTFLOAT** outputs_aux) 191 { 192 if (count == 0) return; // Beware: compiled loop don't work with an index of 0 193 194 if (TRACE > 0 && !this->fInitialized) { 195 std::cout << "======== DSP is not initialized ! ========" << std::endl; 196 } else { 197 // std::cout << "compute " << count << std::endl; 198 T** inputs = reinterpret_cast<T**>(inputs_aux); 199 T** outputs = reinterpret_cast<T**>(outputs_aux); 200 201 // Prepare in/out buffers 202 for (int i = 0; i < this->fFactory->fNumInputs; i++) { 203 this->fFBCExecutor->setInput(i, inputs[i]); 204 } 205 for (int i = 0; i < this->fFactory->fNumOutputs; i++) { 206 this->fFBCExecutor->setOutput(i, outputs[i]); 207 } 208 209 // Set count in 'count' variable at the correct offset in fIntHeap 210 this->fFBCExecutor->setIntValue(this->fFactory->fCountOffset, count); 211 212 // Executes the specialized 'control' block 213 this->fFBCExecutor->ExecuteBlock(this->fComputeBlock); 214 215 // Executes the specialized 'DSP' block 216 #ifdef MACHINE 217 this->fFBCExecutor->ExecuteBlock(this->fComputeDSPBlock, true); 218 #else 219 this->fFBCExecutor->ExecuteBlock(this->fComputeDSPBlock); 220 #endif 221 } 222 } 223 }; 224 225 #endif 226