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

Last change on this file since 5828 was 5828, checked in by nmedfort, 21 months ago

Pablo support for byte comparisions; LineFeed? kernel processes byte streams directly. Some clean up of PabloBuilder? functionality.

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