/*
* Copyright 2012 Phil Pratt-Szeliga and other contributors
* http://chirrup.org/
*
* See the file LICENSE for copying permission.
*/
package org.trifort.rootbeer.runtime.nemu;
import java.io.File;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.List;
import org.trifort.rootbeer.configuration.RootbeerPaths;
import org.trifort.rootbeer.runtime.BlockShaper;
import org.trifort.rootbeer.runtime.CompiledKernel;
import org.trifort.rootbeer.runtime.Kernel;
import org.trifort.rootbeer.runtime.Serializer;
import org.trifort.rootbeer.runtime.ThreadConfig;
import org.trifort.rootbeer.util.ResourceReader;
import org.trifort.rootbeer.util.WindowsCompile;
public class NativeCpuDevice {
private List<CompiledKernel> m_Blocks;
private boolean m_nativeCpuInitialized;
private BlockShaper m_blockShaper;
public NativeCpuDevice(){
m_nativeCpuInitialized = false;
m_blockShaper = new BlockShaper();
}
public long getMaxEnqueueSize() {
return 1024*1024*1024;
}
public void flushQueue() {
}
public void run(Kernel kernel_template, ThreadConfig thread_config){
/*
int block_shape = thread_config.getGridShapeX();
int thread_shape = thread_config.getBlockShapeX();
int num_threads = thread_config.getNumThreads();
NativeCpuGcHeap heap = new NativeCpuGcHeap(this);
int size = heap.writeRuntimeBasicBlock(kernel_template, num_threads);
m_Blocks = heap.getBlocks();
List<Memory> mems = heap.getMemory();
String lib_name = compileNativeCpuDev();
BasicMemory to_space = (BasicMemory) mems.get(0);
BasicMemory handles = (BasicMemory) mems.get(1);
BasicMemory heap_end_ptr = (BasicMemory) mems.get(2);
BasicMemory gc_info = (BasicMemory) mems.get(3);
BasicMemory exceptions = (BasicMemory) mems.get(4);
Serializer serializer = heap.getSerializer();
runOnCpu(to_space.getBuffer(), to_space.getBuffer().size(),
handles.getBuffer().get(0), heap_end_ptr.getBuffer().get(0),
gc_info.getBuffer().get(0), exceptions.getBuffer().get(0),
serializer.getClassRefArray(), num_threads, block_shape, thread_shape,
lib_name);
heap.readRuntimeBasicBlock(kernel_template, num_threads);
*/
}
private native void runOnCpu(List<byte[]> to_space, int to_space_size,
byte[] handles, byte[] heap_end_ptr, byte[] gc_info, byte[] exceptions,
int[] java_lang_class_refs, int num_threads, int block_shape,
int thread_shape, String library_name);
public long getMaxMemoryAllocSize() {
return 1024*1024*1024;
}
private void extractFromNative(String filename, String nemu) throws Exception {
String str = ResourceReader.getResource("/org/trifort/rootbeer/runtime2/native/"+filename);
PrintWriter writer = new PrintWriter(nemu+filename);
writer.println(str);
writer.flush();
writer.close();
}
private String compileMac(File nemu_file) throws Exception {
String nemu = nemu_file.getAbsolutePath()+File.separator;
String name = "libnemu";
int status;
String cmd;
Process p;
String cflags = "-fno-common -Os -arch i386 -arch x86_64 -c";
if(m_nativeCpuInitialized == false){
cmd = "llvm-gcc "+cflags+" -I/System/Library/Frameworks/JavaVM.framework/Versions/A/Headers "+nemu+"NativeCpuDevice.c -o "+nemu+"NativeCpuDevice.o";
p = Runtime.getRuntime().exec(cmd, null, nemu_file);
status = p.waitFor();
if(status != 0){
System.out.println("Compilation failure!");
System.out.println(cmd);
System.exit(-1);
}
p.destroy();
}
cmd = "llvm-gcc "+cflags+" -lpthread "+nemu+"generated.c -o "+nemu+"generated.o";
p = Runtime.getRuntime().exec(cmd, null, nemu_file);
status = p.waitFor();
if(status != 0){
System.out.println("Compilation failure!");
System.out.println(cmd);
System.exit(-1);
}
p.destroy();
String ldflags = "-arch i386 -arch x86_64 -dynamiclib";
if(m_nativeCpuInitialized == false){
cmd = "llvm-gcc "+ldflags+" -o "+nemu+"nativecpudev.dylib -dylib "+nemu+"NativeCpuDevice.o -lc";
p = Runtime.getRuntime().exec(cmd, null, nemu_file);
status = p.waitFor();
if(status != 0){
System.out.println("Compilation failure!");
System.out.println(cmd);
System.exit(-1);
}
p.destroy();
}
cmd = "llvm-gcc "+ldflags+" -o "+nemu+name+".dylib -dylib "+nemu+"generated.o -lc";
p = Runtime.getRuntime().exec(cmd, null, nemu_file);
status = p.waitFor();
if(status != 0){
System.out.println("Compilation failure!");
System.out.println(cmd);
System.exit(-1);
}
p.destroy();
if(m_nativeCpuInitialized == false){
File f1 = new File(nemu+"nativecpudev.dylib");
System.load(f1.getAbsolutePath());
m_nativeCpuInitialized = true;
}
File f2 = new File(nemu+name+".dylib");
return f2.getAbsolutePath();
}
private String compileLinux(File nemu_file) throws Exception {
String nemu = nemu_file.getAbsolutePath()+File.separator;
String name = "libnemu";
int status;
String cmd;
Process p;
if(m_nativeCpuInitialized == false){
cmd = "gcc -ggdb -Wall -fPIC -g -c -I/usr/lib/jvm/default-java/include/ -I/usr/lib/jvm/default-java/include/linux "+nemu+"NativeCpuDevice.c -o "+nemu+"NativeCpuDevice.o";
p = Runtime.getRuntime().exec(cmd, null, nemu_file);
status = p.waitFor();
if(status != 0){
System.out.println("Compilation failure!");
System.out.println(cmd);
System.exit(-1);
}
p.destroy();
}
cmd = "gcc -ggdb -fPIC -Wall -g -c -lpthread "+nemu+"generated.c -o "+nemu+"generated.o";
p = Runtime.getRuntime().exec(cmd, null, nemu_file);
status = p.waitFor();
if(status != 0){
System.out.println("Compilation failure!");
System.out.println(cmd);
System.exit(-1);
}
p.destroy();
cmd = "gcc -shared -Wl,-soname,"+name+" -o "+nemu+name+".so.1 "+nemu+"generated.o -lc";
p = Runtime.getRuntime().exec(cmd, null, nemu_file);
status = p.waitFor();
if(status != 0){
System.out.println("Compilation failure!");
System.out.println(cmd);
System.exit(-1);
}
p.destroy();
if(m_nativeCpuInitialized == false){
cmd = "gcc -shared -Wl,-soname,nativecpudev -o "+nemu+"nativecpudev.so.1 "+nemu+"NativeCpuDevice.o "+nemu+"generated.o -lc";
p = Runtime.getRuntime().exec(cmd, null, nemu_file);
status = p.waitFor();
if(status != 0){
System.out.println("Compilation failure!");
System.out.println(cmd);
System.exit(-1);
}
p.destroy();
}
if(m_nativeCpuInitialized == false){
File f1 = new File(nemu+"nativecpudev.so.1");
System.load(f1.getAbsolutePath());
m_nativeCpuInitialized = true;
}
File f2 = new File(nemu+name+".so.1");
return f2.getAbsolutePath();
}
private String compileWindows(File nemu_file){
String nemu = nemu_file.getAbsolutePath()+File.separator;
String name = "libnemu";
WindowsCompile compiler = new WindowsCompile();
String jdk_path = compiler.jdkPath();
if(m_nativeCpuInitialized == false){
windowsCompile("cl /I\""+jdk_path+"\\include\" /I\""+jdk_path+"\\include\\win32\" "+nemu+"NativeCpuDevice.c /link /DLL /OUT:\""+nemu+"nativecpudevice.dll\" /MACHINE:X64");
}
windowsCompile("cl /I\""+jdk_path+"\\include\" /I\""+jdk_path+"\\include\\win32\" "+nemu+"generated.c /link /DLL /OUT:\""+nemu+"libnemu.dll\" /MACHINE:X64");
if(m_nativeCpuInitialized == false){
File f1 = new File(nemu+"nativecpudevice.dll");
System.load(f1.getAbsolutePath());
m_nativeCpuInitialized = true;
}
File f2 = new File(nemu+name+".dll");
return f2.getAbsolutePath();
}
private void windowsCompile(String cmd){
boolean arch64 = true;
String arch_str = System.getProperty("os.arch");
if(arch_str == null || arch_str.equals("x86")){
arch64 = false;
}
WindowsCompile compiler = new WindowsCompile();
List<String> errors = compiler.compile(cmd, arch64);
if(errors.isEmpty() == false){
System.out.println("compilation failed!");
for(String error : errors){
System.out.println(error);
}
System.exit(-1);
}
}
private String compileNativeCpuDev() {
try {
String code = "";
if ("Mac OS X".equals(System.getProperty("os.name"))){
code = m_Blocks.get(0).getCodeUnix();
} else if(File.separator.equals("/")){
code = m_Blocks.get(0).getCodeUnix();
} else {
code = m_Blocks.get(0).getCodeWindows();
}
File nemu_file = new File(RootbeerPaths.v().getRootbeerHome()+"nemu");
if(nemu_file.exists() == false){
nemu_file.mkdirs();
}
String nemu = nemu_file.getAbsolutePath()+File.separator;
extractFromNative("NativeCpuDevice.c", nemu);
extractFromNative("org_trifort_rootbeer_runtime_nativecpu_NativeCpuDevice.h", nemu);
PrintWriter writer = new PrintWriter(nemu+"generated.c");
writer.println(code);
writer.flush();
writer.close();
if ("Mac OS X".equals(System.getProperty("os.name"))){
return compileMac(nemu_file);
} else if(File.separator.equals("/")){
return compileLinux(nemu_file);
} else {
return compileWindows(nemu_file);
}
} catch(Exception ex){
ex.printStackTrace();
System.exit(0);
return null;
}
}
public long getGlobalMemSize() {
throw new UnsupportedOperationException("Not supported yet.");
}
public long getNumBlocks() {
return 1024*1024*1024;
}
}