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

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

Continued refactoring work. PabloKernel? now abstract base type with a 'generatePabloMethod' hook to generate Pablo code.

File size: 6.8 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/Support/Debug.h"
15
16using namespace pablo;
17using namespace kernel;
18using namespace parabix;
19using namespace IDISA;
20using namespace llvm;
21
22inline bool isStreamType(const Type * ty) {
23    if (ty->isArrayTy()) {
24        ty = ty->getArrayElementType();
25    }
26    if (ty->isVectorTy()) {
27        return (ty->getVectorNumElements() == 0);
28    }
29    return false;
30}
31
32Var * PabloKernel::getInputStreamVar(const std::string & name) {
33    Port port; unsigned index;
34    std::tie(port, index) = getStreamPort(name);
35    assert (port == Port::Input);
36    return mInputs[index];
37}
38
39Var * PabloKernel::getOutputStreamVar(const std::string & name) {
40    Port port; unsigned index;
41    std::tie(port, index) = getStreamPort(name);
42    assert (port == Port::Output);
43    return mOutputs[index];
44}
45
46Var * PabloKernel::getOutputScalarVar(const std::string & name) {
47    const auto f = mScalarOutputNameMap.find(name);
48    if (LLVM_UNLIKELY(f == mScalarOutputNameMap.end())) {
49        report_fatal_error("Kernel does not contain scalar: " + name);
50    }
51    return f->second;
52}
53
54Var * PabloKernel::addInput(const std::string & name, Type * const type) {
55    Var * param = new (mAllocator) Var(mSymbolTable->makeString(type->getContext(), name), type, mAllocator, Var::KernelInputParameter);
56    param->addUser(this);
57    mInputs.push_back(param);
58    mVariables.push_back(param);
59    if (isStreamType(type)) {
60        mStreamMap.emplace(name, std::make_pair(Port::Input, mStreamSetInputs.size()));
61        mStreamSetInputs.emplace_back(type, name);       
62    } else {
63        mScalarInputs.emplace_back(type, name);
64        param->setScalar();
65    }
66    assert (mStreamSetInputs.size() + mScalarInputs.size() == mInputs.size());
67    return param;
68}
69
70Var * PabloKernel::addOutput(const std::string & name, Type * const type) {
71    Var * result = new (mAllocator) Var(mSymbolTable->makeString(type->getContext(), name), type, mAllocator, Var::KernelOutputParameter);
72    result->addUser(this);
73    mOutputs.push_back(result);
74    mVariables.push_back(result);
75    if (isStreamType(type)) {
76        mStreamMap.emplace(name, std::make_pair(Port::Output, mStreamSetOutputs.size()));
77        mStreamSetOutputs.emplace_back(type, name);
78    } else {
79        mScalarOutputs.emplace_back(type, name);
80        mScalarOutputNameMap.emplace(name, result);
81        result->setScalar();
82    }
83    assert (mStreamSetOutputs.size() + mScalarOutputs.size() == mOutputs.size());
84    return result;
85}
86
87Var * PabloKernel::makeVariable(String * name, Type * const type) {
88    Var * const var = new (mAllocator) Var(name, type, mAllocator);
89    mVariables.push_back(var);
90    return var;
91}
92
93Zeroes * PabloKernel::getNullValue(Type * type) {
94    if (type == nullptr) {
95        type = iBuilder->getStreamTy();
96    }
97    for (PabloAST * constant : mConstants) {
98        if (isa<Zeroes>(constant) && constant->getType() == type) {
99            return cast<Zeroes>(constant);
100        }
101    }
102    Zeroes * value = new (mAllocator) Zeroes(type, mAllocator);
103    mConstants.push_back(value);
104    return value;
105}
106
107Ones * PabloKernel::getAllOnesValue(Type * type) {
108    if (type == nullptr) {
109        type = iBuilder->getStreamTy();
110    }
111    for (PabloAST * constant : mConstants) {
112        if (isa<Ones>(constant) && constant->getType() == type) {
113            return cast<Ones>(constant);
114        }
115    }
116    Ones * value = new (mAllocator) Ones(type, mAllocator);
117    mConstants.push_back(value);
118    return value;
119}
120
121void PabloKernel::prepareKernel() {
122    if (DebugOptionIsSet(DumpTrace)) {
123        setName(getName() + "_DumpTrace");
124    }
125    generatePabloMethod();
126    pablo_function_passes(this);
127    mPabloCompiler->initializeKernelData(iBuilder);
128    BlockOrientedKernel::prepareKernel();
129}
130
131void PabloKernel::generateDoBlockMethod() {
132    mPabloCompiler->compile(iBuilder);
133}
134
135void PabloKernel::generateFinalBlockMethod(Value * const remainingBytes) {
136    // Standard Pablo convention for final block processing: set a bit marking
137    // the position just past EOF, as well as a mask marking all positions past EOF.
138    setScalarField("EOFbit", iBuilder->bitblock_set_bit(remainingBytes));
139    setScalarField("EOFmask", iBuilder->bitblock_mask_from(remainingBytes));
140    CreateDoBlockMethodCall();
141}
142
143String * PabloKernel::makeName(const llvm::StringRef & prefix) const {
144    return mSymbolTable->makeString(iBuilder->getContext(), prefix);
145}
146
147Integer * PabloKernel::getInteger(const int64_t value) const {
148    return mSymbolTable->getInteger(iBuilder->getContext(), value);
149}
150
151PabloKernel::PabloKernel(const std::unique_ptr<KernelBuilder> & b,
152                         std::string kernelName,
153                         std::vector<Binding> stream_inputs,
154                         std::vector<Binding> stream_outputs,
155                         std::vector<Binding> scalar_parameters,
156                         std::vector<Binding> scalar_outputs)
157: BlockOrientedKernel(std::move(kernelName),
158                      std::move(stream_inputs), std::move(stream_outputs), 
159                      std::move(scalar_parameters), std::move(scalar_outputs),
160                      {Binding{b->getBitBlockType(), "EOFbit"}, Binding{b->getBitBlockType(), "EOFmask"}})
161, PabloAST(PabloAST::ClassTypeId::Kernel, nullptr, mAllocator)
162, mPabloCompiler(new PabloCompiler(this))
163, mSymbolTable(new SymbolGenerator(mAllocator))
164, mEntryBlock(PabloBlock::Create(this)) {
165    prepareStreamSetNameMap();
166    for (const Binding & ss : mStreamSetInputs) {
167        Var * param = new (mAllocator) Var(mSymbolTable->makeString(b->getContext(), ss.name), ss.type, mAllocator, Var::KernelInputParameter);
168        param->addUser(this);
169        mInputs.push_back(param);
170        mVariables.push_back(param);
171    }
172    for (const Binding & ss : mStreamSetOutputs) {
173        Var * result = new (mAllocator) Var(mSymbolTable->makeString(b->getContext(), ss.name), ss.type, mAllocator, Var::KernelOutputParameter);
174        result->addUser(this);
175        mOutputs.push_back(result);
176        mVariables.push_back(result);
177    }
178    for (const Binding & ss : mScalarOutputs) {
179        Var * result = new (mAllocator) Var(mSymbolTable->makeString(b->getContext(), ss.name), ss.type, mAllocator, Var::KernelOutputParameter);
180        result->addUser(this);
181        mOutputs.push_back(result);
182        mVariables.push_back(result);
183        mScalarOutputNameMap.emplace(ss.name, result);
184        result->setScalar();
185    }
186}
187
188PabloKernel::~PabloKernel() {
189    delete mPabloCompiler;
190    delete mSymbolTable; 
191}
192
Note: See TracBrowser for help on using the repository browser.