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

Last change on this file since 3911 was 3850, checked in by cameron, 5 years ago

icgrep-0.8 distribution

File size: 11.8 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    double timer;
78
79    char * inregex, * fileregex, * infilename, * outfilename;
80    FILE *infile, *outfile, *regexfile;
81
82    int opt_code;
83    int count_only_option = 0;
84    int print_version_option = 0;
85    int regex_from_file_option = 0;
86
87    int compile_time_option = 0;
88
89    size_t result;
90
91    long lSize;
92
93    while ((opt_code = getopt(argc, argv, "cvft")) != -1)
94    {
95        switch (opt_code)
96        {
97        case 'c':
98            count_only_option = 1;
99            break;
100        case 'v':
101            print_version_option = 1;
102            break;
103        case 'f':
104            regex_from_file_option = 1;
105            break;
106        case 't':
107            compile_time_option = 1;
108            break;
109        case '?':
110            break;
111        default:
112            printf ("Invalid option: %c\n", opt_code);
113            printf("Usage: %s [-c] [-v] [-f] <regex|regexfile> <inputfile> [<outputfile>]\n", argv[0]);
114                    exit(-1);
115        }
116    }
117
118    if (optind >= argc)
119    {
120        printf ("Too few arguments\n");
121        printf("Usage: %s [-c] [-v] [-f] <regex|regexfile> <inputfile> [<outputfile>]\n", argv[0]);
122        exit(-1);
123    }
124
125    inregex = argv[optind++];
126    if (inregex == 0)
127    {
128        fprintf(stderr, "Error: cannot read the regular expression.\n");
129        exit(-1);
130    }
131
132    if (regex_from_file_option)
133    {
134        regexfile = fopen(inregex, "rb");
135        if (!regexfile){
136            fprintf(stderr, "Error: cannot open %s for processing.\n", inregex);
137            exit(-1);
138        }
139
140        fseek (regexfile , 0 , SEEK_END);
141        lSize = ftell (regexfile);
142        rewind (regexfile);
143
144        fileregex = (char*) malloc (sizeof(char)*lSize);
145        if (fileregex == NULL) {fputs ("Memory error",stderr); exit (2);}
146
147        result = fread (fileregex, 1, lSize, regexfile);
148        if (result != lSize) {fputs ("Reading error",stderr); exit (3);}
149        fclose(regexfile);
150
151        if (fileregex[lSize - 1] == '\n') fileregex[lSize - 1] = '\0';
152    }
153
154    infilename = argv[optind++];
155    infile = fopen(infilename, "rb");
156    if (!infile) {
157        fprintf(stderr, "Error: cannot open %s for processing.\n", infilename);
158        exit(-1);
159    }
160
161    if (optind >= argc) outfile = stdout;
162    else
163    {
164        outfilename = argv[optind++];
165        if (optind != argc)
166        {
167            printf ("Too many arguments\n");
168            printf("Usage: %s [-c] [-v] [-f] <regex|regexfile> <inputfile> [<outputfile>]\n", argv[0]);
169            exit(-1);
170        }
171        outfile = fopen(outfilename, "wb");
172        if (!outfile)
173        {
174            fprintf(stderr, "Error: cannot open %s for writing.\n", outfilename);
175            exit(-1);
176        }
177    }
178
179    if (print_version_option)
180    {
181        fprintf(outfile, "Parabix icgrep implementation: April 2014\n");
182    }
183
184    UTF_Encoding encoding;
185    encoding.setName("UTF-8");
186    encoding.setBits(8);
187    encoding.setMask(0xFF);
188
189    RE_Compiler* re_compiler = new RE_Compiler();
190    if (compile_time_option) timer = getElapsedTime();
191    LLVM_Gen_RetVal llvm_codegen = re_compiler->compile(compile_time_option, "basis_bits.bit_", "temp", encoding ,(regex_from_file_option ? fileregex : inregex));
192
193    if (compile_time_option)
194    {
195        timer = getElapsedTime() - timer;
196        std::cout << "Total Compile Time: " << timer <<  " seconds" << std::endl;
197    }
198
199    if (llvm_codegen.process_block_fptr != 0)
200    {
201        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;
202        do_process(infile, outfile, count_only_option, llvm_codegen.carry_q_size, FP);
203    }
204
205    delete re_compiler;
206    fclose(infile);
207    fclose(outfile);
208    if (regex_from_file_option) free(fileregex);
209
210    return 0;
211}
212
213void do_process(FILE *infile, FILE *outfile, int count_only_option, int carry_count, process_block_fcn process_block) {
214
215    struct Basis_bits basis_bits;
216    struct Output output;
217
218    BitBlock carry_q[carry_count];
219    memset (carry_q, 0, sizeof(BitBlock) * carry_count);
220
221    BitBlock match_vector = simd<1>::constant<0>();
222    int match_count=0;
223    int blk = 0;
224    int block_base  = 0;
225    int block_pos   = 0;
226    int buffer_pos  = 0;
227    int chars_avail = 0;
228    int chars_read  = 0;
229
230    int line_start = 0;
231    int line_end = 0;
232    int match_pos = 0;
233    int line_no = 0;
234
235    int counter = 0;
236
237    BitStreamScanner<BitBlock, uint64_t, uint64_t, SEGMENT_BLOCKS> LF_scanner;
238    BitStreamScanner<BitBlock, uint64_t, uint64_t, SEGMENT_BLOCKS> match_scanner;
239    ATTRIBUTE_SIMD_ALIGN char src_buffer[SEGMENT_SIZE];
240
241    chars_read = fread((void *)&src_buffer[0], 1, SEGMENT_SIZE, infile);
242    chars_avail = chars_read;
243    if (chars_avail >= SEGMENT_SIZE) chars_avail = SEGMENT_SIZE;
244
245//////////////////////////////////////////////////////////////////////////////////////////
246// Full Segments
247//////////////////////////////////////////////////////////////////////////////////////////
248
249    while (chars_avail >= SEGMENT_SIZE) {
250
251        LF_scanner.init();
252        match_scanner.init();
253
254        counter++;
255
256        for (blk = 0; blk < SEGMENT_BLOCKS; blk++) {
257            block_base = blk*BLOCK_SIZE;
258            s2p_do_block((BytePack *) &src_buffer[block_base], basis_bits);
259            process_block(basis_bits, carry_q, output);
260
261            LF_scanner.load_block(output.LF, blk);
262            match_scanner.load_block(output.matches, blk);
263            if (count_only_option){
264                if (bitblock::any(output.matches))
265                {
266                    if (bitblock::any(simd_and(match_vector, output.matches))){
267                        match_count += bitblock::popcount(match_vector);
268                        match_vector = output.matches;
269                    }
270                    else
271                    {
272                        match_vector = simd_or(match_vector, output.matches);
273                    }
274                }
275            }
276        }
277
278        int copy_back_pos = 0;
279
280        if (LF_scanner.count() > 0) {
281            copy_back_pos = LF_scanner.get_final_pos() + 1;
282            memset (carry_q, 0, sizeof(BitBlock) * carry_count);
283        }
284        else {
285            copy_back_pos =  SEGMENT_SIZE;
286        }
287
288        int  copy_back_size = SEGMENT_SIZE - copy_back_pos;
289
290        if (!count_only_option) {
291            line_start = 0;
292
293            while (match_scanner.has_next()) {
294                match_pos = match_scanner.scan_to_next();
295                line_end = LF_scanner.scan_to_next();
296                while (line_end < match_pos) {
297                    line_start = line_end+1;
298                    line_no++;
299                    line_end = LF_scanner.scan_to_next();
300                }
301                fwrite(&src_buffer[line_start], 1, line_end - line_start + 1, outfile);
302                line_start = line_end+1;
303                line_no++;
304            }
305            while (LF_scanner.has_next()) {
306                line_end = LF_scanner.scan_to_next();
307                line_no++;
308            }
309
310        }
311
312        memmove(&src_buffer[0], &src_buffer[copy_back_pos], copy_back_size);
313
314        //Do another read.
315        chars_read = fread(&src_buffer[copy_back_size], 1, copy_back_pos, infile);
316        chars_avail = chars_read + copy_back_size;
317        if (chars_avail >= SEGMENT_SIZE) chars_avail = SEGMENT_SIZE;
318        buffer_pos += chars_avail;
319    }
320
321
322//////////////////////////////////////////////////////////////////////////////////////////
323// For the Final Partial Segment.
324//////////////////////////////////////////////////////////////////////////////////////////
325
326    block_pos = 0;
327    int remaining = chars_avail;
328
329    LF_scanner.init();
330    match_scanner.init();
331
332    /* Full Blocks */
333    blk = 0;
334    while (remaining >= BLOCK_SIZE) {
335        block_base = block_pos;
336        s2p_do_block((BytePack *) &src_buffer[block_pos], basis_bits);
337        process_block(basis_bits, carry_q, output);
338
339        LF_scanner.load_block(output.LF, blk);
340        match_scanner.load_block(output.matches, blk);
341        if (count_only_option)
342        {
343            if (bitblock::any(output.matches))
344            {
345                if (bitblock::any(simd_and(match_vector, output.matches)))
346                {
347                    match_count += bitblock::popcount(match_vector);
348                    match_vector = output.matches;
349                }
350                else
351                {
352                    match_vector = simd_or(match_vector, output.matches);
353                }
354            }
355        }
356
357        block_pos += BLOCK_SIZE;
358        remaining -= BLOCK_SIZE;
359        blk++;
360    }
361    block_base = block_pos;
362
363    //For the last partial block, or for any carry.
364    EOF_mask = bitblock::srl(simd<1>::constant<1>(), convert(BLOCK_SIZE-remaining));
365    s2p_do_final_block((BytePack *) &src_buffer[block_pos], basis_bits, EOF_mask);
366    process_block(basis_bits, carry_q, output);
367
368    if (count_only_option)
369    {
370        match_count += bitblock::popcount(match_vector);
371        if (bitblock::any(output.matches))
372        {
373            match_count += bitblock::popcount(output.matches);
374        }
375        fprintf(outfile, "Matching Lines:%d\n", match_count);
376    }
377    else
378    {
379        LF_scanner.load_block(output.LF, blk);
380        match_scanner.load_block(output.matches, blk);
381        blk++;
382        for (int i = blk; i < SEGMENT_BLOCKS; i++)
383        {
384            LF_scanner.load_block(simd<1>::constant<0>(), i);
385            match_scanner.load_block(simd<1>::constant<0>(), i);
386        }
387        line_start = 0;
388        while (match_scanner.has_next())
389        {
390            match_pos = match_scanner.scan_to_next();
391            line_end = LF_scanner.scan_to_next();
392            while(line_end < match_pos)
393            {
394                line_start = line_end + 1;
395                line_no++;
396                line_end = LF_scanner.scan_to_next();
397            }
398            fwrite(&src_buffer[line_start], 1, line_end - line_start + 1, outfile);
399            line_start = line_end + 1;
400            line_no++;
401        }
402        while(LF_scanner.has_next())
403        {
404            line_end = LF_scanner.scan_to_next();
405            line_no++;
406        }
407    }
408
409    buffer_pos += chars_avail;
410}
411
412
413
414
Note: See TracBrowser for help on using the repository browser.