modified: src1/input.c
[GalaxyCodeBases.git] / BGI / BASE / src / 2bwt / SSETest.c
blobf286ac840f09d4d1d1435a58e9331d14c6adc72e
1 /* SSETest.c Testing speed of SSE decode of BWT
3 Copyright 2006, Wong Chi Kwong, all rights reserved.
5 This module tests the speed of SSE decode of BWT.
7 This software may be used freely for any purpose. However, when distributed,
8 the original source must be clearly stated, and, when the source code is
9 distributed, the copyright notice must be retained and any alterations in
10 the code must be clearly marked. No warranty is given regarding the quality
11 of this software.
15 #include <stdlib.h>
16 #include <emmintrin.h>
17 #include <mmintrin.h>
18 #include "MiscUtilities.h"
19 #include "MemManager.h"
20 #include "iniparser.h"
21 #include "r250.h"
22 #include "Timing.h"
23 #include "DNACount.h"
25 dictionary *ParseInput(int argc, char** argv);
26 void ValidateParameters();
29 unsigned int MemorySize;
30 unsigned int NumberOfAccess;
31 char *Mode;
32 unsigned int NumberOfIteration;
35 void GenerateDNAOccCountTable1(unsigned int *dnaDecodeTable) {
37 unsigned int i, j, c, t;
39 for (i=0; i<65536; i++) {
40 dnaDecodeTable[i] = 0;
41 c = i;
42 for (j=0; j<8; j++) {
43 t = c & 0x00000003;
44 dnaDecodeTable[i] += 1 << (t * 8);
45 c >>= 2;
51 int main(int argc, char** argv) {
53 #define CHAR_PER_128 64
54 #define CHAR_PER_256 128
55 #define CHAR_PER_WORD 16
58 unsigned int* __restrict address;
59 unsigned int* __restrict memory;
60 unsigned int* __restrict dnaDecodeTable;
61 unsigned int* __restrict index1;
62 unsigned int* __restrict index2;
63 unsigned int* __restrict character;
65 unsigned int i, j;
66 unsigned int t=0, r=0, r1=0;
67 unsigned int temp;
68 unsigned int t4[4] = { 0, 0, 0, 0 };
69 unsigned int r4[4] = { 0, 0, 0, 0 };
70 unsigned int numberOfMemoryLocation;
72 dictionary *programInput;
73 double startTime;
74 double elapsedTime = 0, totalElapsedTime = 0;
75 double initializationTime, experimentTime;
77 unsigned int numChar1, numChar2, minIndex, maxIndex, minIndex128, maxIndex128;
79 const static unsigned int ALIGN_16 partitionOne1[4] = { 47, 31, 15, 0 };
80 const static unsigned int ALIGN_16 partitionOne2[4] = { 0, 15, 31, 47 };
81 const static unsigned int ALIGN_16 partitionZero1[4] = { 63, 47, 31, 15 };
82 const static unsigned int ALIGN_16 partitionZero2[4] = { 15, 31, 47, 63 };
84 // SSE registers
85 __m128i r1e, r2e;
86 __m128i mcl;
88 // Count one alphabet only
89 __m128i m0, m1;
90 __m128i r1a, r1b, r1c;
91 __m128i r2a, r2b, r2c;
93 // Count all alphabets only
94 __m128i rc, rg, rt;
95 __m128i ra1, ra2;
96 __m128i rc1, rc2;
97 __m128i rg1, rg2;
98 __m128i rt1, rt2;
100 programInput = ParseInput(argc, argv);
101 ValidateParameters();
103 // Initialize memory manager
104 MMMasterInitialize(0, 0, FALSE, NULL);
106 numberOfMemoryLocation = MemorySize / sizeof(int);
108 // Allocate memory
109 address = MMUnitAllocate((NumberOfAccess + 8) * sizeof(unsigned int));
110 memory = MMUnitAllocate((numberOfMemoryLocation + 32) * sizeof(unsigned int));
111 index1 = MMUnitAllocate((NumberOfAccess + 8) * sizeof(unsigned int));
112 index2 = MMUnitAllocate((NumberOfAccess + 8) * sizeof(unsigned int));
113 character = MMUnitAllocate((NumberOfAccess + 8) * sizeof(unsigned int));
115 dnaDecodeTable = MMUnitAllocate(65536 * sizeof(unsigned int));
117 // Set random seed
118 r250_init(getRandomSeed());
119 // r250_init(1);
121 // Set start time
122 startTime = setStartTime();
124 printf("Initialize memory pointers with random values..");
126 GenerateDNAOccCountTable1(dnaDecodeTable);
129 for (i=0; i<numberOfMemoryLocation + 32; i++) {
130 memory[i] = r250();
132 // Initialize address and memory
133 for (i=0; i<NumberOfAccess + 8; i++) {
134 address[i] = (r250() % numberOfMemoryLocation) / 8 * 8; // align to 32 byte
135 index1[i] = (r250() % 3) * CHAR_PER_128;
136 index2[i] = r250() % 129;
137 character[i] = r250() % 4;
140 printf("finished.\n");
142 elapsedTime = getElapsedTime(startTime) - totalElapsedTime;
143 totalElapsedTime += elapsedTime;
144 initializationTime = elapsedTime;
146 // Test SSE Decode
147 if (Mode[0] == 'S' || Mode[0] == 's') {
149 for (i=0; i<NumberOfIteration; i++) {
150 for (j=0; j<NumberOfAccess; j++) {
152 // Ordering of index1 and index2 is not important; this module will handle the ordering
153 // index1 and index2 can be on the same aligned 128 bit region or can be on adjacant aligned 128 bit region
154 // If index1 and index2 are in the same aligned 128 bit region, one of them must be on the boundary
155 // These requirements are to reduce the no. of branches in the program flow
157 // Pre-fetch next read
158 //_mm_prefetch((char*)(memory + address[j+1]), _MM_HINT_NTA);
159 //_mm_prefetch((char*)(memory + address[j+2]), _MM_HINT_NTA);
160 //_mm_prefetch((char*)(memory + address[j+3]), _MM_HINT_NTA);
161 //_mm_prefetch((char*)(memory + address[j+4]), _MM_HINT_NTA);
163 // Sort index1 and index2
164 temp = (index1[j] - index2[j]) & -(index1[j] < index2[j]);
165 minIndex = index2[j] + temp;
166 maxIndex = index1[j] - temp;
168 // Locate 128 bit boundary
169 minIndex128 = lastAlignedBoundary(minIndex, CHAR_PER_128);
170 maxIndex128 = lastAlignedBoundary(maxIndex - (maxIndex - minIndex > CHAR_PER_128), CHAR_PER_128);
172 // Determine no.of characters to count
173 numChar1 = maxIndex128 - minIndex;
174 numChar2 = maxIndex - maxIndex128;
176 // Set character extraction masks
177 m0 = _mm_set1_epi32(0xFFFFFFFF + (character[j] & 1)); // Character selection mask for even bits
178 m1 = _mm_set1_epi32(0xFFFFFFFF + (character[j] >> 1)); // Character selection mask for odd bits
179 mcl = _mm_set1_epi32(0x55555555); // Set bit-clearing mask to 0x55555555....(alternate 1-bit)
181 // Set counting mask for 2 x 128 bits
183 r1a = _mm_set1_epi32(numChar1); // Load number of characters into register
184 r2a = _mm_set1_epi32(numChar2); // Load number of characters into register
186 r1b = _mm_load_si128((__m128i*)partitionOne1); // Load partition into register
187 r2b = _mm_load_si128((__m128i*)partitionOne2); // Load partition into register
189 r1c = _mm_load_si128((__m128i*)partitionZero1); // Load partition into register
190 r2c = _mm_load_si128((__m128i*)partitionZero2); // Load partition into register
192 r1b = _mm_cmpgt_epi32(r1a, r1b); // Compare to generate 4x32 bit mask; the word with counting boundary is all ones
193 r2b = _mm_cmpgt_epi32(r2a, r2b); // Compare to generate 4x32 bit mask; the word with counting boundary is all ones
195 r1c = _mm_cmpgt_epi32(r1a, r1c); // Compare to generate 4x32 bit mask; the word with counting boundary is all zeros
196 r2c = _mm_cmpgt_epi32(r2a, r2c); // Compare to generate 4x32 bit mask; the word with counting boundary is all zeros
198 r1b = _mm_srli_epi32(r1b, (16 - numChar1 % 16) * 2); // Shift bits so that all word comform to the requirement of counting the word with counting boundary
199 r2b = _mm_slli_epi32(r2b, (16 - numChar2 % 16) * 2); // Shift bits so that all word comform to the requirement of counting the word with counting boundary
201 r1c = _mm_or_si128(r1b, r1c); // Combine two masks
202 r2c = _mm_or_si128(r2b, r2c); // Combine two masks
204 r1c = _mm_and_si128(r1c, mcl); // Combine with bit-clearing mask (now = 0x55555555....)
205 r2c = _mm_and_si128(r2c, mcl); // Combine with bit-clearing mask (now = 0x55555555....)
207 // Load encoding into register
208 r1e = _mm_load_si128((__m128i *)(memory + address[j] + minIndex128 / CHAR_PER_WORD)); // Load encoding into register
209 r2e = _mm_load_si128((__m128i *)(memory + address[j] + maxIndex128 / CHAR_PER_WORD)); // Load encoding into register
211 // Start counting
213 r1b = _mm_srli_epi32(r1e, 1); // Shift encoding to right by 1 bit
214 r2b = _mm_srli_epi32(r2e, 1); // Shift encoding to right by 1 bit
216 r1a = _mm_xor_si128(r1e, m0); // Check even-bits with mask
217 r2a = _mm_xor_si128(r2e, m0); // Check even-bits with mask
219 r1b = _mm_xor_si128(r1b, m1); // Check odd-bits with mask
220 r2b = _mm_xor_si128(r2b, m1); // Check odd-bits with mask
222 r1a = _mm_and_si128(r1a, r1b); // Combine even and odd bits
223 r2a = _mm_and_si128(r2a, r2b); // Combine even and odd bits
225 r1a = _mm_and_si128(r1a, r1c); // Combine with counting mask, which has been combined with bit-clearing mask of 0x55555555....
226 r2a = _mm_and_si128(r2a, r2c); // Combine with counting mask, which has been combined with bit-clearing mask of 0x55555555....
228 // Combine 2 x 128 bits and continue counting
230 r1a = _mm_add_epi32(r1a, r2a); // Combine 2 x 128 bits by adding them together
232 mcl = _mm_set1_epi32(0x33333333); // Set bit-clearing mask to 0x33333333....(alternate 2-bits)
234 r1b = _mm_srli_epi32(r1a, 2); // Shift intermediate result to right by 2 bit
235 r1a = _mm_and_si128(r1a, mcl); // Clear alternate 2-bits of intermediate result by combining with bit-clearing mask (now = 0x33333333....)
236 r1b = _mm_and_si128(r1b, mcl); // Clear alternate 2-bits of shifted intermediate result by combining with bit-clearing mask (now = 0x33333333....)
237 r1a = _mm_add_epi32(r1a, r1b); // Combine shifted and non-shifted intermediate results by adding them together
239 mcl = _mm_set1_epi32(0x0F0F0F0F); // Set bit-clearing mask to 0x0F0F0F0F....(alternate 4-bits)
240 m0 = _mm_setzero_si128(); // Set an all-zero mask
242 r1b = _mm_srli_epi32(r1a, 4); // Shift intermediate result to right by 2 bit
243 r1a = _mm_add_epi32(r1a, r1b); // Combine shifted and non-shifted intermediate results by adding them together
244 r1a = _mm_and_si128(r1a, mcl); // Clear alternate 4-bits of intermediate result by combining with bit-clearing mask (now = 0xOFOFOFOF....)
246 r1a = _mm_sad_epu8(r1a, m0); // Treating the 128 bit as 16 x 8 bit; summing up the 1st 8 x 8 bit into 1st 64-bit and 2nd 8 x 8 bit into 2nd 64-bit
248 r = _mm_extract_epi16(r1a, 0) + _mm_extract_epi16(r1a, 4); // Extract result from register and store into variable
251 if (index1[j] < index2[j]) {
252 r1 = ForwardDNAOccCount(memory + address[j] + index1[j] / CHAR_PER_WORD, index2[j] - index1[j], character[j], dnaDecodeTable);
253 } else {
254 r1 = BackwardDNAOccCount(memory + address[j] + index1[j] / CHAR_PER_WORD, index1[j] - index2[j], character[j], dnaDecodeTable);
256 if (r != r1) {
257 printf("%u\n",j);
261 t +=r;
267 // Test SSE Decode all alphabets
268 if (Mode[0] == 'A' || Mode[0] == 'a') {
270 for (i=0; i<NumberOfIteration; i++) {
271 for (j=0; j<NumberOfAccess; j++) {
273 // Ordering of index1 and index2 is not important; this module will handle the ordering
274 // index1 and index2 can be on the same aligned 128 bit region or can be on adjacant aligned 128 bit region
275 // If index1 and index2 are in the same aligned 128 bit region, one of them must be on the boundary
276 // These requirements are to reduce the no. of branches in the program flow
278 // Pre-fetch next read
279 //_mm_prefetch((char*)(memory + address[j+1]), _MM_HINT_NTA);
280 //_mm_prefetch((char*)(memory + address[j+2]), _MM_HINT_NTA);
281 //_mm_prefetch((char*)(memory + address[j+3]), _MM_HINT_NTA);
282 //_mm_prefetch((char*)(memory + address[j+4]), _MM_HINT_NTA);
284 // Sort index1 and index2
285 r = (index1[j] - index2[j]) & -(index1[j] < index2[j]);
286 minIndex = index2[j] + r;
287 maxIndex = index1[j] - r;
289 // Locate 128 bit boundary
290 minIndex128 = lastAlignedBoundary(minIndex, CHAR_PER_128);
291 maxIndex128 = lastAlignedBoundary(maxIndex - (maxIndex - minIndex > CHAR_PER_128), CHAR_PER_128);
293 // Determine no.of characters to count
294 numChar1 = maxIndex128 - minIndex;
295 numChar2 = maxIndex - maxIndex128;
297 // Set character extraction masks
298 mcl = _mm_set1_epi32(0x55555555); // Set bit-clearing mask to 0x55555555....(alternate 1-bit)
300 // Set counting mask for 2 x 128 bits
301 ra1 = _mm_set1_epi32(numChar1); // Load number of characters into register
302 ra2 = _mm_set1_epi32(numChar2); // Load number of characters into register
304 rc1 = _mm_load_si128((__m128i*)partitionOne1); // Load partition into register
305 rc2 = _mm_load_si128((__m128i*)partitionOne2); // Load partition into register
307 rg1 = _mm_load_si128((__m128i*)partitionZero1); // Load partition into register
308 rg2 = _mm_load_si128((__m128i*)partitionZero2); // Load partition into register
310 rc1 = _mm_cmpgt_epi32(ra1, rc1); // Compare to generate 4x32 bit mask; the word with counting boundary is all ones
311 rc2 = _mm_cmpgt_epi32(ra2, rc2); // Compare to generate 4x32 bit mask; the word with counting boundary is all ones
313 rg1 = _mm_cmpgt_epi32(ra1, rg1); // Compare to generate 4x32 bit mask; the word with counting boundary is all zeros
314 rg2 = _mm_cmpgt_epi32(ra2, rg2); // Compare to generate 4x32 bit mask; the word with counting boundary is all zeros
316 rc1 = _mm_srli_epi32(rc1, (16 - numChar1 % 16) * 2); // Shift bits so that all word comform to the requirement of counting the word with counting boundary
317 rc2 = _mm_slli_epi32(rc2, (16 - numChar2 % 16) * 2); // Shift bits so that all word comform to the requirement of counting the word with counting boundary
319 ra1 = _mm_or_si128(rc1, rg1); // Combine two masks
320 ra2 = _mm_or_si128(rc2, rg2); // Combine two masks
322 // Load encoding into register
323 r1e = _mm_load_si128((__m128i *)(memory + address[j] + minIndex128 / CHAR_PER_WORD)); // Load encoding into register
324 r2e = _mm_load_si128((__m128i *)(memory + address[j] + maxIndex128 / CHAR_PER_WORD)); // Load encoding into register
326 // Start counting
327 r1e = _mm_and_si128(r1e, ra1); // Combine encoding with counting mask
328 r2e = _mm_and_si128(r2e, ra2); // Combine encoding with counting mask
330 // ra1, ra2, rc1, rc2, rg1, rg2, rt1, rt2 all retired
332 // Shift and combine with character selection mask
334 ra1 = _mm_srli_epi32(r1e, 1); // Shift encoding to right by 1 bit
335 ra2 = _mm_srli_epi32(r2e, 1); // Shift encoding to right by 1 bit
337 rt1 = _mm_and_si128(r1e, mcl); // Check even-bits = '1'
338 rt2 = _mm_and_si128(r2e, mcl); // Check even-bits = '1'
340 rg1 = _mm_and_si128(ra1, mcl); // Check odd-bits = '1'
341 rg2 = _mm_and_si128(ra2, mcl); // Check odd-bits = '1'
343 rc1 = _mm_andnot_si128(r1e, mcl); // Check even-bits = '0'
344 rc2 = _mm_andnot_si128(r2e, mcl); // Check even-bits = '0'
346 ra1 = _mm_andnot_si128(ra1, mcl); // Check odd-bits = '0'
347 ra2 = _mm_andnot_si128(ra2, mcl); // Check odd-bits = '0'
349 // r1e, r2e retired
351 // Count for 'c' 'g' 't'
353 r1e = _mm_and_si128(ra1, rt1); // Combine even and odd bits
354 r2e = _mm_and_si128(ra2, rt2); // Combine even and odd bits
355 ra1 = _mm_and_si128(rg1, rc1); // Combine even and odd bits
356 ra2 = _mm_and_si128(rg2, rc2); // Combine even and odd bits
357 rc1 = _mm_and_si128(rg1, rt1); // Combine even and odd bits
358 rc2 = _mm_and_si128(rg2, rt2); // Combine even and odd bits
360 rc = _mm_add_epi32(r1e, r2e); // Combine 2 x 128 bits by adding them together
361 rg = _mm_add_epi32(ra1, ra2); // Combine 2 x 128 bits by adding them together
362 rt = _mm_add_epi32(rc1, rc2); // Combine 2 x 128 bits by adding them together
364 // All except rc, rg, rt retired
366 // Continue counting rc, rg, rt
368 mcl = _mm_set1_epi32(0x33333333); // Set bit-clearing mask to 0x33333333....(alternate 2-bits)
370 rc1 = _mm_srli_epi32(rc, 2); // Shift intermediate result to right by 2 bit
371 rg1 = _mm_srli_epi32(rg, 2); // Shift intermediate result to right by 2 bit
372 rt1 = _mm_srli_epi32(rt, 2); // Shift intermediate result to right by 2 bit
374 rc2 = _mm_and_si128(rc, mcl); // Clear alternate 2-bits of intermediate result by combining with bit-clearing mask (now = 0x33333333....)
375 rg2 = _mm_and_si128(rg, mcl); // Clear alternate 2-bits of intermediate result by combining with bit-clearing mask (now = 0x33333333....)
376 rt2 = _mm_and_si128(rt, mcl); // Clear alternate 2-bits of intermediate result by combining with bit-clearing mask (now = 0x33333333....)
378 rc1 = _mm_and_si128(rc1, mcl); // Clear alternate 2-bits of shifted intermediate result by combining with bit-clearing mask (now = 0x33333333....)
379 rg1 = _mm_and_si128(rg1, mcl); // Clear alternate 2-bits of shifted intermediate result by combining with bit-clearing mask (now = 0x33333333....)
380 rt1 = _mm_and_si128(rt1, mcl); // Clear alternate 2-bits of shifted intermediate result by combining with bit-clearing mask (now = 0x33333333....)
382 rc = _mm_add_epi32(rc1, rc2); // Combine shifted and non-shifted intermediate results by adding them together
383 rg = _mm_add_epi32(rg1, rg2); // Combine shifted and non-shifted intermediate results by adding them together
384 rt = _mm_add_epi32(rt1, rt2); // Combine shifted and non-shifted intermediate results by adding them together
386 mcl = _mm_set1_epi32(0x0F0F0F0F); // Set bit-clearing mask to 0x0F0F0F0F....(alternate 4-bits)
387 r1e = _mm_setzero_si128(); // Set an all-zero mask
389 rc1 = _mm_srli_epi32(rc, 4); // Shift intermediate result to right by 2 bit
390 rg1 = _mm_srli_epi32(rg, 4); // Shift intermediate result to right by 2 bit
391 rt1 = _mm_srli_epi32(rt, 4); // Shift intermediate result to right by 2 bit
393 rc2 = _mm_add_epi32(rc, rc1); // Combine shifted and non-shifted intermediate results by adding them together
394 rg2 = _mm_add_epi32(rg, rg1); // Combine shifted and non-shifted intermediate results by adding them together
395 rt2 = _mm_add_epi32(rt, rt1); // Combine shifted and non-shifted intermediate results by adding them together
397 rc = _mm_and_si128(rc2, mcl); // Clear alternate 4-bits of intermediate result by combining with bit-clearing mask (now = 0xOFOFOFOF....)
398 rg = _mm_and_si128(rg2, mcl); // Clear alternate 4-bits of intermediate result by combining with bit-clearing mask (now = 0xOFOFOFOF....)
399 rt = _mm_and_si128(rt2, mcl); // Clear alternate 4-bits of intermediate result by combining with bit-clearing mask (now = 0xOFOFOFOF....)
401 rc = _mm_sad_epu8(rc, r1e); // Treating the 128 bit as 16 x 8 bit; summing up the 1st 8 x 8 bit into 1st 64-bit and 2nd 8 x 8 bit into 2nd 64-bit
402 rg = _mm_sad_epu8(rg, r1e); // Treating the 128 bit as 16 x 8 bit; summing up the 1st 8 x 8 bit into 1st 64-bit and 2nd 8 x 8 bit into 2nd 64-bit
403 rt = _mm_sad_epu8(rt, r1e); // Treating the 128 bit as 16 x 8 bit; summing up the 1st 8 x 8 bit into 1st 64-bit and 2nd 8 x 8 bit into 2nd 64-bit
405 r4[1] = _mm_extract_epi16(rc, 0) + _mm_extract_epi16(rc, 4); // Extract result from register and store into variable
406 r4[2] = _mm_extract_epi16(rg, 0) + _mm_extract_epi16(rg, 4); // Extract result from register and store into variable
407 r4[3] = _mm_extract_epi16(rt, 0) + _mm_extract_epi16(rt, 4); // Extract result from register and store into variable
409 r4[0] = maxIndex - minIndex - r4[1] - r4[2] - r4[3];
412 if (index1[j] < index2[j]) {
413 ForwardDNAAllOccCount(memory + address[j] + index1[j] / CHAR_PER_WORD, index2[j] - index1[j], t4, dnaDecodeTable);
414 } else {
415 BackwardDNAAllOccCount(memory + address[j] + index1[j] / CHAR_PER_WORD, index1[j] - index2[j], t4, dnaDecodeTable);
417 if (r4[0] != t4[0] || r4[1] != t4[1] || r4[2] != t4[2] || r4[3] != t4[3]) {
418 printf("%u\n",j);
423 t4[0] += r4[0];
424 t4[1] += r4[1];
425 t4[2] += r4[2];
426 t4[3] += r4[3];
432 // Test decode by lookup
433 if (Mode[0] == 'L' || Mode[0] == 'l') {
434 for (i=0; i<NumberOfIteration; i++) {
435 for (j=0; j<NumberOfAccess; j++) {
437 // Pre-fetch next read
438 //_mm_prefetch((char*)(memory + address[j+1]), _MM_HINT_T0);
439 //_mm_prefetch((char*)(memory + address[j+2]), _MM_HINT_NTA);
440 //_mm_prefetch((char*)(memory + address[j+3]), _MM_HINT_NTA);
441 //_mm_prefetch((char*)(memory + address[j+4]), _MM_HINT_NTA);
443 if (index1[j] < index2[j]) {
444 r = ForwardDNAOccCount(memory + address[j] + index1[j] / CHAR_PER_WORD, index2[j] - index1[j], character[j], dnaDecodeTable);
445 } else {
446 r = BackwardDNAOccCount(memory + address[j] + index1[j] / CHAR_PER_WORD, index1[j] - index2[j], character[j], dnaDecodeTable);
449 t += r;
455 elapsedTime = getElapsedTime(startTime) - totalElapsedTime;
456 totalElapsedTime += elapsedTime;
457 experimentTime = elapsedTime;
459 // So that compiler does not remove code for variables t and r
460 if ((Mode[0] == 'S' || Mode[0] == 's' || Mode[0] == 'L' || Mode[0] == 'l') && t == 0) {
461 printf("\n");
463 if ((Mode[0] == 'A' || Mode[0] == 'a') && t4[0] == 0 && t4[1] == 0 && t4[2] == 0 && t4[3] == 0) {
464 printf("\n");
467 printf("Experiment completed.\n");
469 printf("Initialization time = ");
470 printElapsedTime(stdout, FALSE, FALSE, TRUE, 2, initializationTime);
471 printf("Experiment time = ");
472 printElapsedTime(stdout, FALSE, FALSE, TRUE, 2, experimentTime);
474 MMUnitFree(address, (NumberOfAccess + 8) * sizeof(unsigned int));
475 MMUnitFree(memory, (numberOfMemoryLocation + 32) * sizeof(unsigned int));
476 MMUnitFree(index1, (NumberOfAccess + 8) * sizeof(unsigned int));
477 MMUnitFree(index2, (NumberOfAccess + 8) * sizeof(unsigned int));
478 MMUnitFree(character, (NumberOfAccess + 8) * sizeof(unsigned int));
479 MMUnitFree(dnaDecodeTable, 65536 * sizeof(unsigned int));
481 iniparser_freedict(programInput);
483 return 0;
487 dictionary *ParseInput(int argc, char** argv) {
489 dictionary *programInput;
491 programInput = paraparser_load(argc, argv, 0, NULL);
493 MemorySize = iniparser_getint(programInput, "argument:1", 0);
494 if (!MemorySize) {
495 fprintf(stderr, "Syntax: %s <Memory size> <Number of Access> <SSE/Lookup> <No. of iteration>\n", argv[0]);
496 exit(1);
498 NumberOfAccess = iniparser_getint(programInput, "argument:2", 0);
499 if (!NumberOfAccess) {
500 fprintf(stderr, "Syntax: %s <Memory size> <Number of Access> <SSE/Lookup> <No. of iteration>\n", argv[0]);
501 exit(1);
503 Mode = iniparser_getstring(programInput, "argument:3", 0);
504 if (!NumberOfAccess) {
505 fprintf(stderr, "Syntax: %s <Memory size> <Number of Access> <SSE/Lookup> <No. of iteration>\n", argv[0]);
506 exit(1);
508 NumberOfIteration = iniparser_getint(programInput, "argument:4", 0);
509 if (!NumberOfIteration) {
510 fprintf(stderr, "Syntax: %s <Memory size> <Number of Access> <SSE/Lookup> <No. of iteration>\n", argv[0]);
511 exit(1);
514 return programInput;
518 void ValidateParameters() {
520 if (MemorySize == 0) {
521 fprintf(stderr, "Memory Size = 0!\n");
522 exit(1);
524 if (MemorySize % 4 != 0) {
525 fprintf(stderr, "Memory Size must be multiple of 4!\n");
526 exit(1);
528 if (NumberOfAccess == 0) {
529 fprintf(stderr, "Number of Access = 0!\n");
530 exit(1);
532 if (Mode[0] != 'S' && Mode[0] != 's' && Mode[0] != 'L' && Mode[0] != 'l' && Mode[0] != 'A' && Mode[0] != 'a') {
533 fprintf(stderr, "Testing must be SSE, All alphabet SSE or Lookup!\n");
534 exit(1);
536 if (NumberOfIteration == 0) {
537 fprintf(stderr, "Number of Iteration = 0!\n");
538 exit(1);