source: icGREP/icgrep-devel/icgrep/kernels/grep_kernel.cpp @ 5914

Last change on this file since 5914 was 5914, checked in by cameron, 13 months ago

Optimization for regexps ending $

File size: 19.5 KB
Line 
1/*
2 *  Copyright (c) 2018 International Characters.
3 *  This software is licensed to the public under the Open Software License 3.0.
4 */
5
6#include "grep_kernel.h"
7#include <boost/uuid/sha1.hpp>
8#include <re/printer_re.h>
9#include <re/re_cc.h>
10#include <re/re_name.h>
11#include <re/re_toolchain.h>
12#include <re/re_reverse.h>
13#include <pablo/codegenstate.h>
14#include <pablo/pablo_toolchain.h>
15#include <kernels/kernel_builder.h>
16#include <pablo/builder.hpp>
17#include <pablo/pe_ones.h>          // for Ones
18#include <pablo/pe_var.h>           // for Var
19#include <pablo/pe_zeroes.h>        // for Zeroes
20#include <pablo/pe_infile.h>
21#include <pablo/boolean.h>
22#include <pablo/pe_count.h>
23#include <pablo/pe_matchstar.h>
24#include <pablo/pe_pack.h>
25#include <cc/cc_compiler.h>         // for CC_Compiler
26#include <cc/alphabet.h>
27#include <cc/multiplex_CCs.h>
28#include <re/re_compiler.h>
29#include <UCD/ucd_compiler.hpp>
30#include <llvm/Support/raw_ostream.h>
31
32using namespace kernel;
33using namespace pablo;
34using namespace re;
35using namespace llvm;
36
37inline static std::string sha1sum(const std::string & str) {
38    char buffer[41];    // 40 hex-digits and the terminating null
39    uint32_t digest[5]; // 160 bits in total
40    boost::uuids::detail::sha1 sha1;
41    sha1.process_bytes(str.c_str(), str.size());
42    sha1.get_digest(digest);
43    snprintf(buffer, sizeof(buffer), "%.8x%.8x%.8x%.8x%.8x",
44             digest[0], digest[1], digest[2], digest[3], digest[4]);
45    return std::string(buffer);
46}
47
48
49UnicodeLineBreakKernel::UnicodeLineBreakKernel(const std::unique_ptr<kernel::KernelBuilder> & kb)
50: PabloKernel(kb,
51              "UTF8_LB",
52              {Binding{kb->getStreamSetTy(8), "basis"}, Binding{kb->getStreamSetTy(1), "lf", FixedRate(), LookAhead(1)}},
53              {Binding{kb->getStreamSetTy(1, 1), "UTF8_LB", FixedRate()}}) {
54}
55
56void UnicodeLineBreakKernel::generatePabloMethod() {
57        PabloBuilder pb(getEntryScope());
58        cc::Parabix_CC_Compiler ccc(getEntryScope(), getInputStreamSet("basis"));
59        UCD::UCDCompiler ucdCompiler(ccc);
60   
61    Name * breakChars = re::makeName("breakChars", makeCC(makeCC(makeCC(0x0A, 0x0D), makeCC(0x85)), makeCC(0x2028,0x2029)));
62    UCD::UCDCompiler::NameMap nameMap;
63    nameMap.emplace(breakChars, nullptr);
64    ucdCompiler.generateWithDefaultIfHierarchy(nameMap, pb);
65    auto f = nameMap.find(breakChars);
66    if (f == nameMap.end()) llvm::report_fatal_error("UnicodeLineBreakKernel compilation failure");
67    PabloAST * breakStream = f-> second;
68    PabloAST * const LF = pb.createExtract(getInput(1), pb.getInteger(0), "LF");
69    PabloAST * const CR = ccc.compileCC(makeByte(0x0D));
70    Var * const CR_before_LF = pb.createVar("CR_before_LFCR_before_LF", pb.createZeroes());
71    auto crb = pb.createScope();
72    pb.createIf(CR, crb);
73    PabloAST * const lookaheadLF = crb.createLookahead(LF, 1, "lookaheadLF");
74    crb.createAssign(CR_before_LF, crb.createAnd(CR, lookaheadLF));
75    breakStream = pb.createXor(breakStream, CR_before_LF);  // Remove CR_before_LF from breakStream
76    Var * const UTF8_LB = getOutputStreamVar("UTF8_LB");
77    pb.createAssign(pb.createExtract(UTF8_LB, pb.getInteger(0)), breakStream);
78}
79
80void RequiredStreams_UTF8::generatePabloMethod() {
81    PabloBuilder pb(getEntryScope());
82    cc::Parabix_CC_Compiler ccc(getEntryScope(), getInputStreamSet("basis"));
83   
84    PabloAST * const LF = pb.createExtract(getInput(1), pb.getInteger(0), "LF");
85    PabloAST * const CR = ccc.compileCC(makeByte(0x0D));
86    PabloAST * const LF_VT_FF_CR = ccc.compileCC("LF,VT,FF,CR", makeByte(0x0A, 0x0D), pb);
87    Var * const LineBreak = pb.createVar("LineBreak", LF_VT_FF_CR);
88   
89    // Remove the CR of any CR+LF
90    Var * const CRLF = pb.createVar("CRLF", pb.createZeroes());
91    auto crb = pb.createScope();
92    pb.createIf(CR, crb);
93    PabloAST * const lookaheadLF = crb.createLookahead(LF, 1, "lookaheadLF");
94    PabloAST * const crlf = crb.createAnd(CR, lookaheadLF);
95    crb.createAssign(CRLF, crlf);
96    PabloAST * removedCRLF = crb.createAnd(LineBreak, crb.createNot(CRLF));
97    crb.createAssign(LineBreak, removedCRLF);
98
99   
100    Zeroes * const ZEROES = pb.createZeroes();
101    PabloAST * const u8pfx = ccc.compileCC(makeByte(0xC0, 0xFF));
102
103
104    Var * const nonFinal = pb.createVar("nonFinal", u8pfx);
105    Var * const u8invalid = pb.createVar("u8invalid", ZEROES);
106    Var * const valid_pfx = pb.createVar("valid_pfx", u8pfx);
107
108    auto it = pb.createScope();
109    pb.createIf(u8pfx, it);
110    PabloAST * const u8pfx2 = ccc.compileCC(makeByte(0xC2, 0xDF), it);
111    PabloAST * const u8pfx3 = ccc.compileCC(makeByte(0xE0, 0xEF), it);
112    PabloAST * const u8pfx4 = ccc.compileCC(makeByte(0xF0, 0xF4), it);
113    PabloAST * const u8suffix = ccc.compileCC("u8suffix", makeByte(0x80, 0xBF), it);
114   
115    //
116    // Two-byte sequences
117    Var * const anyscope = it.createVar("anyscope", ZEROES);
118    auto it2 = it.createScope();
119    it.createIf(u8pfx2, it2);
120    it2.createAssign(anyscope, it2.createAdvance(u8pfx2, 1));
121    PabloAST * NEL = it2.createAnd(it2.createAdvance(ccc.compileCC(makeByte(0xC2), it2), 1), ccc.compileCC(makeByte(0x85), it2), "NEL");
122    it2.createAssign(LineBreak, it2.createOr(LineBreak, NEL));
123
124
125    //
126    // Three-byte sequences   
127    Var * const EF_invalid = it.createVar("EF_invalid", ZEROES);
128    auto it3 = it.createScope();
129    it.createIf(u8pfx3, it3);
130    PabloAST * const u8scope32 = it3.createAdvance(u8pfx3, 1);
131    it3.createAssign(nonFinal, it3.createOr(nonFinal, u8scope32));
132    PabloAST * const u8scope33 = it3.createAdvance(u8pfx3, 2);
133    PabloAST * const u8scope3X = it3.createOr(u8scope32, u8scope33);
134    it3.createAssign(anyscope, it3.createOr(anyscope, u8scope3X));
135    PabloAST * const E0_invalid = it3.createAnd(it3.createAdvance(ccc.compileCC(makeByte(0xE0), it3), 1), ccc.compileCC(makeByte(0x80, 0x9F), it3));
136    PabloAST * const ED_invalid = it3.createAnd(it3.createAdvance(ccc.compileCC(makeByte(0xED), it3), 1), ccc.compileCC(makeByte(0xA0, 0xBF), it3));
137    PabloAST * const EX_invalid = it3.createOr(E0_invalid, ED_invalid);
138    it3.createAssign(EF_invalid, EX_invalid);
139    PabloAST * E2_80 = it3.createAnd(it3.createAdvance(ccc.compileCC(makeByte(0xE2), it3), 1), ccc.compileCC(makeByte(0x80), it3));
140    PabloAST * LS_PS = it3.createAnd(it3.createAdvance(E2_80, 1), ccc.compileCC(makeByte(0xA8,0xA9), it3), "LS_PS");
141    it3.createAssign(LineBreak, it3.createOr(LineBreak, LS_PS));
142
143    //
144    // Four-byte sequences
145    auto it4 = it.createScope();
146    it.createIf(u8pfx4, it4);
147    PabloAST * const u8scope42 = it4.createAdvance(u8pfx4, 1, "u8scope42");
148    PabloAST * const u8scope43 = it4.createAdvance(u8scope42, 1, "u8scope43");
149    PabloAST * const u8scope44 = it4.createAdvance(u8scope43, 1, "u8scope44");
150    PabloAST * const u8scope4nonfinal = it4.createOr(u8scope42, u8scope43);
151    it4.createAssign(nonFinal, it4.createOr(nonFinal, u8scope4nonfinal));
152    PabloAST * const u8scope4X = it4.createOr(u8scope4nonfinal, u8scope44);
153    it4.createAssign(anyscope, it4.createOr(anyscope, u8scope4X));
154    PabloAST * const F0_invalid = it4.createAnd(it4.createAdvance(ccc.compileCC(makeByte(0xF0), it4), 1), ccc.compileCC(makeByte(0x80, 0x8F), it4));
155    PabloAST * const F4_invalid = it4.createAnd(it4.createAdvance(ccc.compileCC(makeByte(0xF4), it4), 1), ccc.compileCC(makeByte(0x90, 0xBF), it4));
156    PabloAST * const FX_invalid = it4.createOr(F0_invalid, F4_invalid);
157    it4.createAssign(EF_invalid, it4.createOr(EF_invalid, FX_invalid));
158   
159    //
160    // Invalid cases
161    PabloAST * const legalpfx = it.createOr(it.createOr(u8pfx2, u8pfx3), u8pfx4);
162    //  Any scope that does not have a suffix byte, and any suffix byte that is not in
163    //  a scope is a mismatch, i.e., invalid UTF-8.
164    PabloAST * const mismatch = it.createXor(anyscope, u8suffix);
165    //
166    PabloAST * const pfx_invalid = it.createXor(valid_pfx, legalpfx);
167    it.createAssign(u8invalid, it.createOr(pfx_invalid, it.createOr(mismatch, EF_invalid)));
168    PabloAST * const u8valid = it.createNot(u8invalid, "u8valid");
169    //
170    //
171    it.createAssign(nonFinal, it.createAnd(nonFinal, u8valid));
172    pb.createAssign(nonFinal, pb.createOr(nonFinal, CRLF));
173    //PabloAST * unterminatedLineAtEOF = pb.createAtEOF(pb.createAdvance(pb.createNot(LineBreak), 1), "unterminatedLineAtEOF");
174   
175    Var * const required = getOutputStreamVar("nonFinal");
176    pb.createAssign(pb.createExtract(required, pb.getInteger(0)), nonFinal);
177    pb.createAssign(pb.createExtract(getOutputStreamVar("UnicodeLB"), pb.getInteger(0)), LineBreak);//pb.createOr(LineBreak, unterminatedLineAtEOF, "EOL"));
178}
179
180RequiredStreams_UTF8::RequiredStreams_UTF8(const std::unique_ptr<kernel::KernelBuilder> & kb)
181: PabloKernel(kb, "RequiredStreams_UTF8",
182// input
183{Binding{kb->getStreamSetTy(8), "basis"}, Binding{kb->getStreamSetTy(1), "lf", FixedRate(), LookAhead(1)}},
184// output
185{Binding{kb->getStreamSetTy(1), "nonFinal", FixedRate()},
186 Binding{kb->getStreamSetTy(1), "UnicodeLB", FixedRate()}}) {
187
188}
189
190void RequiredStreams_UTF16::generatePabloMethod() {
191    PabloBuilder pb(getEntryScope());
192    cc::Parabix_CC_Compiler ccc(getEntryScope(), getInputStreamSet("basis"));
193   
194    PabloAST * u16hi_hi_surrogate = ccc.compileCC(makeCC(0xD800, 0xDBFF, &cc::UTF16));    //u16hi_hi_surrogate = [\xD8-\xDB]
195    PabloAST * u16hi_lo_surrogate = ccc.compileCC(makeCC(0xDC00, 0xDFFF, &cc::UTF16));    //u16hi_lo_surrogate = [\xDC-\xDF]
196   
197    PabloAST * invalidTemp = pb.createAdvance(u16hi_hi_surrogate, 1, "InvalidTemp");
198    PabloAST * u16invalid = pb.createXor(invalidTemp, u16hi_lo_surrogate, "u16invalid");
199
200    PabloAST * u16valid = pb.createNot(u16invalid, "u16valid");
201    PabloAST * nonFinal = pb.createAnd(u16hi_hi_surrogate, u16valid, "nonfinal");
202
203    PabloAST * u16single_temp = pb.createOr(ccc.compileCC(makeCC(0x0000, 0xD7FF, &cc::UTF16)), ccc.compileCC(makeCC(0xE000, 0xFFFF, &cc::UTF16)));
204    PabloAST * u16single = pb.createAnd(u16single_temp, pb.createNot(u16invalid));
205
206    PabloAST * const nonFinalCodeUnits = pb.createExtract(getInput(1), pb.getInteger(0));
207    PabloAST * const initial = pb.createOr(u16single, u16hi_hi_surrogate, "initial");
208    PabloAST * const final = pb.createNot(pb.createOr(pb.createOr(u16hi_hi_surrogate, u16invalid), nonFinalCodeUnits), "final");
209
210    Var * const required = getOutputStreamVar("required");
211    pb.createAssign(pb.createExtract(required, pb.getInteger(0)), initial);
212    pb.createAssign(pb.createExtract(required, pb.getInteger(1)), nonFinal);
213    pb.createAssign(pb.createExtract(required, pb.getInteger(2)), final);
214
215}
216
217RequiredStreams_UTF16::RequiredStreams_UTF16(const std::unique_ptr<kernel::KernelBuilder> & kb)
218: PabloKernel(kb, "RequiredStreams_UTF16",               
219// inputs
220{Binding{kb->getStreamSetTy(8), "basis"}},
221// output
222{Binding{kb->getStreamSetTy(3), "required", FixedRate(), Add1()}}) {
223
224}
225
226ICGrepSignature::ICGrepSignature(re::RE * const re_ast)
227: mRE(re_ast)
228, mSignature(Printer_RE::PrintRE(mRE)) {
229   
230}
231
232// Helper to compute stream set inputs to pass into PabloKernel constructor.
233inline std::vector<Binding> icGrepInputs(const std::unique_ptr<kernel::KernelBuilder> & b,
234                                         const std::vector<std::string> & externals,
235                                         const std::vector<cc::Alphabet *> & alphabets) {
236    std::vector<Binding> streamSetInputs = {
237        Binding{b->getStreamSetTy(8), "basis"},
238    };
239    for (auto & e : externals) {
240        streamSetInputs.push_back(Binding{b->getStreamSetTy(1, 1), e});
241    }
242    for (const auto & alphabet : alphabets) {
243        unsigned basis_size = cast<cc::MultiplexedAlphabet>(alphabet)->getMultiplexedCCs().size();
244        streamSetInputs.push_back(Binding{b->getStreamSetTy(basis_size, 1), alphabet->getName() + "_basis"});
245    }
246    return streamSetInputs;
247}
248
249ICGrepKernel::ICGrepKernel(const std::unique_ptr<kernel::KernelBuilder> & b, RE * const re, std::vector<std::string> externals, std::vector<cc::Alphabet *> alphabets)
250: ICGrepSignature(re)
251, PabloKernel(b, "ic" + sha1sum(mSignature),
252// inputs
253icGrepInputs(b, externals, alphabets),
254// output
255{Binding{b->getStreamSetTy(1, 1), "matches", FixedRate(), Add1()}})
256, mExternals(externals)
257, mAlphabets(alphabets) {
258}
259
260std::string ICGrepKernel::makeSignature(const std::unique_ptr<kernel::KernelBuilder> &) {
261    return mSignature;
262}
263
264void ICGrepKernel::generatePabloMethod() {
265    PabloBuilder pb(getEntryScope());
266    cc::Parabix_CC_Compiler ccc(getEntryScope(), getInputStreamSet("basis"));
267    RE_Compiler re_compiler(getEntryScope(), ccc);
268    for (auto & e : mExternals) {
269        re_compiler.addPrecompiled(e, pb.createExtract(getInputStreamVar(e), pb.getInteger(0)));
270    }
271    for (auto a : mAlphabets) {
272        auto mpx_basis = getInputStreamSet(a->getName() + "_basis");
273        re_compiler.addAlphabet(a, mpx_basis);
274    }
275    PabloAST * const matches = re_compiler.compile(mRE);
276    Var * const output = getOutputStreamVar("matches");
277    pb.createAssign(pb.createExtract(output, pb.getInteger(0)), matches);
278}
279
280
281ByteGrepSignature::ByteGrepSignature(RE * re)
282: mRE(re)
283, mSignature(Printer_RE::PrintRE(re) ) {
284}
285
286ByteGrepKernel::ByteGrepKernel(const std::unique_ptr<kernel::KernelBuilder> & b, RE * const re, std::vector<std::string> externals)
287: ByteGrepSignature(re)
288, PabloKernel(b, "bBc" + sha1sum(mSignature),
289              // inputs
290{Binding{b->getStreamSetTy(1, 8), "byteData"}},
291              // output
292{Binding{b->getStreamSetTy(1, 1), "matches", FixedRate(), Add1()}})
293, mExternals(externals) {
294    for (auto & e : externals) {
295        mStreamSetInputs.push_back(Binding{b->getStreamSetTy(1, 1), e});
296    }
297}
298
299std::string ByteGrepKernel::makeSignature(const std::unique_ptr<kernel::KernelBuilder> &) {
300    return mSignature;
301}
302
303
304void ByteGrepKernel::generatePabloMethod() {
305    PabloBuilder pb(getEntryScope());
306    PabloAST * u8bytes = pb.createExtract(getInput(0), pb.getInteger(0));
307    cc::Direct_CC_Compiler dcc(getEntryScope(), u8bytes);
308    RE_Compiler re_byte_compiler(getEntryScope(), dcc);
309    for (auto & e : mExternals) {
310        re_byte_compiler.addPrecompiled(e, pb.createExtract(getInputStreamVar(e), pb.getInteger(0)));
311    }
312    PabloAST * const matches = re_byte_compiler.compile(mRE);
313   
314    Var * const output = getOutputStreamVar("matches");
315    pb.createAssign(pb.createExtract(output, pb.getInteger(0)), matches);
316}
317
318// Helper to compute stream set inputs to pass into PabloKernel constructor.
319inline std::vector<Binding> byteBitGrepInputs(const std::unique_ptr<kernel::KernelBuilder> & b,
320                                              const std::vector<std::string> & externals) {
321    std::vector<Binding> streamSetInputs = {
322        Binding{b->getStreamSetTy(1, 8), "bytedata"},
323    };
324    for (auto & e : externals) {
325        streamSetInputs.push_back(Binding{b->getStreamSetTy(1, 1), e});
326    }
327    return streamSetInputs;
328}
329
330ByteBitGrepSignature::ByteBitGrepSignature(RE * prefix, RE * suffix)
331: mPrefixRE(prefix)
332, mSuffixRE(suffix)
333, mSignature(Printer_RE::PrintRE(mPrefixRE) + Printer_RE::PrintRE(mSuffixRE) ) {
334}
335
336ByteBitGrepKernel::ByteBitGrepKernel(const std::unique_ptr<kernel::KernelBuilder> & b, RE * const prefixRE, RE * const suffixRE, std::vector<std::string> externals)
337: ByteBitGrepSignature(prefixRE, suffixRE)
338, PabloKernel(b, "bBc" + sha1sum(mSignature),
339              // inputs
340              byteBitGrepInputs(b, externals),
341              // output
342{Binding{b->getStreamSetTy(1, 1), "matches", FixedRate(), Add1()}})
343, mExternals(externals) {
344}
345
346std::string ByteBitGrepKernel::makeSignature(const std::unique_ptr<kernel::KernelBuilder> &) {
347    return mSignature;
348}
349
350
351void ByteBitGrepKernel::generatePabloMethod() {
352    PabloBuilder pb(getEntryScope());
353    PabloAST * u8bytes = pb.createExtract(getInput(0), pb.getInteger(0));
354    cc::Direct_CC_Compiler dcc(getEntryScope(), u8bytes);
355    RE_Compiler re_byte_compiler(getEntryScope(), dcc);
356    for (auto & e : mExternals) {
357        re_byte_compiler.addPrecompiled(e, pb.createExtract(getInputStreamVar(e), pb.getInteger(0)));
358    }
359    PabloAST * const prefixMatches = re_byte_compiler.compile(mPrefixRE);
360    Var * const final_matches = pb.createVar("final_matches", pb.createZeroes());
361    PabloBlock * scope1 = getEntryScope()->createScope();
362    pb.createIf(prefixMatches, scope1);
363   
364    PabloAST * nybbles[2];
365    nybbles[0] = scope1->createPackL(scope1->getInteger(8), u8bytes);
366    nybbles[1] = scope1->createPackH(scope1->getInteger(8), u8bytes);
367   
368    PabloAST * bitpairs[4];
369    for (unsigned i = 0; i < 2; i++) {
370        bitpairs[2*i] = scope1->createPackL(scope1->getInteger(4), nybbles[i]);
371        bitpairs[2*i + 1] = scope1->createPackH(scope1->getInteger(4), nybbles[i]);
372    }
373   
374    std::vector<PabloAST *> basis(8);
375    for (unsigned i = 0; i < 4; i++) {
376        // The subtraction 7-bit is because of the confusion between
377        // little-endian and big-endian bit numbering of bytes.
378        // We should fix this, switching to little-endian numbering throughout.
379        basis[7-2*i] = scope1->createPackL(scope1->getInteger(2), bitpairs[i]);
380        basis[7-(2*i + 1)] = scope1->createPackH(scope1->getInteger(2), bitpairs[i]);
381    }
382   
383    cc::Parabix_CC_Compiler ccc(scope1, basis);
384    RE_Compiler re_compiler(scope1, ccc);
385    scope1->createAssign(final_matches, re_compiler.compile(mSuffixRE, prefixMatches));
386    Var * const output = getOutputStreamVar("matches");
387    pb.createAssign(pb.createExtract(output, pb.getInteger(0)), final_matches);
388}
389
390
391void MatchedLinesKernel::generatePabloMethod() {
392    PabloBuilder pb(getEntryScope());
393    PabloAST * matchResults = pb.createExtract(getInputStreamVar("matchResults"), pb.getInteger(0));
394    PabloAST * lineBreaks = pb.createExtract(getInputStreamVar("lineBreaks"), pb.getInteger(0));
395    PabloAST * notLB = pb.createNot(lineBreaks);
396    PabloAST * match_follow = pb.createMatchStar(matchResults, notLB);
397    PabloAST * unterminatedLineAtEOF = pb.createAtEOF(pb.createAdvance(notLB, 1), "unterminatedLineAtEOF");
398    Var * const matchedLines = getOutputStreamVar("matchedLines");
399    pb.createAssign(pb.createExtract(matchedLines, pb.getInteger(0)), pb.createAnd(match_follow, pb.createOr(lineBreaks, unterminatedLineAtEOF)));
400}
401
402MatchedLinesKernel::MatchedLinesKernel (const std::unique_ptr<kernel::KernelBuilder> & iBuilder)
403: PabloKernel(iBuilder, "MatchedLines",
404// inputs
405{Binding{iBuilder->getStreamSetTy(1), "matchResults"}
406,Binding{iBuilder->getStreamSetTy(1), "lineBreaks"}},
407// output
408{Binding{iBuilder->getStreamSetTy(1), "matchedLines", FixedRate(), Add1()}}) {
409
410}
411
412
413void InvertMatchesKernel::generateDoBlockMethod(const std::unique_ptr<KernelBuilder> & iBuilder) {
414    Value * input = iBuilder->loadInputStreamBlock("matchedLines", iBuilder->getInt32(0));
415    Value * lbs = iBuilder->loadInputStreamBlock("lineBreaks", iBuilder->getInt32(0));
416    Value * inverted = iBuilder->CreateXor(input, lbs);
417    iBuilder->storeOutputStreamBlock("nonMatches", iBuilder->getInt32(0), inverted);
418}
419
420InvertMatchesKernel::InvertMatchesKernel(const std::unique_ptr<kernel::KernelBuilder> & builder)
421: BlockOrientedKernel("Invert",
422// Inputs
423{Binding{builder->getStreamSetTy(1, 1), "matchedLines"}, Binding{builder->getStreamSetTy(1, 1), "lineBreaks"}},
424// Outputs
425{Binding{builder->getStreamSetTy(1, 1), "nonMatches"}},
426// Input/Output Scalars and internal state
427{}, {}, {}) {
428
429}
430
431
432void PopcountKernel::generatePabloMethod() {
433    auto pb = this->getEntryScope();
434    const auto toCount = pb->createExtract(getInputStreamVar("toCount"), pb->getInteger(0));
435    pablo::Var * countResult = getOutputScalarVar("countResult");
436   
437    pb->createAssign(countResult, pb->createCount(pb->createInFile(toCount)));
438}
439
440PopcountKernel::PopcountKernel (const std::unique_ptr<kernel::KernelBuilder> & iBuilder)
441: PabloKernel(iBuilder, "Popcount",
442{Binding{iBuilder->getStreamSetTy(1), "toCount"}},
443{},
444{},
445{Binding{iBuilder->getSizeTy(), "countResult"}}) {
446
447}
Note: See TracBrowser for help on using the repository browser.