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

Last change on this file since 3991 was 3991, checked in by daled, 5 years ago

Minor changes.

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