Implemented some pieces of the GenIR to c++ conversion used by the performance simulator
authorBenjamin Segovia <segovia.benjamin@gmail.com>
Tue, 3 Apr 2012 20:31:11 +0000 (20:31 +0000)
committerKeith Packard <keithp@keithp.com>
Fri, 10 Aug 2012 23:16:00 +0000 (16:16 -0700)
backend/src/backend/gbe_program.hpp [new file with mode: 0644]
backend/src/backend/sim/program.cpp
backend/src/backend/sim/program.hpp [new file with mode: 0644]

diff --git a/backend/src/backend/gbe_program.hpp b/backend/src/backend/gbe_program.hpp
new file mode 100644 (file)
index 0000000..4dde610
--- /dev/null
@@ -0,0 +1,132 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+/**
+ * \file program.hpp
+ * \author Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __GBE_PROGRAM_HPP__
+#define __GBE_PROGRAM_HPP__
+
+#include "backend/gbe_program.h"
+#include "sys/hash_map.hpp"
+#include <string>
+
+namespace gbe {
+namespace ir {
+
+  class Unit;        // Compilation unit. Contains the program to compile
+  class Liveness;    // Describes liveness of each ir function register
+  class FunctionDAG; // Describes the instruction dependencies
+
+} /* namespace ir */
+} /* namespace gbe */
+
+namespace gbe {
+
+  struct KernelArgument {
+    gbe_arg_type type; //!< Pointer, structure, regular value?
+    size_t size;       //!< Size of each argument
+  };
+
+  /*! Describe a compiled kernel */
+  struct Kernel : public NonCopyable
+  {
+    /*! Create an empty kernel with the given name */
+    Kernel(const std::string &name);
+    /*! Destroy it */
+    virtual ~Kernel(void);
+    /*! Return the instruction stream */
+    virtual const char *getCode(void) const = 0;
+    /*! Return the instruction stream size */
+    virtual size_t getCodeSize(void) const = 0;
+    /*! Get the kernel name */
+    INLINE const char *getName(void) const { return name.c_str(); }
+    /*! Return the number of arguments for the kernel call */
+    INLINE uint32_t getArgNum(void) const { return argNum; }
+    /*! Return the size of the given argument */
+    INLINE uint32_t getArgSize(uint32_t argID) const {
+      if (argID >= argNum)
+        return 0u;
+      else
+        return args[argID].size;
+    }
+    /*! Return the type of the given argument */
+    INLINE gbe_arg_type getArgType(uint32_t argID) const {
+      if (argID >= argNum)
+        return GBE_ARG_INVALID;
+      else
+        return args[argID].type;
+    }
+  protected:
+    friend class Program;    //!< Owns the kernels
+    const std::string name;  //!< Kernel name
+    KernelArgument *args;    //!< Each argument
+    uint32_t argNum;         //!< Number of function arguments
+    ir::Liveness *liveness;  //!< Used only for the build
+    ir::FunctionDAG *dag;    //!< Used only for the build
+  };
+
+  /*! Describe a compiled program */
+  struct Program : public NonCopyable
+  {
+    /*! Create an empty program */
+    Program(void);
+    /*! Destroy the program */
+    virtual ~Program(void);
+    /*! Get the number of kernels in the program */
+    uint32_t getKernelNum(void) const { return kernels.size(); }
+    /*! Get the kernel from its name */
+    Kernel *getKernel(const std::string &name) const {
+      auto it = kernels.find(name);
+      if (it == kernels.end())
+        return NULL;
+      else
+        return it->second;
+    }
+    /*! Get the kernel from its ID */
+    Kernel *getKernel(const uint32_t ID) const {
+      uint32_t currID = 0;
+      Kernel *kernel = NULL;
+      for (auto it = kernels.begin(); it != kernels.end(); ++it) {
+        if (currID == ID) {
+          kernel = it->second;
+          break;
+        }
+      }
+      return kernel;
+    }
+    /*! Build a program from a ir::Unit */
+    bool buildFromUnit(const ir::Unit &unit, std::string &error);
+    /*! Buils a program from a LLVM source code */
+    bool buildFromLLVMFile(const char *fileName, std::string &error);
+    /*! Buils a program from a OCL string */
+    bool buildFromSource(const char *source, std::string &error);
+    /*! Compile a kernel */
+    virtual Kernel *compileKernel(const std::string &name) = 0;
+  protected:
+    /*! Kernels sorted by their name */
+    hash_map<std::string, Kernel*> kernels;
+  };
+
+} /* namespace gbe */
+
+#endif /* __GBE_PROGRAM_HPP__ */
+
index c283bff..aef7774 100644 (file)
 
 #include "backend/gbe_program.h"
 #include "backend/sim/program.h"
+#include "backend/sim/program.hpp"
+#include <cstring>
+#include <cstdio>
+#include <fstream>
+#include "dlfcn.h"
 
 namespace gbe {
 namespace sim {
 
+  SimKernel::SimKernel(const std::string &name) :
+    Kernel(name), fn(NULL), handle(NULL) {}
+  SimKernel::~SimKernel(void) { if (this->handle) dlclose(this->handle); }
+
+  SimProgram::SimProgram(void) {}
+  SimProgram::~SimProgram(void) {}
+
+  Kernel *SimProgram::compileKernel(const std::string &name) {
+    SimKernel *kernel = GBE_NEW(SimKernel, name);
+    char srcStr[L_tmpnam+1], libStr[L_tmpnam+1];
+    const std::string srcName = std::string(tmpnam_r(srcStr)) + ".cpp"; // unsecure but we don't care
+    const std::string libName = std::string(tmpnam_r(libStr)) + ".so";  // unsecure but we don't care
+
+    // Output the code first
+    std::ofstream ostream;
+    ostream.open(srcName);
+    ostream << "extern \"C\" void " << name << "() {}" << std::endl;
+    ostream.close();
+
+    // Compile the function
+    std::cout << srcName << " " << libName;
+    std::string compileCmd = "g++ -shared -O3 -o ";
+    compileCmd += libName;
+    compileCmd += " ";
+    compileCmd += srcName;
+    printf(compileCmd.c_str());
+    if (UNLIKELY(system(compileCmd.c_str()) != 0))
+      FATAL("Simulation program compilation failed");
+
+    // Load it and get the function pointer
+    kernel->handle = dlopen(libName.c_str(), RTLD_NOW);
+    if (UNLIKELY(kernel->handle == NULL))
+      FATAL("Failed to open the compiled shared object");
+    kernel->fn = (SimKernelCallBack*) dlsym(kernel->handle, name.c_str());
+    if (UNLIKELY(kernel->fn == NULL))
+      FATAL("Failed to get the symbol from the compiled shared object");
+    return kernel;
+  }
 
 } /* namespace sim */
 } /* namespace gen */
 
-  void simSetupCallBacks(void)
-  {
-#if 0
-    GBEProgramNewFromSource = SimProgramNewFromSource;
-    GBEProgramNewFromBinary = SimProgramNewFromBinary;
-    GBEProgramNewFromLLVM = SimProgramNewFromLLVM;
-    GBEProgramDelete = SimProgramDelete;
-    GBEProgramGetKernelNum = SimProgramGetKernelNum;
-    GBEProgramGetKernelByName = SimProgramGetKernelByName;
-    GBEProgramGetKernel = SimProgramGetKernel;
-    GBEKernelGetName = SimKernelGetName;
-    GBEKernelGetCode = SimKernelGetCode;
-    GBEKernelGetCodeSize = SimKernelGetCodeSize;
-    GBEKernelGetArgNum = SimKernelGetArgNum;
-    GBEKernelGetArgSize = SimKernelGetArgSize;
-    GBEKernelGetArgType = SimKernelGetArgType;
-    GBEKernelGetSIMDWidth = SimKernelGetSIMDWidth;
-    GBEKernelGetRequiredWorkGroupSize = SimKernelGetRequiredWorkGroupSize;
-#endif
+static gbe_program SimProgramNewFromSource(const char *source) {
+  NOT_IMPLEMENTED;
+  return NULL;
+}
+
+static gbe_program SimProgramNewFromBinary(const char *binary, size_t size) {
+  NOT_IMPLEMENTED;
+  return NULL;
+}
+
+static gbe_program SimProgramNewFromLLVM(const char *fileName,
+                                         size_t stringSize,
+                                         char *err,
+                                         size_t *errSize)
+{
+  using namespace gbe::sim;
+  SimProgram *program = GBE_NEW(SimProgram);
+  std::string error;
+
+  // Try to compile the program
+  if (program->buildFromLLVMFile(fileName, error) == false) {
+    if (err != NULL && errSize != NULL && stringSize > 0u) {
+      const size_t msgSize = std::min(error.size(), stringSize-1u);
+      std::memcpy(err, error.c_str(), msgSize);
+      *errSize = error.size();
+    }
+    GBE_DELETE(program);
+    return NULL;
   }
 
+  // Everything run fine
+  return (gbe_program) program;
+}
+
+void simSetupCallBacks(void)
+{
+  gbe_program_new_from_source = SimProgramNewFromSource;
+  gbe_program_new_from_binary = SimProgramNewFromBinary;
+  gbe_program_new_from_llvm = SimProgramNewFromLLVM;
+}
+
diff --git a/backend/src/backend/sim/program.hpp b/backend/src/backend/sim/program.hpp
new file mode 100644 (file)
index 0000000..743b039
--- /dev/null
@@ -0,0 +1,70 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+/**
+ * \file program.hpp
+ * \author Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __GBE_SIM_PROGRAM_HPP__
+#define __GBE_SIM_PROGRAM_HPP__
+
+#include "backend/gbe_program.h"
+#include "backend/gbe_program.hpp"
+#include "backend/gen/brw_structs.h"
+
+namespace gbe {
+namespace sim {
+
+  /*! We basically create one real C function for each */
+  typedef void (SimKernelCallBack)();
+
+  /*! Describe a compiled kernel */
+  struct SimKernel : public Kernel
+  {
+    /*! Create an empty kernel with the given name */
+    SimKernel(const std::string &name);
+    /*! Destroy it */
+    virtual ~SimKernel(void);
+    /*! Implements base class */
+    virtual const char *getCode(void) const { return (const char*) fn; }
+    /*! Implements base class */
+    virtual size_t getCodeSize(void) const { return sizeof(fn); }
+    SimKernelCallBack *fn; //!< Function that runs the code
+    void *handle;          //!< dlopen / dlclose / dlsym handle
+    GBE_STRUCT(SimKernel); //!< Use gbe allocators
+  };
+
+  /*! Describe a compiled program */
+  struct SimProgram : public Program
+  {
+    /*! Create an empty program */
+    SimProgram(void);
+    /*! Destroy the program */
+    virtual ~SimProgram(void);
+    /*! Implements base class */
+    virtual Kernel *compileKernel(const std::string &name);
+    GBE_STRUCT(SimProgram);   //!< Use gbe allocators
+  };
+
+} /* namespace sim */
+} /* namespace gbe */
+
+#endif /* __GBE_SIM_PROGRAM_HPP__ */
+