source: icGREP/icgrep-devel/icgrep/kernels/interface.cpp @ 5047

Last change on this file since 5047 was 5047, checked in by cameron, 3 years ago

Kernel interfaces initial check-in

File size: 6.2 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 "interface.h"
7#include <llvm/IR/Module.h>
8#include <llvm/IR/Type.h>
9#include <llvm/IR/Value.h>
10#include <llvm/Support/raw_ostream.h>
11
12using namespace llvm;
13using namespace kernel;
14
15KernelInterface::KernelInterface(IDISA::IDISA_Builder * builder,
16                                 std::string kernelName,
17                                 std::vector<StreamSetBinding> stream_inputs,
18                                 std::vector<StreamSetBinding> stream_outputs,
19                                 std::vector<ScalarBinding> scalar_parameters,
20                                 std::vector<ScalarBinding> scalar_outputs,
21                                 std::vector<ScalarBinding> internal_scalars) {
22    llvm::errs() << "0\n";
23    iBuilder = builder;
24    mKernelName = kernelName;
25    mStreamSetInputs = stream_inputs;
26    mStreamSetOutputs = stream_outputs;
27    mScalarInputs = scalar_parameters;
28    mScalarOutputs = scalar_outputs;
29    mInternalScalars = internal_scalars;
30    llvm::errs() << "1\n";
31    std::vector<Type *> kernelFields;
32    for (auto binding : scalar_parameters) {
33        unsigned index = kernelFields.size();
34        kernelFields.push_back(binding.scalarType);
35        mInternalStateNameMap.emplace(binding.scalarName, iBuilder->getInt32(index));
36    }
37    for (auto binding : scalar_outputs) {
38        unsigned index = kernelFields.size();
39        kernelFields.push_back(binding.scalarType);
40        mInternalStateNameMap.emplace(binding.scalarName, iBuilder->getInt32(index));
41    }
42    for (auto binding : internal_scalars) {
43        unsigned index = kernelFields.size();
44        kernelFields.push_back(binding.scalarType);
45        mInternalStateNameMap.emplace(binding.scalarName, iBuilder->getInt32(index));
46    }
47    mKernelStateType = StructType::create(getGlobalContext(), kernelFields, kernelName);
48    llvm::errs() << "2\n";
49
50}
51
52void KernelInterface::addKernelDeclarations(Module * client) {
53   
54    Type * selfType = PointerType::getUnqual(mKernelStateType);
55    llvm::errs() << "3\n";
56   
57    // Create the accumulator get function prototypes
58    for (auto binding : mScalarOutputs) {
59        FunctionType * accumFnType = FunctionType::get(binding.scalarType, {selfType}, false);
60        Function::Create(accumFnType, GlobalValue::ExternalLinkage, mKernelName + "_get_" + binding.scalarName, client);
61    }
62    llvm::errs() << "4\n";
63
64    // Create the initialization function prototype
65
66    std::vector<Type *> initParameters = {selfType};
67    for (auto binding : mScalarInputs) {
68        initParameters.push_back(binding.scalarType);
69    }
70    FunctionType * initFunctionType = FunctionType::get(iBuilder->getVoidTy(), initParameters, false);
71    Function::Create(initFunctionType, GlobalValue::ExternalLinkage, mKernelName + "_Init", client);
72   
73   
74
75    llvm::errs() << "5\n";
76
77    // Create the doBlock and finalBlock function prototypes
78   
79    std::vector<Type *> doBlockParameters = {selfType};
80    std::vector<Type *> finalBlockParameters = {selfType, iBuilder->getInt64Ty()};
81    for (auto inputSet : mStreamSetInputs) {
82        Type * inputSetParmType = PointerType::getUnqual(inputSet.ssType.getStreamSetBlockType(iBuilder));
83        doBlockParameters.push_back(inputSetParmType);
84        finalBlockParameters.push_back(inputSetParmType);
85    }
86    for (auto outputSet : mStreamSetOutputs) {
87        Type * outputSetParmType = PointerType::getUnqual(outputSet.ssType.getStreamSetBlockType(iBuilder));
88        doBlockParameters.push_back(outputSetParmType);
89        finalBlockParameters.push_back(outputSetParmType);
90    }
91    FunctionType * doBlockFunctionType = FunctionType::get(iBuilder->getVoidTy(), doBlockParameters, false);
92    Function::Create(doBlockFunctionType, GlobalValue::ExternalLinkage, mKernelName + "_DoBlock", client);
93    FunctionType * finalBlockFunctionType = FunctionType::get(iBuilder->getVoidTy(), finalBlockParameters, false);
94    Function::Create(finalBlockFunctionType, GlobalValue::ExternalLinkage, mKernelName + "_FinalBlock", client);
95}
96
97
98std::unique_ptr<Module> KernelInterface::createKernelModule() {
99    std::unique_ptr<Module> theModule = llvm::make_unique<Module>(mKernelName, getGlobalContext());
100    addKernelDeclarations(theModule.get());
101   
102    // Implement the accumulator get functions
103    for (auto binding : mScalarOutputs) {
104        auto fnName = mKernelName + "_get_" + binding.scalarName;
105        Function * accumFn = theModule->getFunction(fnName);
106        iBuilder->SetInsertPoint(BasicBlock::Create(iBuilder->getContext(), "get_" + binding.scalarName, accumFn, 0));
107        Value * self = &*(accumFn->arg_begin());
108        const auto f = mInternalStateNameMap.find(binding.scalarName);
109        if (LLVM_UNLIKELY(f == mInternalStateNameMap.end())) {
110            throw std::runtime_error("Kernel does not contain internal state " + binding.scalarName);
111        }
112        Value * idx = f->second;
113        Value * ptr = iBuilder->CreateGEP(self, {iBuilder->getInt32(0), idx});
114        Value * retVal = iBuilder->CreateLoad(ptr);
115        iBuilder->CreateRet(retVal);
116    }
117   
118    // Implement the initializer function
119    Function * initFunction = theModule->getFunction(mKernelName + "_Init");
120    iBuilder->SetInsertPoint(BasicBlock::Create(iBuilder->getContext(), "Init_entry", initFunction, 0));
121   
122    Function::arg_iterator args = initFunction->arg_begin();
123    Value * self = &*(args++);
124    self->setName("self");
125    for (auto binding : mScalarInputs) {
126        Value * parm = &*(args++);
127        parm->setName(binding.scalarName);
128    }
129
130    iBuilder->CreateStore(Constant::getNullValue(mKernelStateType), self);
131    args = initFunction->arg_begin();
132    args++;   // skip self argument.
133    for (auto binding : mScalarInputs) {
134        Value * parm = &*(args++);
135        const auto f = mInternalStateNameMap.find(binding.scalarName);
136        if (LLVM_UNLIKELY(f == mInternalStateNameMap.end())) {
137            throw std::runtime_error("Kernel does not contain internal state " + binding.scalarName);
138        }
139        Value * idx = f->second;
140        Value * ptr = iBuilder->CreateGEP(self, {iBuilder->getInt32(0), idx});
141        iBuilder->CreateStore(ptr, parm);
142    }
143    iBuilder->CreateRetVoid();
144    return theModule;
145}
Note: See TracBrowser for help on using the repository browser.