source: icGREP/icgrep-devel/icgrep/array-test.cpp @ 5320

Last change on this file since 5320 was 5320, checked in by nmedfort, 2 years ago

memcpy/memset support for 32-bit systems; more error messages/handling; bug fix for ParabixCharacterClassKernelBuilder?. continued work on parenthesis matching + expandable buffers.

File size: 8.8 KB
Line 
1/*
2 *  Copyright (c) 2015 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 <IR_Gen/idisa_builder.h>                  // for IDISA_Builder
8#include <IR_Gen/idisa_target.h>                   // for GetIDISA_Builder
9#include <kernels/mmap_kernel.h>                   // for MMapSourceKernel
10#include <kernels/s2p_kernel.h>                    // for S2PKernel
11#include <kernels/streamset.h>                     // for SingleBlockBuffer
12#include <kernels/pipeline.h>
13#include <llvm/ExecutionEngine/ExecutionEngine.h>  // for ExecutionEngine
14#include <llvm/IR/Function.h>                      // for Function, Function...
15#include <llvm/IR/Module.h>                        // for Module
16#include <llvm/IR/Verifier.h>                      // for verifyModule
17#include <llvm/Support/CommandLine.h>              // for ParseCommandLineOp...
18#include <llvm/Support/raw_ostream.h>              // for errs
19#include <pablo/pablo_kernel.h>                    // for PabloKernel
20#include <pablo/pe_zeroes.h>
21#include <toolchain.h>                             // for JIT_to_ExecutionEn...
22#include <pablo/builder.hpp>                       // for PabloBuilder
23#include <boost/filesystem.hpp>
24#include <boost/iostreams/device/mapped_file.hpp>
25#include "llvm/ADT/StringRef.h"                    // for StringRef
26#include "llvm/IR/CallingConv.h"                   // for ::C
27#include "llvm/IR/DerivedTypes.h"                  // for ArrayType
28#include "llvm/IR/LLVMContext.h"                   // for LLVMContext
29#include "llvm/IR/Value.h"                         // for Value
30#include "llvm/Support/Debug.h"                    // for dbgs
31#include <iostream>
32namespace llvm { class Type; }
33namespace pablo { class Integer; }
34namespace pablo { class Var; }
35
36using namespace pablo;
37using namespace kernel;
38using namespace parabix;
39using namespace llvm;
40
41static cl::list<std::string> inputFiles(cl::Positional, cl::desc("<input file ...>"), cl::OneOrMore);
42
43void generate(PabloKernel * kernel) {
44
45    PabloBuilder pb(kernel->getEntryBlock());
46
47    Var * input = kernel->getInputStreamVar("input");
48    Var * matches = kernel->getOutputStreamVar("matches");
49
50    PabloAST * basis[8];
51    for (int i = 0; i < 8; ++i) {
52        basis[i] = pb.createExtract(input, i);
53    }
54
55    PabloAST * temp1 = pb.createOr(basis[0], basis[1]);
56    PabloAST * temp2 = pb.createAnd(basis[2], pb.createNot(basis[3]));
57    PabloAST * temp3 = pb.createAnd(temp2, pb.createNot(temp1));
58    PabloAST * temp4 = pb.createAnd(basis[4], pb.createNot(basis[5]));
59    PabloAST * temp5 = pb.createOr(basis[6], basis[7]);
60    PabloAST * temp6 = pb.createAnd(temp4, pb.createNot(temp5));
61    PabloAST * lparen = pb.createAnd(temp3, temp6, "lparens");
62    PabloAST * temp7 = pb.createAnd(basis[7], pb.createNot(basis[6]));
63    PabloAST * temp8 = pb.createAnd(temp4, temp7);
64    PabloAST * rparen = pb.createAnd(temp3, temp8, "rparens");
65    PabloAST * parens = pb.createOr(lparen, rparen);
66    PabloAST * pscan = pb.createScanTo(pb.createAdvance(lparen, 1), parens, "pscan");
67    PabloAST * closed = pb.createAnd(pscan, rparen, "closed");
68
69    pb.createAssign(pb.createExtract(matches, 0), closed);
70
71    Var * const all_closed = pb.createVar("all_closed", closed);
72    Var * const pending_lparen = pb.createVar("pending_lparen", pb.createAnd(pscan, lparen));
73    PabloAST * unmatched_rparen = pb.createAnd(rparen, pb.createNot(closed));
74    Var * const in_play = pb.createVar("in_play", pb.createOr(pending_lparen, unmatched_rparen));
75    Var * const errors = pb.createVar("errors", pb.createZeroes());
76
77    Integer * const one = pb.getInteger(1);
78    Var * const index = pb.createVar("i", one);
79
80    PabloBuilder body = PabloBuilder::Create(pb);
81
82    pb.createWhile(pending_lparen, body);
83
84        pscan = body.createScanTo(body.createAdvance(pending_lparen, 1), in_play);
85        closed = body.createAnd(pscan, rparen);
86        body.createAssign(body.createExtract(matches, index), closed);
87        body.createAssign(all_closed, body.createOr(all_closed, closed));
88        body.createAssign(errors, body.createOr(errors, body.createAtEOF(pscan)));
89
90        body.createAssign(pending_lparen, body.createAnd(pscan, lparen));
91
92        unmatched_rparen = body.createAnd(rparen, body.createNot(all_closed));
93        body.createAssign(in_play, body.createOr(pending_lparen, unmatched_rparen));
94        body.createAssign(index, body.createAdd(index, one));
95
96
97    pb.createAssign(errors, pb.createOr(errors, pb.createAnd(rparen, pb.createNot(all_closed))));
98    pb.createAssign(kernel->getOutputStreamVar("errors"), errors);
99
100    pb.print(errs());
101
102}
103
104//42    def Match_Parens(lex, matches):
105//43            parens = lex.LParen | lex.RParen
106//44            i = 0
107//45            pscan = pablo.AdvanceThenScanTo(lex.LParen, parens)
108//46            matches.closed[0] = pscan & lex.RParen
109//47            all_closed = matches.closed[0]
110//48            matches.error = pablo.atEOF(pscan)
111//49            # Not matched, still pending.
112//50            pending_LParen = pscan & lex.LParen
113//51            RParen_unmatched = lex.RParen &~ matches.closed[0]
114//52            inPlay = pending_LParen | RParen_unmatched
115//53            while pending_LParen:
116//54                    i += 1
117//55                    pscan = pablo.AdvanceThenScanTo(pending_LParen, inPlay)
118//56                    matches.closed[i] = pscan & lex.RParen
119//57                    all_closed |= matches.closed[i]
120//58                    matches.error |= pablo.atEOF(pscan)
121//59                    pending_LParen = pscan & lex.LParen
122//60                    RParen_unmatched = lex.RParen &~ all_closed
123//61                    inPlay = pending_LParen | RParen_unmatched
124//62            #
125//63            # Any closing paren that was not actually used to close
126//64            # an opener is in error.
127//65            matches.error |= lex.RParen &~ all_closed
128
129Function * pipeline(IDISA::IDISA_Builder * iBuilder, const unsigned count) {
130
131    Type * byteStreamTy = iBuilder->getStreamSetTy(1, 8);
132
133    Module * const mod = iBuilder->getModule();
134   
135    Function * const main = cast<Function>(mod->getOrInsertFunction("Main", iBuilder->getVoidTy(), byteStreamTy->getPointerTo(), iBuilder->getSizeTy(), nullptr));
136    main->setCallingConv(CallingConv::C);
137    Function::arg_iterator args = main->arg_begin();
138   
139    Value * const inputStream = &*(args++);
140    inputStream->setName("input");
141    Value * const fileSize = &*(args++);
142    fileSize->setName("fileSize");
143   
144    ExternalFileBuffer ByteStream(iBuilder, byteStreamTy);
145    SingleBlockBuffer BasisBits(iBuilder, iBuilder->getStreamSetTy(8, 1));
146    ExpandableBuffer matches(iBuilder, iBuilder->getStreamSetTy(count, 1), 2);
147    SingleBlockBuffer errors(iBuilder, iBuilder->getStreamTy());
148
149    MMapSourceKernel mmapK(iBuilder); 
150    mmapK.generateKernel({}, {&ByteStream});
151    mmapK.setInitialArguments({fileSize});
152   
153    S2PKernel s2pk(iBuilder);
154    s2pk.generateKernel({&ByteStream}, {&BasisBits});
155
156    PabloKernel bm(iBuilder, "MatchParens",
157        {Binding{iBuilder->getStreamSetTy(8), "input"}},
158        {Binding{iBuilder->getStreamSetTy(count), "matches"}, Binding{iBuilder->getStreamTy(), "errors"}});
159
160    generate(&bm);
161
162    bm.generateKernel({&BasisBits}, {&matches, &errors});
163
164    iBuilder->SetInsertPoint(BasicBlock::Create(mod->getContext(), "entry", main, 0));
165
166    ByteStream.setStreamSetBuffer(inputStream, fileSize);
167    BasisBits.allocateBuffer();
168    matches.allocateBuffer();
169    errors.allocateBuffer();
170
171    generatePipelineLoop(iBuilder, {&mmapK, &s2pk, &bm});
172    iBuilder->CreateRetVoid();
173
174    return main;
175}
176
177typedef void (*MatchParens)(char * byteStream, size_t fileSize);
178
179MatchParens generateAlgorithm() {
180    LLVMContext ctx;
181    Module * M = new Module("mp", ctx);
182    IDISA::IDISA_Builder * idb = IDISA::GetIDISA_Builder(M);
183
184    llvm::Function * f = pipeline(idb, 2);
185
186    verifyModule(*M, &dbgs());
187
188    ExecutionEngine * wcEngine = JIT_to_ExecutionEngine(M);
189
190    wcEngine->finalizeObject();
191
192    delete idb;
193
194    return reinterpret_cast<MatchParens>(wcEngine->getPointerToFunction(f));
195}
196
197void run(MatchParens f, const std::string & fileName) {
198    const boost::filesystem::path file(fileName);
199    if (exists(file)) {
200        if (is_directory(file)) {
201            return;
202        }
203        size_t fileSize = file_size(file);
204        boost::iostreams::mapped_file_source mappedFile;
205        if (fileSize > 0) {
206            mappedFile.open(fileName);
207            char * fileBuffer = const_cast<char *>(mappedFile.data());
208            f(fileBuffer, fileSize);
209            mappedFile.close();
210        }
211    } else {
212        std::cerr << "Error: cannot open " << fileName << " for processing. Skipped.\n";
213    }
214}
215
216int main(int argc, char *argv[]) {
217    cl::ParseCommandLineOptions(argc, argv);
218    auto f = generateAlgorithm();
219    for (const auto & inputFile : inputFiles) {
220        run(f, inputFile);
221    }
222    return 0;
223}
Note: See TracBrowser for help on using the repository browser.