source: icGREP/icgrep-devel/icgrep/icgrep.cpp @ 3935

Last change on this file since 3935 was 3914, checked in by cameron, 5 years ago

Updates for icgrep-0.9: re simplifications, re names, replimit mods, debugged while loops

File size: 12.4 KB
Line 
1/*
2 *  Copyright (c) 2014 International Characters.
3 *  This software is licensed to the public under the Open Software License 3.0.
4 *  icgrep is a trademark of International Characters.
5 */
6
7#include "utf_encoding.h"
8#include "re_compiler.h"
9
10#include <fstream>
11#include <sstream>
12#include <iostream>
13#include <string>
14#include <stdint.h>
15
16#define assert_0_error(errkind, errstrm)
17
18// XMLWF application headers and definitions
19#include <stdio.h>
20#include <stdlib.h>
21#include <unistd.h>
22#include <errno.h>
23#include <sys/types.h>
24#include <sys/stat.h>
25
26#include <simd-lib/bitblock.hpp>
27#include <simd-lib/carryQ.hpp>
28#include <simd-lib/pabloSupport.hpp>
29#include <simd-lib/s2p.hpp>
30#include <simd-lib/buffer.hpp>
31#include <simd-lib/bitblock_iterator.hpp>
32//#include <simd-lib/perflib/perfsec.h>
33
34#define SEGMENT_BLOCKS 15
35#define SEGMENT_SIZE (BLOCK_SIZE * SEGMENT_BLOCKS)
36
37#define BUFFER_SEGMENTS 15
38#define BUFFER_SIZE (BUFFER_SEGMENTS * SEGMENT_SIZE)
39
40#define BitBlock_declare(name)  BitBlock name
41
42#define ubitblock_declare(name, n) \
43  ubitblock name[n];\
44  do {int i;\
45      for (i = 0; i < n; i++) name[i]._128 = simd<1>::constant<0>();\
46     }\
47  while (0)
48
49BitBlock EOF_mask = simd<1>::constant<1>();
50
51struct Output {
52    BitBlock matches;
53    BitBlock LF;
54};
55
56struct Basis_bits {
57    BitBlock bit_0;
58    BitBlock bit_1;
59    BitBlock bit_2;
60    BitBlock bit_3;
61    BitBlock bit_4;
62    BitBlock bit_5;
63    BitBlock bit_6;
64    BitBlock bit_7;
65};
66
67#include <simd-lib/transpose.hpp>
68
69using namespace std;
70
71typedef void (*process_block_fcn)(const Basis_bits &basis_bits, BitBlock carry_q[], Output &output);
72
73void do_process(FILE *infile, FILE *outfile, int count_only_option, int carry_count, process_block_fcn process_block);
74
75int main(int argc, char *argv[])
76{
77    char * inregex, * fileregex, * infilename, * outfilename;
78    FILE *infile, *outfile, *regexfile;
79
80    int opt_code;
81    int count_only_option = 0;
82    int print_version_option = 0;
83    int regex_from_file_option = 0;
84    int ascii_only_option = 0;
85
86    int compile_time_option = 0;
87
88    unsigned long long cycles = 0;
89    double timer = 0;
90
91    long lSize = 0;
92
93    size_t result;
94
95    while ((opt_code = getopt(argc, argv, "cvfta")) != -1)
96    {
97        switch (opt_code)
98        {
99        case 'c':
100            count_only_option = 1;
101            break;
102        case 'v':
103            print_version_option = 1;
104            break;
105        case 'f':
106            regex_from_file_option = 1;
107            break;
108        case 't':
109            compile_time_option = 1;
110            break;
111        case 'a':
112            ascii_only_option = 1;
113            break;
114        case '?':
115            break;
116        default:
117            printf ("Invalid option: %c\n", opt_code);
118            printf("Usage: %s [-c] [-v] [-f] [-t] [-a] <regex|regexfile> <inputfile> [<outputfile>]\n", argv[0]);
119                    exit(-1);
120        }
121    }
122
123    if (optind >= argc)
124    {
125        printf ("Too few arguments\n");
126        printf("Usage: %s [-c] [-v] [-f] [-t] [-a] <regex|regexfile> <inputfile> [<outputfile>]\n", argv[0]);
127        exit(-1);
128    }
129
130    inregex = argv[optind++];
131    if (inregex == 0)
132    {
133        fprintf(stderr, "Error: cannot read the regular expression.\n");
134        exit(-1);
135    }
136
137    if (regex_from_file_option)
138    {
139        regexfile = fopen(inregex, "rb");
140        if (!regexfile){
141            fprintf(stderr, "Error: cannot open %s for processing.\n", inregex);
142            exit(-1);
143        }
144
145        fseek (regexfile , 0 , SEEK_END);
146        lSize = ftell (regexfile);
147        rewind (regexfile);
148
149        fileregex = (char*) malloc (sizeof(char)*lSize);
150        if (fileregex == NULL) {fputs ("Memory error",stderr); exit (2);}
151
152        result = fread (fileregex, 1, lSize, regexfile);
153        if (result != lSize) {fputs ("Reading error",stderr); exit (3);}
154        fclose(regexfile);
155
156        if (fileregex[lSize - 1] == '\n') fileregex[lSize - 1] = '\0';
157    }
158
159    infilename = argv[optind++];
160    infile = fopen(infilename, "rb");
161    if (!infile) {
162        fprintf(stderr, "Error: cannot open %s for processing.\n", infilename);
163        exit(-1);
164    }
165
166    if (optind >= argc) outfile = stdout;
167    else
168    {
169        outfilename = argv[optind++];
170        if (optind != argc)
171        {
172            printf ("Too many arguments\n");
173            printf("Usage: %s [-c] [-v] [-f] [-t] [-a] <regex|regexfile> <inputfile> [<outputfile>]\n", argv[0]);
174            exit(-1);
175        }
176        outfile = fopen(outfilename, "wb");
177        if (!outfile)
178        {
179            fprintf(stderr, "Error: cannot open %s for writing.\n", outfilename);
180            exit(-1);
181        }
182    }
183
184    if (print_version_option)
185    {
186        fprintf(outfile, "Parabix icgrep implementation: April 2014\n");
187    }
188
189    UTF_Encoding encoding;
190    encoding.setName("UTF-8");
191    encoding.setBits(8);
192    encoding.setMask(0xFF);
193
194    RE_Compiler* re_compiler = new RE_Compiler();
195    if (compile_time_option)
196    {
197        cycles = get_hrcycles();
198        timer = getElapsedTime();
199    }
200    LLVM_Gen_RetVal llvm_codegen = re_compiler->compile(compile_time_option,
201                                                        ascii_only_option,
202                                                        "basis_bits.bit_",
203                                                        "temp",
204                                                        encoding ,
205                                                        (regex_from_file_option ? fileregex : inregex));
206
207    if (compile_time_option)
208    {
209        cycles = get_hrcycles() - cycles;
210        timer = getElapsedTime() - timer;
211        std::cout << "Total compile time - cycles:       " << cycles << std::endl;
212        std::cout << "Total compile time - milliseconds: " << timer << std::endl;
213    }
214
215    if (llvm_codegen.process_block_fptr != 0)
216    {
217        void (*FP)(const Basis_bits &basis_bits, BitBlock carry_q[], Output &output) = (void (*)(const Basis_bits &basis_bits, BitBlock carry_q[], Output &output))(void*)llvm_codegen.process_block_fptr;
218        do_process(infile, outfile, count_only_option, llvm_codegen.carry_q_size, FP);
219    }
220
221    delete re_compiler;
222    fclose(infile);
223    fclose(outfile);
224    if (regex_from_file_option) free(fileregex);
225
226    return 0;
227}
228
229void do_process(FILE *infile, FILE *outfile, int count_only_option, int carry_count, process_block_fcn process_block) {
230
231    struct Basis_bits basis_bits;
232    struct Output output;
233
234    BitBlock carry_q[carry_count];
235    memset (carry_q, 0, sizeof(BitBlock) * carry_count);
236
237    BitBlock match_vector = simd<1>::constant<0>();
238    int match_count=0;
239    int blk = 0;
240    int block_base  = 0;
241    int block_pos   = 0;
242    int buffer_pos  = 0;
243    int chars_avail = 0;
244    int chars_read  = 0;
245
246    int line_start = 0;
247    int line_end = 0;
248    int match_pos = 0;
249    int line_no = 0;
250
251    int counter = 0;
252
253    BitStreamScanner<BitBlock, uint64_t, uint64_t, SEGMENT_BLOCKS> LF_scanner;
254    BitStreamScanner<BitBlock, uint64_t, uint64_t, SEGMENT_BLOCKS> match_scanner;
255    ATTRIBUTE_SIMD_ALIGN char src_buffer[SEGMENT_SIZE];
256
257    chars_read = fread((void *)&src_buffer[0], 1, SEGMENT_SIZE, infile);
258    chars_avail = chars_read;
259    if (chars_avail >= SEGMENT_SIZE) chars_avail = SEGMENT_SIZE;
260
261//////////////////////////////////////////////////////////////////////////////////////////
262// Full Segments
263//////////////////////////////////////////////////////////////////////////////////////////
264
265    while (chars_avail >= SEGMENT_SIZE) {
266
267        LF_scanner.init();
268        match_scanner.init();
269
270        counter++;
271
272        for (blk = 0; blk < SEGMENT_BLOCKS; blk++) {
273            block_base = blk*BLOCK_SIZE;
274            s2p_do_block((BytePack *) &src_buffer[block_base], basis_bits);
275            process_block(basis_bits, carry_q, output);
276
277            LF_scanner.load_block(output.LF, blk);
278            match_scanner.load_block(output.matches, blk);
279            if (count_only_option){
280                if (bitblock::any(output.matches))
281                {
282                    if (bitblock::any(simd_and(match_vector, output.matches))){
283                        match_count += bitblock::popcount(match_vector);
284                        match_vector = output.matches;
285                    }
286                    else
287                    {
288                        match_vector = simd_or(match_vector, output.matches);
289                    }
290                }
291            }
292        }
293
294        int copy_back_pos = 0;
295
296
297        if (LF_scanner.count() > 0) {
298            copy_back_pos = LF_scanner.get_final_pos() + 1;
299            memset (carry_q, 0, sizeof(BitBlock) * carry_count);
300        }
301        else {
302            copy_back_pos =  SEGMENT_SIZE;
303        }
304
305        int  copy_back_size = SEGMENT_SIZE - copy_back_pos;
306
307        if (!count_only_option) {
308            line_start = 0;
309
310            while (match_scanner.has_next()) {
311                match_pos = match_scanner.scan_to_next();
312                line_end = LF_scanner.scan_to_next();
313                while (line_end < match_pos) {
314                    line_start = line_end+1;
315                    line_no++;
316                    line_end = LF_scanner.scan_to_next();
317                }
318                fwrite(&src_buffer[line_start], 1, line_end - line_start + 1, outfile);
319                line_start = line_end+1;
320                line_no++;
321            }
322            while (LF_scanner.has_next()) {
323                line_end = LF_scanner.scan_to_next();
324                line_no++;
325            }
326
327        }
328
329        memmove(&src_buffer[0], &src_buffer[copy_back_pos], copy_back_size);
330
331        //Do another read.
332        chars_read = fread(&src_buffer[copy_back_size], 1, copy_back_pos, infile);
333        chars_avail = chars_read + copy_back_size;
334        if (chars_avail >= SEGMENT_SIZE) chars_avail = SEGMENT_SIZE;
335        buffer_pos += chars_avail;
336    }
337
338
339//////////////////////////////////////////////////////////////////////////////////////////
340// For the Final Partial Segment.
341//////////////////////////////////////////////////////////////////////////////////////////
342
343    block_pos = 0;
344    int remaining = chars_avail;
345
346    LF_scanner.init();
347    match_scanner.init();
348
349    /* Full Blocks */
350    blk = 0;
351    while (remaining >= BLOCK_SIZE) {
352        block_base = block_pos;
353        s2p_do_block((BytePack *) &src_buffer[block_pos], basis_bits);
354        process_block(basis_bits, carry_q, output);
355
356        LF_scanner.load_block(output.LF, blk);
357        match_scanner.load_block(output.matches, blk);
358        if (count_only_option)
359        {
360            if (bitblock::any(output.matches))
361            {
362                if (bitblock::any(simd_and(match_vector, output.matches)))
363                {
364                    match_count += bitblock::popcount(match_vector);
365                    match_vector = output.matches;
366                }
367                else
368                {
369                    match_vector = simd_or(match_vector, output.matches);
370                }
371            }
372        }
373
374        block_pos += BLOCK_SIZE;
375        remaining -= BLOCK_SIZE;
376        blk++;
377    }
378    block_base = block_pos;
379
380    //For the last partial block, or for any carry.
381    EOF_mask = bitblock::srl(simd<1>::constant<1>(), convert(BLOCK_SIZE-remaining));
382    s2p_do_final_block((BytePack *) &src_buffer[block_pos], basis_bits, EOF_mask);
383    process_block(basis_bits, carry_q, output);
384
385    if (count_only_option)
386    {
387        match_count += bitblock::popcount(match_vector);
388        if (bitblock::any(output.matches))
389        {
390            match_count += bitblock::popcount(output.matches);
391        }
392        fprintf(outfile, "Matching Lines:%d\n", match_count);
393    }
394    else
395    {
396        LF_scanner.load_block(output.LF, blk);
397        match_scanner.load_block(output.matches, blk);
398        blk++;
399        for (int i = blk; i < SEGMENT_BLOCKS; i++)
400        {
401            LF_scanner.load_block(simd<1>::constant<0>(), i);
402            match_scanner.load_block(simd<1>::constant<0>(), i);
403        }
404        line_start = 0;
405        while (match_scanner.has_next())
406        {
407            match_pos = match_scanner.scan_to_next();
408            line_end = LF_scanner.scan_to_next();
409            while(line_end < match_pos)
410            {
411                line_start = line_end + 1;
412                line_no++;
413                line_end = LF_scanner.scan_to_next();
414            }
415            fwrite(&src_buffer[line_start], 1, line_end - line_start + 1, outfile);
416            line_start = line_end + 1;
417            line_no++;
418        }
419        while(LF_scanner.has_next())
420        {
421            line_end = LF_scanner.scan_to_next();
422            line_no++;
423        }
424    }
425
426    buffer_pos += chars_avail;
427}
428
429
430
431
Note: See TracBrowser for help on using the repository browser.