1*e1eccf28SAndroid Build Coastguard Worker /*
2*e1eccf28SAndroid Build Coastguard Worker * Copyright (C) 2015 The Android Open Source Project
3*e1eccf28SAndroid Build Coastguard Worker *
4*e1eccf28SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*e1eccf28SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*e1eccf28SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*e1eccf28SAndroid Build Coastguard Worker *
8*e1eccf28SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*e1eccf28SAndroid Build Coastguard Worker *
10*e1eccf28SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*e1eccf28SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*e1eccf28SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*e1eccf28SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*e1eccf28SAndroid Build Coastguard Worker * limitations under the License.
15*e1eccf28SAndroid Build Coastguard Worker */
16*e1eccf28SAndroid Build Coastguard Worker
17*e1eccf28SAndroid Build Coastguard Worker #include <iomanip>
18*e1eccf28SAndroid Build Coastguard Worker #include <iostream>
19*e1eccf28SAndroid Build Coastguard Worker #include <cmath>
20*e1eccf28SAndroid Build Coastguard Worker #include <sstream>
21*e1eccf28SAndroid Build Coastguard Worker
22*e1eccf28SAndroid Build Coastguard Worker #include "Generator.h"
23*e1eccf28SAndroid Build Coastguard Worker #include "Specification.h"
24*e1eccf28SAndroid Build Coastguard Worker #include "Utilities.h"
25*e1eccf28SAndroid Build Coastguard Worker
26*e1eccf28SAndroid Build Coastguard Worker using namespace std;
27*e1eccf28SAndroid Build Coastguard Worker
28*e1eccf28SAndroid Build Coastguard Worker // Converts float2 to FLOAT_32 and 2, etc.
convertToRsType(const string & name,string * dataType,char * vectorSize)29*e1eccf28SAndroid Build Coastguard Worker static void convertToRsType(const string& name, string* dataType, char* vectorSize) {
30*e1eccf28SAndroid Build Coastguard Worker string s = name;
31*e1eccf28SAndroid Build Coastguard Worker int last = s.size() - 1;
32*e1eccf28SAndroid Build Coastguard Worker char lastChar = s[last];
33*e1eccf28SAndroid Build Coastguard Worker if (lastChar >= '1' && lastChar <= '4') {
34*e1eccf28SAndroid Build Coastguard Worker s.erase(last);
35*e1eccf28SAndroid Build Coastguard Worker *vectorSize = lastChar;
36*e1eccf28SAndroid Build Coastguard Worker } else {
37*e1eccf28SAndroid Build Coastguard Worker *vectorSize = '1';
38*e1eccf28SAndroid Build Coastguard Worker }
39*e1eccf28SAndroid Build Coastguard Worker dataType->clear();
40*e1eccf28SAndroid Build Coastguard Worker for (int i = 0; i < NUM_TYPES; i++) {
41*e1eccf28SAndroid Build Coastguard Worker if (s == TYPES[i].cType) {
42*e1eccf28SAndroid Build Coastguard Worker *dataType = TYPES[i].rsDataType;
43*e1eccf28SAndroid Build Coastguard Worker break;
44*e1eccf28SAndroid Build Coastguard Worker }
45*e1eccf28SAndroid Build Coastguard Worker }
46*e1eccf28SAndroid Build Coastguard Worker }
47*e1eccf28SAndroid Build Coastguard Worker
48*e1eccf28SAndroid Build Coastguard Worker // Returns true if any permutation of the function have tests to b
needTestFiles(const Function & function,unsigned int versionOfTestFiles)49*e1eccf28SAndroid Build Coastguard Worker static bool needTestFiles(const Function& function, unsigned int versionOfTestFiles) {
50*e1eccf28SAndroid Build Coastguard Worker for (auto spec : function.getSpecifications()) {
51*e1eccf28SAndroid Build Coastguard Worker if (spec->hasTests(versionOfTestFiles)) {
52*e1eccf28SAndroid Build Coastguard Worker return true;
53*e1eccf28SAndroid Build Coastguard Worker }
54*e1eccf28SAndroid Build Coastguard Worker }
55*e1eccf28SAndroid Build Coastguard Worker return false;
56*e1eccf28SAndroid Build Coastguard Worker }
57*e1eccf28SAndroid Build Coastguard Worker
58*e1eccf28SAndroid Build Coastguard Worker /* One instance of this class is generated for each permutation of a function for which
59*e1eccf28SAndroid Build Coastguard Worker * we are generating test code. This instance will generate both the script and the Java
60*e1eccf28SAndroid Build Coastguard Worker * section of the test files for this permutation. The class is mostly used to keep track
61*e1eccf28SAndroid Build Coastguard Worker * of the various names shared between script and Java files.
62*e1eccf28SAndroid Build Coastguard Worker * WARNING: Because the constructor keeps a reference to the FunctionPermutation, PermutationWriter
63*e1eccf28SAndroid Build Coastguard Worker * should not exceed the lifetime of FunctionPermutation.
64*e1eccf28SAndroid Build Coastguard Worker */
65*e1eccf28SAndroid Build Coastguard Worker class PermutationWriter {
66*e1eccf28SAndroid Build Coastguard Worker private:
67*e1eccf28SAndroid Build Coastguard Worker FunctionPermutation& mPermutation;
68*e1eccf28SAndroid Build Coastguard Worker
69*e1eccf28SAndroid Build Coastguard Worker string mRsKernelName;
70*e1eccf28SAndroid Build Coastguard Worker string mJavaArgumentsClassName;
71*e1eccf28SAndroid Build Coastguard Worker string mJavaArgumentsNClassName;
72*e1eccf28SAndroid Build Coastguard Worker string mJavaVerifierComputeMethodName;
73*e1eccf28SAndroid Build Coastguard Worker string mJavaVerifierVerifyMethodName;
74*e1eccf28SAndroid Build Coastguard Worker string mJavaCheckMethodName;
75*e1eccf28SAndroid Build Coastguard Worker string mJavaVerifyMethodName;
76*e1eccf28SAndroid Build Coastguard Worker
77*e1eccf28SAndroid Build Coastguard Worker // Pointer to the files we are generating. Handy to avoid always passing them in the calls.
78*e1eccf28SAndroid Build Coastguard Worker GeneratedFile* mRs;
79*e1eccf28SAndroid Build Coastguard Worker GeneratedFile* mJava;
80*e1eccf28SAndroid Build Coastguard Worker
81*e1eccf28SAndroid Build Coastguard Worker /* Shortcuts to the return parameter and the first input parameter of the function
82*e1eccf28SAndroid Build Coastguard Worker * specification.
83*e1eccf28SAndroid Build Coastguard Worker */
84*e1eccf28SAndroid Build Coastguard Worker const ParameterDefinition* mReturnParam; // Can be nullptr. NOT OWNED.
85*e1eccf28SAndroid Build Coastguard Worker const ParameterDefinition* mFirstInputParam; // Can be nullptr. NOT OWNED.
86*e1eccf28SAndroid Build Coastguard Worker
87*e1eccf28SAndroid Build Coastguard Worker /* All the parameters plus the return param, if present. Collecting them together
88*e1eccf28SAndroid Build Coastguard Worker * simplifies code generation. NOT OWNED.
89*e1eccf28SAndroid Build Coastguard Worker */
90*e1eccf28SAndroid Build Coastguard Worker vector<const ParameterDefinition*> mAllInputsAndOutputs;
91*e1eccf28SAndroid Build Coastguard Worker
92*e1eccf28SAndroid Build Coastguard Worker /* We use a class to pass the arguments between the generated code and the CoreVerifier. This
93*e1eccf28SAndroid Build Coastguard Worker * method generates this class. The set keeps track if we've generated this class already
94*e1eccf28SAndroid Build Coastguard Worker * for this test file, as more than one permutation may use the same argument class.
95*e1eccf28SAndroid Build Coastguard Worker */
96*e1eccf28SAndroid Build Coastguard Worker void writeJavaArgumentClass(bool scalar, set<string>* javaGeneratedArgumentClasses) const;
97*e1eccf28SAndroid Build Coastguard Worker
98*e1eccf28SAndroid Build Coastguard Worker // Generate the Check* method that invokes the script and calls the verifier.
99*e1eccf28SAndroid Build Coastguard Worker void writeJavaCheckMethod(bool generateCallToVerifier) const;
100*e1eccf28SAndroid Build Coastguard Worker
101*e1eccf28SAndroid Build Coastguard Worker // Generate code to define and randomly initialize the input allocation.
102*e1eccf28SAndroid Build Coastguard Worker void writeJavaInputAllocationDefinition(const ParameterDefinition& param) const;
103*e1eccf28SAndroid Build Coastguard Worker
104*e1eccf28SAndroid Build Coastguard Worker /* Generate code that instantiate an allocation of floats or integers and fills it with
105*e1eccf28SAndroid Build Coastguard Worker * random data. This random data must be compatible with the specified type. This is
106*e1eccf28SAndroid Build Coastguard Worker * used for the convert_* tests, as converting values that don't fit yield undefined results.
107*e1eccf28SAndroid Build Coastguard Worker */
108*e1eccf28SAndroid Build Coastguard Worker void writeJavaRandomCompatibleFloatAllocation(const string& dataType, const string& seed,
109*e1eccf28SAndroid Build Coastguard Worker char vectorSize,
110*e1eccf28SAndroid Build Coastguard Worker const NumericalType& compatibleType,
111*e1eccf28SAndroid Build Coastguard Worker const NumericalType& generatedType) const;
112*e1eccf28SAndroid Build Coastguard Worker void writeJavaRandomCompatibleIntegerAllocation(const string& dataType, const string& seed,
113*e1eccf28SAndroid Build Coastguard Worker char vectorSize,
114*e1eccf28SAndroid Build Coastguard Worker const NumericalType& compatibleType,
115*e1eccf28SAndroid Build Coastguard Worker const NumericalType& generatedType) const;
116*e1eccf28SAndroid Build Coastguard Worker
117*e1eccf28SAndroid Build Coastguard Worker // Generate code that defines an output allocation.
118*e1eccf28SAndroid Build Coastguard Worker void writeJavaOutputAllocationDefinition(const ParameterDefinition& param) const;
119*e1eccf28SAndroid Build Coastguard Worker
120*e1eccf28SAndroid Build Coastguard Worker /* Generate the code that verifies the results for RenderScript functions where each entry
121*e1eccf28SAndroid Build Coastguard Worker * of a vector is evaluated independently. If verifierValidates is true, CoreMathVerifier
122*e1eccf28SAndroid Build Coastguard Worker * does the actual validation instead of more commonly returning the range of acceptable values.
123*e1eccf28SAndroid Build Coastguard Worker */
124*e1eccf28SAndroid Build Coastguard Worker void writeJavaVerifyScalarMethod(bool verifierValidates) const;
125*e1eccf28SAndroid Build Coastguard Worker
126*e1eccf28SAndroid Build Coastguard Worker /* Generate the code that verify the results for a RenderScript function where a vector
127*e1eccf28SAndroid Build Coastguard Worker * is a point in n-dimensional space.
128*e1eccf28SAndroid Build Coastguard Worker */
129*e1eccf28SAndroid Build Coastguard Worker void writeJavaVerifyVectorMethod() const;
130*e1eccf28SAndroid Build Coastguard Worker
131*e1eccf28SAndroid Build Coastguard Worker // Generate the line that creates the Target.
132*e1eccf28SAndroid Build Coastguard Worker void writeJavaCreateTarget() const;
133*e1eccf28SAndroid Build Coastguard Worker
134*e1eccf28SAndroid Build Coastguard Worker // Generate the method header of the verify function.
135*e1eccf28SAndroid Build Coastguard Worker void writeJavaVerifyMethodHeader() const;
136*e1eccf28SAndroid Build Coastguard Worker
137*e1eccf28SAndroid Build Coastguard Worker // Generate codes that copies the content of an allocation to an array.
138*e1eccf28SAndroid Build Coastguard Worker void writeJavaArrayInitialization(const ParameterDefinition& p) const;
139*e1eccf28SAndroid Build Coastguard Worker
140*e1eccf28SAndroid Build Coastguard Worker // Generate code that tests one value returned from the script.
141*e1eccf28SAndroid Build Coastguard Worker void writeJavaTestAndSetValid(const ParameterDefinition& p, const string& argsIndex,
142*e1eccf28SAndroid Build Coastguard Worker const string& actualIndex) const;
143*e1eccf28SAndroid Build Coastguard Worker void writeJavaTestOneValue(const ParameterDefinition& p, const string& argsIndex,
144*e1eccf28SAndroid Build Coastguard Worker const string& actualIndex) const;
145*e1eccf28SAndroid Build Coastguard Worker // For test:vector cases, generate code that compares returned vector vs. expected value.
146*e1eccf28SAndroid Build Coastguard Worker void writeJavaVectorComparison(const ParameterDefinition& p) const;
147*e1eccf28SAndroid Build Coastguard Worker
148*e1eccf28SAndroid Build Coastguard Worker // Muliple functions that generates code to build the error message if an error is found.
149*e1eccf28SAndroid Build Coastguard Worker void writeJavaAppendOutputToMessage(const ParameterDefinition& p, const string& argsIndex,
150*e1eccf28SAndroid Build Coastguard Worker const string& actualIndex, bool verifierValidates) const;
151*e1eccf28SAndroid Build Coastguard Worker void writeJavaAppendInputToMessage(const ParameterDefinition& p, const string& actual) const;
152*e1eccf28SAndroid Build Coastguard Worker void writeJavaAppendNewLineToMessage() const;
153*e1eccf28SAndroid Build Coastguard Worker void writeJavaAppendVectorInputToMessage(const ParameterDefinition& p) const;
154*e1eccf28SAndroid Build Coastguard Worker void writeJavaAppendVectorOutputToMessage(const ParameterDefinition& p) const;
155*e1eccf28SAndroid Build Coastguard Worker
156*e1eccf28SAndroid Build Coastguard Worker // Generate the set of instructions to call the script.
157*e1eccf28SAndroid Build Coastguard Worker void writeJavaCallToRs(bool relaxed, bool generateCallToVerifier) const;
158*e1eccf28SAndroid Build Coastguard Worker
159*e1eccf28SAndroid Build Coastguard Worker // Write an allocation definition if not already emitted in the .rs file.
160*e1eccf28SAndroid Build Coastguard Worker void writeRsAllocationDefinition(const ParameterDefinition& param,
161*e1eccf28SAndroid Build Coastguard Worker set<string>* rsAllocationsGenerated) const;
162*e1eccf28SAndroid Build Coastguard Worker
163*e1eccf28SAndroid Build Coastguard Worker public:
164*e1eccf28SAndroid Build Coastguard Worker /* NOTE: We keep pointers to the permutation and the files. This object should not
165*e1eccf28SAndroid Build Coastguard Worker * outlive the arguments.
166*e1eccf28SAndroid Build Coastguard Worker */
167*e1eccf28SAndroid Build Coastguard Worker PermutationWriter(FunctionPermutation& permutation, GeneratedFile* rsFile,
168*e1eccf28SAndroid Build Coastguard Worker GeneratedFile* javaFile);
getJavaCheckMethodName() const169*e1eccf28SAndroid Build Coastguard Worker string getJavaCheckMethodName() const { return mJavaCheckMethodName; }
170*e1eccf28SAndroid Build Coastguard Worker
171*e1eccf28SAndroid Build Coastguard Worker // Write the script test function for this permutation.
172*e1eccf28SAndroid Build Coastguard Worker void writeRsSection(set<string>* rsAllocationsGenerated) const;
173*e1eccf28SAndroid Build Coastguard Worker // Write the section of the Java code that calls the script and validates the results
174*e1eccf28SAndroid Build Coastguard Worker void writeJavaSection(set<string>* javaGeneratedArgumentClasses) const;
175*e1eccf28SAndroid Build Coastguard Worker };
176*e1eccf28SAndroid Build Coastguard Worker
PermutationWriter(FunctionPermutation & permutation,GeneratedFile * rsFile,GeneratedFile * javaFile)177*e1eccf28SAndroid Build Coastguard Worker PermutationWriter::PermutationWriter(FunctionPermutation& permutation, GeneratedFile* rsFile,
178*e1eccf28SAndroid Build Coastguard Worker GeneratedFile* javaFile)
179*e1eccf28SAndroid Build Coastguard Worker : mPermutation(permutation),
180*e1eccf28SAndroid Build Coastguard Worker mRs(rsFile),
181*e1eccf28SAndroid Build Coastguard Worker mJava(javaFile),
182*e1eccf28SAndroid Build Coastguard Worker mReturnParam(nullptr),
183*e1eccf28SAndroid Build Coastguard Worker mFirstInputParam(nullptr) {
184*e1eccf28SAndroid Build Coastguard Worker mRsKernelName = "test" + capitalize(permutation.getName());
185*e1eccf28SAndroid Build Coastguard Worker
186*e1eccf28SAndroid Build Coastguard Worker mJavaArgumentsClassName = "Arguments";
187*e1eccf28SAndroid Build Coastguard Worker mJavaArgumentsNClassName = "Arguments";
188*e1eccf28SAndroid Build Coastguard Worker const string trunk = capitalize(permutation.getNameTrunk());
189*e1eccf28SAndroid Build Coastguard Worker mJavaCheckMethodName = "check" + trunk;
190*e1eccf28SAndroid Build Coastguard Worker mJavaVerifyMethodName = "verifyResults" + trunk;
191*e1eccf28SAndroid Build Coastguard Worker
192*e1eccf28SAndroid Build Coastguard Worker for (auto p : permutation.getParams()) {
193*e1eccf28SAndroid Build Coastguard Worker mAllInputsAndOutputs.push_back(p);
194*e1eccf28SAndroid Build Coastguard Worker if (mFirstInputParam == nullptr && !p->isOutParameter) {
195*e1eccf28SAndroid Build Coastguard Worker mFirstInputParam = p;
196*e1eccf28SAndroid Build Coastguard Worker }
197*e1eccf28SAndroid Build Coastguard Worker }
198*e1eccf28SAndroid Build Coastguard Worker mReturnParam = permutation.getReturn();
199*e1eccf28SAndroid Build Coastguard Worker if (mReturnParam) {
200*e1eccf28SAndroid Build Coastguard Worker mAllInputsAndOutputs.push_back(mReturnParam);
201*e1eccf28SAndroid Build Coastguard Worker }
202*e1eccf28SAndroid Build Coastguard Worker
203*e1eccf28SAndroid Build Coastguard Worker for (auto p : mAllInputsAndOutputs) {
204*e1eccf28SAndroid Build Coastguard Worker const string capitalizedRsType = capitalize(p->rsType);
205*e1eccf28SAndroid Build Coastguard Worker const string capitalizedBaseType = capitalize(p->rsBaseType);
206*e1eccf28SAndroid Build Coastguard Worker mRsKernelName += capitalizedRsType;
207*e1eccf28SAndroid Build Coastguard Worker mJavaArgumentsClassName += capitalizedBaseType;
208*e1eccf28SAndroid Build Coastguard Worker mJavaArgumentsNClassName += capitalizedBaseType;
209*e1eccf28SAndroid Build Coastguard Worker if (p->mVectorSize != "1") {
210*e1eccf28SAndroid Build Coastguard Worker mJavaArgumentsNClassName += "N";
211*e1eccf28SAndroid Build Coastguard Worker }
212*e1eccf28SAndroid Build Coastguard Worker mJavaCheckMethodName += capitalizedRsType;
213*e1eccf28SAndroid Build Coastguard Worker mJavaVerifyMethodName += capitalizedRsType;
214*e1eccf28SAndroid Build Coastguard Worker }
215*e1eccf28SAndroid Build Coastguard Worker mJavaVerifierComputeMethodName = "compute" + trunk;
216*e1eccf28SAndroid Build Coastguard Worker mJavaVerifierVerifyMethodName = "verify" + trunk;
217*e1eccf28SAndroid Build Coastguard Worker }
218*e1eccf28SAndroid Build Coastguard Worker
writeJavaSection(set<string> * javaGeneratedArgumentClasses) const219*e1eccf28SAndroid Build Coastguard Worker void PermutationWriter::writeJavaSection(set<string>* javaGeneratedArgumentClasses) const {
220*e1eccf28SAndroid Build Coastguard Worker // By default, we test the results using item by item comparison.
221*e1eccf28SAndroid Build Coastguard Worker const string test = mPermutation.getTest();
222*e1eccf28SAndroid Build Coastguard Worker if (test == "scalar" || test == "limited") {
223*e1eccf28SAndroid Build Coastguard Worker writeJavaArgumentClass(true, javaGeneratedArgumentClasses);
224*e1eccf28SAndroid Build Coastguard Worker writeJavaCheckMethod(true);
225*e1eccf28SAndroid Build Coastguard Worker writeJavaVerifyScalarMethod(false);
226*e1eccf28SAndroid Build Coastguard Worker } else if (test == "custom") {
227*e1eccf28SAndroid Build Coastguard Worker writeJavaArgumentClass(true, javaGeneratedArgumentClasses);
228*e1eccf28SAndroid Build Coastguard Worker writeJavaCheckMethod(true);
229*e1eccf28SAndroid Build Coastguard Worker writeJavaVerifyScalarMethod(true);
230*e1eccf28SAndroid Build Coastguard Worker } else if (test == "vector") {
231*e1eccf28SAndroid Build Coastguard Worker writeJavaArgumentClass(false, javaGeneratedArgumentClasses);
232*e1eccf28SAndroid Build Coastguard Worker writeJavaCheckMethod(true);
233*e1eccf28SAndroid Build Coastguard Worker writeJavaVerifyVectorMethod();
234*e1eccf28SAndroid Build Coastguard Worker } else if (test == "noverify") {
235*e1eccf28SAndroid Build Coastguard Worker writeJavaCheckMethod(false);
236*e1eccf28SAndroid Build Coastguard Worker }
237*e1eccf28SAndroid Build Coastguard Worker }
238*e1eccf28SAndroid Build Coastguard Worker
writeJavaArgumentClass(bool scalar,set<string> * javaGeneratedArgumentClasses) const239*e1eccf28SAndroid Build Coastguard Worker void PermutationWriter::writeJavaArgumentClass(bool scalar,
240*e1eccf28SAndroid Build Coastguard Worker set<string>* javaGeneratedArgumentClasses) const {
241*e1eccf28SAndroid Build Coastguard Worker string name;
242*e1eccf28SAndroid Build Coastguard Worker if (scalar) {
243*e1eccf28SAndroid Build Coastguard Worker name = mJavaArgumentsClassName;
244*e1eccf28SAndroid Build Coastguard Worker } else {
245*e1eccf28SAndroid Build Coastguard Worker name = mJavaArgumentsNClassName;
246*e1eccf28SAndroid Build Coastguard Worker }
247*e1eccf28SAndroid Build Coastguard Worker
248*e1eccf28SAndroid Build Coastguard Worker // Make sure we have not generated the argument class already.
249*e1eccf28SAndroid Build Coastguard Worker if (!testAndSet(name, javaGeneratedArgumentClasses)) {
250*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "public class " << name;
251*e1eccf28SAndroid Build Coastguard Worker mJava->startBlock();
252*e1eccf28SAndroid Build Coastguard Worker
253*e1eccf28SAndroid Build Coastguard Worker for (auto p : mAllInputsAndOutputs) {
254*e1eccf28SAndroid Build Coastguard Worker bool isFieldArray = !scalar && p->mVectorSize != "1";
255*e1eccf28SAndroid Build Coastguard Worker bool isFloatyField = p->isOutParameter && p->isFloatType && mPermutation.getTest() != "custom";
256*e1eccf28SAndroid Build Coastguard Worker
257*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "public ";
258*e1eccf28SAndroid Build Coastguard Worker if (isFloatyField) {
259*e1eccf28SAndroid Build Coastguard Worker *mJava << "Target.Floaty";
260*e1eccf28SAndroid Build Coastguard Worker } else {
261*e1eccf28SAndroid Build Coastguard Worker *mJava << p->javaBaseType;
262*e1eccf28SAndroid Build Coastguard Worker }
263*e1eccf28SAndroid Build Coastguard Worker if (isFieldArray) {
264*e1eccf28SAndroid Build Coastguard Worker *mJava << "[]";
265*e1eccf28SAndroid Build Coastguard Worker }
266*e1eccf28SAndroid Build Coastguard Worker *mJava << " " << p->variableName << ";\n";
267*e1eccf28SAndroid Build Coastguard Worker
268*e1eccf28SAndroid Build Coastguard Worker // For Float16 parameters, add an extra 'double' field in the class
269*e1eccf28SAndroid Build Coastguard Worker // to hold the Double value converted from the input.
270*e1eccf28SAndroid Build Coastguard Worker if (p->isFloat16Parameter() && !isFloatyField) {
271*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "public double";
272*e1eccf28SAndroid Build Coastguard Worker if (isFieldArray) {
273*e1eccf28SAndroid Build Coastguard Worker *mJava << "[]";
274*e1eccf28SAndroid Build Coastguard Worker }
275*e1eccf28SAndroid Build Coastguard Worker *mJava << " " + p->variableName << "Double;\n";
276*e1eccf28SAndroid Build Coastguard Worker }
277*e1eccf28SAndroid Build Coastguard Worker }
278*e1eccf28SAndroid Build Coastguard Worker mJava->endBlock();
279*e1eccf28SAndroid Build Coastguard Worker *mJava << "\n";
280*e1eccf28SAndroid Build Coastguard Worker }
281*e1eccf28SAndroid Build Coastguard Worker }
282*e1eccf28SAndroid Build Coastguard Worker
writeJavaCheckMethod(bool generateCallToVerifier) const283*e1eccf28SAndroid Build Coastguard Worker void PermutationWriter::writeJavaCheckMethod(bool generateCallToVerifier) const {
284*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "private void " << mJavaCheckMethodName << "()";
285*e1eccf28SAndroid Build Coastguard Worker mJava->startBlock();
286*e1eccf28SAndroid Build Coastguard Worker
287*e1eccf28SAndroid Build Coastguard Worker // Generate the input allocations and initialization.
288*e1eccf28SAndroid Build Coastguard Worker for (auto p : mAllInputsAndOutputs) {
289*e1eccf28SAndroid Build Coastguard Worker if (!p->isOutParameter) {
290*e1eccf28SAndroid Build Coastguard Worker writeJavaInputAllocationDefinition(*p);
291*e1eccf28SAndroid Build Coastguard Worker }
292*e1eccf28SAndroid Build Coastguard Worker }
293*e1eccf28SAndroid Build Coastguard Worker // Generate code to enforce ordering between two allocations if needed.
294*e1eccf28SAndroid Build Coastguard Worker for (auto p : mAllInputsAndOutputs) {
295*e1eccf28SAndroid Build Coastguard Worker if (!p->isOutParameter && !p->smallerParameter.empty()) {
296*e1eccf28SAndroid Build Coastguard Worker string smallerAlloc = "in" + capitalize(p->smallerParameter);
297*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "enforceOrdering(" << smallerAlloc << ", " << p->javaAllocName
298*e1eccf28SAndroid Build Coastguard Worker << ");\n";
299*e1eccf28SAndroid Build Coastguard Worker }
300*e1eccf28SAndroid Build Coastguard Worker }
301*e1eccf28SAndroid Build Coastguard Worker
302*e1eccf28SAndroid Build Coastguard Worker // Generate code to check the full and relaxed scripts.
303*e1eccf28SAndroid Build Coastguard Worker writeJavaCallToRs(false, generateCallToVerifier);
304*e1eccf28SAndroid Build Coastguard Worker writeJavaCallToRs(true, generateCallToVerifier);
305*e1eccf28SAndroid Build Coastguard Worker
306*e1eccf28SAndroid Build Coastguard Worker // Generate code to destroy input Allocations.
307*e1eccf28SAndroid Build Coastguard Worker for (auto p : mAllInputsAndOutputs) {
308*e1eccf28SAndroid Build Coastguard Worker if (!p->isOutParameter) {
309*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << p->javaAllocName << ".destroy();\n";
310*e1eccf28SAndroid Build Coastguard Worker }
311*e1eccf28SAndroid Build Coastguard Worker }
312*e1eccf28SAndroid Build Coastguard Worker
313*e1eccf28SAndroid Build Coastguard Worker mJava->endBlock();
314*e1eccf28SAndroid Build Coastguard Worker *mJava << "\n";
315*e1eccf28SAndroid Build Coastguard Worker }
316*e1eccf28SAndroid Build Coastguard Worker
writeJavaInputAllocationDefinition(const ParameterDefinition & param) const317*e1eccf28SAndroid Build Coastguard Worker void PermutationWriter::writeJavaInputAllocationDefinition(const ParameterDefinition& param) const {
318*e1eccf28SAndroid Build Coastguard Worker string dataType;
319*e1eccf28SAndroid Build Coastguard Worker char vectorSize;
320*e1eccf28SAndroid Build Coastguard Worker convertToRsType(param.rsType, &dataType, &vectorSize);
321*e1eccf28SAndroid Build Coastguard Worker
322*e1eccf28SAndroid Build Coastguard Worker const string seed = hashString(mJavaCheckMethodName + param.javaAllocName);
323*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "Allocation " << param.javaAllocName << " = ";
324*e1eccf28SAndroid Build Coastguard Worker if (param.compatibleTypeIndex >= 0) {
325*e1eccf28SAndroid Build Coastguard Worker if (TYPES[param.typeIndex].kind == FLOATING_POINT) {
326*e1eccf28SAndroid Build Coastguard Worker writeJavaRandomCompatibleFloatAllocation(dataType, seed, vectorSize,
327*e1eccf28SAndroid Build Coastguard Worker TYPES[param.compatibleTypeIndex],
328*e1eccf28SAndroid Build Coastguard Worker TYPES[param.typeIndex]);
329*e1eccf28SAndroid Build Coastguard Worker } else {
330*e1eccf28SAndroid Build Coastguard Worker writeJavaRandomCompatibleIntegerAllocation(dataType, seed, vectorSize,
331*e1eccf28SAndroid Build Coastguard Worker TYPES[param.compatibleTypeIndex],
332*e1eccf28SAndroid Build Coastguard Worker TYPES[param.typeIndex]);
333*e1eccf28SAndroid Build Coastguard Worker }
334*e1eccf28SAndroid Build Coastguard Worker } else if (!param.minValue.empty()) {
335*e1eccf28SAndroid Build Coastguard Worker *mJava << "createRandomFloatAllocation(mRS, Element.DataType." << dataType << ", "
336*e1eccf28SAndroid Build Coastguard Worker << vectorSize << ", " << seed << ", " << param.minValue << ", " << param.maxValue
337*e1eccf28SAndroid Build Coastguard Worker << ")";
338*e1eccf28SAndroid Build Coastguard Worker } else {
339*e1eccf28SAndroid Build Coastguard Worker /* TODO Instead of passing always false, check whether we are doing a limited test.
340*e1eccf28SAndroid Build Coastguard Worker * Use instead: (mPermutation.getTest() == "limited" ? "false" : "true")
341*e1eccf28SAndroid Build Coastguard Worker */
342*e1eccf28SAndroid Build Coastguard Worker *mJava << "createRandomAllocation(mRS, Element.DataType." << dataType << ", " << vectorSize
343*e1eccf28SAndroid Build Coastguard Worker << ", " << seed << ", false)";
344*e1eccf28SAndroid Build Coastguard Worker }
345*e1eccf28SAndroid Build Coastguard Worker *mJava << ";\n";
346*e1eccf28SAndroid Build Coastguard Worker }
347*e1eccf28SAndroid Build Coastguard Worker
writeJavaRandomCompatibleFloatAllocation(const string & dataType,const string & seed,char vectorSize,const NumericalType & compatibleType,const NumericalType & generatedType) const348*e1eccf28SAndroid Build Coastguard Worker void PermutationWriter::writeJavaRandomCompatibleFloatAllocation(
349*e1eccf28SAndroid Build Coastguard Worker const string& dataType, const string& seed, char vectorSize,
350*e1eccf28SAndroid Build Coastguard Worker const NumericalType& compatibleType, const NumericalType& generatedType) const {
351*e1eccf28SAndroid Build Coastguard Worker *mJava << "createRandomFloatAllocation"
352*e1eccf28SAndroid Build Coastguard Worker << "(mRS, Element.DataType." << dataType << ", " << vectorSize << ", " << seed << ", ";
353*e1eccf28SAndroid Build Coastguard Worker double minValue = 0.0;
354*e1eccf28SAndroid Build Coastguard Worker double maxValue = 0.0;
355*e1eccf28SAndroid Build Coastguard Worker switch (compatibleType.kind) {
356*e1eccf28SAndroid Build Coastguard Worker case FLOATING_POINT: {
357*e1eccf28SAndroid Build Coastguard Worker // We're generating floating point values. We just worry about the exponent.
358*e1eccf28SAndroid Build Coastguard Worker // Subtract 1 for the exponent sign.
359*e1eccf28SAndroid Build Coastguard Worker int bits = min(compatibleType.exponentBits, generatedType.exponentBits) - 1;
360*e1eccf28SAndroid Build Coastguard Worker maxValue = ldexp(0.95, (1 << bits) - 1);
361*e1eccf28SAndroid Build Coastguard Worker minValue = -maxValue;
362*e1eccf28SAndroid Build Coastguard Worker break;
363*e1eccf28SAndroid Build Coastguard Worker }
364*e1eccf28SAndroid Build Coastguard Worker case UNSIGNED_INTEGER:
365*e1eccf28SAndroid Build Coastguard Worker maxValue = maxDoubleForInteger(compatibleType.significantBits,
366*e1eccf28SAndroid Build Coastguard Worker generatedType.significantBits);
367*e1eccf28SAndroid Build Coastguard Worker minValue = 0.0;
368*e1eccf28SAndroid Build Coastguard Worker break;
369*e1eccf28SAndroid Build Coastguard Worker case SIGNED_INTEGER:
370*e1eccf28SAndroid Build Coastguard Worker maxValue = maxDoubleForInteger(compatibleType.significantBits,
371*e1eccf28SAndroid Build Coastguard Worker generatedType.significantBits);
372*e1eccf28SAndroid Build Coastguard Worker minValue = -maxValue - 1.0;
373*e1eccf28SAndroid Build Coastguard Worker break;
374*e1eccf28SAndroid Build Coastguard Worker }
375*e1eccf28SAndroid Build Coastguard Worker *mJava << scientific << std::setprecision(19);
376*e1eccf28SAndroid Build Coastguard Worker *mJava << minValue << ", " << maxValue << ")";
377*e1eccf28SAndroid Build Coastguard Worker mJava->unsetf(ios_base::floatfield);
378*e1eccf28SAndroid Build Coastguard Worker }
379*e1eccf28SAndroid Build Coastguard Worker
writeJavaRandomCompatibleIntegerAllocation(const string & dataType,const string & seed,char vectorSize,const NumericalType & compatibleType,const NumericalType & generatedType) const380*e1eccf28SAndroid Build Coastguard Worker void PermutationWriter::writeJavaRandomCompatibleIntegerAllocation(
381*e1eccf28SAndroid Build Coastguard Worker const string& dataType, const string& seed, char vectorSize,
382*e1eccf28SAndroid Build Coastguard Worker const NumericalType& compatibleType, const NumericalType& generatedType) const {
383*e1eccf28SAndroid Build Coastguard Worker *mJava << "createRandomIntegerAllocation"
384*e1eccf28SAndroid Build Coastguard Worker << "(mRS, Element.DataType." << dataType << ", " << vectorSize << ", " << seed << ", ";
385*e1eccf28SAndroid Build Coastguard Worker
386*e1eccf28SAndroid Build Coastguard Worker if (compatibleType.kind == FLOATING_POINT) {
387*e1eccf28SAndroid Build Coastguard Worker // Currently, all floating points can take any number we generate.
388*e1eccf28SAndroid Build Coastguard Worker bool isSigned = generatedType.kind == SIGNED_INTEGER;
389*e1eccf28SAndroid Build Coastguard Worker *mJava << (isSigned ? "true" : "false") << ", " << generatedType.significantBits;
390*e1eccf28SAndroid Build Coastguard Worker } else {
391*e1eccf28SAndroid Build Coastguard Worker bool isSigned =
392*e1eccf28SAndroid Build Coastguard Worker compatibleType.kind == SIGNED_INTEGER && generatedType.kind == SIGNED_INTEGER;
393*e1eccf28SAndroid Build Coastguard Worker *mJava << (isSigned ? "true" : "false") << ", "
394*e1eccf28SAndroid Build Coastguard Worker << min(compatibleType.significantBits, generatedType.significantBits);
395*e1eccf28SAndroid Build Coastguard Worker }
396*e1eccf28SAndroid Build Coastguard Worker *mJava << ")";
397*e1eccf28SAndroid Build Coastguard Worker }
398*e1eccf28SAndroid Build Coastguard Worker
writeJavaOutputAllocationDefinition(const ParameterDefinition & param) const399*e1eccf28SAndroid Build Coastguard Worker void PermutationWriter::writeJavaOutputAllocationDefinition(
400*e1eccf28SAndroid Build Coastguard Worker const ParameterDefinition& param) const {
401*e1eccf28SAndroid Build Coastguard Worker string dataType;
402*e1eccf28SAndroid Build Coastguard Worker char vectorSize;
403*e1eccf28SAndroid Build Coastguard Worker convertToRsType(param.rsType, &dataType, &vectorSize);
404*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "Allocation " << param.javaAllocName << " = Allocation.createSized(mRS, "
405*e1eccf28SAndroid Build Coastguard Worker << "getElement(mRS, Element.DataType." << dataType << ", " << vectorSize
406*e1eccf28SAndroid Build Coastguard Worker << "), INPUTSIZE);\n";
407*e1eccf28SAndroid Build Coastguard Worker }
408*e1eccf28SAndroid Build Coastguard Worker
writeJavaVerifyScalarMethod(bool verifierValidates) const409*e1eccf28SAndroid Build Coastguard Worker void PermutationWriter::writeJavaVerifyScalarMethod(bool verifierValidates) const {
410*e1eccf28SAndroid Build Coastguard Worker writeJavaVerifyMethodHeader();
411*e1eccf28SAndroid Build Coastguard Worker mJava->startBlock();
412*e1eccf28SAndroid Build Coastguard Worker
413*e1eccf28SAndroid Build Coastguard Worker string vectorSize = "1";
414*e1eccf28SAndroid Build Coastguard Worker for (auto p : mAllInputsAndOutputs) {
415*e1eccf28SAndroid Build Coastguard Worker writeJavaArrayInitialization(*p);
416*e1eccf28SAndroid Build Coastguard Worker if (p->mVectorSize != "1" && p->mVectorSize != vectorSize) {
417*e1eccf28SAndroid Build Coastguard Worker if (vectorSize == "1") {
418*e1eccf28SAndroid Build Coastguard Worker vectorSize = p->mVectorSize;
419*e1eccf28SAndroid Build Coastguard Worker } else {
420*e1eccf28SAndroid Build Coastguard Worker cerr << "Error. Had vector " << vectorSize << " and " << p->mVectorSize << "\n";
421*e1eccf28SAndroid Build Coastguard Worker }
422*e1eccf28SAndroid Build Coastguard Worker }
423*e1eccf28SAndroid Build Coastguard Worker }
424*e1eccf28SAndroid Build Coastguard Worker
425*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "StringBuilder message = new StringBuilder();\n";
426*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "boolean errorFound = false;\n";
427*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "for (int i = 0; i < INPUTSIZE; i++)";
428*e1eccf28SAndroid Build Coastguard Worker mJava->startBlock();
429*e1eccf28SAndroid Build Coastguard Worker
430*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "for (int j = 0; j < " << vectorSize << " ; j++)";
431*e1eccf28SAndroid Build Coastguard Worker mJava->startBlock();
432*e1eccf28SAndroid Build Coastguard Worker
433*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "// Extract the inputs.\n";
434*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << mJavaArgumentsClassName << " args = new " << mJavaArgumentsClassName
435*e1eccf28SAndroid Build Coastguard Worker << "();\n";
436*e1eccf28SAndroid Build Coastguard Worker for (auto p : mAllInputsAndOutputs) {
437*e1eccf28SAndroid Build Coastguard Worker if (!p->isOutParameter) {
438*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "args." << p->variableName << " = " << p->javaArrayName << "[i";
439*e1eccf28SAndroid Build Coastguard Worker if (p->vectorWidth != "1") {
440*e1eccf28SAndroid Build Coastguard Worker *mJava << " * " << p->vectorWidth << " + j";
441*e1eccf28SAndroid Build Coastguard Worker }
442*e1eccf28SAndroid Build Coastguard Worker *mJava << "];\n";
443*e1eccf28SAndroid Build Coastguard Worker
444*e1eccf28SAndroid Build Coastguard Worker // Convert the Float16 parameter to double and store it in the appropriate field in the
445*e1eccf28SAndroid Build Coastguard Worker // Arguments class.
446*e1eccf28SAndroid Build Coastguard Worker if (p->isFloat16Parameter()) {
447*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "args." << p->doubleVariableName
448*e1eccf28SAndroid Build Coastguard Worker << " = Float16Utils.convertFloat16ToDouble(args."
449*e1eccf28SAndroid Build Coastguard Worker << p->variableName << ");\n";
450*e1eccf28SAndroid Build Coastguard Worker }
451*e1eccf28SAndroid Build Coastguard Worker }
452*e1eccf28SAndroid Build Coastguard Worker }
453*e1eccf28SAndroid Build Coastguard Worker const bool hasFloat = mPermutation.hasFloatAnswers();
454*e1eccf28SAndroid Build Coastguard Worker if (verifierValidates) {
455*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "// Extract the outputs.\n";
456*e1eccf28SAndroid Build Coastguard Worker for (auto p : mAllInputsAndOutputs) {
457*e1eccf28SAndroid Build Coastguard Worker if (p->isOutParameter) {
458*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "args." << p->variableName << " = " << p->javaArrayName
459*e1eccf28SAndroid Build Coastguard Worker << "[i * " << p->vectorWidth << " + j];\n";
460*e1eccf28SAndroid Build Coastguard Worker if (p->isFloat16Parameter()) {
461*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "args." << p->doubleVariableName
462*e1eccf28SAndroid Build Coastguard Worker << " = Float16Utils.convertFloat16ToDouble(args."
463*e1eccf28SAndroid Build Coastguard Worker << p->variableName << ");\n";
464*e1eccf28SAndroid Build Coastguard Worker }
465*e1eccf28SAndroid Build Coastguard Worker }
466*e1eccf28SAndroid Build Coastguard Worker }
467*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "// Ask the CoreMathVerifier to validate.\n";
468*e1eccf28SAndroid Build Coastguard Worker if (hasFloat) {
469*e1eccf28SAndroid Build Coastguard Worker writeJavaCreateTarget();
470*e1eccf28SAndroid Build Coastguard Worker }
471*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "String errorMessage = CoreMathVerifier."
472*e1eccf28SAndroid Build Coastguard Worker << mJavaVerifierVerifyMethodName << "(args";
473*e1eccf28SAndroid Build Coastguard Worker if (hasFloat) {
474*e1eccf28SAndroid Build Coastguard Worker *mJava << ", target";
475*e1eccf28SAndroid Build Coastguard Worker }
476*e1eccf28SAndroid Build Coastguard Worker *mJava << ");\n";
477*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "boolean valid = errorMessage == null;\n";
478*e1eccf28SAndroid Build Coastguard Worker } else {
479*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "// Figure out what the outputs should have been.\n";
480*e1eccf28SAndroid Build Coastguard Worker if (hasFloat) {
481*e1eccf28SAndroid Build Coastguard Worker writeJavaCreateTarget();
482*e1eccf28SAndroid Build Coastguard Worker }
483*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "CoreMathVerifier." << mJavaVerifierComputeMethodName << "(args";
484*e1eccf28SAndroid Build Coastguard Worker if (hasFloat) {
485*e1eccf28SAndroid Build Coastguard Worker *mJava << ", target";
486*e1eccf28SAndroid Build Coastguard Worker }
487*e1eccf28SAndroid Build Coastguard Worker *mJava << ");\n";
488*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "// Validate the outputs.\n";
489*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "boolean valid = true;\n";
490*e1eccf28SAndroid Build Coastguard Worker for (auto p : mAllInputsAndOutputs) {
491*e1eccf28SAndroid Build Coastguard Worker if (p->isOutParameter) {
492*e1eccf28SAndroid Build Coastguard Worker writeJavaTestAndSetValid(*p, "", "[i * " + p->vectorWidth + " + j]");
493*e1eccf28SAndroid Build Coastguard Worker }
494*e1eccf28SAndroid Build Coastguard Worker }
495*e1eccf28SAndroid Build Coastguard Worker }
496*e1eccf28SAndroid Build Coastguard Worker
497*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "if (!valid)";
498*e1eccf28SAndroid Build Coastguard Worker mJava->startBlock();
499*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "if (!errorFound)";
500*e1eccf28SAndroid Build Coastguard Worker mJava->startBlock();
501*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "errorFound = true;\n";
502*e1eccf28SAndroid Build Coastguard Worker
503*e1eccf28SAndroid Build Coastguard Worker for (auto p : mAllInputsAndOutputs) {
504*e1eccf28SAndroid Build Coastguard Worker if (p->isOutParameter) {
505*e1eccf28SAndroid Build Coastguard Worker writeJavaAppendOutputToMessage(*p, "", "[i * " + p->vectorWidth + " + j]",
506*e1eccf28SAndroid Build Coastguard Worker verifierValidates);
507*e1eccf28SAndroid Build Coastguard Worker } else {
508*e1eccf28SAndroid Build Coastguard Worker writeJavaAppendInputToMessage(*p, "args." + p->variableName);
509*e1eccf28SAndroid Build Coastguard Worker }
510*e1eccf28SAndroid Build Coastguard Worker }
511*e1eccf28SAndroid Build Coastguard Worker if (verifierValidates) {
512*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "message.append(errorMessage);\n";
513*e1eccf28SAndroid Build Coastguard Worker }
514*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "message.append(\"Errors at\");\n";
515*e1eccf28SAndroid Build Coastguard Worker mJava->endBlock();
516*e1eccf28SAndroid Build Coastguard Worker
517*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "message.append(\" [\");\n";
518*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "message.append(Integer.toString(i));\n";
519*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "message.append(\", \");\n";
520*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "message.append(Integer.toString(j));\n";
521*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "message.append(\"]\");\n";
522*e1eccf28SAndroid Build Coastguard Worker
523*e1eccf28SAndroid Build Coastguard Worker mJava->endBlock();
524*e1eccf28SAndroid Build Coastguard Worker mJava->endBlock();
525*e1eccf28SAndroid Build Coastguard Worker mJava->endBlock();
526*e1eccf28SAndroid Build Coastguard Worker
527*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "assertFalse(\"Incorrect output for " << mJavaCheckMethodName << "\" +\n";
528*e1eccf28SAndroid Build Coastguard Worker mJava->indentPlus()
529*e1eccf28SAndroid Build Coastguard Worker << "(relaxed ? \"_relaxed\" : \"\") + \":\\n\" + message.toString(), errorFound);\n";
530*e1eccf28SAndroid Build Coastguard Worker
531*e1eccf28SAndroid Build Coastguard Worker mJava->endBlock();
532*e1eccf28SAndroid Build Coastguard Worker *mJava << "\n";
533*e1eccf28SAndroid Build Coastguard Worker }
534*e1eccf28SAndroid Build Coastguard Worker
writeJavaVerifyVectorMethod() const535*e1eccf28SAndroid Build Coastguard Worker void PermutationWriter::writeJavaVerifyVectorMethod() const {
536*e1eccf28SAndroid Build Coastguard Worker writeJavaVerifyMethodHeader();
537*e1eccf28SAndroid Build Coastguard Worker mJava->startBlock();
538*e1eccf28SAndroid Build Coastguard Worker
539*e1eccf28SAndroid Build Coastguard Worker for (auto p : mAllInputsAndOutputs) {
540*e1eccf28SAndroid Build Coastguard Worker writeJavaArrayInitialization(*p);
541*e1eccf28SAndroid Build Coastguard Worker }
542*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "StringBuilder message = new StringBuilder();\n";
543*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "boolean errorFound = false;\n";
544*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "for (int i = 0; i < INPUTSIZE; i++)";
545*e1eccf28SAndroid Build Coastguard Worker mJava->startBlock();
546*e1eccf28SAndroid Build Coastguard Worker
547*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << mJavaArgumentsNClassName << " args = new " << mJavaArgumentsNClassName
548*e1eccf28SAndroid Build Coastguard Worker << "();\n";
549*e1eccf28SAndroid Build Coastguard Worker
550*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "// Create the appropriate sized arrays in args\n";
551*e1eccf28SAndroid Build Coastguard Worker for (auto p : mAllInputsAndOutputs) {
552*e1eccf28SAndroid Build Coastguard Worker if (p->mVectorSize != "1") {
553*e1eccf28SAndroid Build Coastguard Worker string type = p->javaBaseType;
554*e1eccf28SAndroid Build Coastguard Worker if (p->isOutParameter && p->isFloatType) {
555*e1eccf28SAndroid Build Coastguard Worker type = "Target.Floaty";
556*e1eccf28SAndroid Build Coastguard Worker }
557*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "args." << p->variableName << " = new " << type << "["
558*e1eccf28SAndroid Build Coastguard Worker << p->mVectorSize << "];\n";
559*e1eccf28SAndroid Build Coastguard Worker if (p->isFloat16Parameter() && !p->isOutParameter) {
560*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "args." << p->variableName << "Double = new double["
561*e1eccf28SAndroid Build Coastguard Worker << p->mVectorSize << "];\n";
562*e1eccf28SAndroid Build Coastguard Worker }
563*e1eccf28SAndroid Build Coastguard Worker }
564*e1eccf28SAndroid Build Coastguard Worker }
565*e1eccf28SAndroid Build Coastguard Worker
566*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "// Fill args with the input values\n";
567*e1eccf28SAndroid Build Coastguard Worker for (auto p : mAllInputsAndOutputs) {
568*e1eccf28SAndroid Build Coastguard Worker if (!p->isOutParameter) {
569*e1eccf28SAndroid Build Coastguard Worker if (p->mVectorSize == "1") {
570*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "args." << p->variableName << " = " << p->javaArrayName << "[i]"
571*e1eccf28SAndroid Build Coastguard Worker << ";\n";
572*e1eccf28SAndroid Build Coastguard Worker // Convert the Float16 parameter to double and store it in the appropriate field in
573*e1eccf28SAndroid Build Coastguard Worker // the Arguments class.
574*e1eccf28SAndroid Build Coastguard Worker if (p->isFloat16Parameter()) {
575*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "args." << p->doubleVariableName << " = "
576*e1eccf28SAndroid Build Coastguard Worker << "Float16Utils.convertFloat16ToDouble(args."
577*e1eccf28SAndroid Build Coastguard Worker << p->variableName << ");\n";
578*e1eccf28SAndroid Build Coastguard Worker }
579*e1eccf28SAndroid Build Coastguard Worker } else {
580*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "for (int j = 0; j < " << p->mVectorSize << " ; j++)";
581*e1eccf28SAndroid Build Coastguard Worker mJava->startBlock();
582*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "args." << p->variableName << "[j] = "
583*e1eccf28SAndroid Build Coastguard Worker << p->javaArrayName << "[i * " << p->vectorWidth << " + j]"
584*e1eccf28SAndroid Build Coastguard Worker << ";\n";
585*e1eccf28SAndroid Build Coastguard Worker
586*e1eccf28SAndroid Build Coastguard Worker // Convert the Float16 parameter to double and store it in the appropriate field in
587*e1eccf28SAndroid Build Coastguard Worker // the Arguments class.
588*e1eccf28SAndroid Build Coastguard Worker if (p->isFloat16Parameter()) {
589*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "args." << p->doubleVariableName << "[j] = "
590*e1eccf28SAndroid Build Coastguard Worker << "Float16Utils.convertFloat16ToDouble(args."
591*e1eccf28SAndroid Build Coastguard Worker << p->variableName << "[j]);\n";
592*e1eccf28SAndroid Build Coastguard Worker }
593*e1eccf28SAndroid Build Coastguard Worker mJava->endBlock();
594*e1eccf28SAndroid Build Coastguard Worker }
595*e1eccf28SAndroid Build Coastguard Worker }
596*e1eccf28SAndroid Build Coastguard Worker }
597*e1eccf28SAndroid Build Coastguard Worker writeJavaCreateTarget();
598*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "CoreMathVerifier." << mJavaVerifierComputeMethodName
599*e1eccf28SAndroid Build Coastguard Worker << "(args, target);\n\n";
600*e1eccf28SAndroid Build Coastguard Worker
601*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "// Compare the expected outputs to the actual values returned by RS.\n";
602*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "boolean valid = true;\n";
603*e1eccf28SAndroid Build Coastguard Worker for (auto p : mAllInputsAndOutputs) {
604*e1eccf28SAndroid Build Coastguard Worker if (p->isOutParameter) {
605*e1eccf28SAndroid Build Coastguard Worker writeJavaVectorComparison(*p);
606*e1eccf28SAndroid Build Coastguard Worker }
607*e1eccf28SAndroid Build Coastguard Worker }
608*e1eccf28SAndroid Build Coastguard Worker
609*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "if (!valid)";
610*e1eccf28SAndroid Build Coastguard Worker mJava->startBlock();
611*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "if (!errorFound)";
612*e1eccf28SAndroid Build Coastguard Worker mJava->startBlock();
613*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "errorFound = true;\n";
614*e1eccf28SAndroid Build Coastguard Worker
615*e1eccf28SAndroid Build Coastguard Worker for (auto p : mAllInputsAndOutputs) {
616*e1eccf28SAndroid Build Coastguard Worker if (p->isOutParameter) {
617*e1eccf28SAndroid Build Coastguard Worker writeJavaAppendVectorOutputToMessage(*p);
618*e1eccf28SAndroid Build Coastguard Worker } else {
619*e1eccf28SAndroid Build Coastguard Worker writeJavaAppendVectorInputToMessage(*p);
620*e1eccf28SAndroid Build Coastguard Worker }
621*e1eccf28SAndroid Build Coastguard Worker }
622*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "message.append(\"Errors at\");\n";
623*e1eccf28SAndroid Build Coastguard Worker mJava->endBlock();
624*e1eccf28SAndroid Build Coastguard Worker
625*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "message.append(\" [\");\n";
626*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "message.append(Integer.toString(i));\n";
627*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "message.append(\"]\");\n";
628*e1eccf28SAndroid Build Coastguard Worker
629*e1eccf28SAndroid Build Coastguard Worker mJava->endBlock();
630*e1eccf28SAndroid Build Coastguard Worker mJava->endBlock();
631*e1eccf28SAndroid Build Coastguard Worker
632*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "assertFalse(\"Incorrect output for " << mJavaCheckMethodName << "\" +\n";
633*e1eccf28SAndroid Build Coastguard Worker mJava->indentPlus()
634*e1eccf28SAndroid Build Coastguard Worker << "(relaxed ? \"_relaxed\" : \"\") + \":\\n\" + message.toString(), errorFound);\n";
635*e1eccf28SAndroid Build Coastguard Worker
636*e1eccf28SAndroid Build Coastguard Worker mJava->endBlock();
637*e1eccf28SAndroid Build Coastguard Worker *mJava << "\n";
638*e1eccf28SAndroid Build Coastguard Worker }
639*e1eccf28SAndroid Build Coastguard Worker
640*e1eccf28SAndroid Build Coastguard Worker
writeJavaCreateTarget() const641*e1eccf28SAndroid Build Coastguard Worker void PermutationWriter::writeJavaCreateTarget() const {
642*e1eccf28SAndroid Build Coastguard Worker string name = mPermutation.getName();
643*e1eccf28SAndroid Build Coastguard Worker
644*e1eccf28SAndroid Build Coastguard Worker const char* functionType = "NORMAL";
645*e1eccf28SAndroid Build Coastguard Worker size_t end = name.find('_');
646*e1eccf28SAndroid Build Coastguard Worker if (end != string::npos) {
647*e1eccf28SAndroid Build Coastguard Worker if (name.compare(0, end, "native") == 0) {
648*e1eccf28SAndroid Build Coastguard Worker functionType = "NATIVE";
649*e1eccf28SAndroid Build Coastguard Worker } else if (name.compare(0, end, "half") == 0) {
650*e1eccf28SAndroid Build Coastguard Worker functionType = "HALF";
651*e1eccf28SAndroid Build Coastguard Worker } else if (name.compare(0, end, "fast") == 0) {
652*e1eccf28SAndroid Build Coastguard Worker functionType = "FAST";
653*e1eccf28SAndroid Build Coastguard Worker }
654*e1eccf28SAndroid Build Coastguard Worker }
655*e1eccf28SAndroid Build Coastguard Worker
656*e1eccf28SAndroid Build Coastguard Worker string floatType = mReturnParam->specType;
657*e1eccf28SAndroid Build Coastguard Worker const char* precisionStr = "";
658*e1eccf28SAndroid Build Coastguard Worker if (floatType.compare("f16") == 0) {
659*e1eccf28SAndroid Build Coastguard Worker precisionStr = "HALF";
660*e1eccf28SAndroid Build Coastguard Worker } else if (floatType.compare("f32") == 0) {
661*e1eccf28SAndroid Build Coastguard Worker precisionStr = "FLOAT";
662*e1eccf28SAndroid Build Coastguard Worker } else if (floatType.compare("f64") == 0) {
663*e1eccf28SAndroid Build Coastguard Worker precisionStr = "DOUBLE";
664*e1eccf28SAndroid Build Coastguard Worker } else {
665*e1eccf28SAndroid Build Coastguard Worker cerr << "Error. Unreachable. Return type is not floating point\n";
666*e1eccf28SAndroid Build Coastguard Worker }
667*e1eccf28SAndroid Build Coastguard Worker
668*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "Target target = new Target(Target.FunctionType." <<
669*e1eccf28SAndroid Build Coastguard Worker functionType << ", Target.ReturnType." << precisionStr <<
670*e1eccf28SAndroid Build Coastguard Worker ", relaxed);\n";
671*e1eccf28SAndroid Build Coastguard Worker }
672*e1eccf28SAndroid Build Coastguard Worker
writeJavaVerifyMethodHeader() const673*e1eccf28SAndroid Build Coastguard Worker void PermutationWriter::writeJavaVerifyMethodHeader() const {
674*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "private void " << mJavaVerifyMethodName << "(";
675*e1eccf28SAndroid Build Coastguard Worker for (auto p : mAllInputsAndOutputs) {
676*e1eccf28SAndroid Build Coastguard Worker *mJava << "Allocation " << p->javaAllocName << ", ";
677*e1eccf28SAndroid Build Coastguard Worker }
678*e1eccf28SAndroid Build Coastguard Worker *mJava << "boolean relaxed)";
679*e1eccf28SAndroid Build Coastguard Worker }
680*e1eccf28SAndroid Build Coastguard Worker
writeJavaArrayInitialization(const ParameterDefinition & p) const681*e1eccf28SAndroid Build Coastguard Worker void PermutationWriter::writeJavaArrayInitialization(const ParameterDefinition& p) const {
682*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << p.javaBaseType << "[] " << p.javaArrayName << " = new " << p.javaBaseType
683*e1eccf28SAndroid Build Coastguard Worker << "[INPUTSIZE * " << p.vectorWidth << "];\n";
684*e1eccf28SAndroid Build Coastguard Worker
685*e1eccf28SAndroid Build Coastguard Worker /* For basic types, populate the array with values, to help understand failures. We have had
686*e1eccf28SAndroid Build Coastguard Worker * bugs where the output buffer was all 0. We were not sure if there was a failed copy or
687*e1eccf28SAndroid Build Coastguard Worker * the GPU driver was copying zeroes.
688*e1eccf28SAndroid Build Coastguard Worker */
689*e1eccf28SAndroid Build Coastguard Worker if (p.typeIndex >= 0) {
690*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "Arrays.fill(" << p.javaArrayName << ", (" << TYPES[p.typeIndex].javaType
691*e1eccf28SAndroid Build Coastguard Worker << ") 42);\n";
692*e1eccf28SAndroid Build Coastguard Worker }
693*e1eccf28SAndroid Build Coastguard Worker
694*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << p.javaAllocName << ".copyTo(" << p.javaArrayName << ");\n";
695*e1eccf28SAndroid Build Coastguard Worker }
696*e1eccf28SAndroid Build Coastguard Worker
writeJavaTestAndSetValid(const ParameterDefinition & p,const string & argsIndex,const string & actualIndex) const697*e1eccf28SAndroid Build Coastguard Worker void PermutationWriter::writeJavaTestAndSetValid(const ParameterDefinition& p,
698*e1eccf28SAndroid Build Coastguard Worker const string& argsIndex,
699*e1eccf28SAndroid Build Coastguard Worker const string& actualIndex) const {
700*e1eccf28SAndroid Build Coastguard Worker writeJavaTestOneValue(p, argsIndex, actualIndex);
701*e1eccf28SAndroid Build Coastguard Worker mJava->startBlock();
702*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "valid = false;\n";
703*e1eccf28SAndroid Build Coastguard Worker mJava->endBlock();
704*e1eccf28SAndroid Build Coastguard Worker }
705*e1eccf28SAndroid Build Coastguard Worker
writeJavaTestOneValue(const ParameterDefinition & p,const string & argsIndex,const string & actualIndex) const706*e1eccf28SAndroid Build Coastguard Worker void PermutationWriter::writeJavaTestOneValue(const ParameterDefinition& p, const string& argsIndex,
707*e1eccf28SAndroid Build Coastguard Worker const string& actualIndex) const {
708*e1eccf28SAndroid Build Coastguard Worker string actualOut;
709*e1eccf28SAndroid Build Coastguard Worker if (p.isFloat16Parameter()) {
710*e1eccf28SAndroid Build Coastguard Worker // For Float16 values, the output needs to be converted to Double.
711*e1eccf28SAndroid Build Coastguard Worker actualOut = "Float16Utils.convertFloat16ToDouble(" + p.javaArrayName + actualIndex + ")";
712*e1eccf28SAndroid Build Coastguard Worker } else {
713*e1eccf28SAndroid Build Coastguard Worker actualOut = p.javaArrayName + actualIndex;
714*e1eccf28SAndroid Build Coastguard Worker }
715*e1eccf28SAndroid Build Coastguard Worker
716*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "if (";
717*e1eccf28SAndroid Build Coastguard Worker if (p.isFloatType) {
718*e1eccf28SAndroid Build Coastguard Worker *mJava << "!args." << p.variableName << argsIndex << ".couldBe(" << actualOut;
719*e1eccf28SAndroid Build Coastguard Worker const string s = mPermutation.getPrecisionLimit();
720*e1eccf28SAndroid Build Coastguard Worker if (!s.empty()) {
721*e1eccf28SAndroid Build Coastguard Worker *mJava << ", " << s;
722*e1eccf28SAndroid Build Coastguard Worker }
723*e1eccf28SAndroid Build Coastguard Worker *mJava << ")";
724*e1eccf28SAndroid Build Coastguard Worker } else {
725*e1eccf28SAndroid Build Coastguard Worker *mJava << "args." << p.variableName << argsIndex << " != " << p.javaArrayName
726*e1eccf28SAndroid Build Coastguard Worker << actualIndex;
727*e1eccf28SAndroid Build Coastguard Worker }
728*e1eccf28SAndroid Build Coastguard Worker
729*e1eccf28SAndroid Build Coastguard Worker if (p.undefinedIfOutIsNan && mReturnParam) {
730*e1eccf28SAndroid Build Coastguard Worker *mJava << " && !args." << mReturnParam->variableName << argsIndex << ".isNaN()";
731*e1eccf28SAndroid Build Coastguard Worker }
732*e1eccf28SAndroid Build Coastguard Worker *mJava << ")";
733*e1eccf28SAndroid Build Coastguard Worker }
734*e1eccf28SAndroid Build Coastguard Worker
writeJavaVectorComparison(const ParameterDefinition & p) const735*e1eccf28SAndroid Build Coastguard Worker void PermutationWriter::writeJavaVectorComparison(const ParameterDefinition& p) const {
736*e1eccf28SAndroid Build Coastguard Worker if (p.mVectorSize == "1") {
737*e1eccf28SAndroid Build Coastguard Worker writeJavaTestAndSetValid(p, "", "[i]");
738*e1eccf28SAndroid Build Coastguard Worker } else {
739*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "for (int j = 0; j < " << p.mVectorSize << " ; j++)";
740*e1eccf28SAndroid Build Coastguard Worker mJava->startBlock();
741*e1eccf28SAndroid Build Coastguard Worker writeJavaTestAndSetValid(p, "[j]", "[i * " + p.vectorWidth + " + j]");
742*e1eccf28SAndroid Build Coastguard Worker mJava->endBlock();
743*e1eccf28SAndroid Build Coastguard Worker }
744*e1eccf28SAndroid Build Coastguard Worker }
745*e1eccf28SAndroid Build Coastguard Worker
writeJavaAppendOutputToMessage(const ParameterDefinition & p,const string & argsIndex,const string & actualIndex,bool verifierValidates) const746*e1eccf28SAndroid Build Coastguard Worker void PermutationWriter::writeJavaAppendOutputToMessage(const ParameterDefinition& p,
747*e1eccf28SAndroid Build Coastguard Worker const string& argsIndex,
748*e1eccf28SAndroid Build Coastguard Worker const string& actualIndex,
749*e1eccf28SAndroid Build Coastguard Worker bool verifierValidates) const {
750*e1eccf28SAndroid Build Coastguard Worker if (verifierValidates) {
751*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "message.append(\"Output " << p.variableName << ": \");\n";
752*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "appendVariableToMessage(message, args." << p.variableName << argsIndex
753*e1eccf28SAndroid Build Coastguard Worker << ");\n";
754*e1eccf28SAndroid Build Coastguard Worker writeJavaAppendNewLineToMessage();
755*e1eccf28SAndroid Build Coastguard Worker if (p.isFloat16Parameter()) {
756*e1eccf28SAndroid Build Coastguard Worker writeJavaAppendNewLineToMessage();
757*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "message.append(\"Output " << p.variableName
758*e1eccf28SAndroid Build Coastguard Worker << " (in double): \");\n";
759*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "appendVariableToMessage(message, args." << p.doubleVariableName
760*e1eccf28SAndroid Build Coastguard Worker << ");\n";
761*e1eccf28SAndroid Build Coastguard Worker writeJavaAppendNewLineToMessage();
762*e1eccf28SAndroid Build Coastguard Worker }
763*e1eccf28SAndroid Build Coastguard Worker } else {
764*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "message.append(\"Expected output " << p.variableName << ": \");\n";
765*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "appendVariableToMessage(message, args." << p.variableName << argsIndex
766*e1eccf28SAndroid Build Coastguard Worker << ");\n";
767*e1eccf28SAndroid Build Coastguard Worker writeJavaAppendNewLineToMessage();
768*e1eccf28SAndroid Build Coastguard Worker
769*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "message.append(\"Actual output " << p.variableName << ": \");\n";
770*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "appendVariableToMessage(message, " << p.javaArrayName << actualIndex
771*e1eccf28SAndroid Build Coastguard Worker << ");\n";
772*e1eccf28SAndroid Build Coastguard Worker
773*e1eccf28SAndroid Build Coastguard Worker if (p.isFloat16Parameter()) {
774*e1eccf28SAndroid Build Coastguard Worker writeJavaAppendNewLineToMessage();
775*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "message.append(\"Actual output " << p.variableName
776*e1eccf28SAndroid Build Coastguard Worker << " (in double): \");\n";
777*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble("
778*e1eccf28SAndroid Build Coastguard Worker << p.javaArrayName << actualIndex << "));\n";
779*e1eccf28SAndroid Build Coastguard Worker }
780*e1eccf28SAndroid Build Coastguard Worker
781*e1eccf28SAndroid Build Coastguard Worker writeJavaTestOneValue(p, argsIndex, actualIndex);
782*e1eccf28SAndroid Build Coastguard Worker mJava->startBlock();
783*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "message.append(\" FAIL\");\n";
784*e1eccf28SAndroid Build Coastguard Worker mJava->endBlock();
785*e1eccf28SAndroid Build Coastguard Worker writeJavaAppendNewLineToMessage();
786*e1eccf28SAndroid Build Coastguard Worker }
787*e1eccf28SAndroid Build Coastguard Worker }
788*e1eccf28SAndroid Build Coastguard Worker
writeJavaAppendInputToMessage(const ParameterDefinition & p,const string & actual) const789*e1eccf28SAndroid Build Coastguard Worker void PermutationWriter::writeJavaAppendInputToMessage(const ParameterDefinition& p,
790*e1eccf28SAndroid Build Coastguard Worker const string& actual) const {
791*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "message.append(\"Input " << p.variableName << ": \");\n";
792*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "appendVariableToMessage(message, " << actual << ");\n";
793*e1eccf28SAndroid Build Coastguard Worker writeJavaAppendNewLineToMessage();
794*e1eccf28SAndroid Build Coastguard Worker }
795*e1eccf28SAndroid Build Coastguard Worker
writeJavaAppendNewLineToMessage() const796*e1eccf28SAndroid Build Coastguard Worker void PermutationWriter::writeJavaAppendNewLineToMessage() const {
797*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "message.append(\"\\n\");\n";
798*e1eccf28SAndroid Build Coastguard Worker }
799*e1eccf28SAndroid Build Coastguard Worker
writeJavaAppendVectorInputToMessage(const ParameterDefinition & p) const800*e1eccf28SAndroid Build Coastguard Worker void PermutationWriter::writeJavaAppendVectorInputToMessage(const ParameterDefinition& p) const {
801*e1eccf28SAndroid Build Coastguard Worker if (p.mVectorSize == "1") {
802*e1eccf28SAndroid Build Coastguard Worker writeJavaAppendInputToMessage(p, p.javaArrayName + "[i]");
803*e1eccf28SAndroid Build Coastguard Worker } else {
804*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "for (int j = 0; j < " << p.mVectorSize << " ; j++)";
805*e1eccf28SAndroid Build Coastguard Worker mJava->startBlock();
806*e1eccf28SAndroid Build Coastguard Worker writeJavaAppendInputToMessage(p, p.javaArrayName + "[i * " + p.vectorWidth + " + j]");
807*e1eccf28SAndroid Build Coastguard Worker mJava->endBlock();
808*e1eccf28SAndroid Build Coastguard Worker }
809*e1eccf28SAndroid Build Coastguard Worker }
810*e1eccf28SAndroid Build Coastguard Worker
writeJavaAppendVectorOutputToMessage(const ParameterDefinition & p) const811*e1eccf28SAndroid Build Coastguard Worker void PermutationWriter::writeJavaAppendVectorOutputToMessage(const ParameterDefinition& p) const {
812*e1eccf28SAndroid Build Coastguard Worker if (p.mVectorSize == "1") {
813*e1eccf28SAndroid Build Coastguard Worker writeJavaAppendOutputToMessage(p, "", "[i]", false);
814*e1eccf28SAndroid Build Coastguard Worker } else {
815*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "for (int j = 0; j < " << p.mVectorSize << " ; j++)";
816*e1eccf28SAndroid Build Coastguard Worker mJava->startBlock();
817*e1eccf28SAndroid Build Coastguard Worker writeJavaAppendOutputToMessage(p, "[j]", "[i * " + p.vectorWidth + " + j]", false);
818*e1eccf28SAndroid Build Coastguard Worker mJava->endBlock();
819*e1eccf28SAndroid Build Coastguard Worker }
820*e1eccf28SAndroid Build Coastguard Worker }
821*e1eccf28SAndroid Build Coastguard Worker
writeJavaCallToRs(bool relaxed,bool generateCallToVerifier) const822*e1eccf28SAndroid Build Coastguard Worker void PermutationWriter::writeJavaCallToRs(bool relaxed, bool generateCallToVerifier) const {
823*e1eccf28SAndroid Build Coastguard Worker string script = "script";
824*e1eccf28SAndroid Build Coastguard Worker if (relaxed) {
825*e1eccf28SAndroid Build Coastguard Worker script += "Relaxed";
826*e1eccf28SAndroid Build Coastguard Worker }
827*e1eccf28SAndroid Build Coastguard Worker
828*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "try";
829*e1eccf28SAndroid Build Coastguard Worker mJava->startBlock();
830*e1eccf28SAndroid Build Coastguard Worker
831*e1eccf28SAndroid Build Coastguard Worker for (auto p : mAllInputsAndOutputs) {
832*e1eccf28SAndroid Build Coastguard Worker if (p->isOutParameter) {
833*e1eccf28SAndroid Build Coastguard Worker writeJavaOutputAllocationDefinition(*p);
834*e1eccf28SAndroid Build Coastguard Worker }
835*e1eccf28SAndroid Build Coastguard Worker }
836*e1eccf28SAndroid Build Coastguard Worker
837*e1eccf28SAndroid Build Coastguard Worker for (auto p : mPermutation.getParams()) {
838*e1eccf28SAndroid Build Coastguard Worker if (p != mFirstInputParam) {
839*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << script << ".set_" << p->rsAllocName << "(" << p->javaAllocName
840*e1eccf28SAndroid Build Coastguard Worker << ");\n";
841*e1eccf28SAndroid Build Coastguard Worker }
842*e1eccf28SAndroid Build Coastguard Worker }
843*e1eccf28SAndroid Build Coastguard Worker
844*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << script << ".forEach_" << mRsKernelName << "(";
845*e1eccf28SAndroid Build Coastguard Worker bool needComma = false;
846*e1eccf28SAndroid Build Coastguard Worker if (mFirstInputParam) {
847*e1eccf28SAndroid Build Coastguard Worker *mJava << mFirstInputParam->javaAllocName;
848*e1eccf28SAndroid Build Coastguard Worker needComma = true;
849*e1eccf28SAndroid Build Coastguard Worker }
850*e1eccf28SAndroid Build Coastguard Worker if (mReturnParam) {
851*e1eccf28SAndroid Build Coastguard Worker if (needComma) {
852*e1eccf28SAndroid Build Coastguard Worker *mJava << ", ";
853*e1eccf28SAndroid Build Coastguard Worker }
854*e1eccf28SAndroid Build Coastguard Worker *mJava << mReturnParam->variableName << ");\n";
855*e1eccf28SAndroid Build Coastguard Worker }
856*e1eccf28SAndroid Build Coastguard Worker
857*e1eccf28SAndroid Build Coastguard Worker if (generateCallToVerifier) {
858*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << mJavaVerifyMethodName << "(";
859*e1eccf28SAndroid Build Coastguard Worker for (auto p : mAllInputsAndOutputs) {
860*e1eccf28SAndroid Build Coastguard Worker *mJava << p->variableName << ", ";
861*e1eccf28SAndroid Build Coastguard Worker }
862*e1eccf28SAndroid Build Coastguard Worker
863*e1eccf28SAndroid Build Coastguard Worker if (relaxed) {
864*e1eccf28SAndroid Build Coastguard Worker *mJava << "true";
865*e1eccf28SAndroid Build Coastguard Worker } else {
866*e1eccf28SAndroid Build Coastguard Worker *mJava << "false";
867*e1eccf28SAndroid Build Coastguard Worker }
868*e1eccf28SAndroid Build Coastguard Worker *mJava << ");\n";
869*e1eccf28SAndroid Build Coastguard Worker }
870*e1eccf28SAndroid Build Coastguard Worker
871*e1eccf28SAndroid Build Coastguard Worker // Generate code to destroy output Allocations.
872*e1eccf28SAndroid Build Coastguard Worker for (auto p : mAllInputsAndOutputs) {
873*e1eccf28SAndroid Build Coastguard Worker if (p->isOutParameter) {
874*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << p->javaAllocName << ".destroy();\n";
875*e1eccf28SAndroid Build Coastguard Worker }
876*e1eccf28SAndroid Build Coastguard Worker }
877*e1eccf28SAndroid Build Coastguard Worker
878*e1eccf28SAndroid Build Coastguard Worker mJava->decreaseIndent();
879*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "} catch (Exception e) {\n";
880*e1eccf28SAndroid Build Coastguard Worker mJava->increaseIndent();
881*e1eccf28SAndroid Build Coastguard Worker mJava->indent() << "throw new RSRuntimeException(\"RenderScript. Can't invoke forEach_"
882*e1eccf28SAndroid Build Coastguard Worker << mRsKernelName << ": \" + e.toString());\n";
883*e1eccf28SAndroid Build Coastguard Worker mJava->endBlock();
884*e1eccf28SAndroid Build Coastguard Worker }
885*e1eccf28SAndroid Build Coastguard Worker
886*e1eccf28SAndroid Build Coastguard Worker /* Write the section of the .rs file for this permutation.
887*e1eccf28SAndroid Build Coastguard Worker *
888*e1eccf28SAndroid Build Coastguard Worker * We communicate the extra input and output parameters via global allocations.
889*e1eccf28SAndroid Build Coastguard Worker * For example, if we have a function that takes three arguments, two for input
890*e1eccf28SAndroid Build Coastguard Worker * and one for output:
891*e1eccf28SAndroid Build Coastguard Worker *
892*e1eccf28SAndroid Build Coastguard Worker * start:
893*e1eccf28SAndroid Build Coastguard Worker * name: gamn
894*e1eccf28SAndroid Build Coastguard Worker * ret: float3
895*e1eccf28SAndroid Build Coastguard Worker * arg: float3 a
896*e1eccf28SAndroid Build Coastguard Worker * arg: int b
897*e1eccf28SAndroid Build Coastguard Worker * arg: float3 *c
898*e1eccf28SAndroid Build Coastguard Worker * end:
899*e1eccf28SAndroid Build Coastguard Worker *
900*e1eccf28SAndroid Build Coastguard Worker * We'll produce:
901*e1eccf28SAndroid Build Coastguard Worker *
902*e1eccf28SAndroid Build Coastguard Worker * rs_allocation gAllocInB;
903*e1eccf28SAndroid Build Coastguard Worker * rs_allocation gAllocOutC;
904*e1eccf28SAndroid Build Coastguard Worker *
905*e1eccf28SAndroid Build Coastguard Worker * float3 __attribute__((kernel)) test_gamn_float3_int_float3(float3 inA, unsigned int x) {
906*e1eccf28SAndroid Build Coastguard Worker * int inB;
907*e1eccf28SAndroid Build Coastguard Worker * float3 outC;
908*e1eccf28SAndroid Build Coastguard Worker * float2 out;
909*e1eccf28SAndroid Build Coastguard Worker * inB = rsGetElementAt_int(gAllocInB, x);
910*e1eccf28SAndroid Build Coastguard Worker * out = gamn(a, in_b, &outC);
911*e1eccf28SAndroid Build Coastguard Worker * rsSetElementAt_float4(gAllocOutC, &outC, x);
912*e1eccf28SAndroid Build Coastguard Worker * return out;
913*e1eccf28SAndroid Build Coastguard Worker * }
914*e1eccf28SAndroid Build Coastguard Worker *
915*e1eccf28SAndroid Build Coastguard Worker * We avoid re-using x and y from the definition because these have reserved
916*e1eccf28SAndroid Build Coastguard Worker * meanings in a .rs file.
917*e1eccf28SAndroid Build Coastguard Worker */
writeRsSection(set<string> * rsAllocationsGenerated) const918*e1eccf28SAndroid Build Coastguard Worker void PermutationWriter::writeRsSection(set<string>* rsAllocationsGenerated) const {
919*e1eccf28SAndroid Build Coastguard Worker // Write the allocation declarations we'll need.
920*e1eccf28SAndroid Build Coastguard Worker for (auto p : mPermutation.getParams()) {
921*e1eccf28SAndroid Build Coastguard Worker // Don't need allocation for one input and one return value.
922*e1eccf28SAndroid Build Coastguard Worker if (p != mFirstInputParam) {
923*e1eccf28SAndroid Build Coastguard Worker writeRsAllocationDefinition(*p, rsAllocationsGenerated);
924*e1eccf28SAndroid Build Coastguard Worker }
925*e1eccf28SAndroid Build Coastguard Worker }
926*e1eccf28SAndroid Build Coastguard Worker *mRs << "\n";
927*e1eccf28SAndroid Build Coastguard Worker
928*e1eccf28SAndroid Build Coastguard Worker // Write the function header.
929*e1eccf28SAndroid Build Coastguard Worker if (mReturnParam) {
930*e1eccf28SAndroid Build Coastguard Worker *mRs << mReturnParam->rsType;
931*e1eccf28SAndroid Build Coastguard Worker } else {
932*e1eccf28SAndroid Build Coastguard Worker *mRs << "void";
933*e1eccf28SAndroid Build Coastguard Worker }
934*e1eccf28SAndroid Build Coastguard Worker *mRs << " __attribute__((kernel)) " << mRsKernelName;
935*e1eccf28SAndroid Build Coastguard Worker *mRs << "(";
936*e1eccf28SAndroid Build Coastguard Worker bool needComma = false;
937*e1eccf28SAndroid Build Coastguard Worker if (mFirstInputParam) {
938*e1eccf28SAndroid Build Coastguard Worker *mRs << mFirstInputParam->rsType << " " << mFirstInputParam->variableName;
939*e1eccf28SAndroid Build Coastguard Worker needComma = true;
940*e1eccf28SAndroid Build Coastguard Worker }
941*e1eccf28SAndroid Build Coastguard Worker if (mPermutation.getOutputCount() > 1 || mPermutation.getInputCount() > 1) {
942*e1eccf28SAndroid Build Coastguard Worker if (needComma) {
943*e1eccf28SAndroid Build Coastguard Worker *mRs << ", ";
944*e1eccf28SAndroid Build Coastguard Worker }
945*e1eccf28SAndroid Build Coastguard Worker *mRs << "unsigned int x";
946*e1eccf28SAndroid Build Coastguard Worker }
947*e1eccf28SAndroid Build Coastguard Worker *mRs << ")";
948*e1eccf28SAndroid Build Coastguard Worker mRs->startBlock();
949*e1eccf28SAndroid Build Coastguard Worker
950*e1eccf28SAndroid Build Coastguard Worker // Write the local variable declarations and initializations.
951*e1eccf28SAndroid Build Coastguard Worker for (auto p : mPermutation.getParams()) {
952*e1eccf28SAndroid Build Coastguard Worker if (p == mFirstInputParam) {
953*e1eccf28SAndroid Build Coastguard Worker continue;
954*e1eccf28SAndroid Build Coastguard Worker }
955*e1eccf28SAndroid Build Coastguard Worker mRs->indent() << p->rsType << " " << p->variableName;
956*e1eccf28SAndroid Build Coastguard Worker if (p->isOutParameter) {
957*e1eccf28SAndroid Build Coastguard Worker *mRs << " = 0;\n";
958*e1eccf28SAndroid Build Coastguard Worker } else {
959*e1eccf28SAndroid Build Coastguard Worker *mRs << " = rsGetElementAt_" << p->rsType << "(" << p->rsAllocName << ", x);\n";
960*e1eccf28SAndroid Build Coastguard Worker }
961*e1eccf28SAndroid Build Coastguard Worker }
962*e1eccf28SAndroid Build Coastguard Worker
963*e1eccf28SAndroid Build Coastguard Worker // Write the function call.
964*e1eccf28SAndroid Build Coastguard Worker if (mReturnParam) {
965*e1eccf28SAndroid Build Coastguard Worker if (mPermutation.getOutputCount() > 1) {
966*e1eccf28SAndroid Build Coastguard Worker mRs->indent() << mReturnParam->rsType << " " << mReturnParam->variableName << " = ";
967*e1eccf28SAndroid Build Coastguard Worker } else {
968*e1eccf28SAndroid Build Coastguard Worker mRs->indent() << "return ";
969*e1eccf28SAndroid Build Coastguard Worker }
970*e1eccf28SAndroid Build Coastguard Worker }
971*e1eccf28SAndroid Build Coastguard Worker *mRs << mPermutation.getName() << "(";
972*e1eccf28SAndroid Build Coastguard Worker needComma = false;
973*e1eccf28SAndroid Build Coastguard Worker for (auto p : mPermutation.getParams()) {
974*e1eccf28SAndroid Build Coastguard Worker if (needComma) {
975*e1eccf28SAndroid Build Coastguard Worker *mRs << ", ";
976*e1eccf28SAndroid Build Coastguard Worker }
977*e1eccf28SAndroid Build Coastguard Worker if (p->isOutParameter) {
978*e1eccf28SAndroid Build Coastguard Worker *mRs << "&";
979*e1eccf28SAndroid Build Coastguard Worker }
980*e1eccf28SAndroid Build Coastguard Worker *mRs << p->variableName;
981*e1eccf28SAndroid Build Coastguard Worker needComma = true;
982*e1eccf28SAndroid Build Coastguard Worker }
983*e1eccf28SAndroid Build Coastguard Worker *mRs << ");\n";
984*e1eccf28SAndroid Build Coastguard Worker
985*e1eccf28SAndroid Build Coastguard Worker if (mPermutation.getOutputCount() > 1) {
986*e1eccf28SAndroid Build Coastguard Worker // Write setting the extra out parameters into the allocations.
987*e1eccf28SAndroid Build Coastguard Worker for (auto p : mPermutation.getParams()) {
988*e1eccf28SAndroid Build Coastguard Worker if (p->isOutParameter) {
989*e1eccf28SAndroid Build Coastguard Worker mRs->indent() << "rsSetElementAt_" << p->rsType << "(" << p->rsAllocName << ", ";
990*e1eccf28SAndroid Build Coastguard Worker // Check if we need to use '&' for this type of argument.
991*e1eccf28SAndroid Build Coastguard Worker char lastChar = p->variableName.back();
992*e1eccf28SAndroid Build Coastguard Worker if (lastChar >= '0' && lastChar <= '9') {
993*e1eccf28SAndroid Build Coastguard Worker *mRs << "&";
994*e1eccf28SAndroid Build Coastguard Worker }
995*e1eccf28SAndroid Build Coastguard Worker *mRs << p->variableName << ", x);\n";
996*e1eccf28SAndroid Build Coastguard Worker }
997*e1eccf28SAndroid Build Coastguard Worker }
998*e1eccf28SAndroid Build Coastguard Worker if (mReturnParam) {
999*e1eccf28SAndroid Build Coastguard Worker mRs->indent() << "return " << mReturnParam->variableName << ";\n";
1000*e1eccf28SAndroid Build Coastguard Worker }
1001*e1eccf28SAndroid Build Coastguard Worker }
1002*e1eccf28SAndroid Build Coastguard Worker mRs->endBlock();
1003*e1eccf28SAndroid Build Coastguard Worker }
1004*e1eccf28SAndroid Build Coastguard Worker
writeRsAllocationDefinition(const ParameterDefinition & param,set<string> * rsAllocationsGenerated) const1005*e1eccf28SAndroid Build Coastguard Worker void PermutationWriter::writeRsAllocationDefinition(const ParameterDefinition& param,
1006*e1eccf28SAndroid Build Coastguard Worker set<string>* rsAllocationsGenerated) const {
1007*e1eccf28SAndroid Build Coastguard Worker if (!testAndSet(param.rsAllocName, rsAllocationsGenerated)) {
1008*e1eccf28SAndroid Build Coastguard Worker *mRs << "rs_allocation " << param.rsAllocName << ";\n";
1009*e1eccf28SAndroid Build Coastguard Worker }
1010*e1eccf28SAndroid Build Coastguard Worker }
1011*e1eccf28SAndroid Build Coastguard Worker
1012*e1eccf28SAndroid Build Coastguard Worker // Open the mJavaFile and writes the header.
startJavaFile(GeneratedFile * file,const string & directory,const string & testName,const string & relaxedTestName)1013*e1eccf28SAndroid Build Coastguard Worker static bool startJavaFile(GeneratedFile* file, const string& directory,
1014*e1eccf28SAndroid Build Coastguard Worker const string& testName,
1015*e1eccf28SAndroid Build Coastguard Worker const string& relaxedTestName) {
1016*e1eccf28SAndroid Build Coastguard Worker const string fileName = testName + ".java";
1017*e1eccf28SAndroid Build Coastguard Worker if (!file->start(directory, fileName)) {
1018*e1eccf28SAndroid Build Coastguard Worker return false;
1019*e1eccf28SAndroid Build Coastguard Worker }
1020*e1eccf28SAndroid Build Coastguard Worker file->writeNotices();
1021*e1eccf28SAndroid Build Coastguard Worker
1022*e1eccf28SAndroid Build Coastguard Worker *file << "package android.renderscript.cts;\n\n";
1023*e1eccf28SAndroid Build Coastguard Worker
1024*e1eccf28SAndroid Build Coastguard Worker *file << "import android.renderscript.Allocation;\n";
1025*e1eccf28SAndroid Build Coastguard Worker *file << "import android.renderscript.RSRuntimeException;\n";
1026*e1eccf28SAndroid Build Coastguard Worker *file << "import android.renderscript.Element;\n";
1027*e1eccf28SAndroid Build Coastguard Worker *file << "import android.renderscript.cts.Target;\n\n";
1028*e1eccf28SAndroid Build Coastguard Worker *file << "import java.util.Arrays;\n\n";
1029*e1eccf28SAndroid Build Coastguard Worker
1030*e1eccf28SAndroid Build Coastguard Worker *file << "public class " << testName << " extends RSBaseCompute";
1031*e1eccf28SAndroid Build Coastguard Worker file->startBlock(); // The corresponding endBlock() is in finishJavaFile()
1032*e1eccf28SAndroid Build Coastguard Worker *file << "\n";
1033*e1eccf28SAndroid Build Coastguard Worker
1034*e1eccf28SAndroid Build Coastguard Worker file->indent() << "private ScriptC_" << testName << " script;\n";
1035*e1eccf28SAndroid Build Coastguard Worker file->indent() << "private ScriptC_" << relaxedTestName << " scriptRelaxed;\n\n";
1036*e1eccf28SAndroid Build Coastguard Worker
1037*e1eccf28SAndroid Build Coastguard Worker file->indent() << "@Override\n";
1038*e1eccf28SAndroid Build Coastguard Worker file->indent() << "protected void setUp() throws Exception";
1039*e1eccf28SAndroid Build Coastguard Worker file->startBlock();
1040*e1eccf28SAndroid Build Coastguard Worker
1041*e1eccf28SAndroid Build Coastguard Worker file->indent() << "super.setUp();\n";
1042*e1eccf28SAndroid Build Coastguard Worker file->indent() << "script = new ScriptC_" << testName << "(mRS);\n";
1043*e1eccf28SAndroid Build Coastguard Worker file->indent() << "scriptRelaxed = new ScriptC_" << relaxedTestName << "(mRS);\n";
1044*e1eccf28SAndroid Build Coastguard Worker
1045*e1eccf28SAndroid Build Coastguard Worker file->endBlock();
1046*e1eccf28SAndroid Build Coastguard Worker *file << "\n";
1047*e1eccf28SAndroid Build Coastguard Worker
1048*e1eccf28SAndroid Build Coastguard Worker file->indent() << "@Override\n";
1049*e1eccf28SAndroid Build Coastguard Worker file->indent() << "protected void tearDown() throws Exception";
1050*e1eccf28SAndroid Build Coastguard Worker file->startBlock();
1051*e1eccf28SAndroid Build Coastguard Worker
1052*e1eccf28SAndroid Build Coastguard Worker file->indent() << "script.destroy();\n";
1053*e1eccf28SAndroid Build Coastguard Worker file->indent() << "scriptRelaxed.destroy();\n";
1054*e1eccf28SAndroid Build Coastguard Worker file->indent() << "super.tearDown();\n";
1055*e1eccf28SAndroid Build Coastguard Worker
1056*e1eccf28SAndroid Build Coastguard Worker file->endBlock();
1057*e1eccf28SAndroid Build Coastguard Worker *file << "\n";
1058*e1eccf28SAndroid Build Coastguard Worker
1059*e1eccf28SAndroid Build Coastguard Worker return true;
1060*e1eccf28SAndroid Build Coastguard Worker }
1061*e1eccf28SAndroid Build Coastguard Worker
1062*e1eccf28SAndroid Build Coastguard Worker // Write the test method that calls all the generated Check methods.
finishJavaFile(GeneratedFile * file,const Function & function,const vector<string> & javaCheckMethods)1063*e1eccf28SAndroid Build Coastguard Worker static void finishJavaFile(GeneratedFile* file, const Function& function,
1064*e1eccf28SAndroid Build Coastguard Worker const vector<string>& javaCheckMethods) {
1065*e1eccf28SAndroid Build Coastguard Worker file->indent() << "public void test" << function.getCapitalizedName() << "()";
1066*e1eccf28SAndroid Build Coastguard Worker file->startBlock();
1067*e1eccf28SAndroid Build Coastguard Worker for (auto m : javaCheckMethods) {
1068*e1eccf28SAndroid Build Coastguard Worker file->indent() << m << "();\n";
1069*e1eccf28SAndroid Build Coastguard Worker }
1070*e1eccf28SAndroid Build Coastguard Worker file->endBlock();
1071*e1eccf28SAndroid Build Coastguard Worker
1072*e1eccf28SAndroid Build Coastguard Worker file->endBlock();
1073*e1eccf28SAndroid Build Coastguard Worker }
1074*e1eccf28SAndroid Build Coastguard Worker
1075*e1eccf28SAndroid Build Coastguard Worker // Open the script file and write its header.
startRsFile(GeneratedFile * file,const string & directory,const string & testName)1076*e1eccf28SAndroid Build Coastguard Worker static bool startRsFile(GeneratedFile* file, const string& directory,
1077*e1eccf28SAndroid Build Coastguard Worker const string& testName) {
1078*e1eccf28SAndroid Build Coastguard Worker string fileName = testName + ".rs";
1079*e1eccf28SAndroid Build Coastguard Worker if (!file->start(directory, fileName)) {
1080*e1eccf28SAndroid Build Coastguard Worker return false;
1081*e1eccf28SAndroid Build Coastguard Worker }
1082*e1eccf28SAndroid Build Coastguard Worker file->writeNotices();
1083*e1eccf28SAndroid Build Coastguard Worker
1084*e1eccf28SAndroid Build Coastguard Worker *file << "#pragma version(1)\n";
1085*e1eccf28SAndroid Build Coastguard Worker *file << "#pragma rs java_package_name(android.renderscript.cts)\n\n";
1086*e1eccf28SAndroid Build Coastguard Worker return true;
1087*e1eccf28SAndroid Build Coastguard Worker }
1088*e1eccf28SAndroid Build Coastguard Worker
1089*e1eccf28SAndroid Build Coastguard Worker // Write the entire *Relaxed.rs test file, as it only depends on the name.
writeRelaxedRsFile(const string & directory,const string & testName,const string & relaxedTestName)1090*e1eccf28SAndroid Build Coastguard Worker static bool writeRelaxedRsFile(const string& directory, const string& testName,
1091*e1eccf28SAndroid Build Coastguard Worker const string& relaxedTestName) {
1092*e1eccf28SAndroid Build Coastguard Worker string name = relaxedTestName + ".rs";
1093*e1eccf28SAndroid Build Coastguard Worker
1094*e1eccf28SAndroid Build Coastguard Worker GeneratedFile file;
1095*e1eccf28SAndroid Build Coastguard Worker if (!file.start(directory, name)) {
1096*e1eccf28SAndroid Build Coastguard Worker return false;
1097*e1eccf28SAndroid Build Coastguard Worker }
1098*e1eccf28SAndroid Build Coastguard Worker file.writeNotices();
1099*e1eccf28SAndroid Build Coastguard Worker
1100*e1eccf28SAndroid Build Coastguard Worker file << "#include \"" << testName << ".rs\"\n";
1101*e1eccf28SAndroid Build Coastguard Worker file << "#pragma rs_fp_relaxed\n";
1102*e1eccf28SAndroid Build Coastguard Worker file.close();
1103*e1eccf28SAndroid Build Coastguard Worker return true;
1104*e1eccf28SAndroid Build Coastguard Worker }
1105*e1eccf28SAndroid Build Coastguard Worker
1106*e1eccf28SAndroid Build Coastguard Worker /* Write the .java and the two .rs test files. versionOfTestFiles is used to restrict which API
1107*e1eccf28SAndroid Build Coastguard Worker * to test.
1108*e1eccf28SAndroid Build Coastguard Worker */
writeTestFilesForFunction(const Function & function,const string & directory,unsigned int versionOfTestFiles)1109*e1eccf28SAndroid Build Coastguard Worker static bool writeTestFilesForFunction(const Function& function, const string& directory,
1110*e1eccf28SAndroid Build Coastguard Worker unsigned int versionOfTestFiles) {
1111*e1eccf28SAndroid Build Coastguard Worker // Avoid creating empty files if we're not testing this function.
1112*e1eccf28SAndroid Build Coastguard Worker if (!needTestFiles(function, versionOfTestFiles)) {
1113*e1eccf28SAndroid Build Coastguard Worker return true;
1114*e1eccf28SAndroid Build Coastguard Worker }
1115*e1eccf28SAndroid Build Coastguard Worker
1116*e1eccf28SAndroid Build Coastguard Worker const string testName = "Test" + function.getCapitalizedName();
1117*e1eccf28SAndroid Build Coastguard Worker const string relaxedTestName = testName + "Relaxed";
1118*e1eccf28SAndroid Build Coastguard Worker
1119*e1eccf28SAndroid Build Coastguard Worker if (!writeRelaxedRsFile(directory, testName, relaxedTestName)) {
1120*e1eccf28SAndroid Build Coastguard Worker return false;
1121*e1eccf28SAndroid Build Coastguard Worker }
1122*e1eccf28SAndroid Build Coastguard Worker
1123*e1eccf28SAndroid Build Coastguard Worker GeneratedFile rsFile; // The Renderscript test file we're generating.
1124*e1eccf28SAndroid Build Coastguard Worker GeneratedFile javaFile; // The Jave test file we're generating.
1125*e1eccf28SAndroid Build Coastguard Worker if (!startRsFile(&rsFile, directory, testName)) {
1126*e1eccf28SAndroid Build Coastguard Worker return false;
1127*e1eccf28SAndroid Build Coastguard Worker }
1128*e1eccf28SAndroid Build Coastguard Worker
1129*e1eccf28SAndroid Build Coastguard Worker if (!startJavaFile(&javaFile, directory, testName, relaxedTestName)) {
1130*e1eccf28SAndroid Build Coastguard Worker return false;
1131*e1eccf28SAndroid Build Coastguard Worker }
1132*e1eccf28SAndroid Build Coastguard Worker
1133*e1eccf28SAndroid Build Coastguard Worker /* We keep track of the allocations generated in the .rs file and the argument classes defined
1134*e1eccf28SAndroid Build Coastguard Worker * in the Java file, as we share these between the functions created for each specification.
1135*e1eccf28SAndroid Build Coastguard Worker */
1136*e1eccf28SAndroid Build Coastguard Worker set<string> rsAllocationsGenerated;
1137*e1eccf28SAndroid Build Coastguard Worker set<string> javaGeneratedArgumentClasses;
1138*e1eccf28SAndroid Build Coastguard Worker // Lines of Java code to invoke the check methods.
1139*e1eccf28SAndroid Build Coastguard Worker vector<string> javaCheckMethods;
1140*e1eccf28SAndroid Build Coastguard Worker
1141*e1eccf28SAndroid Build Coastguard Worker for (auto spec : function.getSpecifications()) {
1142*e1eccf28SAndroid Build Coastguard Worker if (spec->hasTests(versionOfTestFiles)) {
1143*e1eccf28SAndroid Build Coastguard Worker for (auto permutation : spec->getPermutations()) {
1144*e1eccf28SAndroid Build Coastguard Worker PermutationWriter w(*permutation, &rsFile, &javaFile);
1145*e1eccf28SAndroid Build Coastguard Worker w.writeRsSection(&rsAllocationsGenerated);
1146*e1eccf28SAndroid Build Coastguard Worker w.writeJavaSection(&javaGeneratedArgumentClasses);
1147*e1eccf28SAndroid Build Coastguard Worker
1148*e1eccf28SAndroid Build Coastguard Worker // Store the check method to be called.
1149*e1eccf28SAndroid Build Coastguard Worker javaCheckMethods.push_back(w.getJavaCheckMethodName());
1150*e1eccf28SAndroid Build Coastguard Worker }
1151*e1eccf28SAndroid Build Coastguard Worker }
1152*e1eccf28SAndroid Build Coastguard Worker }
1153*e1eccf28SAndroid Build Coastguard Worker
1154*e1eccf28SAndroid Build Coastguard Worker finishJavaFile(&javaFile, function, javaCheckMethods);
1155*e1eccf28SAndroid Build Coastguard Worker // There's no work to wrap-up in the .rs file.
1156*e1eccf28SAndroid Build Coastguard Worker
1157*e1eccf28SAndroid Build Coastguard Worker rsFile.close();
1158*e1eccf28SAndroid Build Coastguard Worker javaFile.close();
1159*e1eccf28SAndroid Build Coastguard Worker return true;
1160*e1eccf28SAndroid Build Coastguard Worker }
1161*e1eccf28SAndroid Build Coastguard Worker
generateTestFiles(const string & directory,unsigned int versionOfTestFiles)1162*e1eccf28SAndroid Build Coastguard Worker bool generateTestFiles(const string& directory, unsigned int versionOfTestFiles) {
1163*e1eccf28SAndroid Build Coastguard Worker bool success = true;
1164*e1eccf28SAndroid Build Coastguard Worker for (auto f : systemSpecification.getFunctions()) {
1165*e1eccf28SAndroid Build Coastguard Worker if (!writeTestFilesForFunction(*f.second, directory, versionOfTestFiles)) {
1166*e1eccf28SAndroid Build Coastguard Worker success = false;
1167*e1eccf28SAndroid Build Coastguard Worker }
1168*e1eccf28SAndroid Build Coastguard Worker }
1169*e1eccf28SAndroid Build Coastguard Worker return success;
1170*e1eccf28SAndroid Build Coastguard Worker }
1171