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

Last change on this file since 5337 was 5337, checked in by nmedfort, 3 years ago

Work on parenthesis matching and expandable buffers. Changed CBuilder CreateMemZero? to zero n bytes rather than n units to conform to the built-in CreateMemSet? and CreateMemCpy? methods.

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