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

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

Moved toolchain and object_cache to kernels directory. Continued work on providing input consumed information.

File size: 9.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/alignedprint.h>
12#include <kernels/streamset.h>                     // for SingleBlockBuffer
13#include <kernels/pipeline.h>
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
21#include <pablo/pe_zeroes.h>
22#include <pablo/pe_ones.h>
23#include <kernels/toolchain.h>
24#include <pablo/builder.hpp>                       // for PabloBuilder
25#include <boost/filesystem.hpp>
26#include <boost/iostreams/device/mapped_file.hpp>
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
33#include <pablo/pablo_toolchain.h>
34#include <iostream>
35
36#include <pablo/passes/ssapass.h>
37
38namespace llvm { class Type; }
39namespace pablo { class Integer; }
40namespace pablo { class Var; }
41
42using namespace pablo;
43using namespace kernel;
44using namespace parabix;
45using namespace llvm;
46
47static cl::list<std::string> inputFiles(cl::Positional, cl::desc("<input file ...>"), cl::OneOrMore);
48
49void generate(PabloKernel * kernel) {
50
51    PabloBuilder pb(kernel->getEntryBlock());
52
53    Var * input = kernel->getInputStreamVar("input");
54
55    PabloAST * basis[8];
56    for (int i = 0; i < 8; ++i) {
57        basis[i] = pb.createExtract(input, i);
58    }
59
60    PabloAST * temp1 = pb.createOr(basis[0], basis[1], "temp1");
61    PabloAST * temp2 = pb.createAnd(basis[2], pb.createNot(basis[3]), "temp2");
62    PabloAST * temp3 = pb.createAnd(temp2, pb.createNot(temp1), "temp3");
63    PabloAST * temp4 = pb.createAnd(basis[4], pb.createNot(basis[5]), "temp4");
64    PabloAST * temp5 = pb.createOr(basis[6], basis[7], "temp5");
65    PabloAST * temp6 = pb.createAnd(temp4, pb.createNot(temp5), "temp6");
66    PabloAST * lparen = pb.createAnd(temp3, temp6, "lparens");
67    PabloAST * temp7 = pb.createAnd(basis[7], pb.createNot(basis[6]), "temp7");
68    PabloAST * temp8 = pb.createAnd(temp4, temp7, "temp8");
69    PabloAST * rparen = pb.createAnd(temp3, temp8, "rparens");
70    PabloAST * parens = pb.createOr(lparen, rparen, "parens");
71
72
73    Var * const pending_lparen = pb.createVar("pending_lparen", lparen);
74    Var * const all_closed = pb.createVar("all_closed", pb.createZeroes());
75    Var * const accumulated_errors = pb.createVar("accumulated_errors", pb.createZeroes());
76    Var * const in_play = pb.createVar("in_play", parens);
77    Var * const index = pb.createVar("i", pb.getInteger(0));
78
79    Var * matches = kernel->getOutputStreamVar("matches");
80
81//    PabloBuilder outer = PabloBuilder::Create(pb);
82
83//    pb.createWhile(pending_lparen, outer);
84
85    PabloBuilder body = PabloBuilder::Create(pb); // outer
86
87    pb.createWhile(pending_lparen, body); // outer
88
89        PabloAST * adv_pending_lparen = body.createAdvance(pending_lparen, 1);
90
91        Var * pscan = body.createVar("pscan", pb.createZeroes());
92
93        PabloBuilder ifPScan = PabloBuilder::Create(body);
94
95        body.createIf(adv_pending_lparen, ifPScan); // <-- inefficient but tests whether we're probably calculating the summary later
96
97            ifPScan.createAssign(pscan, ifPScan.createScanTo(adv_pending_lparen, in_play));
98
99//        body.createAssign(pscan, body.createScanTo(adv_pending_lparen, in_play));
100
101        body.createAssign(pending_lparen, body.createAnd(pscan, lparen));
102
103        PabloAST * closed_rparen = body.createAnd(pscan, rparen, "closed_rparen");
104
105        body.createAssign(all_closed, body.createOr(all_closed, closed_rparen));
106
107        // Mark any opening paren without a matching closer as an error.
108        PabloAST * unmatched_lparen = body.createAtEOF(pscan, "unmatched_lparen");
109
110        body.createAssign(accumulated_errors, body.createOr(accumulated_errors, unmatched_lparen));
111
112        PabloAST * pending_rparen = body.createAnd(rparen, body.createNot(all_closed, "open_rparen"), "pending_rparen");
113
114        body.createAssign(in_play, body.createOr(pending_lparen, pending_rparen));
115
116        body.createAssign(body.createExtract(matches, index), closed_rparen);
117
118        body.createAssign(index, body.createAdd(index, body.getInteger(1)));
119
120    // Mark any closing paren that was not actually used to close an opener as an error.
121    PabloAST * const unmatched_rparen = pb.createAnd(rparen, pb.createNot(all_closed), "unmatched_rparen");
122    pb.createAssign(kernel->getOutputStreamVar("errors"), pb.createOr(accumulated_errors, unmatched_rparen));
123
124}
125
126void pipeline(ParabixDriver & pxDriver, const unsigned count) {
127
128    IDISA::IDISA_Builder * const iBuilder = pxDriver.getIDISA_Builder();
129    Module * const mod = iBuilder->getModule();
130
131    Type * byteStreamTy = iBuilder->getStreamSetTy(1, 8);
132
133    Function * const main = cast<Function>(mod->getOrInsertFunction("Main", iBuilder->getVoidTy(), byteStreamTy->getPointerTo(), iBuilder->getSizeTy(), nullptr));
134    main->setCallingConv(CallingConv::C);
135    Function::arg_iterator args = main->arg_begin();
136   
137    Value * const inputStream = &*(args++);
138    inputStream->setName("input");
139    Value * const fileSize = &*(args++);
140    fileSize->setName("fileSize");
141
142    const unsigned segmentSize = codegen::SegmentSize;
143    const unsigned bufferSegments = codegen::BufferSegments;
144   
145    ExternalFileBuffer ByteStream(iBuilder, iBuilder->getStreamSetTy(1, 8));
146
147    MMapSourceKernel mmapK(iBuilder, segmentSize);
148    mmapK.setInitialArguments({fileSize});
149
150    pxDriver.addKernelCall(mmapK, {}, {&ByteStream});
151
152    CircularBuffer BasisBits(iBuilder, iBuilder->getStreamSetTy(8), segmentSize * bufferSegments);
153
154    S2PKernel s2pk(iBuilder);
155    pxDriver.addKernelCall(s2pk, {&ByteStream}, {&BasisBits});
156
157    PabloKernel bm(iBuilder, "MatchParens",
158        {Binding{iBuilder->getStreamSetTy(8), "input"}},
159        {Binding{iBuilder->getStreamSetTy(count), "matches"}, Binding{iBuilder->getStreamTy(), "errors"}});
160
161    generate(&bm);
162
163    ExpandableBuffer matches(iBuilder, iBuilder->getStreamSetTy(count), segmentSize * bufferSegments);
164    SingleBlockBuffer errors(iBuilder, iBuilder->getStreamTy());
165
166    pxDriver.addKernelCall(bm, {&BasisBits}, {&matches, &errors});
167
168    PrintStreamSet printer(iBuilder, {"matches", "errors"});
169    pxDriver.addKernelCall(printer, {&matches, &errors}, {});
170
171    iBuilder->SetInsertPoint(BasicBlock::Create(mod->getContext(), "entry", main, 0));
172
173    ByteStream.setStreamSetBuffer(inputStream);
174    BasisBits.allocateBuffer();
175    matches.allocateBuffer();
176    errors.allocateBuffer();
177
178    pxDriver.generatePipelineIR();
179    iBuilder->CreateRetVoid();
180
181    pxDriver.linkAndFinalize();
182}
183
184typedef void (*MatchParens)(char * byteStream, size_t fileSize);
185
186MatchParens generateAlgorithm() {
187    LLVMContext ctx;
188    Module * M = new Module("mp", ctx);
189    IDISA::IDISA_Builder * idb = IDISA::GetIDISA_Builder(M);
190    ParabixDriver pxDriver(idb);
191    pipeline(pxDriver, 3);
192    delete idb;
193    return reinterpret_cast<MatchParens>(pxDriver.getPointerToMain());
194}
195
196template <typename T>
197std::ostream & operator<< (std::ostream& out, const std::vector<T>& v) {
198  if ( !v.empty() ) {
199    out << '[';
200    std::copy (v.begin(), v.end(), std::ostream_iterator<T>(out, ", "));
201    out << "\b\b]";
202  }
203  return out;
204}
205
206void check(const char * byteStream, const size_t fileSize) {
207
208    std::vector<size_t> unmatched_left;
209    std::vector<size_t> unmatched_right;
210    size_t maxDepth = 0;
211    for (size_t i = 0; i < fileSize; ++i) {
212        switch (byteStream[i]) {
213            case '(':
214                unmatched_left.push_back(i);
215                maxDepth = std::max<size_t>(maxDepth, unmatched_left.size());
216                break;
217            case ')':
218                if (unmatched_left.empty()) {
219                    unmatched_right.push_back(i);
220                } else {
221                    unmatched_left.pop_back();
222                }
223            default:
224                break;
225        }
226    }
227
228    std::cerr << "maximum depth:        " << maxDepth << "\n"
229                 "invalid left parens:  " << unmatched_left << "\n"
230                 "invalid right parens: " << unmatched_right <<
231                 std::endl;
232}
233
234void run(MatchParens match, const std::string & fileName) {
235    const boost::filesystem::path file(fileName);
236    if (exists(file)) {
237        if (is_directory(file)) {
238            return;
239        }
240        size_t fileSize = file_size(file);
241        boost::iostreams::mapped_file_source mappedFile;
242        if (fileSize > 0) {
243            mappedFile.open(fileName);
244            char * fileBuffer = const_cast<char *>(mappedFile.data());
245            check(fileBuffer, fileSize);
246            match(fileBuffer, fileSize);
247            mappedFile.close();
248        }
249    } else {
250        std::cerr << "Error: cannot open " << fileName << " for processing. Skipped.\n";
251    }
252}
253
254int main(int argc, char *argv[]) {
255    cl::ParseCommandLineOptions(argc, argv);
256    auto f = generateAlgorithm();
257    for (const auto & inputFile : inputFiles) {
258        run(f, inputFile);
259    }
260    return 0;
261}
Note: See TracBrowser for help on using the repository browser.