source: icGREP/icgrep-devel/icgrep/pablo/pablo_kernel.cpp @ 5782

Last change on this file since 5782 was 5782, checked in by nmedfort, 13 months ago

Initial check-in of LookAhead? support; modified LineBreakKernel? to compute CR+LF using LookAhead?(1) + misc. fixes.

File size: 8.6 KB
Line 
1/*
2 *  Copyright (c) 2016 International Characters.
3 *  This software is licensed to the public under the Open Software License 3.0.
4 */
5
6#include "pablo_kernel.h"
7#include <pablo/codegenstate.h>
8#include <pablo/pablo_compiler.h>
9#include <pablo/pe_var.h>
10#include <pablo/pe_zeroes.h>
11#include <pablo/pe_ones.h>
12#include <pablo/pablo_toolchain.h>
13#include <kernels/kernel_builder.h>
14#include <llvm/IR/Module.h>
15
16#include <pablo/branch.h>
17#include <sys/stat.h>
18#include <fcntl.h>
19#include <llvm/Support/raw_ostream.h>
20
21using namespace kernel;
22using namespace parabix;
23using namespace IDISA;
24using namespace llvm;
25
26inline bool isStreamType(const Type * ty) {
27    if (ty->isArrayTy()) {
28        ty = ty->getArrayElementType();
29    }
30    if (ty->isVectorTy()) {
31        return (ty->getVectorNumElements() == 0);
32    }
33    return false;
34}
35
36namespace pablo {
37
38Var * PabloKernel::getInputStreamVar(const std::string & name) {
39    Port port; unsigned index;
40    std::tie(port, index) = getStreamPort(name);
41    assert (port == Port::Input);
42    return mInputs[index];
43}
44
45Var * PabloKernel::getOutputStreamVar(const std::string & name) {
46    Port port; unsigned index;
47    std::tie(port, index) = getStreamPort(name);
48    assert (port == Port::Output);
49    return mOutputs[index];
50}
51
52Var * PabloKernel::getOutputScalarVar(const std::string & name) {
53    const auto f = mScalarOutputNameMap.find(name);
54    if (LLVM_UNLIKELY(f == mScalarOutputNameMap.end())) {
55        report_fatal_error("Kernel does not contain scalar: " + name);
56    }
57    return f->second;
58}
59
60Var * PabloKernel::addInput(const std::string & name, Type * const type) {
61    Var * param = new (mAllocator) Var(makeName(name), type, mAllocator, Var::KernelInputParameter);
62    param->addUser(this);
63    mInputs.push_back(param);
64    mVariables.push_back(param);
65    if (isStreamType(type)) {
66        mStreamMap.emplace(name, std::make_pair(Port::Input, mStreamSetInputs.size()));
67        mStreamSetInputs.emplace_back(type, name);       
68    } else {
69        mScalarInputs.emplace_back(type, name);
70        param->setScalar();
71    }
72    assert (mStreamSetInputs.size() + mScalarInputs.size() == mInputs.size());
73    return param;
74}
75
76Var * PabloKernel::addOutput(const std::string & name, Type * const type) {
77    Var * result = new (mAllocator) Var(makeName(name), type, mAllocator, Var::KernelOutputParameter);
78    result->addUser(this);
79    mOutputs.push_back(result);
80    mVariables.push_back(result);
81    if (isStreamType(type)) {
82        mStreamMap.emplace(name, std::make_pair(Port::Output, mStreamSetOutputs.size()));
83        mStreamSetOutputs.emplace_back(type, name);
84    } else {
85        mScalarOutputs.emplace_back(type, name);
86        mScalarOutputNameMap.emplace(name, result);
87        result->setScalar();
88    }
89    assert (mStreamSetOutputs.size() + mScalarOutputs.size() == mOutputs.size());
90    return result;
91}
92
93Var * PabloKernel::makeVariable(String * name, Type * const type) {
94    Var * const var = new (mAllocator) Var(name, type, mAllocator);
95    mVariables.push_back(var);
96    return var;
97}
98
99Zeroes * PabloKernel::getNullValue(Type * type) {
100    if (LLVM_LIKELY(type == nullptr)) {
101        type = getStreamTy();
102    }
103    for (PabloAST * constant : mConstants) {
104        if (isa<Zeroes>(constant) && constant->getType() == type) {
105            return cast<Zeroes>(constant);
106        }
107    }
108    Zeroes * value = new (mAllocator) Zeroes(type, mAllocator);
109    mConstants.push_back(value);
110    return value;
111}
112
113Ones * PabloKernel::getAllOnesValue(Type * type) {
114    if (LLVM_LIKELY(type == nullptr)) {
115        type = getStreamTy();
116    }
117    for (PabloAST * constant : mConstants) {
118        if (isa<Ones>(constant) && constant->getType() == type) {
119            return cast<Ones>(constant);
120        }
121    }
122    Ones * value = new (mAllocator) Ones(type, mAllocator);
123    mConstants.push_back(value);
124    return value;
125}
126
127void PabloKernel::addInternalKernelProperties(const std::unique_ptr<kernel::KernelBuilder> & iBuilder) {
128    mSizeTy = iBuilder->getSizeTy();
129    mStreamTy = iBuilder->getStreamTy();
130    generatePabloMethod();   
131    pablo_function_passes(this);
132    mPabloCompiler->initializeKernelData(iBuilder);
133    mSizeTy = nullptr;
134    mStreamTy = nullptr;   
135}
136
137void PabloKernel::generateDoBlockMethod(const std::unique_ptr<KernelBuilder> & iBuilder) {
138    mSizeTy = iBuilder->getSizeTy();
139    mStreamTy = iBuilder->getStreamTy();
140    mPabloCompiler->compile(iBuilder);
141    mSizeTy = nullptr;
142    mStreamTy = nullptr;
143}
144
145void PabloKernel::generateFinalBlockMethod(const std::unique_ptr<KernelBuilder> & iBuilder, Value * const remainingBytes) {
146    // Standard Pablo convention for final block processing: set a bit marking
147    // the position just past EOF, as well as a mask marking all positions past EOF.
148    iBuilder->setScalarField("EOFbit", iBuilder->bitblock_set_bit(remainingBytes));
149    iBuilder->setScalarField("EOFmask", iBuilder->bitblock_mask_from(remainingBytes));
150    CreateDoBlockMethodCall(iBuilder);
151}
152
153void PabloKernel::generateFinalizeMethod(const std::unique_ptr<kernel::KernelBuilder> & iBuilder) {
154    mPabloCompiler->releaseKernelData(iBuilder);
155
156    if (CompileOptionIsSet(PabloCompilationFlags::EnableProfiling)) {
157
158
159        Value * fd = iBuilder->CreateOpenCall(iBuilder->GetString("./" + getName() + ".profile"),
160                                              iBuilder->getInt32(O_WRONLY | O_CREAT | O_TRUNC),
161                                              iBuilder->getInt32(S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH));
162
163        Function * dprintf = iBuilder->GetDprintf();
164
165
166
167        Value * profile = iBuilder->getScalarFieldPtr("profile");
168
169
170        unsigned branchCount = 0;
171
172        for (const auto bb : mPabloCompiler->mBasicBlock) {
173
174            std::string tmp;
175            raw_string_ostream str(tmp);
176            str << "%lu\t";
177            str << bb->getName();
178            str << "\n";
179
180            Value * taken = iBuilder->CreateLoad(iBuilder->CreateGEP(profile, {iBuilder->getInt32(0), iBuilder->getInt32(branchCount++)}));
181            iBuilder->CreateCall(dprintf, {fd, iBuilder->GetString(str.str()), taken});
182
183        }
184
185        iBuilder->CreateCloseCall(fd);
186    }
187
188}
189
190String * PabloKernel::makeName(const llvm::StringRef & prefix) const {
191    return mSymbolTable->makeString(prefix);
192}
193
194Integer * PabloKernel::getInteger(const int64_t value) const {
195    return mSymbolTable->getInteger(value);
196}
197
198llvm::IntegerType * PabloKernel::getInt1Ty() const {
199    return IntegerType::getInt1Ty(getModule()->getContext());
200}
201
202static inline std::string && annotateKernelNameWithDebugFlags(std::string && name) {
203    if (DebugOptionIsSet(DumpTrace)) {
204        name += "_DumpTrace";
205    }
206    if (CompileOptionIsSet(EnableProfiling)) {
207        name += "_BranchProfiling";
208    }
209    return std::move(name);
210}
211
212PabloKernel::PabloKernel(const std::unique_ptr<KernelBuilder> & b,
213                         std::string && kernelName,
214                         std::vector<Binding> stream_inputs,
215                         std::vector<Binding> stream_outputs,
216                         std::vector<Binding> scalar_parameters,
217                         std::vector<Binding> scalar_outputs)
218: BlockOrientedKernel(annotateKernelNameWithDebugFlags(std::move(kernelName)),
219                      std::move(stream_inputs), std::move(stream_outputs), 
220                      std::move(scalar_parameters), std::move(scalar_outputs),
221                      {Binding{b->getBitBlockType(), "EOFbit"}, Binding{b->getBitBlockType(), "EOFmask"}})
222, PabloAST(PabloAST::ClassTypeId::Kernel, nullptr, mAllocator)
223, mPabloCompiler(new PabloCompiler(this))
224, mSymbolTable(new SymbolGenerator(b->getContext(), mAllocator))
225, mEntryBlock(PabloBlock::Create(this))
226, mSizeTy(nullptr)
227, mStreamTy(nullptr) {
228    prepareStreamSetNameMap();
229    for (const Binding & ss : mStreamSetInputs) {
230        Var * param = new (mAllocator) Var(makeName(ss.getName()), ss.getType(), mAllocator, Var::KernelInputParameter);
231        param->addUser(this);
232        mInputs.push_back(param);
233        mVariables.push_back(param);
234    }
235    for (const Binding & ss : mStreamSetOutputs) {
236        Var * result = new (mAllocator) Var(makeName(ss.getName()), ss.getType(), mAllocator, Var::KernelOutputParameter);
237        result->addUser(this);
238        mOutputs.push_back(result);
239        mVariables.push_back(result);
240    }
241    for (const Binding & ss : mScalarOutputs) {
242        Var * result = new (mAllocator) Var(makeName(ss.getName()), ss.getType(), mAllocator, Var::KernelOutputParameter);
243        result->addUser(this);
244        mOutputs.push_back(result);
245        mVariables.push_back(result);
246        mScalarOutputNameMap.emplace(ss.getName(), result);
247        result->setScalar();
248    }
249}
250
251PabloKernel::~PabloKernel() {
252    delete mPabloCompiler;
253    delete mSymbolTable; 
254}
255
256}
Note: See TracBrowser for help on using the repository browser.