├── include ├── CMakeLists.txt └── profile_h │ ├── CMakeLists.txt │ ├── generic_func.h │ ├── color_macros.h │ ├── DynamicDatapath.h │ ├── power_delay.h │ ├── TraceFunctions.h │ ├── xilinx_node_latency.h │ ├── AssignBasicBlockIDPass.h │ ├── Registers.h │ ├── QueryBasicBlockIDPass.h │ ├── LoopNumberPass.h │ ├── GetInstDistributionPass.h │ ├── file_func.h │ ├── lin-profile.h │ ├── AssignLoadStoreIDPass.h │ ├── QueryLoadStoreIDPass.h │ ├── Passes.h │ ├── ExtractLoopInfoPass.h │ ├── opcode_func.h │ ├── SlotTracker.h │ ├── btree_set.h │ ├── InstrumentForDDDGPass.h │ ├── DDDG.h │ ├── GetLoopBoundPass.h │ ├── auxiliary.h │ ├── btree_map.h │ ├── AnalysisProfilingPass.h │ ├── TraceDataStructure.h │ └── fpga_resources.h ├── testsuite ├── Ecobench │ ├── syrk │ │ ├── syrk_array_info │ │ ├── main.c │ │ ├── abstract_kernel.c │ │ ├── abstract_kernel.h │ │ ├── smallinput.data │ │ ├── syrk.h │ │ ├── syrk_configuration │ │ ├── directives.tcl │ │ ├── common.h │ │ ├── syrk.c │ │ ├── README.txt │ │ ├── script.tcl │ │ └── CMakeLists.txt │ ├── convolution2d │ │ ├── convolution2d_array_info │ │ ├── main.c │ │ ├── smallinput.data │ │ ├── abstract_kernel.c │ │ ├── abstract_kernel.h │ │ ├── README.txt │ │ ├── convolution2d.h │ │ ├── convolution2d_configuration │ │ ├── common.h │ │ ├── directives.tcl │ │ ├── script.tcl │ │ ├── CMakeLists.txt │ │ └── convolution2d.c │ ├── convolution3d │ │ ├── convolution3d_array_info │ │ ├── main.c │ │ ├── smallinput.data │ │ ├── abstract_kernel.c │ │ ├── abstract_kernel.h │ │ ├── README.txt │ │ ├── convolution3d.h │ │ ├── common.h │ │ ├── convolution3d_configuration │ │ ├── directives.tcl │ │ ├── script.tcl │ │ ├── CMakeLists.txt │ │ └── convolution3d.c │ ├── gemm │ │ ├── gemm_array_info │ │ ├── main.c │ │ ├── abstract_kernel.c │ │ ├── abstract_kernel.h │ │ ├── smallinput.data │ │ ├── README.txt │ │ ├── gemm.h │ │ ├── gemm_configuration │ │ ├── directives.tcl │ │ ├── gemm.c │ │ ├── common.h │ │ ├── script.tcl │ │ └── CMakeLists.txt │ ├── syr2k │ │ ├── syr2k_array_info │ │ ├── main.c │ │ ├── smallinput.data │ │ ├── abstract_kernel.c │ │ ├── abstract_kernel.h │ │ ├── README.txt │ │ ├── syr2k.h │ │ ├── directives.tcl │ │ ├── syr2k_configuration │ │ ├── common.h │ │ ├── syr2k.c │ │ ├── script.tcl │ │ └── CMakeLists.txt │ ├── atax │ │ ├── atax_array_info │ │ ├── main.c │ │ ├── smallinput.data │ │ ├── README.txt │ │ ├── atax.h │ │ ├── atax_configuration │ │ ├── directives.tcl │ │ ├── common.h │ │ ├── atax.c │ │ ├── script.tcl │ │ ├── CMakeLists.txt │ │ ├── abstract_kernel.h │ │ └── abstract_kernel.c │ ├── mm │ │ ├── main.c │ │ ├── smallinput.data │ │ ├── abstract_kernel.c │ │ ├── abstract_kernel.h │ │ ├── mm.h │ │ ├── common.h │ │ └── mm.c │ ├── bicg │ │ ├── main.c │ │ ├── bicg_array_info │ │ ├── abstract_kernel.c │ │ ├── abstract_kernel.h │ │ ├── smallinput.data │ │ ├── README.txt │ │ ├── bicg_configuration │ │ ├── bicg.h │ │ ├── directives.tcl │ │ ├── bicg.c │ │ ├── common.h │ │ ├── script.tcl │ │ └── CMakeLists.txt │ ├── main │ │ └── main.c │ ├── mvt │ │ ├── main.c │ │ ├── mvt_array_info │ │ ├── abstract_kernel.h │ │ ├── smallinput.data │ │ ├── README.txt │ │ ├── mvt.h │ │ ├── directives.tcl │ │ ├── mvt_configuration │ │ ├── common.h │ │ ├── mvt.c │ │ ├── script.tcl │ │ ├── CMakeLists.txt │ │ └── abstract_kernel.c │ ├── gesummv │ │ ├── main.c │ │ ├── gesummv_array_info │ │ ├── smallinput.data │ │ ├── abstract_kernel.c │ │ ├── abstract_kernel.h │ │ ├── README.txt │ │ ├── gesummv_configuration │ │ ├── gesummv.h │ │ ├── directives.tcl │ │ ├── common.h │ │ ├── gesummv.c │ │ ├── script.tcl │ │ └── CMakeLists.txt │ ├── CMakeLists.txt │ └── run_hls.py ├── cmake │ └── FindLinProfiler.cmake └── CMakeLists.txt ├── lib ├── LLVMBuild.txt ├── CMakeLists.txt ├── Build_DDDG │ ├── CMakeLists.txt │ ├── Registers.cpp │ ├── LLVMBuild.txt │ ├── generic_func.cpp │ ├── DynamicDatapath.cpp │ ├── TraceFunctions.cpp │ ├── opcode_func.cpp │ └── file_func.cpp └── Profile │ ├── CMakeLists.txt │ ├── LLVMBuild.txt │ ├── QueryBasicBlockID.cpp │ ├── LoopNumberPass.cpp │ ├── AssignBasicBlockID.cpp │ ├── GetInstDistributionPass.cpp │ └── QueryLoadStoreID.cpp ├── LLVMBuild.txt ├── cmake ├── FindBOOST.cmake └── FindZLIB.cmake ├── CMakeLists.txt └── README.md /include/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #add_subdirectory(Giri) 2 | add_subdirectory(profile_h) -------------------------------------------------------------------------------- /testsuite/Ecobench/syrk/syrk_array_info: -------------------------------------------------------------------------------- 1 | array,A,65536,4 2 | array,C,65536,4 -------------------------------------------------------------------------------- /lib/LLVMBuild.txt: -------------------------------------------------------------------------------- 1 | [common] 2 | subdirectories = Profile 3 | subdirectories = Build_DDDG 4 | -------------------------------------------------------------------------------- /testsuite/Ecobench/convolution2d/convolution2d_array_info: -------------------------------------------------------------------------------- 1 | array,A,65536,4 2 | array,B,65536,4 -------------------------------------------------------------------------------- /testsuite/Ecobench/convolution3d/convolution3d_array_info: -------------------------------------------------------------------------------- 1 | array,A,131072,4 2 | array,B,131072,4 -------------------------------------------------------------------------------- /testsuite/Ecobench/gemm/gemm_array_info: -------------------------------------------------------------------------------- 1 | array,A,65536,4 2 | array,B,65536,4 3 | array,C,65536,4 -------------------------------------------------------------------------------- /testsuite/Ecobench/syr2k/syr2k_array_info: -------------------------------------------------------------------------------- 1 | array,A,65536,4 2 | array,B,65536,4 3 | array,C,65536,4 -------------------------------------------------------------------------------- /testsuite/Ecobench/atax/atax_array_info: -------------------------------------------------------------------------------- 1 | array,A,65536,4 2 | array,x,512,4 3 | array,y,512,4 4 | array,tmp,512,4 -------------------------------------------------------------------------------- /testsuite/Ecobench/mm/main.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhguanw/lin-analyzer/HEAD/testsuite/Ecobench/mm/main.c -------------------------------------------------------------------------------- /testsuite/Ecobench/atax/main.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhguanw/lin-analyzer/HEAD/testsuite/Ecobench/atax/main.c -------------------------------------------------------------------------------- /testsuite/Ecobench/bicg/main.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhguanw/lin-analyzer/HEAD/testsuite/Ecobench/bicg/main.c -------------------------------------------------------------------------------- /testsuite/Ecobench/gemm/main.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhguanw/lin-analyzer/HEAD/testsuite/Ecobench/gemm/main.c -------------------------------------------------------------------------------- /testsuite/Ecobench/main/main.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhguanw/lin-analyzer/HEAD/testsuite/Ecobench/main/main.c -------------------------------------------------------------------------------- /testsuite/Ecobench/mvt/main.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhguanw/lin-analyzer/HEAD/testsuite/Ecobench/mvt/main.c -------------------------------------------------------------------------------- /testsuite/Ecobench/syr2k/main.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhguanw/lin-analyzer/HEAD/testsuite/Ecobench/syr2k/main.c -------------------------------------------------------------------------------- /testsuite/Ecobench/syrk/main.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhguanw/lin-analyzer/HEAD/testsuite/Ecobench/syrk/main.c -------------------------------------------------------------------------------- /testsuite/Ecobench/gesummv/main.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhguanw/lin-analyzer/HEAD/testsuite/Ecobench/gesummv/main.c -------------------------------------------------------------------------------- /testsuite/Ecobench/bicg/bicg_array_info: -------------------------------------------------------------------------------- 1 | array,A,262144,4 2 | array,r,1024,4 3 | array,s,1024,4 4 | array,p,1024,4 5 | array,q,1024,4 -------------------------------------------------------------------------------- /testsuite/Ecobench/mm/smallinput.data: -------------------------------------------------------------------------------- 1 | This file does not contain input data. The input data is self-contained inside abstract_kernel.c -------------------------------------------------------------------------------- /testsuite/Ecobench/mvt/mvt_array_info: -------------------------------------------------------------------------------- 1 | array,a,262144,4 2 | array,x1,1024,4 3 | array,x2,1024,4 4 | array,y1,1024,4 5 | array,y2,1024,4 -------------------------------------------------------------------------------- /testsuite/Ecobench/atax/smallinput.data: -------------------------------------------------------------------------------- 1 | This file does not contain input data. The input data is self-contained inside abstract_kernel.c -------------------------------------------------------------------------------- /testsuite/Ecobench/bicg/abstract_kernel.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhguanw/lin-analyzer/HEAD/testsuite/Ecobench/bicg/abstract_kernel.c -------------------------------------------------------------------------------- /testsuite/Ecobench/bicg/abstract_kernel.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhguanw/lin-analyzer/HEAD/testsuite/Ecobench/bicg/abstract_kernel.h -------------------------------------------------------------------------------- /testsuite/Ecobench/bicg/smallinput.data: -------------------------------------------------------------------------------- 1 | This file does not contain input data. The input data is self-contained inside abstract_kernel.c -------------------------------------------------------------------------------- /testsuite/Ecobench/convolution2d/main.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhguanw/lin-analyzer/HEAD/testsuite/Ecobench/convolution2d/main.c -------------------------------------------------------------------------------- /testsuite/Ecobench/convolution3d/main.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhguanw/lin-analyzer/HEAD/testsuite/Ecobench/convolution3d/main.c -------------------------------------------------------------------------------- /testsuite/Ecobench/gemm/abstract_kernel.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhguanw/lin-analyzer/HEAD/testsuite/Ecobench/gemm/abstract_kernel.c -------------------------------------------------------------------------------- /testsuite/Ecobench/gemm/abstract_kernel.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhguanw/lin-analyzer/HEAD/testsuite/Ecobench/gemm/abstract_kernel.h -------------------------------------------------------------------------------- /testsuite/Ecobench/gemm/smallinput.data: -------------------------------------------------------------------------------- 1 | This file does not contain input data. The input data is self-contained inside abstract_kernel.c -------------------------------------------------------------------------------- /testsuite/Ecobench/gesummv/gesummv_array_info: -------------------------------------------------------------------------------- 1 | array,A,65536,4 2 | array,B,65536,4 3 | array,x,512,4 4 | array,y,512,4 5 | array,tmp,512,4 -------------------------------------------------------------------------------- /testsuite/Ecobench/gesummv/smallinput.data: -------------------------------------------------------------------------------- 1 | This file does not contain input data. The input data is self-contained inside abstract_kernel.c -------------------------------------------------------------------------------- /testsuite/Ecobench/mm/abstract_kernel.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhguanw/lin-analyzer/HEAD/testsuite/Ecobench/mm/abstract_kernel.c -------------------------------------------------------------------------------- /testsuite/Ecobench/mm/abstract_kernel.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhguanw/lin-analyzer/HEAD/testsuite/Ecobench/mm/abstract_kernel.h -------------------------------------------------------------------------------- /testsuite/Ecobench/mvt/abstract_kernel.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhguanw/lin-analyzer/HEAD/testsuite/Ecobench/mvt/abstract_kernel.h -------------------------------------------------------------------------------- /testsuite/Ecobench/mvt/smallinput.data: -------------------------------------------------------------------------------- 1 | This file does not contain input data. The input data is self-contained inside abstract_kernel.c -------------------------------------------------------------------------------- /testsuite/Ecobench/syr2k/smallinput.data: -------------------------------------------------------------------------------- 1 | This file does not contain input data. The input data is self-contained inside abstract_kernel.c -------------------------------------------------------------------------------- /testsuite/Ecobench/syrk/abstract_kernel.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhguanw/lin-analyzer/HEAD/testsuite/Ecobench/syrk/abstract_kernel.c -------------------------------------------------------------------------------- /testsuite/Ecobench/syrk/abstract_kernel.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhguanw/lin-analyzer/HEAD/testsuite/Ecobench/syrk/abstract_kernel.h -------------------------------------------------------------------------------- /testsuite/Ecobench/syrk/smallinput.data: -------------------------------------------------------------------------------- 1 | This file does not contain input data. The input data is self-contained inside abstract_kernel.c -------------------------------------------------------------------------------- /testsuite/Ecobench/syr2k/abstract_kernel.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhguanw/lin-analyzer/HEAD/testsuite/Ecobench/syr2k/abstract_kernel.c -------------------------------------------------------------------------------- /testsuite/Ecobench/syr2k/abstract_kernel.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhguanw/lin-analyzer/HEAD/testsuite/Ecobench/syr2k/abstract_kernel.h -------------------------------------------------------------------------------- /testsuite/Ecobench/convolution2d/smallinput.data: -------------------------------------------------------------------------------- 1 | This file does not contain input data. The input data is self-contained inside abstract_kernel.c -------------------------------------------------------------------------------- /testsuite/Ecobench/convolution3d/smallinput.data: -------------------------------------------------------------------------------- 1 | This file does not contain input data. The input data is self-contained inside abstract_kernel.c -------------------------------------------------------------------------------- /testsuite/Ecobench/gesummv/abstract_kernel.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhguanw/lin-analyzer/HEAD/testsuite/Ecobench/gesummv/abstract_kernel.c -------------------------------------------------------------------------------- /testsuite/Ecobench/gesummv/abstract_kernel.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhguanw/lin-analyzer/HEAD/testsuite/Ecobench/gesummv/abstract_kernel.h -------------------------------------------------------------------------------- /testsuite/Ecobench/atax/README.txt: -------------------------------------------------------------------------------- 1 | The input data of 2D Convolution benchmark is self-contained. For the input file, smallinput.data, we can just ignore it. -------------------------------------------------------------------------------- /testsuite/Ecobench/bicg/README.txt: -------------------------------------------------------------------------------- 1 | The input data of 2D Convolution benchmark is self-contained. For the input file, smallinput.data, we can just ignore it. -------------------------------------------------------------------------------- /testsuite/Ecobench/convolution2d/abstract_kernel.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhguanw/lin-analyzer/HEAD/testsuite/Ecobench/convolution2d/abstract_kernel.c -------------------------------------------------------------------------------- /testsuite/Ecobench/convolution2d/abstract_kernel.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhguanw/lin-analyzer/HEAD/testsuite/Ecobench/convolution2d/abstract_kernel.h -------------------------------------------------------------------------------- /testsuite/Ecobench/convolution3d/abstract_kernel.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhguanw/lin-analyzer/HEAD/testsuite/Ecobench/convolution3d/abstract_kernel.c -------------------------------------------------------------------------------- /testsuite/Ecobench/convolution3d/abstract_kernel.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhguanw/lin-analyzer/HEAD/testsuite/Ecobench/convolution3d/abstract_kernel.h -------------------------------------------------------------------------------- /testsuite/Ecobench/gemm/README.txt: -------------------------------------------------------------------------------- 1 | The input data of 2D Convolution benchmark is self-contained. For the input file, smallinput.data, we can just ignore it. -------------------------------------------------------------------------------- /testsuite/Ecobench/gesummv/README.txt: -------------------------------------------------------------------------------- 1 | The input data of 2D Convolution benchmark is self-contained. For the input file, smallinput.data, we can just ignore it. -------------------------------------------------------------------------------- /testsuite/Ecobench/mvt/README.txt: -------------------------------------------------------------------------------- 1 | The input data of 2D Convolution benchmark is self-contained. For the input file, smallinput.data, we can just ignore it. -------------------------------------------------------------------------------- /testsuite/Ecobench/syr2k/README.txt: -------------------------------------------------------------------------------- 1 | The input data of 2D Convolution benchmark is self-contained. For the input file, smallinput.data, we can just ignore it. -------------------------------------------------------------------------------- /testsuite/Ecobench/convolution2d/README.txt: -------------------------------------------------------------------------------- 1 | The input data of 2D Convolution benchmark is self-contained. For the input file, smallinput.data, we can just ignore it. -------------------------------------------------------------------------------- /testsuite/Ecobench/convolution3d/README.txt: -------------------------------------------------------------------------------- 1 | The input data of 2D Convolution benchmark is self-contained. For the input file, smallinput.data, we can just ignore it. -------------------------------------------------------------------------------- /LLVMBuild.txt: -------------------------------------------------------------------------------- 1 | [common] 2 | subdirectories = lib tools 3 | 4 | [component_0] 5 | type = Tool 6 | name = lin-analyzer 7 | parent = Tools 8 | required_libraries = Support LLVMLinProfiler BuildDDDGlib 9 | -------------------------------------------------------------------------------- /testsuite/Ecobench/syrk/syrk.h: -------------------------------------------------------------------------------- 1 | #ifndef CONVOLUTION2D_H 2 | #define CONVOLUTION2D_H 3 | 4 | #include "common.h" 5 | 6 | void syrk(DATA_TYPE A[SIZE], DATA_TYPE C[SIZE]); 7 | 8 | #endif // End of CONVOLUTION2D_H 9 | -------------------------------------------------------------------------------- /lib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #add_subdirectory(Giri) 2 | if (NOT TARGET LLVMLinProfiler) 3 | add_subdirectory(Profile) 4 | endif (NOT TARGET LLVMLinProfiler) 5 | 6 | #add_subdirectory(Profile) 7 | add_subdirectory(Build_DDDG) 8 | -------------------------------------------------------------------------------- /testsuite/Ecobench/mm/mm.h: -------------------------------------------------------------------------------- 1 | #ifndef CONVOLUTION2D_H 2 | #define CONVOLUTION2D_H 3 | 4 | #include "common.h" 5 | 6 | void mm(DATA_TYPE A[SIZE_A], DATA_TYPE B[SIZE_B], DATA_TYPE C[SIZE_C]); 7 | 8 | #endif // End of CONVOLUTION2D_H 9 | -------------------------------------------------------------------------------- /testsuite/Ecobench/syr2k/syr2k.h: -------------------------------------------------------------------------------- 1 | #ifndef CONVOLUTION2D_H 2 | #define CONVOLUTION2D_H 3 | 4 | #include "common.h" 5 | 6 | void syr2k(DATA_TYPE A[SIZE], DATA_TYPE B[SIZE], DATA_TYPE C[SIZE]); 7 | 8 | #endif // End of CONVOLUTION2D_H 9 | -------------------------------------------------------------------------------- /testsuite/Ecobench/convolution2d/convolution2d.h: -------------------------------------------------------------------------------- 1 | #ifndef CONVOLUTION2D_H 2 | #define CONVOLUTION2D_H 3 | 4 | #include "common.h" 5 | 6 | void convolution2d(DATA_TYPE A[SIZE], DATA_TYPE B[SIZE]); 7 | 8 | #endif // End of CONVOLUTION2D_H 9 | -------------------------------------------------------------------------------- /testsuite/Ecobench/convolution2d/convolution2d_configuration: -------------------------------------------------------------------------------- 1 | array,A,65536,4 2 | array,B,65536,4 3 | unrolling,convolution2d,0,1,17,1 4 | unrolling,convolution2d,0,2,18,2 5 | #partition,cyclic,A,65536,4,2 6 | #pipeline,convolution2d,0,2 7 | -------------------------------------------------------------------------------- /testsuite/Ecobench/convolution3d/convolution3d.h: -------------------------------------------------------------------------------- 1 | #ifndef CONVOLUTION3D_H 2 | #define CONVOLUTION3D_H 3 | 4 | #include "common.h" 5 | 6 | void convolution3d(DATA_TYPE A[SIZE], DATA_TYPE B[SIZE]); 7 | 8 | #endif // End of CONVOLUTION2D_H 9 | -------------------------------------------------------------------------------- /testsuite/Ecobench/gemm/gemm.h: -------------------------------------------------------------------------------- 1 | #ifndef CONVOLUTION2D_H 2 | #define CONVOLUTION2D_H 3 | 4 | #include "common.h" 5 | 6 | void gemm(DATA_TYPE A[SIZE_A], DATA_TYPE B[SIZE_B], DATA_TYPE C[SIZE_C]); 7 | 8 | #endif // End of CONVOLUTION2D_H 9 | -------------------------------------------------------------------------------- /testsuite/Ecobench/gemm/gemm_configuration: -------------------------------------------------------------------------------- 1 | array,A,65536,4 2 | array,B,65536,4 3 | array,C,65536,4 4 | unrolling,gemm,0,1,7,1 5 | unrolling,gemm,0,2,8,1 6 | unrolling,gemm,0,3,11,128 7 | #partition,cyclic,A,65536,4,2 8 | #pipeline,gemm,0,2 9 | -------------------------------------------------------------------------------- /testsuite/Ecobench/bicg/bicg_configuration: -------------------------------------------------------------------------------- 1 | array,A,262144,4 2 | array,r,1024,4 3 | array,s,1024,4 4 | array,p,1024,4 5 | array,q,1024,4 6 | unrolling,bicg,0,1,11,1 7 | unrolling,bicg,0,2,13,4 8 | #partition,cyclic,A,262144,4,2 9 | #pipeline,bicg,0,1 10 | -------------------------------------------------------------------------------- /testsuite/Ecobench/convolution2d/common.h: -------------------------------------------------------------------------------- 1 | #ifndef COMMON_H 2 | #define COMMON_H 3 | 4 | #define FLOAT_TYPE 5 | typedef float DATA_TYPE; 6 | 7 | /* Problem size */ 8 | #define NI 128 9 | #define NJ 128 10 | #define SIZE NI*NJ 11 | 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /testsuite/Ecobench/atax/atax.h: -------------------------------------------------------------------------------- 1 | #ifndef CONVOLUTION2D_H 2 | #define CONVOLUTION2D_H 3 | 4 | #include "common.h" 5 | 6 | void atax(DATA_TYPE A[SIZE_A], DATA_TYPE x[SIZE_X],/* DATA_TYPE y[SIZE_Y],*/ DATA_TYPE tmp[SIZE_TMP]); 7 | 8 | #endif // End of CONVOLUTION2D_H 9 | -------------------------------------------------------------------------------- /testsuite/Ecobench/convolution3d/common.h: -------------------------------------------------------------------------------- 1 | #ifndef COMMON_H 2 | #define COMMON_H 3 | 4 | #define FLOAT_TYPE 5 | typedef float DATA_TYPE; 6 | 7 | /* Problem size */ 8 | #define NI 32 9 | #define NJ 32 10 | #define NK 32 11 | #define SIZE NI*NJ*NK 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /testsuite/Ecobench/gesummv/gesummv_configuration: -------------------------------------------------------------------------------- 1 | array,A,65536,4 2 | array,B,65536,4 3 | array,x,512,4 4 | array,y,512,4 5 | array,tmp,512,4 6 | unrolling,gesummv,0,1,7,1 7 | unrolling,gesummv,0,2,10,4 8 | #partition,cyclic,A,65536,4,2 9 | #pipeline,gesummv,0,2 10 | -------------------------------------------------------------------------------- /testsuite/Ecobench/bicg/bicg.h: -------------------------------------------------------------------------------- 1 | #ifndef CONVOLUTION2D_H 2 | #define CONVOLUTION2D_H 3 | 4 | #include "common.h" 5 | 6 | void bicg(DATA_TYPE A[SIZE_A], DATA_TYPE r[SIZE_R], DATA_TYPE s[SIZE_S], DATA_TYPE p[SIZE_P], DATA_TYPE q[SIZE_Q]); 7 | 8 | #endif // End of CONVOLUTION2D_H 9 | -------------------------------------------------------------------------------- /testsuite/Ecobench/convolution3d/convolution3d_configuration: -------------------------------------------------------------------------------- 1 | array,A,131072,4 2 | array,B,131072,4 3 | unrolling,convolution3d,0,1,16,1 4 | unrolling,convolution3d,0,2,17,1 5 | unrolling,convolution3d,0,3,18,2 6 | #partition,cyclic,A,131072,4,2 7 | #pipeline,convolution3d,0,2 8 | -------------------------------------------------------------------------------- /testsuite/Ecobench/mvt/mvt.h: -------------------------------------------------------------------------------- 1 | #ifndef CONVOLUTION2D_H 2 | #define CONVOLUTION2D_H 3 | 4 | #include "common.h" 5 | 6 | void mvt(DATA_TYPE a[SIZE_A], DATA_TYPE x1[SIZE], /*DATA_TYPE x2[SIZE],*/ DATA_TYPE y1[SIZE]/*, DATA_TYPE y2[SIZE]*/); 7 | 8 | #endif // End of CONVOLUTION2D_H 9 | -------------------------------------------------------------------------------- /testsuite/Ecobench/syrk/syrk_configuration: -------------------------------------------------------------------------------- 1 | array,A,65536,4 2 | array,C,65536,4 3 | unrolling,syrk,0,1,8,1 4 | unrolling,syrk,0,2,9,4 5 | unrolling,syrk,1,1,14,1 6 | unrolling,syrk,1,2,15,1 7 | unrolling,syrk,1,3,16,4 8 | #partition,cyclic,A,65536,4,2 9 | #pipeline,syrk,1,2 10 | -------------------------------------------------------------------------------- /testsuite/Ecobench/atax/atax_configuration: -------------------------------------------------------------------------------- 1 | array,A,65536,4 2 | array,x,512,4 3 | array,y,512,4 4 | array,tmp,512,4 5 | unrolling,atax,0,1,7,1 6 | unrolling,atax,0,2,9,4 7 | unrolling,atax,1,1,15,1 8 | unrolling,atax,1,2,16,8 9 | #partition,cyclic,A,65536,4,2 10 | #pipeline,atax,0,2 11 | -------------------------------------------------------------------------------- /testsuite/Ecobench/gesummv/gesummv.h: -------------------------------------------------------------------------------- 1 | #ifndef CONVOLUTION2D_H 2 | #define CONVOLUTION2D_H 3 | 4 | #include "common.h" 5 | 6 | void gesummv(DATA_TYPE A[SIZE_AB], DATA_TYPE B[SIZE_AB], DATA_TYPE x[SIZE_XY], DATA_TYPE y[SIZE_XY], DATA_TYPE tmp[SIZE_XY]); 7 | 8 | #endif // End of CONVOLUTION2D_H 9 | -------------------------------------------------------------------------------- /testsuite/Ecobench/atax/directives.tcl: -------------------------------------------------------------------------------- 1 | ############################################################ 2 | ## This file is generated automatically by Vivado HLS. 3 | ## Please DO NOT edit it. 4 | ## Copyright (C) 2013 Xilinx Inc. All rights reserved. 5 | ############################################################ 6 | -------------------------------------------------------------------------------- /testsuite/Ecobench/bicg/directives.tcl: -------------------------------------------------------------------------------- 1 | ############################################################ 2 | ## This file is generated automatically by Vivado HLS. 3 | ## Please DO NOT edit it. 4 | ## Copyright (C) 2013 Xilinx Inc. All rights reserved. 5 | ############################################################ 6 | -------------------------------------------------------------------------------- /testsuite/Ecobench/gemm/directives.tcl: -------------------------------------------------------------------------------- 1 | ############################################################ 2 | ## This file is generated automatically by Vivado HLS. 3 | ## Please DO NOT edit it. 4 | ## Copyright (C) 2013 Xilinx Inc. All rights reserved. 5 | ############################################################ 6 | -------------------------------------------------------------------------------- /testsuite/Ecobench/mvt/directives.tcl: -------------------------------------------------------------------------------- 1 | ############################################################ 2 | ## This file is generated automatically by Vivado HLS. 3 | ## Please DO NOT edit it. 4 | ## Copyright (C) 2013 Xilinx Inc. All rights reserved. 5 | ############################################################ 6 | -------------------------------------------------------------------------------- /testsuite/Ecobench/syr2k/directives.tcl: -------------------------------------------------------------------------------- 1 | ############################################################ 2 | ## This file is generated automatically by Vivado HLS. 3 | ## Please DO NOT edit it. 4 | ## Copyright (C) 2013 Xilinx Inc. All rights reserved. 5 | ############################################################ 6 | -------------------------------------------------------------------------------- /testsuite/Ecobench/syr2k/syr2k_configuration: -------------------------------------------------------------------------------- 1 | array,A,65536,4 2 | array,B,65536,4 3 | array,C,65536,4 4 | unrolling,syr2k,0,1,7,1 5 | unrolling,syr2k,0,2,8,2 6 | unrolling,syr2k,1,1,13,1 7 | unrolling,syr2k,1,2,14,1 8 | unrolling,syr2k,1,3,15,4 9 | #partition,cyclic,A,65536,4,2 10 | #pipeline,syr2k,1,2 11 | -------------------------------------------------------------------------------- /testsuite/Ecobench/syrk/directives.tcl: -------------------------------------------------------------------------------- 1 | ############################################################ 2 | ## This file is generated automatically by Vivado HLS. 3 | ## Please DO NOT edit it. 4 | ## Copyright (C) 2013 Xilinx Inc. All rights reserved. 5 | ############################################################ 6 | -------------------------------------------------------------------------------- /testsuite/Ecobench/gesummv/directives.tcl: -------------------------------------------------------------------------------- 1 | ############################################################ 2 | ## This file is generated automatically by Vivado HLS. 3 | ## Please DO NOT edit it. 4 | ## Copyright (C) 2013 Xilinx Inc. All rights reserved. 5 | ############################################################ 6 | -------------------------------------------------------------------------------- /testsuite/Ecobench/convolution2d/directives.tcl: -------------------------------------------------------------------------------- 1 | ############################################################ 2 | ## This file is generated automatically by Vivado HLS. 3 | ## Please DO NOT edit it. 4 | ## Copyright (C) 2013 Xilinx Inc. All rights reserved. 5 | ############################################################ 6 | -------------------------------------------------------------------------------- /testsuite/Ecobench/convolution3d/directives.tcl: -------------------------------------------------------------------------------- 1 | ############################################################ 2 | ## This file is generated automatically by Vivado HLS. 3 | ## Please DO NOT edit it. 4 | ## Copyright (C) 2013 Xilinx Inc. All rights reserved. 5 | ############################################################ 6 | -------------------------------------------------------------------------------- /testsuite/Ecobench/mm/common.h: -------------------------------------------------------------------------------- 1 | #ifndef COMMON_H 2 | #define COMMON_H 3 | 4 | typedef float DATA_TYPE; 5 | 6 | /* Problem size */ 7 | # define NI 128 8 | # define NJ 128 9 | # define NK 128 10 | # define NL 128 11 | 12 | #define SIZE_A NI*NK 13 | #define SIZE_B NK*NJ 14 | #define SIZE_C NI*NJ 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /testsuite/Ecobench/mvt/mvt_configuration: -------------------------------------------------------------------------------- 1 | array,a,262144,4 2 | array,x1,1024,4 3 | array,x2,1024,4 4 | array,y1,1024,4 5 | array,y2,1024,4 6 | unrolling,mvt,0,1,7,1 7 | unrolling,mvt,0,2,8,2 8 | unrolling,mvt,1,1,13,1 9 | unrolling,mvt,1,2,14,1 10 | #partition,cyclic,a,262144,4,2 11 | #pipeline,mvt,0,2 12 | #pipeline,mvt,1,1 13 | -------------------------------------------------------------------------------- /testsuite/Ecobench/syr2k/common.h: -------------------------------------------------------------------------------- 1 | #ifndef COMMON_H 2 | #define COMMON_H 3 | 4 | typedef float DATA_TYPE; 5 | 6 | /* Problem size */ 7 | #define N 128 8 | #define M 128 9 | #define SIZE N*M 10 | 11 | /* Declared constant values for ALPHA and BETA (same as values in PolyBench 2.0) */ 12 | #define ALPHA 1 13 | #define BETA 1 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /testsuite/Ecobench/syrk/common.h: -------------------------------------------------------------------------------- 1 | #ifndef COMMON_H 2 | #define COMMON_H 3 | 4 | typedef float DATA_TYPE; 5 | 6 | /* Problem size */ 7 | #define N 128 8 | #define M 128 9 | #define SIZE N*M 10 | 11 | /* Declared constant values for ALPHA and BETA (same as values in PolyBench 2.0) */ 12 | #define ALPHA 123 13 | #define BETA 14512 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /testsuite/Ecobench/gesummv/common.h: -------------------------------------------------------------------------------- 1 | #ifndef COMMON_H 2 | #define COMMON_H 3 | 4 | typedef float DATA_TYPE; 5 | 6 | /* Problem size */ 7 | #define N 128 8 | 9 | #define SIZE_AB N*N 10 | #define SIZE_XY N 11 | 12 | /* Declared constant values for ALPHA and BETA (same as values in PolyBench 2.0) */ 13 | #define ALPHA 1 14 | #define BETA 1 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /testsuite/Ecobench/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(convolution2d) 2 | add_subdirectory(convolution3d) 3 | 4 | add_subdirectory(mm) 5 | add_subdirectory(mvt) 6 | 7 | add_subdirectory(atax) 8 | add_subdirectory(bicg) 9 | add_subdirectory(gemm) 10 | add_subdirectory(gesummv) 11 | 12 | add_subdirectory(syrk) 13 | add_subdirectory(syr2k) 14 | 15 | #add_subdirectory(main) 16 | -------------------------------------------------------------------------------- /include/profile_h/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if( MSVC_IDE OR XCODE) 2 | # Creates a dummy target containing all headers for the benefit of 3 | # Visual Studio users. 4 | file(GLOB_RECURSE headers *.h) 5 | add_library(lin-profile_headers_do_not_build EXCLUDE_FROM_ALL 6 | # We need at least one source file: 7 | ${LLVM_MAIN_SRC_DIR}/lib/Transforms/Hello/Hello.cpp 8 | ${headers}) 9 | endif() -------------------------------------------------------------------------------- /testsuite/Ecobench/gemm/gemm.c: -------------------------------------------------------------------------------- 1 | #include "gemm.h" 2 | 3 | void gemm(DATA_TYPE A[SIZE_A], DATA_TYPE B[SIZE_B], DATA_TYPE C[SIZE_C]) 4 | { 5 | int i,j,k; 6 | 7 | for (i = 0; i < NI; i++) { 8 | for (j = 0; j < NJ; j++) { 9 | C[i*NJ + j] *= BETA; 10 | 11 | for (k = 0; k < NK; ++k) { 12 | C[i*NJ + j] += ALPHA * A[i*NK + k] * B[k*NJ + j]; 13 | } 14 | } 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /testsuite/Ecobench/mm/mm.c: -------------------------------------------------------------------------------- 1 | #include "mm.h" 2 | 3 | void mm(DATA_TYPE A[SIZE_A], DATA_TYPE B[SIZE_B], DATA_TYPE C[SIZE_C]) { 4 | 5 | int i, j, k; 6 | 7 | for (i = 0; i < NI; i++) { 8 | for (j = 0; j < NJ; j++) { 9 | DATA_TYPE tmpSum1 = 0.0f; 10 | for (k = 0; k < NK; ++k) { 11 | tmpSum1 += A[i*NK + k] * B[k*NJ + j]; 12 | } 13 | C[i*NJ + j] = tmpSum1; 14 | } 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /testsuite/Ecobench/mvt/common.h: -------------------------------------------------------------------------------- 1 | #ifndef COMMON_H 2 | #define COMMON_H 3 | 4 | // In original Polybench, this DATA_TYPE is 'double' type 5 | typedef float DATA_TYPE; 6 | 7 | /* Problem size */ 8 | #define N 256 9 | 10 | #define SIZE_A N*N 11 | #define SIZE N 12 | 13 | /* Declared constant values for ALPHA and BETA (same as values in PolyBench 2.0) */ 14 | #define ALPHA 23 15 | #define BETA 15 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /include/profile_h/generic_func.h: -------------------------------------------------------------------------------- 1 | #ifndef GENERIC_FUNC_H 2 | #define GENERIC_FUNC_H 3 | #include 4 | using namespace std; 5 | std::vector make_vector(int size); 6 | int max_value(const vector array, int start, int end); 7 | 8 | int min_value(const vector array, int start, int end); 9 | unsigned next_power_of_two(unsigned int x); 10 | 11 | //extern std::vector staticInstIDvec; 12 | #endif 13 | -------------------------------------------------------------------------------- /testsuite/Ecobench/gemm/common.h: -------------------------------------------------------------------------------- 1 | #ifndef COMMON_H 2 | #define COMMON_H 3 | 4 | typedef float DATA_TYPE; 5 | 6 | /* Problem size */ 7 | #define NI 128 8 | #define NJ 128 9 | #define NK 128 10 | #define SIZE_A NI*NK 11 | #define SIZE_B NK*NJ 12 | #define SIZE_C NI*NJ 13 | 14 | /* Declared constant values for ALPHA and BETA (same as values in PolyBench 2.0) */ 15 | #define ALPHA 32412.0f 16 | #define BETA 2123.0f 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /lib/Build_DDDG/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories( ${ZLIB_INCLUDE_DIRS} ) 2 | 3 | add_llvm_library(BuildDDDGlib 4 | DynamicDatapath.cpp 5 | BaseDatapath.cpp 6 | DDDG.cpp 7 | SlotTracker.cpp 8 | TraceFunctions.cpp 9 | file_func.cpp 10 | Registers.cpp 11 | opcode_func.cpp 12 | generic_func.cpp 13 | fpga_resources.cpp 14 | 15 | LINK_LIBS 16 | ${ZLIB_LIBRARY} 17 | ) 18 | 19 | #target_link_libraries(BuildDDDGlib ${ZLIB_LIBRARY}) -------------------------------------------------------------------------------- /testsuite/Ecobench/bicg/bicg.c: -------------------------------------------------------------------------------- 1 | #include "bicg.h" 2 | 3 | void bicg(DATA_TYPE A[SIZE_A], DATA_TYPE r[SIZE_R], DATA_TYPE s[SIZE_S], DATA_TYPE p[SIZE_P], DATA_TYPE q[SIZE_Q]) { 4 | 5 | int i,j; 6 | 7 | for (i = 0; i < NY; i++) { 8 | s[i] = 0.0; 9 | } 10 | 11 | for (i = 0; i < NX; i++) { 12 | q[i] = 0.0; 13 | for (j = 0; j < NY; j++) { 14 | s[j] = s[j] + r[i] * A[i*NY + j]; 15 | q[i] = q[i] + A[i*NY + j] * p[j]; 16 | } 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /testsuite/Ecobench/gesummv/gesummv.c: -------------------------------------------------------------------------------- 1 | #include "gesummv.h" 2 | 3 | void gesummv(DATA_TYPE A[SIZE_AB], DATA_TYPE B[SIZE_AB], DATA_TYPE x[SIZE_XY], DATA_TYPE y[SIZE_XY], DATA_TYPE tmp[SIZE_XY]) 4 | { 5 | int i,j; 6 | 7 | for (i = 0; i < N; i++) { 8 | tmp[i] = 0; 9 | y[i] = 0; 10 | for (j = 0; j < N; j++) { 11 | tmp[i] = A[i*N + j] * x[j] + tmp[i]; 12 | y[i] = B[i*N + j] * x[j] + y[i]; 13 | } 14 | 15 | y[i] = ALPHA * tmp[i] + BETA * y[i]; 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /testsuite/Ecobench/mvt/mvt.c: -------------------------------------------------------------------------------- 1 | #include "mvt.h" 2 | 3 | void mvt(DATA_TYPE a[SIZE_A], DATA_TYPE x1[SIZE], /*DATA_TYPE x2[SIZE],*/ DATA_TYPE y1[SIZE]/*, DATA_TYPE y2[SIZE]*/) { 4 | 5 | int i, j, k, l; 6 | 7 | for (i=0; i 10, just use the default color. Also, it is easy 6 | // to extend the Color_enum. 7 | // We follow the color rule from the url: http://www.graphviz.org/doc/info/colors.html#brewer 8 | enum Color_enum { RED, GREEN, BLUE, CYAN, GOLD, HOTPINK, NAVY, ORANGE, OLIVEDRAB, MAGENTA}; 9 | #define NUM_COLOR_ENUM 10 10 | 11 | #endif -------------------------------------------------------------------------------- /testsuite/Ecobench/syr2k/syr2k.c: -------------------------------------------------------------------------------- 1 | #include "syr2k.h" 2 | 3 | void syr2k(DATA_TYPE A[SIZE], DATA_TYPE B[SIZE], DATA_TYPE C[SIZE]) 4 | { 5 | int i, j, k; 6 | 7 | // for (i = 0; i < N; i++) { 8 | // for (j = 0; j < N; j++) { 9 | // C[i*N + j] *= BETA; 10 | // } 11 | // } 12 | 13 | for (i = 0; i < N; i++) { 14 | for (j = 0; j < N; j++) { 15 | C[i*N + j] *= BETA; 16 | for (k = 0; k < M; k++) { 17 | C[i*N + j] += ALPHA * A[i*M + k] * B[j*M + k]; 18 | C[i*N + j] += ALPHA * B[i*M + k] * A[j*M + k]; 19 | } 20 | } 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /cmake/FindZLIB.cmake: -------------------------------------------------------------------------------- 1 | FIND_PATH(ZLIB_INCLUDE_DIRS zlib.h) 2 | 3 | FIND_LIBRARY(ZLIB_LIBRARY NAMES zlibstat) 4 | 5 | IF (ZLIB_INCLUDE_DIRS) 6 | SET(ZLIB_FOUND TRUE) 7 | ENDIF (ZLIB_INCLUDE_DIRS) 8 | 9 | 10 | IF (ZLIB_FOUND) 11 | IF (NOT ZLIB_FIND_QUIETLY) 12 | MESSAGE(STATUS "Found ZLIB: ${ZLIB_INCLUDE_DIRS}") 13 | ENDIF (NOT ZLIB_FIND_QUIETLY) 14 | ELSE (ZLIB_FOUND) 15 | IF (ZLIB_FIND_REQUIRED) 16 | MESSAGE(FATAL_ERROR "Could not find ZLIB") 17 | ENDIF (ZLIB_FIND_REQUIRED) 18 | ENDIF (ZLIB_FOUND) 19 | 20 | IF (NOT ZLIB_LIBRARY) 21 | MESSAGE(FATAL_ERROR "Cannot find ZLIB Library!") 22 | ENDIF (NOT ZLIB_LIBRARY) 23 | -------------------------------------------------------------------------------- /lib/Profile/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_llvm_library(LLVMLinProfiler 2 | InstrumentForDDDGPass.cpp 3 | #SlotTracker.cpp 4 | #TraceFunctions.cpp 5 | #BaseDatapath.cpp 6 | #DDDG.cpp 7 | #DynamicDatapath.cpp 8 | #file_func.cpp 9 | #opcode_func.cpp 10 | #generic_func.cpp 11 | GetInstDistributionPass.cpp 12 | LoopNumberPass.cpp 13 | AssignBasicBlockID.cpp 14 | AssignLoadStoreID.cpp 15 | QueryBasicBlockID.cpp 16 | QueryLoadStoreID.cpp 17 | ExtractLoopInfoPass.cpp 18 | GetLoopBoundPass.cpp 19 | CodeInstrumentPass.cpp 20 | TraceDataStructure.cpp 21 | AnalysisProfilingPass.cpp 22 | ) 23 | 24 | llvm_config(LLVMLinProfiler jit) 25 | 26 | #MESSAGE(STATUS "add llvm library LLVMLinProfiler") 27 | -------------------------------------------------------------------------------- /testsuite/Ecobench/syrk/README.txt: -------------------------------------------------------------------------------- 1 | Polybench Input Parameter: (Version 0 -> Version 1 -> Version 2 -> Version 3 -> Version 4... ) 2 | mm2: 128 -> 512 -> 256 -> 128 3 | mm3: 128 -> 512 -> 256 -> 128 4 | correlation: 128 -> 512 -> 256 -> 128 5 | covariance: 128 -> 512 -> 256 -> 128 6 | convolution2d: 256 -> 1024 -> 1024 -> 1024 7 | convolution3d: 64 -> 256 -> 128 -> 64 8 | gemm: 128 -> 256 -> 128 -> 128 9 | gesummv: 512 -> 1024 -> 1024 -> 1024 10 | atax: 512 -> 1024 -> 1024 -> 1024 11 | bicg: 512 -> 1024 -> 1024 -> 1024 12 | gramschmidt: 64 -> 128 -> 128 -> 128 13 | mvt: 512 -> 1024 -> 1024 -> 1024 14 | syrk: 128 -> 256 -> 128 -> 128 15 | syr2k: 128 -> 256 -> 128 -> 128 -------------------------------------------------------------------------------- /include/profile_h/DynamicDatapath.h: -------------------------------------------------------------------------------- 1 | #ifndef DYNAMIC_DATAPATH_H 2 | #define DYNAMIC_DATAPATH_H 3 | 4 | #include 5 | #include "profile_h/BaseDatapath.h" 6 | #include "profile_h/lin-profile.h" 7 | 8 | class DynamicDatapath : public BaseDatapath { 9 | public: 10 | DynamicDatapath(std::string kernel_name, std::string trace_file_name, std::string input_path, std::string lp_name, unsigned lp_level, unsigned lp_unroll_factor, bool enable_pipelining, unsigned IL_asap); 11 | ~DynamicDatapath(); 12 | 13 | unsigned getIL_asap_ii() const; 14 | private: 15 | std::string target_loop_name; 16 | unsigned target_loop_level; 17 | unsigned target_lp_level_unroll_factor; 18 | unsigned IL_asap_ii; 19 | }; 20 | 21 | #endif // End of DYNAMIC_DATAPATH_H -------------------------------------------------------------------------------- /include/profile_h/power_delay.h: -------------------------------------------------------------------------------- 1 | #ifndef __POWER_DELAY_H__ 2 | #define __POWER_DELAY_H__ 3 | 4 | 5 | #define CYCLE_TIME 1 6 | #define ADD_LATENCY 1 7 | #define MEMOP_LATENCY 1.43f 8 | #define MUL_LATENCY 5.84f 9 | 10 | #define RW_PORTS 1 11 | #define ADD_int_power 0.0151f 12 | #define ADD_switch_power 0.00615f 13 | #define ADD_leak_power 0.00000129f 14 | #define ADD_area 280 15 | #define MUL_int_power 0.72f 16 | #define MUL_switch_power 0.60f 17 | #define MUL_leak_power 0.025f 18 | #define MUL_area 4595 19 | #define REG_int_power 0.0018f 20 | #define REG_sw_power 0.00013f 21 | #define REG_leak_power 0.000055f 22 | #define REG_area 7.98f 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /lib/Build_DDDG/Registers.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "profile_h/Registers.h" 4 | 5 | Registers::~Registers() 6 | { 7 | for (auto it = regs.begin(); it != regs.end(); ++it) 8 | { 9 | delete it->second; 10 | } 11 | } 12 | 13 | void Registers::createRegister( 14 | std::string baseName, unsigned int num_bytes) 15 | { 16 | assert(regs.find(baseName) == regs.end()); 17 | unsigned int new_id = regs.size(); 18 | regs[baseName] = new Register(baseName, num_bytes, new_id); 19 | } 20 | 21 | void Registers::getRegisterNames(std::vector &names) 22 | { 23 | for (auto it = regs.begin(); it != regs.end(); it++) 24 | names.push_back(it->first); 25 | } 26 | 27 | bool Registers::has(std::string baseName) 28 | { 29 | return (regs.find(baseName) != regs.end()); 30 | } 31 | -------------------------------------------------------------------------------- /testsuite/Ecobench/atax/script.tcl: -------------------------------------------------------------------------------- 1 | ############################################################ 2 | ## This file is generated automatically by Vivado HLS. 3 | ## Please DO NOT edit it. 4 | ## Copyright (C) 2013 Xilinx Inc. All rights reserved. 5 | ############################################################ 6 | open_project atax 7 | set_top atax 8 | add_files atax.c 9 | add_files -tb abstract_kernel.c 10 | add_files -tb main.c 11 | add_files -tb smallinput.data 12 | open_solution "solution1" 13 | set_part {xc7z020clg484-1} 14 | create_clock -period 10 -name default 15 | source "./directives.tcl" 16 | csim_design 17 | csynth_design 18 | #cosim_design -trace_level none 19 | export_design -format ip_catalog -description "An IP generated by Vivado HLS" -vendor "xilinx.com" -library "hls" -version "1.0" 20 | exit 21 | -------------------------------------------------------------------------------- /testsuite/Ecobench/bicg/script.tcl: -------------------------------------------------------------------------------- 1 | ############################################################ 2 | ## This file is generated automatically by Vivado HLS. 3 | ## Please DO NOT edit it. 4 | ## Copyright (C) 2013 Xilinx Inc. All rights reserved. 5 | ############################################################ 6 | open_project bicg 7 | set_top bicg 8 | add_files bicg.c 9 | add_files -tb abstract_kernel.c 10 | add_files -tb main.c 11 | add_files -tb smallinput.data 12 | open_solution "solution1" 13 | set_part {xc7z020clg484-1} 14 | create_clock -period 10 -name default 15 | source "./directives.tcl" 16 | csim_design 17 | csynth_design 18 | #cosim_design -trace_level none 19 | export_design -format ip_catalog -description "An IP generated by Vivado HLS" -vendor "xilinx.com" -library "hls" -version "1.0" 20 | exit 21 | -------------------------------------------------------------------------------- /testsuite/Ecobench/mvt/script.tcl: -------------------------------------------------------------------------------- 1 | ############################################################ 2 | ## This file is generated automatically by Vivado HLS. 3 | ## Please DO NOT edit it. 4 | ## Copyright (C) 2013 Xilinx Inc. All rights reserved. 5 | ############################################################ 6 | open_project mvt 7 | set_top mvt 8 | add_files mvt.c 9 | add_files -tb abstract_kernel.c 10 | add_files -tb main.c 11 | add_files -tb smallinput.data 12 | open_solution "solution1" 13 | set_part {xc7z020clg484-1} 14 | create_clock -period 10 -name default 15 | source "./directives.tcl" 16 | csim_design 17 | csynth_design 18 | #cosim_design -trace_level none 19 | export_design -format ip_catalog -description "An IP generated by Vivado HLS" -vendor "xilinx.com" -library "hls" -version "1.0" 20 | exit 21 | -------------------------------------------------------------------------------- /testsuite/Ecobench/gemm/script.tcl: -------------------------------------------------------------------------------- 1 | ############################################################ 2 | ## This file is generated automatically by Vivado HLS. 3 | ## Please DO NOT edit it. 4 | ## Copyright (C) 2013 Xilinx Inc. All rights reserved. 5 | ############################################################ 6 | open_project gemm 7 | set_top gemm 8 | add_files gemm.c 9 | add_files -tb abstract_kernel.c 10 | add_files -tb main.c 11 | add_files -tb smallinput.data 12 | open_solution "solution1" 13 | set_part {xc7z020clg484-1} 14 | create_clock -period 10 -name default 15 | source "./directives.tcl" 16 | csim_design 17 | csynth_design 18 | #cosim_design -trace_level none 19 | #export_design -format ip_catalog -description "An IP generated by Vivado HLS" -vendor "xilinx.com" -library "hls" -version "1.0" 20 | exit 21 | -------------------------------------------------------------------------------- /testsuite/Ecobench/syrk/script.tcl: -------------------------------------------------------------------------------- 1 | ############################################################ 2 | ## This file is generated automatically by Vivado HLS. 3 | ## Please DO NOT edit it. 4 | ## Copyright (C) 2013 Xilinx Inc. All rights reserved. 5 | ############################################################ 6 | open_project syrk 7 | set_top syrk 8 | add_files syrk.c 9 | add_files -tb abstract_kernel.c 10 | add_files -tb main.c 11 | add_files -tb smallinput.data 12 | open_solution "solution1" 13 | set_part {xc7z020clg484-1} 14 | create_clock -period 10 -name default 15 | source "./directives.tcl" 16 | csim_design 17 | csynth_design 18 | #cosim_design -trace_level none 19 | #export_design -format ip_catalog -description "An IP generated by Vivado HLS" -vendor "xilinx.com" -library "hls" -version "1.0" 20 | exit 21 | -------------------------------------------------------------------------------- /testsuite/Ecobench/gesummv/script.tcl: -------------------------------------------------------------------------------- 1 | ############################################################ 2 | ## This file is generated automatically by Vivado HLS. 3 | ## Please DO NOT edit it. 4 | ## Copyright (C) 2013 Xilinx Inc. All rights reserved. 5 | ############################################################ 6 | open_project gesummv 7 | set_top gesummv 8 | add_files gesummv.c 9 | add_files -tb abstract_kernel.c 10 | add_files -tb main.c 11 | add_files -tb smallinput.data 12 | open_solution "solution1" 13 | set_part {xc7z020clg484-1} 14 | create_clock -period 10 -name default 15 | source "./directives.tcl" 16 | csim_design 17 | csynth_design 18 | #cosim_design -trace_level none 19 | #export_design -format ip_catalog -description "An IP generated by Vivado HLS" -vendor "xilinx.com" -library "hls" -version "1.0" 20 | exit 21 | -------------------------------------------------------------------------------- /testsuite/Ecobench/syr2k/script.tcl: -------------------------------------------------------------------------------- 1 | ############################################################ 2 | ## This file is generated automatically by Vivado HLS. 3 | ## Please DO NOT edit it. 4 | ## Copyright (C) 2013 Xilinx Inc. All rights reserved. 5 | ############################################################ 6 | open_project syr2k 7 | set_top syr2k 8 | add_files syr2k.c 9 | add_files -tb abstract_kernel.c 10 | add_files -tb main.c 11 | add_files -tb smallinput.data 12 | open_solution "solution1" 13 | set_part {xc7z020clg484-1} 14 | create_clock -period 10 -name default 15 | source "./directives.tcl" 16 | csim_design -clean 17 | csynth_design 18 | #cosim_design -trace_level none 19 | #export_design -format ip_catalog -description "An IP generated by Vivado HLS" -vendor "xilinx.com" -library "hls" -version "1.0" 20 | exit 21 | -------------------------------------------------------------------------------- /lib/Build_DDDG/LLVMBuild.txt: -------------------------------------------------------------------------------- 1 | ;===- ./lib/Target/VerilogBackend/lib/BitLevelOpt/LLVMBuild.txt ------------*- Conf -*--===; 2 | ; 3 | ; The LLVM Compiler Infrastructure 4 | ; 5 | ; This file is distributed under the University of Illinois Open Source 6 | ; License. See LICENSE.TXT for details. 7 | ; 8 | ;===------------------------------------------------------------------------===; 9 | ; 10 | ; This is an LLVMBuild description file for the components in this subdirectory. 11 | ; 12 | ; For more information on the LLVMBuild system, please see: 13 | ; 14 | ; http://llvm.org/docs/LLVMBuild.html 15 | ; 16 | ;===------------------------------------------------------------------------===; 17 | 18 | [component_0] 19 | type = Library 20 | name = BuildDDDGlib 21 | parent = lin-profile 22 | add_to_library_groups = lin-profile 23 | -------------------------------------------------------------------------------- /lib/Profile/LLVMBuild.txt: -------------------------------------------------------------------------------- 1 | ;===- ./lib/Target/VerilogBackend/lib/BitLevelOpt/LLVMBuild.txt ------------*- Conf -*--===; 2 | ; 3 | ; The LLVM Compiler Infrastructure 4 | ; 5 | ; This file is distributed under the University of Illinois Open Source 6 | ; License. See LICENSE.TXT for details. 7 | ; 8 | ;===------------------------------------------------------------------------===; 9 | ; 10 | ; This is an LLVMBuild description file for the components in this subdirectory. 11 | ; 12 | ; For more information on the LLVMBuild system, please see: 13 | ; 14 | ; http://llvm.org/docs/LLVMBuild.html 15 | ; 16 | ;===------------------------------------------------------------------------===; 17 | 18 | [component_0] 19 | type = Library 20 | name = LLVMLinProfiler 21 | parent = lin-profile 22 | add_to_library_groups = lin-profile 23 | -------------------------------------------------------------------------------- /testsuite/Ecobench/convolution3d/script.tcl: -------------------------------------------------------------------------------- 1 | ############################################################ 2 | ## This file is generated automatically by Vivado HLS. 3 | ## Please DO NOT edit it. 4 | ## Copyright (C) 2013 Xilinx Inc. All rights reserved. 5 | ############################################################ 6 | open_project convolution3d 7 | set_top convolution3d 8 | add_files convolution3d.c 9 | add_files -tb abstract_kernel.c 10 | add_files -tb main.c 11 | add_files -tb smallinput.data 12 | open_solution "solution1" 13 | set_part {xc7z020clg484-1} 14 | create_clock -period 10 -name default 15 | source "./directives.tcl" 16 | csim_design 17 | csynth_design 18 | #cosim_design -trace_level none 19 | #export_design -format ip_catalog -description "An IP generated by Vivado HLS" -vendor "xilinx.com" -library "hls" -version "1.0" 20 | exit 21 | -------------------------------------------------------------------------------- /testsuite/Ecobench/convolution2d/script.tcl: -------------------------------------------------------------------------------- 1 | ############################################################ 2 | ## This file is generated automatically by Vivado HLS. 3 | ## Please DO NOT edit it. 4 | ## Copyright (C) 2013 Xilinx Inc. All rights reserved. 5 | ############################################################ 6 | open_project convolution2d 7 | set_top convolution2d 8 | add_files convolution2d.c 9 | add_files -tb abstract_kernel.c 10 | add_files -tb main.c 11 | add_files -tb smallinput.data 12 | open_solution "solution1" 13 | set_part {xc7z020clg484-1} 14 | create_clock -period 10 -name default 15 | source "./directives.tcl" 16 | csim_design -clean 17 | csynth_design 18 | #cosim_design -trace_level none 19 | #export_design -format ip_catalog -description "An IP generated by Vivado HLS" -vendor "xilinx.com" -library "hls" -version "1.0" 20 | exit 21 | -------------------------------------------------------------------------------- /testsuite/Ecobench/mvt/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #compile_polybench("mvt" "mvt" "c") 2 | set(kernel_name "mvt") 3 | #remove_bin_bc_files(${kernel_name}) 4 | #file(GLOB test_files *.c) 5 | #MESSAGE(STATUS "CMAKE_CURRENT_SOURCE_DIR in mvt: ${CMAKE_CURRENT_SOURCE_DIR}") 6 | file(GLOB test_files RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/*.c") 7 | MESSAGE(STATUS "test_files in compile_polybench: ${test_files}") 8 | foreach(test_file ${test_files}) 9 | get_filename_component(file_name ${test_file} NAME_WE) 10 | MESSAGE(STATUS "file_name in compile_polybench: ${file_name}") 11 | compile_polybench(${file_name} ${kernel_name} "c") 12 | list(APPEND bc_files ${file_name}.bc) 13 | endforeach(test_file) 14 | 15 | MESSAGE(STATUS "bc_files: ${bc_files}") 16 | link_polybench(${kernel_name} ${bc_files}) 17 | 18 | #Test polybench using Lin-profiler 19 | #test_polybench(${kernel_name}) 20 | -------------------------------------------------------------------------------- /testsuite/Ecobench/atax/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #compile_polybench("atax" "atax" "c") 2 | set(kernel_name "atax") 3 | #remove_bin_bc_files(${kernel_name}) 4 | #file(GLOB test_files *.c) 5 | #MESSAGE(STATUS "CMAKE_CURRENT_SOURCE_DIR in atax: ${CMAKE_CURRENT_SOURCE_DIR}") 6 | file(GLOB test_files RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/*.c") 7 | MESSAGE(STATUS "test_files in compile_polybench: ${test_files}") 8 | foreach(test_file ${test_files}) 9 | get_filename_component(file_name ${test_file} NAME_WE) 10 | MESSAGE(STATUS "file_name in compile_polybench: ${file_name}") 11 | compile_polybench(${file_name} ${kernel_name} "c") 12 | list(APPEND bc_files ${file_name}.bc) 13 | endforeach(test_file) 14 | 15 | MESSAGE(STATUS "bc_files: ${bc_files}") 16 | link_polybench(${kernel_name} ${bc_files}) 17 | 18 | #Test polybench using Lin-profiler 19 | #test_polybench(${kernel_name}) 20 | -------------------------------------------------------------------------------- /testsuite/Ecobench/bicg/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #compile_polybench("bicg" "bicg" "c") 2 | set(kernel_name "bicg") 3 | #remove_bin_bc_files(${kernel_name}) 4 | #file(GLOB test_files *.c) 5 | #MESSAGE(STATUS "CMAKE_CURRENT_SOURCE_DIR in bicg: ${CMAKE_CURRENT_SOURCE_DIR}") 6 | file(GLOB test_files RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/*.c") 7 | MESSAGE(STATUS "test_files in compile_polybench: ${test_files}") 8 | foreach(test_file ${test_files}) 9 | get_filename_component(file_name ${test_file} NAME_WE) 10 | MESSAGE(STATUS "file_name in compile_polybench: ${file_name}") 11 | compile_polybench(${file_name} ${kernel_name} "c") 12 | list(APPEND bc_files ${file_name}.bc) 13 | endforeach(test_file) 14 | 15 | MESSAGE(STATUS "bc_files: ${bc_files}") 16 | link_polybench(${kernel_name} ${bc_files}) 17 | 18 | #Test polybench using Lin-profiler 19 | #test_polybench(${kernel_name}) 20 | -------------------------------------------------------------------------------- /testsuite/Ecobench/gemm/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #compile_polybench("gemm" "gemm" "c") 2 | set(kernel_name "gemm") 3 | #remove_bin_bc_files(${kernel_name}) 4 | #file(GLOB test_files *.c) 5 | #MESSAGE(STATUS "CMAKE_CURRENT_SOURCE_DIR in gemm: ${CMAKE_CURRENT_SOURCE_DIR}") 6 | file(GLOB test_files RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/*.c") 7 | MESSAGE(STATUS "test_files in compile_polybench: ${test_files}") 8 | foreach(test_file ${test_files}) 9 | get_filename_component(file_name ${test_file} NAME_WE) 10 | MESSAGE(STATUS "file_name in compile_polybench: ${file_name}") 11 | compile_polybench(${file_name} ${kernel_name} "c") 12 | list(APPEND bc_files ${file_name}.bc) 13 | endforeach(test_file) 14 | 15 | MESSAGE(STATUS "bc_files: ${bc_files}") 16 | link_polybench(${kernel_name} ${bc_files}) 17 | 18 | #Test polybench using Lin-profiler 19 | #test_polybench(${kernel_name}) 20 | -------------------------------------------------------------------------------- /testsuite/Ecobench/syrk/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #compile_polybench("atax" "atax" "c") 2 | set(kernel_name "syrk") 3 | #remove_bin_bc_files(${kernel_name}) 4 | #file(GLOB test_files *.c) 5 | #MESSAGE(STATUS "CMAKE_CURRENT_SOURCE_DIR in atax: ${CMAKE_CURRENT_SOURCE_DIR}") 6 | file(GLOB test_files RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/*.c") 7 | MESSAGE(STATUS "test_files in compile_polybench: ${test_files}") 8 | foreach(test_file ${test_files}) 9 | get_filename_component(file_name ${test_file} NAME_WE) 10 | MESSAGE(STATUS "file_name in compile_polybench: ${file_name}") 11 | compile_polybench(${file_name} ${kernel_name} "c") 12 | list(APPEND bc_files ${file_name}.bc) 13 | endforeach(test_file) 14 | 15 | MESSAGE(STATUS "bc_files: ${bc_files}") 16 | link_polybench(${kernel_name} ${bc_files}) 17 | 18 | #Test polybench using Lin-profiler 19 | #test_polybench(${kernel_name}) 20 | -------------------------------------------------------------------------------- /testsuite/Ecobench/syr2k/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #compile_polybench("syr2k" "syr2k" "c") 2 | set(kernel_name "syr2k") 3 | #remove_bin_bc_files(${kernel_name}) 4 | #file(GLOB test_files *.c) 5 | #MESSAGE(STATUS "CMAKE_CURRENT_SOURCE_DIR in syr2k: ${CMAKE_CURRENT_SOURCE_DIR}") 6 | file(GLOB test_files RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/*.c") 7 | MESSAGE(STATUS "test_files in compile_polybench: ${test_files}") 8 | foreach(test_file ${test_files}) 9 | get_filename_component(file_name ${test_file} NAME_WE) 10 | MESSAGE(STATUS "file_name in compile_polybench: ${file_name}") 11 | compile_polybench(${file_name} ${kernel_name} "c") 12 | list(APPEND bc_files ${file_name}.bc) 13 | endforeach(test_file) 14 | 15 | MESSAGE(STATUS "bc_files: ${bc_files}") 16 | link_polybench(${kernel_name} ${bc_files}) 17 | 18 | #Test polybench using Lin-profiler 19 | #test_polybench(${kernel_name}) 20 | -------------------------------------------------------------------------------- /testsuite/Ecobench/gesummv/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #compile_polybench("gesummv" "gesummv" "c") 2 | set(kernel_name "gesummv") 3 | #remove_bin_bc_files(${kernel_name}) 4 | #file(GLOB test_files *.c) 5 | #MESSAGE(STATUS "CMAKE_CURRENT_SOURCE_DIR in gesummv: ${CMAKE_CURRENT_SOURCE_DIR}") 6 | file(GLOB test_files RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/*.c") 7 | MESSAGE(STATUS "test_files in compile_polybench: ${test_files}") 8 | foreach(test_file ${test_files}) 9 | get_filename_component(file_name ${test_file} NAME_WE) 10 | MESSAGE(STATUS "file_name in compile_polybench: ${file_name}") 11 | compile_polybench(${file_name} ${kernel_name} "c") 12 | list(APPEND bc_files ${file_name}.bc) 13 | endforeach(test_file) 14 | 15 | MESSAGE(STATUS "bc_files: ${bc_files}") 16 | link_polybench(${kernel_name} ${bc_files}) 17 | 18 | #Test polybench using Lin-profiler 19 | #test_polybench(${kernel_name}) 20 | -------------------------------------------------------------------------------- /lib/Build_DDDG/generic_func.cpp: -------------------------------------------------------------------------------- 1 | #include "profile_h/generic_func.h" 2 | 3 | std::vector make_vector(int size) 4 | { 5 | std::vector tmp_vector(size, 0); 6 | return tmp_vector; 7 | } 8 | int max_value(const vector array, int start, int end) 9 | { 10 | int max = array.at(start); 11 | for (int i = start; i < end; ++i) 12 | { 13 | if (array.at(i) > max) 14 | max = array.at(i); 15 | } 16 | return max; 17 | } 18 | 19 | int min_value(const vector array, int start, int end) 20 | { 21 | int min = array.at(start); 22 | for (int i = start; i < end; ++i) 23 | { 24 | if (array.at(i) < min) 25 | min = array.at(i); 26 | } 27 | return min; 28 | } 29 | unsigned next_power_of_two(unsigned int x) 30 | { 31 | x = x - 1; 32 | x = x | (x >> 1); 33 | x = x | (x >> 2); 34 | x = x | (x >> 4); 35 | x = x | (x >> 8); 36 | x = x | (x >> 16); 37 | return x + 1; 38 | } 39 | -------------------------------------------------------------------------------- /testsuite/Ecobench/convolution2d/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #compile_polybench("convolution2d" "convolution2d" "c") 2 | set(kernel_name "convolution2d") 3 | #remove_bin_bc_files(${kernel_name}) 4 | #file(GLOB test_files *.c) 5 | #MESSAGE(STATUS "CMAKE_CURRENT_SOURCE_DIR in convolution2d: ${CMAKE_CURRENT_SOURCE_DIR}") 6 | file(GLOB test_files RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/*.c") 7 | MESSAGE(STATUS "test_files in compile_polybench: ${test_files}") 8 | foreach(test_file ${test_files}) 9 | get_filename_component(file_name ${test_file} NAME_WE) 10 | MESSAGE(STATUS "file_name in compile_polybench: ${file_name}") 11 | compile_polybench(${file_name} ${kernel_name} "c") 12 | list(APPEND bc_files ${file_name}.bc) 13 | endforeach(test_file) 14 | 15 | MESSAGE(STATUS "bc_files: ${bc_files}") 16 | link_polybench(${kernel_name} ${bc_files}) 17 | 18 | #Test polybench using Lin-profiler 19 | #test_polybench(${kernel_name}) 20 | -------------------------------------------------------------------------------- /testsuite/Ecobench/convolution3d/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #compile_polybench("convolution3d" "convolution3d" "c") 2 | set(kernel_name "convolution3d") 3 | #remove_bin_bc_files(${kernel_name}) 4 | #file(GLOB test_files *.c) 5 | #MESSAGE(STATUS "CMAKE_CURRENT_SOURCE_DIR in convolution3d: ${CMAKE_CURRENT_SOURCE_DIR}") 6 | file(GLOB test_files RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/*.c") 7 | MESSAGE(STATUS "test_files in compile_polybench: ${test_files}") 8 | foreach(test_file ${test_files}) 9 | get_filename_component(file_name ${test_file} NAME_WE) 10 | MESSAGE(STATUS "file_name in compile_polybench: ${file_name}") 11 | compile_polybench(${file_name} ${kernel_name} "c") 12 | list(APPEND bc_files ${file_name}.bc) 13 | endforeach(test_file) 14 | 15 | MESSAGE(STATUS "bc_files: ${bc_files}") 16 | link_polybench(${kernel_name} ${bc_files}) 17 | 18 | #Test polybench using Lin-profiler 19 | #test_polybench(${kernel_name}) 20 | -------------------------------------------------------------------------------- /testsuite/Ecobench/convolution2d/convolution2d.c: -------------------------------------------------------------------------------- 1 | #include "convolution2d.h" 2 | 3 | void convolution2d(DATA_TYPE A[SIZE], DATA_TYPE B[SIZE]) { 4 | int i, j; 5 | DATA_TYPE c11, c12, c13, c21, c22, c23, c31, c32, c33; 6 | #ifdef FLOAT_TYPE 7 | c11 = +0.2f; c21 = +0.5f; c31 = -0.8f; 8 | c12 = -0.3f; c22 = +0.6f; c32 = -0.9f; 9 | c13 = +0.4f; c23 = +0.7f; c33 = +0.10f; 10 | #else // Double type 11 | c11 = +0.2; c21 = +0.5; c31 = -0.8; 12 | c12 = -0.3; c22 = +0.6; c32 = -0.9; 13 | c13 = +0.4; c23 = +0.7; c33 = +0.10; 14 | #endif 15 | 16 | 17 | for (i = 1; i < NI - 1; ++i) { 18 | for (j = 1; j < NJ - 1; ++j) { 19 | B[i*NJ + j] = c11 * A[(i - 1)*NJ + (j - 1)] + c12 * A[(i + 0)*NJ + (j - 1)] + c13 * A[(i + 1)*NJ + (j - 1)] 20 | + c21 * A[(i - 1)*NJ + (j + 0)] + c22 * A[(i + 0)*NJ + (j + 0)] + c23 * A[(i + 1)*NJ + (j + 0)] 21 | + c31 * A[(i - 1)*NJ + (j + 1)] + c32 * A[(i + 0)*NJ + (j + 1)] + c33 * A[(i + 1)*NJ + (j + 1)]; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /include/profile_h/TraceFunctions.h: -------------------------------------------------------------------------------- 1 | #ifndef TRACEFUNCTIONS_H 2 | #define TRACEFUNCTIONS_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "profile_h/lin-profile.h" 11 | #include 12 | 13 | #if !defined(RESULT_LINE) && !defined(FORWARD_LINE) 14 | #define RESULT_LINE 19134 15 | #define FORWARD_LINE 24601 16 | #endif 17 | 18 | void trace_logger_fin(); 19 | void trace_logger_init(); 20 | void trace_logger_log0(int line_number, char *name, char *bbid, char *instid, int opcode); 21 | void trace_logger_log_int(int line, int size, int64_t value, int is_reg, char *label); 22 | void trace_logger_log_double(int line, int size, double value, int is_reg, char *label); 23 | void trace_logger_log_int_noreg(int line, int size, int64_t value, int is_reg); 24 | void trace_logger_log_double_noreg(int line, int size, double value, int is_reg); 25 | //void trace_logger_log_label(); 26 | 27 | #endif // End of TRACEFUNCTIONS_H -------------------------------------------------------------------------------- /include/profile_h/xilinx_node_latency.h: -------------------------------------------------------------------------------- 1 | #ifndef __XILINX_NODE_LATENCY_H__ 2 | #define __XILINX_NODE_LATENCY_H__ 3 | 4 | /* 5 | #define ADD_LATENCY 1 6 | #define SUB_LATENCY 1 7 | #define MUL_LATENCY 2 8 | #define DIV_LATENCY 2 9 | #define AND_LATENCY 1 10 | #define OR_LATENCY 1 11 | #define XOR_LATENCY 1 12 | #define SHL_LATENCY 1 13 | #define BR_LATENCY 1 14 | #define ICMP_LATENCY 1 15 | #define IndexAdd_LATENCY 1 16 | #define IndexSub_LATENCY 1 17 | 18 | #define FADD_LATENCY 5 19 | #define FSUB_LATENCY 5 20 | #define FMUL_LATENCY 4 21 | #define FDIV_LATENCY 6 22 | #define FCMP_LATENCY 1 23 | */ 24 | 25 | #define LOAD_LATENCY 2 26 | #define STORE_LATENCY 1 27 | 28 | #define ADDSUB_LATENCY 1 29 | #define MUL32BIT_LATENCY 6 30 | #define DIV32BIT_LATENCY 36 31 | 32 | #define FADDSUB32BIT_LATENCY 5 33 | #define FMUL32BIT_LATENCY 4 34 | #define FDIV32BIT_LATENCY 16 35 | #define FCMP_LATENCY 1 36 | 37 | #define BRAM_R_PORTS 2 38 | #define BRAM_W_PORTS 1 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /include/profile_h/AssignBasicBlockIDPass.h: -------------------------------------------------------------------------------- 1 | #ifndef ASSIGNBASICBLOCKID_PASS_H 2 | #define ASSIGNBASICBLOCKID_PASS_H 3 | 4 | #include "llvm/Pass.h" 5 | #include "llvm/IR/Module.h" 6 | #include "llvm/IR/InstVisitor.h" 7 | #include "llvm/Support/raw_ostream.h" 8 | #include "llvm/Support/Debug.h" 9 | #include "llvm/IR/Verifier.h" 10 | //#include "llvm/IR/BasicBlock.h" 11 | 12 | #include "llvm/Transforms/Scalar.h" 13 | #include "llvm/Analysis/LoopInfo.h" 14 | 15 | #include "profile_h/Passes.h" 16 | #include "profile_h/auxiliary.h" 17 | #include "profile_h/DDDG.h" 18 | 19 | namespace llvm{ 20 | 21 | class AssignBasicBlockID : public ModulePass, 22 | public InstVisitor{ 23 | 24 | public: 25 | static char ID; 26 | AssignBasicBlockID(); 27 | 28 | void getAnalysisUsage(AnalysisUsage &AU) const; 29 | 30 | bool runOnModule(Module &M); 31 | 32 | private: 33 | unsigned int counter; 34 | MDNode* assignID(BasicBlock *BB, unsigned id); 35 | }; 36 | 37 | } // End namespace LLVM 38 | 39 | #endif // End ASSIGNBASICBLOCKID_PASS_H -------------------------------------------------------------------------------- /include/profile_h/Registers.h: -------------------------------------------------------------------------------- 1 | #ifndef __REGISTERS_H__ 2 | #define __REGISTERS_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class Register 9 | { 10 | public: 11 | Register(std::string baseName, unsigned int size, unsigned int id) 12 | { 13 | this->baseName = baseName; 14 | this->id = id; 15 | num_bytes = size; 16 | loads = 0; 17 | stores = 0; 18 | } 19 | 20 | void increment_loads() { loads++; } 21 | void increment_stores() { stores++; } 22 | 23 | private: 24 | std::string baseName; 25 | unsigned int num_bytes; 26 | unsigned int id; 27 | 28 | unsigned int loads; 29 | unsigned int stores; 30 | }; 31 | 32 | class Registers 33 | { 34 | 35 | public: 36 | Registers() {} 37 | ~Registers(); 38 | 39 | void createRegister( 40 | std::string baseName, unsigned num_bytes); 41 | void getRegisterNames(std::vector &names); 42 | Register* getRegister(std::string baseName) { return regs[baseName]; } 43 | bool has(std::string baseName); 44 | 45 | private: 46 | std::map regs; 47 | 48 | }; 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /include/profile_h/QueryBasicBlockIDPass.h: -------------------------------------------------------------------------------- 1 | #ifndef QueryBasicBlockID_PASS_H 2 | #define QueryBasicBlockID_PASS_H 3 | 4 | #include "llvm/Pass.h" 5 | #include "llvm/IR/Module.h" 6 | //#include "llvm/IR/InstVisitor.h" 7 | #include "llvm/Support/raw_ostream.h" 8 | #include "llvm/Support/Debug.h" 9 | #include "llvm/IR/Verifier.h" 10 | #include "llvm/IR/Constants.h" 11 | //#include "llvm/IR/BasicBlock.h" 12 | 13 | #include "profile_h/AssignBasicBlockIDPass.h" 14 | #include "profile_h/Passes.h" 15 | #include "profile_h/auxiliary.h" 16 | 17 | #include 18 | 19 | namespace llvm{ 20 | 21 | class QueryBasicBlockID : public ModulePass{ 22 | 23 | public: 24 | static char ID; 25 | QueryBasicBlockID(); 26 | 27 | void getAnalysisUsage(AnalysisUsage &AU) const; 28 | 29 | unsigned getBBid(BasicBlock* BB) const; 30 | 31 | BasicBlock* getBBbyID(unsigned id); 32 | 33 | uint64_t getNumOfBB() const; 34 | 35 | bool runOnModule(Module &M); 36 | 37 | private: 38 | uint64_t numOfBB; 39 | unsigned int counter; 40 | std::map BBstr2IDMap; 41 | std::map BB2IDMap; 42 | std::map ID2BBMap; 43 | 44 | }; 45 | } // End namespace LLVM 46 | 47 | #endif // End QueryBasicBlockID_PASS_H -------------------------------------------------------------------------------- /include/profile_h/LoopNumberPass.h: -------------------------------------------------------------------------------- 1 | /// This pass is used to calculate the number of 2 | /// loops inside functions. 3 | 4 | #ifndef LOOPNUMBERPASS_H 5 | #define LOOPNUMBERPASS_H 6 | 7 | #include "llvm/Pass.h" 8 | #include "llvm/IR/Module.h" 9 | #include "llvm/IR/Function.h" 10 | #include "llvm/Analysis/LoopPass.h" 11 | #include "llvm/Analysis/LoopInfo.h" 12 | #include "llvm/Support/raw_os_ostream.h" 13 | #include "llvm/Support/Debug.h" 14 | #include "llvm/Transforms/Scalar.h" 15 | 16 | #include "profile_h/Passes.h" 17 | #include "profile_h/lin-profile.h" 18 | 19 | namespace llvm { 20 | 21 | class LoopNumber : public LoopPass { 22 | 23 | public: 24 | static char ID; 25 | LoopNumber(); 26 | bool doInitialization(Loop *lp, LPPassManager &LPM); 27 | void getAnalysisUsage(AnalysisUsage &AU) const; 28 | bool runOnLoop(Loop* lp, LPPassManager &LPM); 29 | /* 30 | unsigned getNumberLoopOfFunc(std::string func_name) const; 31 | unsigned getNumberFuncHasLoop() const; 32 | */ 33 | 34 | private: 35 | //unsigned func_hasLoop_number; 36 | unsigned loop_counter; 37 | //std::map loopNumInaFunc; 38 | NamedMDNode* NMD; 39 | std::vector LoopsMetadataNode; 40 | std::vector exploredFunc; 41 | }; 42 | 43 | } // End of llvm namespace 44 | 45 | #endif // End of definition of LOOPNUMBERPASS_H -------------------------------------------------------------------------------- /include/profile_h/GetInstDistributionPass.h: -------------------------------------------------------------------------------- 1 | #ifndef GETINSTDISTRIBUTION_H 2 | #define GETINSTDISTRIBUTION_H 3 | 4 | #include 5 | 6 | #include "llvm/Pass.h" 7 | #include "llvm/IR/Module.h" 8 | #include "llvm/IR/InstVisitor.h" 9 | #include "llvm/IR/InstIterator.h" 10 | #include "llvm/IR/Verifier.h" 11 | //#include "llvm/IR/BasicBlock.h" 12 | 13 | #include "llvm/Support/raw_ostream.h" 14 | #include "llvm/Support/Debug.h" 15 | #include "llvm/Support/Casting.h" 16 | 17 | #include "llvm/Transforms/Scalar.h" 18 | #include "llvm/ADT/Statistic.h" 19 | 20 | #include "profile_h/Passes.h" 21 | #include "profile_h/auxiliary.h" 22 | #include "profile_h/QueryBasicBlockIDPass.h" 23 | 24 | namespace llvm{ 25 | 26 | struct instDis { 27 | uint64_t meminst; 28 | uint64_t ldinst; 29 | uint64_t stinst; 30 | uint64_t brinst; 31 | uint64_t compinst; 32 | uint64_t others; 33 | }; 34 | 35 | typedef std::map bbID2instDisMapTy; 36 | 37 | class GetInstDistribution : public ModulePass{ 38 | 39 | public: 40 | static char ID; 41 | GetInstDistribution(); 42 | 43 | void getAnalysisUsage(AnalysisUsage &AU) const; 44 | 45 | bool runOnModule(Module &M); 46 | 47 | private: 48 | bbID2instDisMapTy bbID2instDisMap; 49 | QueryBasicBlockID* bbIDpass; 50 | 51 | }; 52 | 53 | } // End namespace LLVM 54 | 55 | #endif // End GETINSTDISTRIBUTION_H -------------------------------------------------------------------------------- /testsuite/Ecobench/atax/abstract_kernel.h: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Author: Guanwen Zhong 3 | * Associated Filename: abstract_kernel.h 4 | * Purpose: The abstract_kernel file of 2D Convolution kernel 5 | * Origin: Ecobench benchmarch v1.0 6 | 7 | This benchmark is modified from Polybench_GPU v1.0. For more information, please check: 8 | http://xxxxx 9 | 10 | ********************************************************************** 11 | Reserved. 12 | � Copyright 13 | 14 | **********************************************************************/ 15 | #ifndef ABSTRACT_KERNEL_H 16 | #define ABSTRACT_KERNEL_H 17 | 18 | /********************************************************************* 19 | * The following part is an implemetation of an abstraction function. 20 | * 21 | **********************************************************************/ 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include "common.h" 28 | #include "atax.h" 29 | 30 | void init(DATA_TYPE x[SIZE_X], DATA_TYPE A[SIZE_A], DATA_TYPE y[SIZE_Y], DATA_TYPE tmp[SIZE_TMP]); 31 | 32 | void abstract_kernel (void * arguments); 33 | 34 | void atax_sw(DATA_TYPE A[SIZE_A], DATA_TYPE x[SIZE_X], /*DATA_TYPE y[SIZE_Y],*/ DATA_TYPE tmp[SIZE_TMP]); 35 | 36 | int compare_result(char * input_fileName, char * hw_result); 37 | 38 | #endif // End of ABSTRACT_KERNEL_H 39 | -------------------------------------------------------------------------------- /include/profile_h/file_func.h: -------------------------------------------------------------------------------- 1 | #ifndef FILE_FUNC_H 2 | #define FILE_FUNC_H 3 | 4 | #include 5 | #include // std::istringstream 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | using namespace std; 15 | 16 | void write_gzip_file(string gzip_file_name, unsigned size, vector &output); 17 | void write_gzip_bool_file(string gzip_file_name, unsigned size, vector &output); 18 | void write_gzip_unsigned_file(string gzip_file_name, unsigned size, vector &output); 19 | void write_gzip_string_file(string gzip_file_name, unsigned size, vector &output); 20 | void write_string_file(string file_name, unsigned size, vector &output); 21 | 22 | void read_file(string file_name, vector &output); 23 | void read_gzip_file(string gzip_file_name, unsigned size, vector &output); 24 | void read_gzip_unsigned_file(string gzip_file_name, unsigned size, vector &output); 25 | void read_gzip_string_file(string gzip_file_name, unsigned size, vector &output); 26 | void read_gzip_file_no_size(string gzip_file_name, vector &output); 27 | void read_gzip_2_unsigned_file(string gzip_file_name, unsigned size, vector< pair > &output); 28 | void read_gzip_1in2_unsigned_file(string gzip_file_name, unsigned size, vector &output); 29 | 30 | bool fileExists(const string file_name); 31 | #endif 32 | -------------------------------------------------------------------------------- /include/profile_h/lin-profile.h: -------------------------------------------------------------------------------- 1 | #ifndef LIN_PROFILE_H 2 | #define LIN_PROFILE_H 3 | 4 | #define BUILD_DDDG_H 5 | 6 | #include "profile_h/AssignBasicBlockIDPass.h" 7 | #include "profile_h/AssignLoadStoreIDPass.h" 8 | #include "profile_h/QueryBasicBlockIDPass.h" 9 | #include "profile_h/QueryLoadStoreIDPass.h" 10 | #include "profile_h/LoopNumberPass.h" 11 | #include "profile_h/ExtractLoopInfoPass.h" 12 | 13 | #ifndef BUILD_DDDG_H 14 | //#include "profile_h/GetLoopBoundPass.h" 15 | #include "profile_h/CodeInstrumentPass.h" 16 | #include "profile_h/AnalysisProfilingPass.h" 17 | 18 | #else // define BUILD_DDDG_H 19 | #include "profile_h/InstrumentForDDDGPass.h" 20 | #endif // End of ifndef BUILD_DDDG_H 21 | 22 | //#include "profile_h/Passes.h" 23 | #include "profile_h/auxiliary.h" 24 | 25 | //#define ENABLE_INSTDISTRIBUTION 26 | #ifdef ENABLE_INSTDISTRIBUTION 27 | #include "profile_h/GetInstDistributionPass.h" 28 | #endif // End of ENABLE_INSTDISTRIBUTION 29 | 30 | #define TWO_TIME_PROFILING 31 | #if defined(TWO_TIME_PROFILING) || defined(ENABLE_INSTDISTRIBUTION) 32 | #include "profile_h/GetLoopBoundPass.h" 33 | #endif // End of TWO_TIME_PROFILING or ENABLE_INSTDISTRIBUTION 34 | 35 | static llvm::cl::opt 36 | InputFilename(llvm::cl::Positional, llvm::cl::desc(""), llvm::cl::init("-"), llvm::cl::value_desc("filename")); 37 | 38 | static llvm::cl::opt 39 | OutputFilename("o", llvm::cl::desc(""), llvm::cl::value_desc("filename")); 40 | 41 | void parse_input_arguments(int argc, char **argv); 42 | #endif // End LIN_PROFILE_H 43 | -------------------------------------------------------------------------------- /testsuite/Ecobench/convolution3d/convolution3d.c: -------------------------------------------------------------------------------- 1 | #include "convolution3d.h" 2 | 3 | void convolution3d(DATA_TYPE A[SIZE], DATA_TYPE B[SIZE]) { 4 | int i, j, k; 5 | DATA_TYPE c11, c12, c13, c21, c22, c23, c31, c32, c33; 6 | #ifdef FLOAT_TYPE 7 | c11 = +2.0f; c21 = +5.0f; c31 = -8.0f; 8 | c12 = -3.0f; c22 = +6.0f; c32 = -9.0f; 9 | c13 = +4.0f; c23 = +7.0f; c33 = +10.0f; 10 | #else // Double type 11 | c11 = +2.0; c21 = +5.0; c31 = -8.0; 12 | c12 = -3.0; c22 = +6.0; c32 = -9.0; 13 | c13 = +4.0; c23 = +7.0; c33 = +10.0; 14 | #endif 15 | 16 | for (i = 1; i < NI - 1; ++i) { 17 | for (j = 1; j < NJ - 1; ++j) { 18 | for (k = 1; k < NK -1; ++k) { 19 | //printf("i:%d\nj:%d\nk:%d\n", i, j, k); 20 | B[i*(NK * NJ) + j*NK + k] = c11 * A[(i - 1)*(NK * NJ) + (j - 1)*NK + (k - 1)] + c13 * A[(i + 1)*(NK * NJ) + (j - 1)*NK + (k - 1)] 21 | + c21 * A[(i - 1)*(NK * NJ) + (j - 1)*NK + (k - 1)] + c23 * A[(i + 1)*(NK * NJ) + (j - 1)*NK + (k - 1)] 22 | + c31 * A[(i - 1)*(NK * NJ) + (j - 1)*NK + (k - 1)] + c33 * A[(i + 1)*(NK * NJ) + (j - 1)*NK + (k - 1)] 23 | + c12 * A[(i + 0)*(NK * NJ) + (j - 1)*NK + (k + 0)] + c22 * A[(i + 0)*(NK * NJ) + (j + 0)*NK + (k + 0)] 24 | + c32 * A[(i + 0)*(NK * NJ) + (j + 1)*NK + (k + 0)] + c11 * A[(i - 1)*(NK * NJ) + (j - 1)*NK + (k + 1)] 25 | + c13 * A[(i + 1)*(NK * NJ) + (j - 1)*NK + (k + 1)] + c21 * A[(i - 1)*(NK * NJ) + (j + 0)*NK + (k + 1)] 26 | + c23 * A[(i + 1)*(NK * NJ) + (j + 0)*NK + (k + 1)] + c31 * A[(i - 1)*(NK * NJ) + (j + 1)*NK + (k + 1)] 27 | + c33 * A[(i + 1)*(NK * NJ) + (j + 1)*NK + (k + 1)]; 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /testsuite/cmake/FindLinProfiler.cmake: -------------------------------------------------------------------------------- 1 | MESSAGE(STATUS "LLVM_TOOLS_BINARY_DIR: ${LLVM_TOOLS_BINARY_DIR}") 2 | 3 | FIND_PATH(LLVM_BUILD_BIN_DIR lin-analyzer) 4 | #SET(LLVM_BUILD_BIN_DIR ${LLVM_BINARY_BIN}/"bin") 5 | MESSAGE(STATUS "LLVM_BUILD_BIN_DIR Found: ${LLVM_BUILD_BIN_DIR}") 6 | 7 | IF (LLVM_BUILD_BIN_DIR) 8 | #MESSAGE(STATUS "LLVM_TOOLS_BINARY_DIR") 9 | SET(LLVM_BIN_DIR_FOUND TRUE) 10 | SET(LIN-ANALYZER ${LLVM_BUILD_BIN_DIR}/lin-analyzer) 11 | MESSAGE(STATUS "LLVM_BUILD_BIN_DIR: ${LLVM_BUILD_BIN_DIR}") 12 | ENDIF (LLVM_BUILD_BIN_DIR) 13 | 14 | IF (LLVM_BIN_DIR_FOUND) 15 | MESSAGE(STATUS "LLVM_BUILD_BIN_DIR found!") 16 | ELSE (LLVM_BIN_DIR_FOUND) 17 | MESSAGE(FATAL_ERROR "ERROR: LLVM_BUILD_BIN_DIR NOT found!") 18 | ENDIF (LLVM_BIN_DIR_FOUND) 19 | 20 | IF (LLVM_BIN_DIR_FOUND AND CLANG) 21 | MESSAGE(STATUS "Found clang!") 22 | ELSE (LLVM_BIN_DIR_FOUND AND CLANG) 23 | SET(CLANG ${LLVM_BUILD_BIN_DIR}/clang) 24 | ENDIF (LLVM_BIN_DIR_FOUND AND CLANG) 25 | 26 | IF (LLVM_BIN_DIR_FOUND AND OPT) 27 | MESSAGE(STATUS "Found opt!") 28 | ELSE (LLVM_BIN_DIR_FOUND AND OPT) 29 | SET(OPT ${LLVM_BUILD_BIN_DIR}/opt) 30 | ENDIF (LLVM_BIN_DIR_FOUND AND OPT) 31 | 32 | IF (LLVM_BIN_DIR_FOUND AND LLC) 33 | MESSAGE(STATUS "Found llc!") 34 | ELSE (LLVM_BIN_DIR_FOUND AND LLC) 35 | SET(LLC ${LLVM_BUILD_BIN_DIR}/llc) 36 | ENDIF (LLVM_BIN_DIR_FOUND AND LLC) 37 | 38 | IF (LLVM_BIN_DIR_FOUND AND LLI) 39 | MESSAGE(STATUS "Found lli!") 40 | ELSE (LLVM_BIN_DIR_FOUND AND LLI) 41 | SET(LLI ${LLVM_BUILD_BIN_DIR}/lli) 42 | ENDIF (LLVM_BIN_DIR_FOUND AND LLI) 43 | 44 | IF (LLVM_BIN_DIR_FOUND AND LLVM_LINK) 45 | MESSAGE(STATUS "Found llvm-link") 46 | ELSE (LLVM_BIN_DIR_FOUND AND LLVM_LINK) 47 | SET(LLVM_LINK ${LLVM_BUILD_BIN_DIR}/llvm-link) 48 | ENDIF (LLVM_BIN_DIR_FOUND AND LLVM_LINK) 49 | 50 | MESSAGE(STATUS "Found all necessary binaries!") 51 | -------------------------------------------------------------------------------- /include/profile_h/AssignLoadStoreIDPass.h: -------------------------------------------------------------------------------- 1 | #ifndef ASSIGNLOADSTOREID_PASS_H 2 | #define ASSIGNLOADSTOREID_PASS_H 3 | 4 | #include "llvm/Pass.h" 5 | #include "llvm/IR/Module.h" 6 | #include "llvm/IR/InstVisitor.h" 7 | #include "llvm/Support/raw_ostream.h" 8 | #include "llvm/Support/Debug.h" 9 | #include "llvm/IR/Verifier.h" 10 | #include "llvm/ADT/SmallString.h" 11 | #include "llvm/IR/InstIterator.h" 12 | #include "llvm/ADT/Statistic.h" 13 | 14 | #include "profile_h/Passes.h" 15 | #include "profile_h/auxiliary.h" 16 | //#include "llvm/IR/BasicBlock.h" 17 | 18 | #include "llvm/Transforms/Scalar.h" 19 | #include "llvm/Analysis/LoopInfo.h" 20 | 21 | namespace llvm{ 22 | 23 | class AssignLoadStoreID : public ModulePass, 24 | public InstVisitor{ 25 | 26 | public: 27 | static char ID; 28 | AssignLoadStoreID(); 29 | 30 | void getAnalysisUsage(AnalysisUsage &AU) const; 31 | 32 | bool runOnModule(Module &M); 33 | 34 | void visitLoad(LoadInst& I); 35 | 36 | void visitStore(StoreInst& I); 37 | 38 | /* 39 | unsigned getlsID(Instruction* I) const; 40 | 41 | Instruction* getlsbylsID(unsigned lsid) const; 42 | 43 | unsigned getlsLineID(Instruction* I) const; 44 | 45 | unsigned getInstLineID(Instruction* I) const; 46 | 47 | Instruction* getInstbyInstLineID(unsigned instLineid) const; 48 | */ 49 | 50 | private: 51 | unsigned counter; 52 | unsigned instID; 53 | 54 | 55 | // Query ID of Load/Store instructions 56 | typedef std::map InstToIDMapTy; 57 | InstToIDMapTy Inst2IDmap; 58 | typedef std::map IDToInstMapTy; 59 | IDToInstMapTy ID2Instmap; 60 | /* 61 | typedef std::map InstLineToLoadStoreIDMapTy; 62 | InstLineToLoadStoreIDMapTy LineID2lsIDmap; 63 | std::map> lsInst2lsIDMap; 64 | typedef std::map LSIDToLSinstMapTy; 65 | LSIDToLSinstMapTy lsID2lsInstMap; 66 | */ 67 | 68 | NamedMDNode *NMD; 69 | 70 | MDNode* assignID(Instruction* I, unsigned id); 71 | }; 72 | 73 | } // End namespace LLVM 74 | 75 | #endif // End ASSIGNLOADSTOREID_PASS_H -------------------------------------------------------------------------------- /include/profile_h/QueryLoadStoreIDPass.h: -------------------------------------------------------------------------------- 1 | #ifndef QUERYLOADSTOREID_PASS_H 2 | #define QUERYLOADSTOREID_PASS_H 3 | 4 | #include "llvm/Pass.h" 5 | #include "llvm/IR/Module.h" 6 | //#include "llvm/IR/InstVisitor.h" 7 | #include "llvm/Support/raw_ostream.h" 8 | #include "llvm/Support/Debug.h" 9 | #include "llvm/IR/Verifier.h" 10 | #include "llvm/IR/Constants.h" 11 | #include "llvm/IR/Instructions.h" 12 | #include "llvm/IR/InstIterator.h" 13 | #include "llvm/ADT/Statistic.h" 14 | //#include "llvm/IR/BasicBlock.h" 15 | 16 | #include "profile_h/AssignLoadStoreIDPass.h" 17 | #include "profile_h/Passes.h" 18 | #include "profile_h/auxiliary.h" 19 | 20 | #include 21 | 22 | #include 23 | 24 | namespace llvm{ 25 | class QueryLoadStoreID : public ModulePass{ 26 | 27 | public: 28 | static char ID; 29 | QueryLoadStoreID(); 30 | 31 | void getAnalysisUsage(AnalysisUsage &AU) const; 32 | 33 | //unsigned getLoadStoreid(Instruction* I) const; 34 | 35 | //Instruction* getLoadStorebyID(unsigned id) const; 36 | 37 | bool runOnModule(Module &M); 38 | 39 | // Query function members 40 | unsigned getlsID(Instruction* I) const; 41 | 42 | Instruction* getlsbylsID(unsigned lsid) const; 43 | 44 | unsigned getlsLineID(Instruction* I) const; 45 | 46 | unsigned getInstLineID(Instruction* I) const; 47 | 48 | Instruction* getInstbyInstLineID(unsigned instLineid) const; 49 | 50 | BasicBlock* getBBbylsID(unsigned lsid) const; 51 | 52 | private: 53 | 54 | /* 55 | std::map INSTstr2IDMap; 56 | std::map INST2IDMap; 57 | std::map ID2INSTMap; 58 | */ 59 | 60 | // Query ID of Load/Store instructions 61 | typedef std::map InstToIDMapTy; 62 | //InstToIDMapTy Inst2IDmap; 63 | typedef std::map IDToInstMapTy; 64 | //IDToInstMapTy ID2Instmap; 65 | 66 | std::vector worklist; 67 | 68 | typedef std::map InstLineToLoadStoreIDMapTy; 69 | InstLineToLoadStoreIDMapTy LineID2lsIDmap; 70 | std::map> lsInst2lsIDMap; 71 | typedef std::map LSIDToLSinstMapTy; 72 | LSIDToLSinstMapTy lsID2lsInstMap; 73 | 74 | }; 75 | 76 | } // End namespace LLVM 77 | 78 | #endif // End QUERYLOADSTOREID_PASS_H -------------------------------------------------------------------------------- /lib/Build_DDDG/DynamicDatapath.cpp: -------------------------------------------------------------------------------- 1 | #include "profile_h/DynamicDatapath.h" 2 | 3 | DynamicDatapath::DynamicDatapath(std::string kernel_name, std::string trace_file_name, std::string input_path, std::string lp_name, unsigned lp_level, unsigned lp_unroll_factor, bool enable_pipelining, unsigned IL_asap) : BaseDatapath(kernel_name, trace_file_name, "", input_path, lp_name, lp_level, lp_unroll_factor, IL_asap) { 4 | std::cout << "===========================\n"; 5 | std::cout << "DEBUG-INFO: [trace-analysis_dynamic-trace] Analyzing DDDG for loop " << lp_name << "\n"; 6 | std::cout << "===========================\n"; 7 | 8 | /// Initialization 9 | // initialize_graph(); 10 | 11 | // FPGA flow 12 | //removeInductionDependence(); 13 | //removePhiNodes(); 14 | initBaseAddress(); 15 | 16 | /// completePartition() and scratchpadPartition() should be called when we enable optimization, otherwise it will 17 | /// make calculateFPGAResRequired(...) invoked by asap_scheduling(...) or alap_scheduling(...) failed because of 18 | /// modified array name 19 | //completePartition(); 20 | //scratchpadPartition(); 21 | //loopUnrolling(); 22 | 23 | //loopFlatten(); 24 | //calculateInstructionDistribution(); 25 | //calculateTimestampDDDG(); 26 | //parallelismProfileDDDG(); 27 | 28 | /// Schedule and Calculate execution cycles 29 | //uint64_t exe_cycles = run_fpga_simulation(); 30 | if (enable_pipelining == false) { 31 | 32 | if (show_dddg_bf_opt == true) { 33 | /// Output the Graph 34 | dumpGraph(); 35 | } 36 | 37 | uint64_t exe_cycles = fpga_estimation(); 38 | std::cout << "DEBUG-INFO: [trace-analysis_dynamic-trace] FPGA execution time = " << exe_cycles << "(cycles)" << std::endl; 39 | } 40 | else { 41 | VERBOSE_PRINT(std::cout << "DEBUG-INFO: [trace-analysis_dynamic-trace] Analyzing recurrence initiation interval\n"); 42 | IL_asap_ii = fpga_estimation_one_more_subtrace_for_recII_calculation(); 43 | } 44 | 45 | //uint64_t exe_cycles = run_parallel_simulation(); 46 | //cout << "Parallel Execution cycles = " << num_cycles << endl; 47 | 48 | // GPU flow 49 | VERBOSE_PRINT(std::cout << "DEBUG-INFO: [trace-analysis_dynamic-trace] Finished\n"); 50 | VERBOSE_PRINT(std::cout << "-------------------\n"); 51 | } 52 | 53 | DynamicDatapath::~DynamicDatapath() {} 54 | 55 | unsigned DynamicDatapath::getIL_asap_ii() const { 56 | return IL_asap_ii; 57 | } -------------------------------------------------------------------------------- /testsuite/Ecobench/mvt/abstract_kernel.c: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | Author: Guanwen Zhong 3 | Associated Filename: abstract_kernel.c 4 | Purpose: The abstract kernel wrapper for 2D Convolution kernel 5 | Origin: 2D Convolution benchmarch from Polybench GPU v1.0 6 | 7 | This benchmark is modified from cpu-based 2D Convolution application in 8 | Polybench GPU v1.0. For more information, please check: 9 | http://web.cse.ohio-state.edu/~pouchet/software/polybench/GPU/index.html 10 | 11 | ********************************************************************** 12 | Reserved. 13 | � Copyright 14 | 15 | **********************************************************************/ 16 | 17 | #include "abstract_kernel.h" 18 | 19 | DATA_TYPE hw_a[SIZE_A], hw_x1[SIZE], hw_x2[SIZE], hw_y1[SIZE], hw_y2[SIZE]; 20 | DATA_TYPE sw_a[SIZE_A], sw_x1[SIZE], sw_x2[SIZE], sw_y1[SIZE], sw_y2[SIZE]; 21 | 22 | void init(DATA_TYPE a[SIZE_A], DATA_TYPE x1[SIZE], DATA_TYPE x2[SIZE], DATA_TYPE y_1[SIZE], DATA_TYPE y_2[SIZE]) { 23 | 24 | int i, j; 25 | 26 | for (i=0; i 0.00001){ 76 | return -1; // Failure 77 | } 78 | } 79 | /* 80 | for (i=0; i 0.00001){ 82 | return -1; // Failure 83 | } 84 | } 85 | */ 86 | return 0; // Success 87 | } 88 | -------------------------------------------------------------------------------- /testsuite/Ecobench/atax/abstract_kernel.c: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | Author: Guanwen Zhong 3 | Associated Filename: abstract_kernel.c 4 | Purpose: The abstract kernel wrapper for 2D Convolution kernel 5 | Origin: 2D Convolution benchmarch from Polybench GPU v1.0 6 | 7 | This benchmark is modified from cpu-based 2D Convolution application in 8 | Polybench GPU v1.0. For more information, please check: 9 | http://web.cse.ohio-state.edu/~pouchet/software/polybench/GPU/index.html 10 | 11 | ********************************************************************** 12 | Reserved. 13 | � Copyright 14 | 15 | **********************************************************************/ 16 | 17 | #include "abstract_kernel.h" 18 | 19 | DATA_TYPE hw_A[SIZE_A], hw_x[SIZE_X], hw_y[SIZE_Y], hw_tmp[SIZE_TMP]; 20 | DATA_TYPE sw_A[SIZE_A], sw_x[SIZE_X], sw_y[SIZE_Y], sw_tmp[SIZE_TMP]; 21 | 22 | void init(DATA_TYPE x[SIZE_X], DATA_TYPE A[SIZE_A], DATA_TYPE y[SIZE_Y], DATA_TYPE tmp[SIZE_TMP]) { 23 | 24 | int i, j; 25 | 26 | for (i = 0; i < NX; i++) { 27 | x[i] = i * M_PI; 28 | for (j = 0; j < NY; j++) { 29 | A[i*NY + j] = ((DATA_TYPE) i*(j)) / NX; 30 | } 31 | } 32 | 33 | for (i= 0; i < NY; i++) { 34 | y[i] = 0; 35 | } 36 | 37 | for (i = 0; i < NX; i++) { 38 | tmp[i] = 0; 39 | } 40 | } 41 | 42 | void abstract_kernel (void * arguments) { 43 | 44 | init( hw_x, hw_A, hw_y, hw_tmp ); 45 | 46 | atax( hw_A, hw_x, /*hw_y,*/ hw_tmp ); 47 | 48 | } 49 | 50 | void atax_sw(DATA_TYPE A[SIZE_A], DATA_TYPE x[SIZE_X], /*DATA_TYPE y[SIZE_Y],*/ DATA_TYPE tmp[SIZE_TMP]) { 51 | int i,j; 52 | /* 53 | for (i= 0; i < NY; i++) { 54 | y[i] = 0; 55 | } 56 | */ 57 | for (i = 0; i < NX; i++) { 58 | tmp[i] = 0; 59 | 60 | for (j = 0; j < NY; j++) { 61 | tmp[i] = tmp[i] + A[i*NY + j] * x[j]; 62 | } 63 | /* 64 | for (j = 0; j < NY; j++) { 65 | y[j] = y[j] + A[i*NY + j] * tmp[i]; 66 | } 67 | */ 68 | } 69 | 70 | } 71 | 72 | int compare_result(char * input_fileName, char * hw_result) { 73 | 74 | init( sw_x, sw_A, sw_y, sw_tmp ); 75 | 76 | // Run software version 77 | atax_sw( sw_A, sw_x, /*sw_y,*/ sw_tmp ); 78 | 79 | int i; 80 | for (i=0; i 0.00001){ 82 | return -1; // Failure 83 | } 84 | } 85 | /* 86 | for (i=0; i 0.00001){ 88 | return -1; // Failure 89 | } 90 | }*/ 91 | 92 | return 0; // Success 93 | } 94 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #Modified from Shang cmakelist.txt 2 | cmake_minimum_required(VERSION 2.8) 3 | project(lin-profile) 4 | 5 | IF (MSVC) 6 | # Activate C++ exception handling 7 | IF (NOT CMAKE_CXX_FLAGS MATCHES "/EHsc") 8 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc") 9 | ENDIF () 10 | ENDIF (MSVC) 11 | 12 | set(LIN_PROF_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) 13 | set(LIN_PROF_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}) 14 | 15 | #if(MSVC) # Work around for the fucking msvc bug on rtti. 16 | set(LLVM_REQUIRES_RTTI 1) 17 | set(LLVM_ENABLE_EH 1) 18 | #endif (MSVC) 19 | 20 | # Set your project compile flags. 21 | # E.g. if using the C++ header files 22 | # you will need to enable C++11 support 23 | # for your compiler. 24 | 25 | #Add path for custom modules 26 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${LIN_PROF_SOURCE_DIR}/cmake") 27 | #MESSAGE(STATUS "CMAKE_MODULE_PATH: ${CMAKE_MODULE_PATH}") 28 | 29 | FIND_PACKAGE(BOOST REQUIRED) 30 | FIND_PACKAGE(ZLIB REQUIRED) 31 | 32 | include_directories( 33 | ${CMAKE_CURRENT_SOURCE_DIR}/include 34 | ${CMAKE_CURRENT_BINARY_DIR}/include 35 | ) 36 | 37 | IF (BOOST_FOUND) 38 | include_directories( ${BOOST_INCLUDE_DIR} ) 39 | MESSAGE(STATUS "ADD BOOST directory: ${BOOST_INCLUDE_DIR}") 40 | ADD_DEFINITIONS(-DBOOST_EXCEPTION_DISABLE) 41 | ENDIF (BOOST_FOUND) 42 | 43 | IF (ZLIB_FOUND) 44 | include_directories( ${ZLIB_INCLUDE_DIRS} ) 45 | MESSAGE(STATUS "ADD ZLIB directory: ${ZLIB_INCLUDE_DIRS}") 46 | ENDIF (ZLIB_FOUND) 47 | #MESSAGE(STATUS "LLVM_TOOLS_BINARY_DIR: ${LLVM_TOOLS_BINARY_DIR}") 48 | #MESSAGE(STATUS "CMAKE_CURRENT_BINARY_DIR: ${CMAKE_CURRENT_BINARY_DIR}") 49 | #MESSAGE(STATUS "LLVM_BINARY_DIR: ${LLVM_BINARY_DIR}") 50 | add_definitions( -D_GNU_SOURCE ) 51 | 52 | set(LLVM_LINK_COMPONENTS 53 | #$(LLVM_TARGETS_TO_BUILD) 54 | Support 55 | ) 56 | 57 | install(DIRECTORY include 58 | DESTINATION . 59 | PATTERN ".svn" EXCLUDE 60 | ) 61 | 62 | set(LLVM_LINK_COMPONENTS 63 | ${LLVM_TARGETS_TO_BUILD} 64 | Analysis 65 | BitWriter 66 | CodeGen 67 | Core 68 | IPA 69 | IPO 70 | IRReader 71 | InstCombine 72 | Instrumentation 73 | MC 74 | ObjCARCOpts 75 | ScalarOpts 76 | Support 77 | Target 78 | TransformUtils 79 | Vectorize 80 | ) 81 | 82 | #add a dummy file in lin-profile lib 83 | add_llvm_tool(lin-analyzer 84 | lin-profile.cpp 85 | ) 86 | 87 | target_link_libraries(lin-analyzer 88 | LLVMLinProfiler 89 | BuildDDDGlib 90 | #${ZLIB_LIBRARY} 91 | ) 92 | 93 | add_subdirectory(include) 94 | add_subdirectory(lib) 95 | # add_subdirectory(tools) 96 | 97 | OPTION(ENABLE_TESTSUITE "setup the testsuite environment for lin-analyzer" OFF) 98 | IF (ENABLE_TESTSUITE) 99 | add_subdirectory(testsuite) 100 | ENDIF (ENABLE_TESTSUITE) 101 | -------------------------------------------------------------------------------- /include/profile_h/Passes.h: -------------------------------------------------------------------------------- 1 | #ifndef PASSES_H 2 | #define PASSES_H 3 | 4 | namespace llvm{ 5 | class ModulePass; 6 | class Pass; 7 | 8 | /// GetInstDistribution Pass 9 | ModulePass *createGetInstDistributionPass(); 10 | void initializeGetInstDistributionPass(PassRegistry &Registry); 11 | 12 | /// AssignBasicBlockID Pass and QueryBasicBlockID Pass 13 | ModulePass *createAssignBasicBlockIDPass(); 14 | void initializeAssignBasicBlockIDPass(PassRegistry &Registry); 15 | 16 | ModulePass *createQueryBasicBlockIDPass(); 17 | void initializeQueryBasicBlockIDPass(PassRegistry &Registry); 18 | 19 | /// AssignLoadStoreID Pass and QueryLoadStoreID Pass 20 | ModulePass *createAssignLoadStoreIDPass(); 21 | void initializeAssignLoadStoreIDPass(PassRegistry &Registry); 22 | 23 | ModulePass *createQueryLoadStoreIDPass(); 24 | void initializeQueryLoadStoreIDPass(PassRegistry &Registry); 25 | 26 | /// ExtractLoopInfo Pass and LoopNumber Pass 27 | Pass* createExtractLoopInfoPass(); 28 | void initializeExtractLoopInfoPass(PassRegistry &Registry); 29 | 30 | Pass* createLoopNumberPass(); 31 | void initializeLoopNumberPass(PassRegistry &Registry); 32 | 33 | /// GetLoopBound pass 34 | ModulePass* createGetLoopBoundPass(); 35 | void initializeGetLoopBoundPass(PassRegistry &Registry); 36 | 37 | /// CodeInstrument Pass 38 | ModulePass* createCodeInstrumentPass(); 39 | void initializeCodeInstrumentPass(PassRegistry &Registry); 40 | 41 | /// AnalysisProfiling Pass 42 | ModulePass* createAnalysisProfilingPass(); 43 | void initializeAnalysisProfilingPass(PassRegistry &Registry); 44 | 45 | /// InstrumentForDDDG Pass 46 | ModulePass* createInstrumentForDDDGPass(); 47 | void initializeInstrumentForDDDGPass(PassRegistry &Registry); 48 | 49 | // Basic Block ID to frequency 50 | typedef std::map BBidFreqMap; 51 | typedef std::map BBFreqMap; 52 | // Basic Block ID to BBFreqMap 53 | typedef std::map BranchidFreqMap; 54 | typedef std::map BranchFreqMap; 55 | 56 | extern BBidFreqMap BBidFreq; 57 | extern BranchidFreqMap BranchIDFreq; 58 | 59 | // Calculate number of arithmatic operations for loops inside functions except for the "main" function 60 | // The map used to trace binary operators: (functionName, loopName) -> std::vector > fnlpNamePair2BinaryOpBBidMap. 61 | // After we get the basic block frequency, we can get the total number of binary operations executed by 62 | // multiplication. 63 | typedef std::map, std::vector > fnlpNamePair2BinaryOpBBidMapTy; 64 | extern fnlpNamePair2BinaryOpBBidMapTy fnlpNamePair2BinaryOpBBidMap; 65 | 66 | #ifdef _MSC_VER // If we use microsoft visual studio 67 | const uint32_t INITIAL_BIGVALUE = UINT_MAX; 68 | #else 69 | const uint32_t INITIAL_BIGVALUE = 0xffffffff; 70 | #endif 71 | 72 | } 73 | 74 | #endif // End PASSES_H -------------------------------------------------------------------------------- /include/profile_h/ExtractLoopInfoPass.h: -------------------------------------------------------------------------------- 1 | #ifndef EXTRACTLOOPINFOPASS_H 2 | #define EXTRACTLOOPINFOPASS_H 3 | 4 | #include "llvm/Pass.h" 5 | #include "llvm/IR/Module.h" 6 | #include "llvm/Analysis/LoopPass.h" 7 | #include "llvm/Analysis/LoopInfo.h" 8 | #include "llvm/Support/raw_os_ostream.h" 9 | #include "llvm/Support/Debug.h" 10 | #include "llvm/ADT/Statistic.h" 11 | #include "llvm/IR/Metadata.h" 12 | #include "llvm/Transforms/Scalar.h" 13 | #include "llvm/IR/Dominators.h" 14 | #include "llvm/Analysis/CFGPrinter.h" 15 | #include "llvm/IR/InstIterator.h" 16 | #include "llvm/Analysis/ScalarEvolution.h" 17 | 18 | #include "profile_h/QueryBasicBlockIDPass.h" 19 | #include "profile_h/QueryLoadStoreIDPass.h" 20 | #include "profile_h/LoopNumberPass.h" 21 | #include "profile_h/Passes.h" 22 | #include "profile_h/auxiliary.h" 23 | #include "profile_h/DDDG.h" 24 | 25 | namespace llvm { 26 | 27 | /// Basic Block --> Loop Level Map 28 | //typedef std::map BB2LoopLevelMapTy; 29 | /// Load/Store ID --> (Basic Block, Loop Level Map) Map 30 | typedef std::map > LSID2BBLoopLevelPairMapTy; 31 | /// Loop Name (NOT loop level) --> LSID2BBLoopLevelPairMapTy Map 32 | typedef std::map LoopID2LSInfoMapTy; 33 | /// Function Name --> vector Map 34 | typedef std::map Func2LoopInfoMapTy; 35 | 36 | class ExtractLoopInfo : public LoopPass { 37 | public: 38 | static char ID; 39 | 40 | ExtractLoopInfo(); 41 | bool doInitialization(Loop *lp, LPPassManager &LPM); 42 | void getAnalysisUsage(AnalysisUsage &AU) const; 43 | bool runOnLoop(Loop* lp, LPPassManager &LPM); 44 | bool isPerfectNest(Loop *L, LoopInfo* li); 45 | bool hasNoMemoryOps(BasicBlock *b); 46 | LoopID2LSInfoMapTy getFunc2LoopInfomap(std::string func_name) const; 47 | 48 | private: 49 | //LoopNumber* loopNumberpass; 50 | //QueryLoadStoreID* lsIDpass; 51 | 52 | //BB2LoopLevelMapTy BB2LoopLevelmap; 53 | LSID2BBLoopLevelPairMapTy LSID2_BB2LoopLevel_map; 54 | LoopID2LSInfoMapTy LoopID2LSInfomap; 55 | Func2LoopInfoMapTy Func2LoopInfomap; 56 | 57 | //std::vector LSID2BBLoopLevelMap_vec; 58 | //std::vector LoopID2LSInfoMap_vec; 59 | std::vector exploredFunc; 60 | unsigned loopID; 61 | unsigned depth; 62 | NamedMDNode* NMD; 63 | NamedMDNode* loopNumNMD; 64 | unsigned countNumLoopInaFunc; 65 | std::vector LoopsMetadataNode; 66 | //std::map funcName2loopNumMap; 67 | 68 | /// Load/Store Instruction -> Load/StoreID 69 | std::map > LoadStoreIDMap; 70 | std::map LineID2LSMap; 71 | NamedMDNode* recordLSMDNode; 72 | bool alreadyCheck; 73 | 74 | typedef std::map BB2BBidMapTy; 75 | BB2BBidMapTy BB2BBidMap; 76 | 77 | unsigned depth_record; 78 | 79 | std::vector exploredLoop; 80 | }; 81 | 82 | } // End namespace LLVM 83 | 84 | #endif // End of definition of EXTRACTLOOPINFOPASS_H -------------------------------------------------------------------------------- /include/profile_h/opcode_func.h: -------------------------------------------------------------------------------- 1 | #include "profile_h/xilinx_node_latency.h" 2 | 3 | #ifndef OPCODE_FUNC_H 4 | #define OPCODE_FUNC_H 5 | 6 | #define LLVM_IR_Move 0 7 | #define LLVM_IR_Ret 1 8 | #define LLVM_IR_Br 2 9 | #define LLVM_IR_Switch 3 10 | #define LLVM_IR_IndirectBr 4 11 | #define LLVM_IR_Invoke 5 12 | #define LLVM_IR_Resume 6 13 | #define LLVM_IR_Unreachable 7 14 | #define LLVM_IR_Add 8 15 | #define LLVM_IR_FAdd 9 16 | #define LLVM_IR_Sub 10 17 | #define LLVM_IR_FSub 11 18 | #define LLVM_IR_Mul 12 19 | #define LLVM_IR_FMul 13 20 | #define LLVM_IR_UDiv 14 21 | #define LLVM_IR_SDiv 15 22 | #define LLVM_IR_FDiv 16 23 | #define LLVM_IR_URem 17 24 | #define LLVM_IR_SRem 18 25 | #define LLVM_IR_FRem 19 26 | #define LLVM_IR_Shl 20 27 | #define LLVM_IR_LShr 21 28 | #define LLVM_IR_AShr 22 29 | #define LLVM_IR_And 23 30 | #define LLVM_IR_Or 24 31 | #define LLVM_IR_Xor 25 32 | #define LLVM_IR_Alloca 26 33 | #define LLVM_IR_Load 27 34 | #define LLVM_IR_Store 28 35 | #define LLVM_IR_GetElementPtr 29 36 | #define LLVM_IR_Fence 30 37 | #define LLVM_IR_AtomicCmpXchg 31 38 | #define LLVM_IR_AtomicRMW 32 39 | #define LLVM_IR_Trunc 33 40 | #define LLVM_IR_ZExt 34 41 | #define LLVM_IR_SExt 35 42 | #define LLVM_IR_FPToUI 36 43 | #define LLVM_IR_FPToSI 37 44 | #define LLVM_IR_UIToFP 38 45 | #define LLVM_IR_SIToFP 39 46 | #define LLVM_IR_FPTrunc 40 47 | #define LLVM_IR_FPExt 41 48 | #define LLVM_IR_PtrToInt 42 49 | #define LLVM_IR_IntToPtr 43 50 | #define LLVM_IR_BitCast 44 51 | #define LLVM_IR_AddrSpaceCast 45 52 | #define LLVM_IR_ICmp 46 53 | #define LLVM_IR_FCmp 47 54 | #define LLVM_IR_PHI 48 55 | #define LLVM_IR_Call 49 56 | #define LLVM_IR_Select 50 57 | #define LLVM_IR_VAArg 53 58 | #define LLVM_IR_ExtractElement 54 59 | #define LLVM_IR_InsertElement 55 60 | #define LLVM_IR_ShuffleVector 56 61 | #define LLVM_IR_ExtractValue 57 62 | #define LLVM_IR_InsertValue 58 63 | #define LLVM_IR_LandingPad 59 64 | #define LLVM_IR_DMAStore 98 65 | #define LLVM_IR_DMALoad 99 66 | #define LLVM_IR_IndexAdd 100 67 | #define LLVM_IR_IndexSub 102 68 | #define LLVM_IR_SilentStore 101 69 | 70 | bool is_associative(unsigned microop); 71 | bool is_fassociative(unsigned microop); 72 | bool is_memory_op(unsigned microop); 73 | bool is_compute_op(unsigned microop); 74 | bool is_store_op(unsigned microop); 75 | bool is_bit_op(unsigned microop); 76 | bool is_add_op(unsigned microop); 77 | bool is_mul_op(unsigned microop); 78 | bool is_load_op(unsigned microop); 79 | bool is_call_op(unsigned microop); 80 | bool is_branch_op (unsigned microop); 81 | bool is_phi_op(unsigned microop); 82 | bool is_control_op (unsigned microop); 83 | bool is_index_op (unsigned microop); 84 | bool is_dma_load(unsigned microop); 85 | bool is_dma_store(unsigned microop); 86 | bool is_dma_op(unsigned microop); 87 | bool is_fadd_op(unsigned microop); 88 | bool is_fsub_op(unsigned microop); 89 | bool is_fmul_op(unsigned microop); 90 | bool is_fdiv_op(unsigned microop); 91 | bool is_fcmp_op(unsigned microop); 92 | bool is_float_op(unsigned microop); 93 | unsigned fpga_node_latency (unsigned microop); 94 | 95 | #endif 96 | -------------------------------------------------------------------------------- /testsuite/Ecobench/run_hls.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import commands 4 | import subprocess 5 | 6 | root = os.getcwd() 7 | polybench = ['atax', 'bicg', 'convolution2d', 'convolution3d', 'correlation', 'covariance', 'fdtd2d', 'gemm', 'gesummv', 'gramschmidt', 'mm2', 'mm3', 'mvt', 'syr2k', 'syrk'] 8 | #polybench = ['atax'] 9 | reports = "report_repository" 10 | report_dir = root + '/' + reports 11 | subprocess.call(["mkdir", "-p", reports]) 12 | 13 | for name in polybench: 14 | print 'Working on kernel ' + name 15 | kernel_path = root + '/' + name 16 | #print kernel_path 17 | os.chdir(kernel_path) 18 | subprocess.call(["vivado_hls", "-f", "script.tcl"]) 19 | print 'Copy synthesized report into root folder' 20 | syn_rpt_name = kernel_path+'/'+name+'/solution1/syn/report/'+name+'_csynth.rpt' 21 | subprocess.call(["cp", syn_rpt_name, report_dir]) 22 | print 'Clean Vivado_HLS project for kernel ' + name 23 | subprocess.call(["rm", "-r", name]) 24 | os.chdir(root) 25 | print 'Kernel ' + name + ' Done!' 26 | 27 | print '\nParsing synthesized reports to obtain latency and area of each kernel' 28 | os.chdir(report_dir) 29 | temp_filenames = commands.getstatusoutput("ls .") 30 | filenames = temp_filenames[1].split('\n') 31 | #print temp_filenames 32 | result_dir = root+'/results' 33 | subprocess.call(["mkdir", "-p", result_dir]) 34 | clock_check_str = " | Clock | Target| Estimated| Uncertainty|\n" 35 | latency_check_str = " | Latency | Interval | Pipeline|\n" 36 | resources_check_str = "| Name | BRAM_18K| DSP48E| FF | LUT |\n" 37 | 38 | ecobenchResult = open(result_dir+'/ecobenchResult.csv', 'w') 39 | title_str = "Benchmark,Target Clock,Estimated Clock,Uncertainty,min Latency,max Latency,min Interval,max Interval,BRAM_18K,DSP48E,FF,LUT" 40 | ecobenchResult.write(title_str + '\n') 41 | print title_str 42 | for filename in filenames: 43 | f = open(report_dir + '/' + filename,'r') 44 | 45 | clock_str_enc = False 46 | clock_ct = 0 47 | 48 | lat_str_enc = False 49 | lat_ct = 0 50 | lat_found = False 51 | 52 | res_str_enc = False 53 | res_ct = 0 54 | 55 | out = '' 56 | 57 | kernel = filename.replace('_', ' ').split() 58 | kernel_name = kernel[0] 59 | for line in f: 60 | y = line.replace('|',' ').split() 61 | 62 | if(len(y)>=4 and y[0] == "Clock" and y[1] == "Target" and y[2] == "Estimated" and y[3] == "Uncertainty"): 63 | clock_str_enc = True 64 | if(clock_str_enc == True): 65 | clock_ct += 1 66 | if(clock_ct == 3): 67 | clock_ct = 0 68 | clock_str_enc = False 69 | x = line.replace('|', ' ').split() 70 | out += ',' + str(x[1]) + ',' + str(x[2]) + ',' + str(x[3]) 71 | 72 | if(lat_found == False and len(y)>=3 and y[0] == "Latency" and y[1] == "Interval" and y[2] == "Pipeline"): 73 | lat_str_enc = True 74 | if(lat_str_enc == True): 75 | lat_ct += 1 76 | if(lat_ct == 4): 77 | lat_ct = 0 78 | lat_str_enc = False 79 | lat_found = True 80 | 81 | x = line.replace('|',' ').split() 82 | out += ',' + str(long(x[0])) + ',' + str(long(x[1])) + ',' + str(long(x[2])) + ',' + str(long(x[3])) 83 | #out += ';' + str( (long(x[1]) + long(x[0]) )/2.0) 84 | #out += ';' + str( (long(x[3]) + long(x[2]) )/2.0) 85 | 86 | if(line == resources_check_str): 87 | res_str_enc = True 88 | if(res_str_enc == True): 89 | res_ct += 1 90 | if(res_ct == 11): 91 | res_ct = 0 92 | res_str_enc = False 93 | 94 | x = line.replace('|',' ').split() 95 | out += ',' + x[1] + ',' + x[2] + ',' + x[3] + ',' + x[4] 96 | break 97 | f.close() 98 | 99 | print kernel_name + out 100 | ecobenchResult.write(kernel_name + out + '\n') 101 | 102 | ecobenchResult.close() 103 | os.chdir(root) 104 | #print root 105 | print "Finish collecting ecobench FPGA results!\n" 106 | -------------------------------------------------------------------------------- /lib/Profile/QueryBasicBlockID.cpp: -------------------------------------------------------------------------------- 1 | #include "profile_h/QueryBasicBlockIDPass.h" 2 | 3 | #define DEBUG_TYPE "query-bb-id" 4 | using namespace llvm; 5 | 6 | static const char *mdKindName = "recordBBid"; // Record Basic Block ID 7 | 8 | QueryBasicBlockID::QueryBasicBlockID() : ModulePass(ID) { 9 | numOfBB = 0; 10 | counter = 0; 11 | numOfBB = 0; 12 | DEBUG(dbgs() << "Initialize QueryBasicBlockID pass\n"); 13 | initializeQueryBasicBlockIDPass(*PassRegistry::getPassRegistry()); 14 | } 15 | 16 | void QueryBasicBlockID::getAnalysisUsage(AnalysisUsage &AU) const { 17 | //AU.addRequired(); 18 | //AU.setPreservesCFG(); 19 | AU.setPreservesAll(); 20 | } 21 | 22 | unsigned QueryBasicBlockID::getBBid(BasicBlock* BB) const { 23 | std::map::const_iterator it; 24 | it = BB2IDMap.find(BB); 25 | if (it != BB2IDMap.end()) { 26 | return BB2IDMap.at(BB); 27 | } 28 | else { 29 | assert(false && "Error: Basic Block is not in the BB2IDMap\n"); 30 | return 1; 31 | } 32 | } 33 | 34 | BasicBlock* QueryBasicBlockID::getBBbyID(unsigned id) { 35 | std::map::const_iterator it; 36 | it = ID2BBMap.find(id); 37 | if (it != ID2BBMap.end()) { 38 | return ID2BBMap.at(id); 39 | } 40 | else { 41 | assert(false && "Error: Cannot find ID of the Basic Block!\n"); 42 | return NULL; 43 | } 44 | } 45 | 46 | bool QueryBasicBlockID::runOnModule(Module &M) { 47 | DEBUG(dbgs() << "\n\nBegin QueryBasicBlockID Pass :\n"); 48 | // Create a named Metadata node: 49 | 50 | NamedMDNode *NMD = M.getNamedMetadata(mdKindName); 51 | 52 | /// Scan the NamedMDNode we get and extract its BB-ID pairs 53 | /// Actually, we can remove the metadata for BB and function name 54 | for (unsigned i = 0; i < NMD->getNumOperands(); i++) { 55 | MDNode* node = NMD->getOperand(i); 56 | MDString* Funcmdstr = dyn_cast(node->getOperand(0)); 57 | std::string Func = Funcmdstr->getString(); 58 | MDString* BBmdstr = dyn_cast(node->getOperand(1)); 59 | std::string BB = BBmdstr->getString(); 60 | ConstantInt* ID = dyn_cast(node->getOperand(2)); 61 | unsigned id = static_cast (ID->getZExtValue()); 62 | //errs() << "BB = " << BBmdstr->getString() << " -> ID = " \ 63 | // << *ID << "\n"; 64 | BBstr2IDMap.insert(std::make_pair(Func+BB, id)); 65 | } 66 | 67 | // Convert BBstr to Basic Block 68 | std::vector::iterator fn_it; 69 | unsigned counter = 0; 70 | for (Module::iterator FI = M.begin(), FE = M.end(); FI != FE; ++FI) { 71 | if (FI->isDeclaration()) { 72 | continue; 73 | } 74 | fn_it = std::find(kernel_names.begin(), kernel_names.end(), FI->getName()); 75 | if (fn_it == kernel_names.end()) { 76 | // Ignore uninteresting functions 77 | continue; 78 | } 79 | for (Function::iterator BI = FI->begin(), BE = FI->end(); BI != BE; ++BI) { 80 | // Check if we have BB in BBstr2IDMap, then we store the BB with id into 81 | // BB2IDMap 82 | /* 83 | std::map::iterator it = BBstr2IDMap.find(BI->getName()); 84 | if (BBstr2IDMap.end() != it){ 85 | BB2IDMap.insert(std::make_pair(BI, it->second)); 86 | ID2BBMap.insert(std::make_pair(it->second, BI)); 87 | }*/ 88 | BB2IDMap.insert(std::make_pair(BI, counter)); 89 | ID2BBMap.insert(std::make_pair(counter, BI)); 90 | counter++; 91 | } 92 | } 93 | numOfBB = BB2IDMap.size(); 94 | if (numOfBB != counter) { 95 | assert(false && "Error: Number of Basic Block is wrong\n"); 96 | } 97 | 98 | //Verify the module 99 | std::string ErrorStr; 100 | raw_string_ostream OS(ErrorStr); 101 | if (verifyModule(M, &OS)){ 102 | errs() << OS.str() << "\n"; 103 | return false; 104 | } 105 | 106 | DEBUG(dbgs() << "\nEnd QueryBasicBlockID Pass\n\n"); 107 | return false; 108 | } 109 | 110 | uint64_t QueryBasicBlockID::getNumOfBB() const { 111 | return numOfBB; 112 | } 113 | 114 | char QueryBasicBlockID::ID = 0; 115 | INITIALIZE_PASS(QueryBasicBlockID, "queryBBid", 116 | "This pass is used to get the unique id of specific basic block", 117 | false, 118 | false 119 | ) 120 | 121 | ModulePass *llvm::createQueryBasicBlockIDPass() { 122 | return new QueryBasicBlockID(); 123 | } -------------------------------------------------------------------------------- /include/profile_h/SlotTracker.h: -------------------------------------------------------------------------------- 1 | #ifndef SLOTTRACKER_H 2 | #define SLOTTRACKER_H 3 | 4 | #include "llvm/ADT/DenseMap.h" 5 | #include "llvm/ADT/DenseMap.h" 6 | #include "llvm/ADT/SmallString.h" 7 | #include "llvm/ADT/StringExtras.h" 8 | #include "llvm/IR/Module.h" 9 | #include "llvm/IR/DebugInfo.h" 10 | #include "llvm/IR/DerivedTypes.h" 11 | #include "llvm/IR/ValueSymbolTable.h" 12 | #include "llvm/IR/IntrinsicInst.h" 13 | #include "llvm/IR/CallingConv.h" 14 | #include "llvm/Support/Debug.h" 15 | #include 16 | #include 17 | 18 | namespace llvm { 19 | 20 | /// MDNode map iterators. 21 | typedef DenseMap::iterator mdn_iterator; 22 | /// AttributeSet map iterators. 23 | typedef DenseMap::iterator as_iterator; 24 | 25 | class SlotTracker { 26 | public: 27 | 28 | /// ValueMap - A mapping of Values to slot numbers. 29 | typedef DenseMap ValueMap; 30 | 31 | /// Construct from a module 32 | explicit SlotTracker(const Module *M); 33 | /// Construct from a function, starting out in incorp state. 34 | explicit SlotTracker(const Function *F); 35 | 36 | /// Return the slot number of the specified value in it's type 37 | /// plane. If something is not in the SlotTracker, return -1. 38 | int getLocalSlot(const Value *V); 39 | int getGlobalSlot(const GlobalValue *V); 40 | int getMetadataSlot(const MDNode *N); 41 | int getAttributeGroupSlot(AttributeSet AS); 42 | 43 | /// If you'd like to deal with a function instead of just a module, use 44 | /// this method to get its data into the SlotTracker. 45 | void incorporateFunction(const Function *F); 46 | 47 | /// After calling incorporateFunction, use this method to remove the 48 | /// most recently incorporated function from the SlotTracker. This 49 | /// will reset the state of the machine back to just the module contents. 50 | void purgeFunction(); 51 | 52 | /// MDNode map iterators. 53 | mdn_iterator mdn_begin(); 54 | mdn_iterator mdn_end(); 55 | unsigned mdn_size() const; 56 | bool mdn_empty() const; 57 | 58 | /// AttributeSet map iterators. 59 | as_iterator as_begin(); 60 | as_iterator as_end(); 61 | unsigned as_size() const; 62 | bool as_empty() const; 63 | 64 | /// This function does the actual initialization. 65 | inline void initialize(); 66 | 67 | // Implementation Details 68 | private: 69 | /// TheModule - The module for which we are holding slot numbers. 70 | const Module* TheModule; 71 | 72 | /// TheFunction - The function for which we are holding slot numbers. 73 | const Function* TheFunction; 74 | bool FunctionProcessed; 75 | 76 | /// mMap - The slot map for the module level data. 77 | ValueMap mMap; 78 | unsigned mNext; 79 | 80 | /// fMap - The slot map for the function level data. 81 | ValueMap fMap; 82 | unsigned fNext; 83 | 84 | /// mdnMap - Map for MDNodes. 85 | DenseMap mdnMap; 86 | unsigned mdnNext; 87 | 88 | /// asMap - The slot map for attribute sets. 89 | DenseMap asMap; 90 | unsigned asNext; 91 | 92 | /// CreateModuleSlot - Insert the specified GlobalValue* into the slot table. 93 | void CreateModuleSlot(const GlobalValue *V); 94 | 95 | /// CreateMetadataSlot - Insert the specified MDNode* into the slot table. 96 | void CreateMetadataSlot(const MDNode *N); 97 | 98 | /// CreateFunctionSlot - Insert the specified Value* into the slot table. 99 | void CreateFunctionSlot(const Value *V); 100 | 101 | /// \brief Insert the specified AttributeSet into the slot table. 102 | void CreateAttributeSetSlot(AttributeSet AS); 103 | 104 | /// Add all of the module level global variables (and their initializers) 105 | /// and function declarations, but not the contents of those functions. 106 | void processModule(); 107 | 108 | /// Add all of the functions arguments, basic blocks, and instructions. 109 | void processFunction(); 110 | 111 | SlotTracker(const SlotTracker &) LLVM_DELETED_FUNCTION; 112 | void operator=(const SlotTracker &)LLVM_DELETED_FUNCTION; 113 | }; 114 | 115 | SlotTracker *createSlotTracker(const Module *M); 116 | static SlotTracker *createSlotTracker(const Value *V); 117 | 118 | } // End of llvm namespace 119 | 120 | #endif // End of SLOTTRACKER_H -------------------------------------------------------------------------------- /lib/Build_DDDG/TraceFunctions.cpp: -------------------------------------------------------------------------------- 1 | #include "profile_h/TraceFunctions.h" 2 | 3 | //FILE *full_trace_file; 4 | gzFile full_trace_file; 5 | 6 | int initp = 0; 7 | 8 | int inst_count = 0; 9 | 10 | void trace_logger_init() { 11 | std::string trace_file_name = inputPath + "dynamic_trace.gz"; 12 | //std::string trace_file_name = "dynamic_trace.gz"; 13 | //full_trace_file = fopen("dynamic_trace", "w"); 14 | //full_trace_file = fopen(trace_file_name.c_str(), "w"); 15 | full_trace_file = gzopen(trace_file_name.c_str(), "w"); 16 | 17 | //if (full_trace_file == NULL) { 18 | if (full_trace_file == Z_NULL) { 19 | //perror("Failed to open logfile \"dynamic_trace\""); 20 | //exit(-1); 21 | std::string err_str = "Error, can not open file " + trace_file_name; 22 | assert(false && err_str.c_str() ); 23 | } 24 | //atexit(trace_logger_fin); 25 | } 26 | 27 | void trace_logger_fin() { 28 | //fclose(full_trace_file); 29 | std::cout << "DEBUG-INFO: [profiling_trace-generation] Dynamic trace generated successfully\n"; 30 | gzclose(full_trace_file); 31 | } 32 | 33 | void trace_logger_log0(int line_number, char *name, char *bbid, char *instid, int opcode) { 34 | if (!initp) { 35 | trace_logger_init(); 36 | initp = 1; 37 | } 38 | //fprintf(full_trace_file, "\n0,%d,%s,%s,%s,%d,%d\n", line_number, name, bbid, instid, opcode, inst_count); 39 | gzprintf(full_trace_file, "\n0,%d,%s,%s,%s,%d,%d\n", line_number, name, bbid, instid, opcode, inst_count); 40 | inst_count++; 41 | } 42 | 43 | void trace_logger_log_int(int line, int size, int64_t value, int is_reg, char *label) { 44 | assert(initp == 1 && "initp is not equal to 1"); 45 | if (line == RESULT_LINE){ 46 | //fprintf(full_trace_file, "r,%d,%ld,%d,%s\n", size, value, is_reg, label); 47 | gzprintf(full_trace_file, "r,%d,%ld,%d,%s\n", size, value, is_reg, label); 48 | } 49 | else if (line == FORWARD_LINE){ 50 | //fprintf(full_trace_file, "f,%d,%ld,%d,%s\n", size, value, is_reg, label); 51 | gzprintf(full_trace_file, "f,%d,%ld,%d,%s\n", size, value, is_reg, label); 52 | } 53 | else{ 54 | //fprintf(full_trace_file, "%d,%d,%ld,%d,%s\n", line, size, value, is_reg, label); 55 | gzprintf(full_trace_file, "%d,%d,%ld,%d,%s\n", line, size, value, is_reg, label); 56 | } 57 | } 58 | 59 | void trace_logger_log_double(int line, int size, double value, int is_reg, char *label) { 60 | assert(initp == 1 && "initp is not equal to 1"); 61 | if (line == RESULT_LINE){ 62 | //fprintf(full_trace_file, "r,%d,%f,%d,%s\n", size, value, is_reg, label); 63 | gzprintf(full_trace_file, "r,%d,%f,%d,%s\n", size, value, is_reg, label); 64 | } 65 | else if (line == FORWARD_LINE){ 66 | //fprintf(full_trace_file, "f,%d,%f,%d,%s\n", size, value, is_reg, label); 67 | gzprintf(full_trace_file, "f,%d,%f,%d,%s\n", size, value, is_reg, label); 68 | } 69 | else{ 70 | //fprintf(full_trace_file, "%d,%d,%f,%d,%s\n", line, size, value, is_reg, label); 71 | gzprintf(full_trace_file, "%d,%d,%f,%d,%s\n", line, size, value, is_reg, label); 72 | } 73 | } 74 | 75 | void trace_logger_log_int_noreg(int line, int size, int64_t value, int is_reg) { 76 | assert(initp == 1 && "initp is not equal to 1"); 77 | if (line == RESULT_LINE){ 78 | //fprintf(full_trace_file, "r,%d,%ld,%d\n", size, value, is_reg); 79 | gzprintf(full_trace_file, "r,%d,%ld,%d\n", size, value, is_reg); 80 | } 81 | else if (line == FORWARD_LINE) { 82 | //fprintf(full_trace_file, "f,%d,%ld,%d\n", size, value, is_reg); 83 | gzprintf(full_trace_file, "f,%d,%ld,%d\n", size, value, is_reg); 84 | } 85 | else{ 86 | //fprintf(full_trace_file, "%d,%d,%ld,%d\n", line, size, value, is_reg); 87 | gzprintf(full_trace_file, "%d,%d,%ld,%d\n", line, size, value, is_reg); 88 | } 89 | } 90 | 91 | void trace_logger_log_double_noreg(int line, int size, double value, int is_reg) { 92 | assert(initp == 1 && "initp is not equal to 1"); 93 | if (line == RESULT_LINE) { 94 | //fprintf(full_trace_file, "r,%d,%f,%d\n", size, value, is_reg); 95 | gzprintf(full_trace_file, "r,%d,%f,%d\n", size, value, is_reg); 96 | } 97 | else if (line == FORWARD_LINE) { 98 | //fprintf(full_trace_file, "f,%d,%f,%d\n", size, value, is_reg); 99 | gzprintf(full_trace_file, "f,%d,%f,%d\n", size, value, is_reg); 100 | } 101 | else { 102 | //fprintf(full_trace_file, "%d,%d,%f,%d\n", line, size, value, is_reg); 103 | gzprintf(full_trace_file, "%d,%d,%f,%d\n", line, size, value, is_reg); 104 | } 105 | } -------------------------------------------------------------------------------- /include/profile_h/btree_set.h: -------------------------------------------------------------------------------- 1 | // Copyright 2013 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // A btree_set<> implements the STL unique sorted associative container 16 | // interface (a.k.a set<>) using a btree. A btree_multiset<> implements the STL 17 | // multiple sorted associative container interface (a.k.a multiset<>) using a 18 | // btree. See btree.h for details of the btree implementation and caveats. 19 | 20 | #ifndef UTIL_BTREE_BTREE_SET_H__ 21 | #define UTIL_BTREE_BTREE_SET_H__ 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | #include "btree.h" 28 | #include "btree_container.h" 29 | 30 | namespace btree { 31 | 32 | // The btree_set class is needed mainly for its constructors. 33 | template , 35 | typename Alloc = std::allocator, 36 | int TargetNodeSize = 256> 37 | class btree_set : public btree_unique_container< 38 | btree > > { 39 | 40 | typedef btree_set self_type; 41 | typedef btree_set_params params_type; 42 | typedef btree btree_type; 43 | typedef btree_unique_container super_type; 44 | 45 | public: 46 | typedef typename btree_type::key_compare key_compare; 47 | typedef typename btree_type::allocator_type allocator_type; 48 | 49 | public: 50 | // Default constructor. 51 | btree_set(const key_compare &comp = key_compare(), 52 | const allocator_type &alloc = allocator_type()) 53 | : super_type(comp, alloc) { 54 | } 55 | 56 | // Copy constructor. 57 | btree_set(const self_type &x) 58 | : super_type(x) { 59 | } 60 | 61 | // Range constructor. 62 | template 63 | btree_set(InputIterator b, InputIterator e, 64 | const key_compare &comp = key_compare(), 65 | const allocator_type &alloc = allocator_type()) 66 | : super_type(b, e, comp, alloc) { 67 | } 68 | }; 69 | 70 | template 71 | inline void swap(btree_set &x, btree_set &y) { 72 | x.swap(y); 73 | } 74 | 75 | // The btree_multiset class is needed mainly for its constructors. 76 | template , 78 | typename Alloc = std::allocator, 79 | int TargetNodeSize = 256> 80 | class btree_multiset : public btree_multi_container< 81 | btree > > { 82 | 83 | typedef btree_multiset self_type; 84 | typedef btree_set_params params_type; 85 | typedef btree btree_type; 86 | typedef btree_multi_container super_type; 87 | 88 | public: 89 | typedef typename btree_type::key_compare key_compare; 90 | typedef typename btree_type::allocator_type allocator_type; 91 | 92 | public: 93 | // Default constructor. 94 | btree_multiset(const key_compare &comp = key_compare(), 95 | const allocator_type &alloc = allocator_type()) 96 | : super_type(comp, alloc) { 97 | } 98 | 99 | // Copy constructor. 100 | btree_multiset(const self_type &x) 101 | : super_type(x) { 102 | } 103 | 104 | // Range constructor. 105 | template 106 | btree_multiset(InputIterator b, InputIterator e, 107 | const key_compare &comp = key_compare(), 108 | const allocator_type &alloc = allocator_type()) 109 | : super_type(b, e, comp, alloc) { 110 | } 111 | }; 112 | 113 | template 114 | inline void swap(btree_multiset &x, 115 | btree_multiset &y) { 116 | x.swap(y); 117 | } 118 | 119 | } // namespace btree 120 | 121 | #endif // UTIL_BTREE_BTREE_SET_H__ 122 | -------------------------------------------------------------------------------- /include/profile_h/InstrumentForDDDGPass.h: -------------------------------------------------------------------------------- 1 | #ifndef INSTRUMENT_FOR_DDDG_PASS_H 2 | #define INSTRUMENT_FOR_DDDG_PASS_H 3 | 4 | #include 5 | #include 6 | #include "llvm/Pass.h" 7 | #include "llvm/IR/BasicBlock.h" 8 | #include "llvm/IR/Constants.h" 9 | #include "llvm/IR/Instructions.h" 10 | #include "llvm/IR/Module.h" 11 | #include "llvm/IR/IRBuilder.h" 12 | #include "llvm/IR/Metadata.h" 13 | #include "llvm/IR/DebugInfo.h" 14 | #include "llvm/IR/Verifier.h" 15 | #include "llvm/ExecutionEngine/GenericValue.h" 16 | #include "llvm/ExecutionEngine/JIT.h" 17 | #include "llvm/Support/raw_os_ostream.h" 18 | #include "llvm/Support/Debug.h" 19 | #include "llvm/Support/ManagedStatic.h" 20 | #include "llvm/Support/TargetSelect.h" 21 | 22 | #include "llvm/Transforms/Utils/Cloning.h" 23 | #include "llvm/Transforms/Utils/ValueMapper.h" 24 | 25 | #include "profile_h/Passes.h" 26 | #include "profile_h/auxiliary.h" 27 | 28 | #include "profile_h/SlotTracker.h" 29 | #include "profile_h/TraceFunctions.h" 30 | #include "profile_h/generic_func.h" 31 | #include "profile_h/BaseDatapath.h" 32 | #include "profile_h/DDDG.h" 33 | #include "profile_h/DynamicDatapath.h" 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | #define NUM_OF_INTRINSICS 35 43 | #define NUM_OF_LLVM_INTRINSICS 33 44 | #define RESULT_LINE 19134 45 | #define FORWARD_LINE 24601 46 | #define DMA_STORE 98 47 | #define DMA_LOAD 99 48 | 49 | using namespace std; 50 | 51 | namespace llvm { 52 | 53 | class InstrumentForDDDG : public ModulePass { 54 | 55 | public: 56 | static char ID; 57 | InstrumentForDDDG(); 58 | void getAnalysisUsage(AnalysisUsage &AU) const; 59 | bool doInitialization(Module &M); 60 | bool runOnModule(Module &M); 61 | 62 | char ** str_split(char *a_str, const char a_delim, unsigned *size); 63 | int trace_or_not(char* func); 64 | bool is_tracking_function(string func); 65 | int getMemSize(Type *T); 66 | 67 | /// Function used to instrument LLVM-IR 68 | void print_line(BasicBlock::iterator itr, int line, int line_number, char *func_or_reg_id, 69 | char *bbID, char *instID, int opty, int datasize = 0, Value *value = NULL, 70 | bool is_reg = 0); 71 | 72 | void insertInstid(std::string inst_id, unsigned op_code); 73 | 74 | void insertInstid2bbName(std::string inst_id, std::string bbName); 75 | 76 | bool getInstId(Instruction *itr, char* bbid, char* instid, int &instc); 77 | 78 | void getBBId(Value *BB, char *bbid); 79 | 80 | bool performOnBasicBlock(BasicBlock &BB); 81 | 82 | void remove_config(std::string kernel_name, std::string input_path); 83 | void parse_config(std::string kernel_name, std::string input_path); 84 | void getUnrollingConfiguration(lpNameLevelPair2headBBnameMapTy& lpNameLvPair2headerBBMap); 85 | bool readUnrollingConfig(loopName2levelUnrollVecMapTy& lpName2levelUrPairVecMap, std::unordered_map &unrolling_config); 86 | 87 | void loopBasedTraceAnalysis(); 88 | 89 | void open_summary_file(ofstream& summary_file, std::string kernel_name); 90 | void close_summary_file(ofstream& summary_file); 91 | 92 | private: 93 | Function *TL_log0, *TL_log_int, *TL_log_double, *TL_log_int_noreg, *TL_log_double_noreg; 94 | Module *curr_module; 95 | 96 | SlotTracker *st; 97 | Function *curr_function; 98 | 99 | void extract_memory_trace_for_access_pattern(); 100 | 101 | char **functions; 102 | unsigned num_of_functions; 103 | 104 | //loopName2levelUnrollVecMapTy loopName2levelUnrollVecMap; 105 | std::unordered_map unrollingConfig; 106 | std::vector pipeline_loop_levelVec; 107 | }; 108 | 109 | //Embedded Profiler Engine 110 | class ProfilingEngine { 111 | 112 | public: 113 | 114 | ProfilingEngine(Module &M, Function* log0Fn, Function* log_intFn, Function* log_doubleFn, 115 | Function* log_int_noregFn, Function* log_double_noregFn); 116 | /* 117 | explicit EmbeddedProfilerEngine(Module &M, Function* loadFn, Function* storeFn) : 118 | Mod(M), RecordLoadFn(loadFn), RecordStoreFn(storeFn) {}*/ 119 | void runOnProfiler(); 120 | 121 | private: 122 | 123 | Module& Mod; 124 | 125 | Function* log0_Fn; 126 | Function* log_int_Fn; 127 | Function* log_double_Fn; 128 | Function* log_int_noreg_Fn; 129 | Function* log_double_noreg_Fn; 130 | 131 | }; 132 | 133 | struct ProfilingJITContext { 134 | ProfilingEngine *P; 135 | ProfilingJITContext(); 136 | 137 | private: 138 | //uint64_t LastBBid; 139 | }; 140 | 141 | struct ProfilingJITSingletonContext{ 142 | ProfilingJITSingletonContext(ProfilingEngine *P); 143 | ~ProfilingJITSingletonContext(); 144 | }; 145 | 146 | static ManagedStatic GlobalContextDDDG; 147 | 148 | } // End of llvm namespace 149 | 150 | #endif // End of INSTRUMENT_FOR_DDDG_PASS_H 151 | -------------------------------------------------------------------------------- /lib/Profile/LoopNumberPass.cpp: -------------------------------------------------------------------------------- 1 | /// Format of the NamedMDNode: 2 | /// !Loop_Number_of_kernel = !{!1, !2, !3, ...} 3 | /// !1 = metadata !{metadata !"matrixmul", metadata !"loop1"} 4 | /// !2 = metadata !{metadata !"matrixmul", metadata !"loop2"} 5 | /// !3 = metadata !{metadata !"main", metadata !"loop1"} 6 | /// ... 7 | 8 | /// Therefore, to get loop number in a function, we need to check the number of 9 | /// metadata node that contains the function name. 10 | /// 11 | 12 | #include "profile_h/LoopNumberPass.h" 13 | 14 | #define DEBUG_TYPE "loop-number" 15 | 16 | static const char *mdKindName = "Loop_Number_of_kernel"; 17 | 18 | using namespace llvm; 19 | 20 | LoopNumber::LoopNumber() : LoopPass(ID) { 21 | //func_hasLoop_number = 0; 22 | //loopNumInaFunc.clear(); 23 | loop_counter = 0; 24 | LoopsMetadataNode.clear(); 25 | DEBUG(dbgs() << "Initialize LoopNumber pass\n"); 26 | initializeLoopNumberPass(*PassRegistry::getPassRegistry()); 27 | } 28 | 29 | bool LoopNumber::doInitialization(Loop* lp, LPPassManager &LPM) { 30 | Module* M = lp->getHeader()->getParent()->getParent(); 31 | if (!M->getNamedMetadata(mdKindName)) { 32 | NMD = M->getOrInsertNamedMetadata(mdKindName); 33 | } 34 | 35 | return true; 36 | } 37 | 38 | void LoopNumber::getAnalysisUsage(AnalysisUsage &AU) const { 39 | AU.addRequired(); 40 | AU.addPreserved(); 41 | 42 | AU.addRequiredID(LoopSimplifyID); 43 | AU.addPreservedID(LoopSimplifyID); 44 | 45 | //AU.addRequiredID(LCSSAID); 46 | //AU.addPreservedID(LCSSAID); 47 | 48 | AU.setPreservesCFG(); 49 | AU.setPreservesAll(); 50 | // FIXME: Loop unroll requires LCSSA. And LCSSA requires dom info. 51 | // If loop unroll does not preserve dom info then LCSSA pass on next 52 | // loop will receive invalid dom info. 53 | // For now, recreate dom info, if loop is unrolled. 54 | //AU.addPreserved(); 55 | } 56 | 57 | bool LoopNumber::runOnLoop(Loop* lp, LPPassManager &LPM) { 58 | 59 | /// Check whether loop is in a simplify form 60 | if (!lp->isLoopSimplifyForm()) { 61 | assert(false && "Loop is not in a Simplify Form!\n"); 62 | } 63 | 64 | Function* func = lp->getHeader()->getParent(); 65 | /// Ignore uninterested functions 66 | std::vector::iterator fnName_it; 67 | fnName_it = std::find(kernel_names.begin(), kernel_names.end(), func->getName()); 68 | if (fnName_it == kernel_names.end()) { 69 | // This function is uninteresting, just ignore it. 70 | return false; 71 | } 72 | 73 | LLVMContext &Context = func->getContext(); 74 | 75 | std::vector::iterator it; 76 | it = std::find(exploredFunc.begin(), exploredFunc.end(), func); 77 | if (it == exploredFunc.end()) { 78 | // Reset loop counter for a new function. 79 | loop_counter = 0; 80 | exploredFunc.push_back(func); 81 | } 82 | 83 | /* 84 | std::string func_name = func->getName(); 85 | std::map::iterator it; 86 | it = loopNumInaFunc.find(func_name); 87 | if (it == loopNumInaFunc.end()) { 88 | // Create an entry of the map for this function and initialize the number 89 | // of loops in the function as 0 90 | loopNumInaFunc.insert(std::make_pair(func_name, 0)); 91 | MDString* func_MDname = MDString::get(Context, func->getName()); 92 | LoopsMetadataNode.push_back(func_MDname); 93 | // Initialize loop_counter 94 | loop_counter = 0; 95 | }*/ 96 | 97 | unsigned depth = lp->getLoopDepth(); 98 | /// Trace the top-level loop of a loop 99 | if (depth == 1) { 100 | loop_counter++; 101 | 102 | MDString* func_name = MDString::get(Context, func->getName()); 103 | LoopsMetadataNode.push_back(func_name); 104 | std::string loop_name = "loop" + std::to_string(loop_counter); 105 | LoopsMetadataNode.push_back(MDString::get(Context, loop_name)); 106 | MDNode* MD = MDNode::getWhenValsUnresolved(Context, ArrayRef(LoopsMetadataNode), false); 107 | NMD->addOperand(MD); 108 | LoopsMetadataNode.clear(); 109 | } 110 | 111 | /// Update loop number in a function 112 | //loopNumInaFunc[func_name] = loop_counter; 113 | 114 | return true; 115 | } 116 | 117 | /* 118 | unsigned LoopNumber::getNumberLoopOfFunc(std::string func_name) const{ 119 | return loopNumInaFunc.at(func_name); 120 | } 121 | 122 | unsigned LoopNumber::getNumberFuncHasLoop() const { 123 | return loopNumInaFunc.size(); 124 | }*/ 125 | 126 | char LoopNumber::ID = 0; 127 | INITIALIZE_PASS_BEGIN(LoopNumber, "LoopNumber", 128 | "This pass is used to calculate the number of loops inside functions.", 129 | false, 130 | true) 131 | INITIALIZE_PASS_DEPENDENCY(LoopInfo) 132 | INITIALIZE_PASS_DEPENDENCY(LoopSimplify) 133 | INITIALIZE_PASS_END(LoopNumber, "LoopNumber", 134 | "This pass is used to calculate the number of loops inside functions.", 135 | false, 136 | true) 137 | 138 | Pass* llvm::createLoopNumberPass() { 139 | return new LoopNumber(); 140 | } -------------------------------------------------------------------------------- /include/profile_h/DDDG.h: -------------------------------------------------------------------------------- 1 | #ifndef __DDDG_H__ 2 | #define __DDDG_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "profile_h/file_func.h" 15 | #include "profile_h/opcode_func.h" 16 | #include "profile_h/auxiliary.h" 17 | /*#define HANDLE_INST(num, opc, clas) case num: return opc;*/ 18 | using namespace std; 19 | 20 | struct edge_node_info{ 21 | unsigned sink_node; 22 | int par_id; 23 | }; 24 | 25 | //data structure used to tract dependency 26 | typedef unordered_map string_to_uint; 27 | typedef unordered_map uint_to_uint; 28 | typedef unordered_multimap multi_uint_to_node_info; 29 | typedef std::unordered_map instName2bbNameMapTy; 30 | typedef std::map, std::string> headerBBFuncNamePair2lastInstMapTy; 31 | typedef std::pair lpNameLevelStrPairTy; 32 | typedef std::map lpNameLevelPair2headBBnameMapTy; 33 | /// (Function Name, Basic Block Name) --> number of instructions in a BB Map 34 | typedef std::map, unsigned> funcBBNmPair2numInstInBBMapTy; 35 | //typedef std::map > loopName2levelLpBoundVecMapTy; 36 | typedef std::map > loopName2levelUnrollVecMapTy; 37 | typedef std::map > headerBBlastInst2loopNameLevelPairMapTy; 38 | typedef std::map wholeloopName2loopBoundMapTy; 39 | typedef std::map wholeloopName2perfectOrNotMapTy; 40 | 41 | extern instName2bbNameMapTy instName2bbNameMap; 42 | extern headerBBFuncNamePair2lastInstMapTy headerBBFuncNamePair2lastInstMap; 43 | extern headerBBFuncNamePair2lastInstMapTy exitingBBFuncNamePair2lastInstMap; 44 | extern lpNameLevelPair2headBBnameMapTy lpNameLevelPair2headBBnameMap; 45 | extern lpNameLevelPair2headBBnameMapTy lpNameLevelPair2exitingBBnameMap; 46 | extern funcBBNmPair2numInstInBBMapTy funcBBNmPair2numInstInBBMap; 47 | extern loopName2levelUnrollVecMapTy loopName2levelUnrollVecMap; 48 | extern wholeloopName2loopBoundMapTy wholeloopName2loopBoundMap; 49 | extern wholeloopName2perfectOrNotMapTy wholeloopName2perfectOrNotMap; 50 | //extern loopName2levelLpBoundVecMapTy loopName2levelLpBoundVecMap; 51 | 52 | namespace llvm { 53 | //funcBBNmPair2numInstInBBMapTy funcBBNmPair2numInstInBBMap; 54 | } 55 | 56 | typedef std::pair line_from_to_Ty; 57 | 58 | class BaseDatapath; 59 | 60 | class DDDG 61 | { 62 | 63 | private: 64 | BaseDatapath *datapath; 65 | std::string inputPath; 66 | 67 | public: 68 | DDDG(BaseDatapath *_datapath, std::string _trace_name, std::string input_path); 69 | int num_edges(); 70 | int num_nodes(); 71 | int num_of_register_dependency(); 72 | int num_of_memory_dependency(); 73 | void output_method_call_graph(std::string bench); 74 | void output_dddg(); 75 | bool build_initial_dddg(); 76 | 77 | private: 78 | line_from_to_Ty getTraceLineFromTo(std::string loopName, unsigned loopLevel, unsigned unroll_factor); 79 | void extract_trace_file(gzFile& trace_file); 80 | void extract_trace_file(gzFile& trace_file, uint64_t from, uint64_t to); 81 | void parse_instruction_line(std::string line); 82 | void parse_parameter(std::string line, int param_tag); 83 | void parse_result(std::string line); 84 | void parse_forward(std::string line); 85 | void parse_call_parameter(std::string line, int param_tag); 86 | 87 | std::string trace_name; 88 | std::string curr_dynamic_function; 89 | 90 | uint8_t curr_microop; 91 | uint8_t prev_microop; 92 | std::string prev_bblock; 93 | std::string curr_bblock; 94 | 95 | std::string callee_function; 96 | std::string callee_dynamic_function; 97 | 98 | bool last_parameter; 99 | int num_of_parameters; 100 | //Used to track the instruction that initialize call function parameters 101 | int last_call_source; 102 | 103 | std::string curr_instid; 104 | std::vector parameter_value_per_inst; 105 | std::vector parameter_size_per_inst; 106 | std::vector parameter_label_per_inst; 107 | std::vector method_call_graph; 108 | /*unordered_map to_ignore_methodid;*/ 109 | int num_of_instructions; 110 | int num_of_reg_dep; 111 | int num_of_mem_dep; 112 | 113 | //register dependency tracking table using hash_map(hash_map) 114 | //memory dependency tracking table 115 | //edge multimap 116 | multi_uint_to_node_info register_edge_table; 117 | multi_uint_to_node_info memory_edge_table; 118 | //keep track of currently executed methods 119 | stack active_method; 120 | //manage methods 121 | string_to_uint function_counter; 122 | string_to_uint register_last_written; 123 | uint_to_uint address_last_written; 124 | //loopName2levelLpBoundVecMapTy loopName2levelLpBoundVecMap; 125 | }; 126 | 127 | #endif 128 | -------------------------------------------------------------------------------- /include/profile_h/GetLoopBoundPass.h: -------------------------------------------------------------------------------- 1 | #ifndef GETLOOPBOUNDPASS_H 2 | #define GETLOOPBOUNDPASS_H 3 | 4 | #include "llvm/Pass.h" 5 | #include "llvm/IR/Module.h" 6 | #include "llvm/IR/InstVisitor.h" 7 | #include "llvm/Support/raw_ostream.h" 8 | #include "llvm/Support/Debug.h" 9 | #include "llvm/IR/Verifier.h" 10 | #include "llvm/ADT/SmallString.h" 11 | #include "llvm/IR/InstIterator.h" 12 | #include "llvm/ADT/Statistic.h" 13 | #include "llvm/ExecutionEngine/GenericValue.h" 14 | #include "llvm/Transforms/Utils/Cloning.h" 15 | #include "llvm/IR/DataLayout.h" 16 | #include "llvm/ExecutionEngine/JIT.h" 17 | #include "llvm/Support/ManagedStatic.h" 18 | #include "llvm/Support/TargetSelect.h" 19 | #include "llvm/Transforms/Utils/ValueMapper.h" 20 | #include "llvm/Bitcode/ReaderWriter.h" 21 | #include "llvm/Support/ToolOutputFile.h" 22 | #include "llvm/Support/FileSystem.h" 23 | #include "llvm/Support/CommandLine.h" 24 | //#include "llvm/IR/BasicBlock.h" 25 | 26 | #include "profile_h/Passes.h" 27 | #include "profile_h/auxiliary.h" 28 | #include "profile_h/ExtractLoopInfoPass.h" 29 | #include "profile_h/QueryBasicBlockIDPass.h" 30 | #include "profile_h/QueryLoadStoreIDPass.h" 31 | #include "profile_h/lin-profile.h" 32 | //#include "profile_h/CodeInstrumentPass.h" 33 | 34 | #include "llvm/Transforms/Scalar.h" 35 | #include "llvm/Analysis/LoopInfo.h" 36 | 37 | #include 38 | 39 | static llvm::cl::opt 40 | OutputModifiedLBBCFilename("o", llvm::cl::desc(""), llvm::cl::value_desc("filename")); 41 | 42 | namespace llvm { 43 | 44 | class GetLoopBound : public ModulePass { 45 | 46 | public: 47 | static char ID; 48 | ValueToValueMapTy VMap; 49 | 50 | GetLoopBound(); 51 | void getAnalysisUsage(AnalysisUsage &AU) const; 52 | bool doInitialization(Module &M); 53 | bool runOnModule(Module &M); 54 | 55 | void getLoopBBID2HeaderAndloopDepthPairMap(Module &M); 56 | bool isLoopHeader(uint64_t bbid); 57 | void getHeaderID_list_vec(Module &M); 58 | void extract_loopInfo_inFunc(Module &M); 59 | void calculateLoopBound(Function* func); 60 | 61 | private: 62 | const DataLayout* DL; 63 | QueryBasicBlockID* bbIDpass; 64 | QueryLoadStoreID* lsIDpass; 65 | 66 | Type* Int64Type; 67 | Type* VoidType; 68 | Type* VoidPtrType; 69 | 70 | Type* VoidPtrBBType; 71 | 72 | Function* BBFreqIncFn; 73 | Function* RecordLoadFn; 74 | Function* RecordStoreFn; 75 | BasicBlock* LastBB; 76 | 77 | Module* NewM; 78 | 79 | //typedef std::map > loop2subloopMapTy; 80 | loop2subloopMapTy loop2subloopMap; 81 | std::map subloopDepthandLoopBound; 82 | 83 | /// Loop Basic Block ID --> (the corresponding Loop Header BB id, loop depth) 84 | //typedef std::map > loopBBid2HeaderAndloopDepthPairMapTy; 85 | //loopBBid2HeaderAndloopDepthPairMapTy loopBBid2HeaderAndloopDepthPairMap; 86 | 87 | /// headerID_list_vec contains a vector of headerID_list 88 | /// headerID_list: The header BB id of the innermost loop --> The header BB id of the outermost loop 89 | //typedef std::vector > headerID_list_vecTy; 90 | //headerID_list_vecTy headerID_list_vec; 91 | 92 | //typedef std::map funcName2headIDlistVecMapTy; 93 | //funcName2headIDlistVecMapTy funcName2headIDlistVecMap; 94 | 95 | std::vector functionNameVec; 96 | 97 | void instrumentFunction(Function* F); 98 | 99 | void instrumentBasicBlock(BasicBlock* BB); 100 | 101 | void insertCounterBefore(Instruction* Inst, bool Increase, bool edgeIncrease); 102 | 103 | void write_Modified_bitcode_to_File(); 104 | }; 105 | 106 | //Embedded Profiler Engine 107 | class EmbeddedProfilerEngine_lb { 108 | 109 | public: 110 | 111 | //BBidFreqMap BBFreq; 112 | //BranchidFreqMap BranchFreq; 113 | 114 | EmbeddedProfilerEngine_lb(Module &M, Function* bbFreqfn); 115 | /* 116 | explicit EmbeddedProfilerEngine(Module &M, Function* loadFn, Function* storeFn) : 117 | Mod(M), RecordLoadFn(loadFn), RecordStoreFn(storeFn) {}*/ 118 | 119 | void runOnProfiler(); 120 | 121 | //void increaseEdgeCounter(BasicBlock* src, BasicBlock* dest); 122 | void increaseEdgeCounter(uint64_t src_id, uint64_t dest_id, uint64_t increase_edge); 123 | 124 | uint64_t getBBidFreq(uint64_t BBid) const; 125 | 126 | uint64_t getBranchFreq(uint64_t Src_id, uint64_t Dest_id) const; 127 | 128 | private: 129 | 130 | Module& Mod; 131 | Function* BBFreqFn; 132 | 133 | //ValueToValueMapTy V2VMap; 134 | //typedef std::map BBFreqMap; 135 | //typedef std::map BranchFreqMap; 136 | 137 | /// Used in VerifyProfile() 138 | //BBFreqMap BBFreq; 139 | //BranchFreqMap BranchFreq; 140 | 141 | void VerifyProfile(); 142 | }; 143 | 144 | struct ProfilerJITContext_lb { 145 | EmbeddedProfilerEngine_lb *P; 146 | ProfilerJITContext_lb(); 147 | uint64_t getLastBB() const { 148 | return LastBBid; 149 | } 150 | 151 | void setLastBB(uint64_t lastbbid) { 152 | LastBBid = lastbbid; 153 | } 154 | private: 155 | uint64_t LastBBid; 156 | }; 157 | 158 | struct ProfilerJITSingletonContext_lb{ 159 | ProfilerJITSingletonContext_lb(EmbeddedProfilerEngine_lb *P); 160 | ~ProfilerJITSingletonContext_lb(); 161 | }; 162 | 163 | static ManagedStatic GlobalContext_lb; 164 | 165 | } // End namespace LLVM 166 | 167 | namespace { 168 | std::vector EntryBBid_vec; 169 | } 170 | 171 | #endif // End of GETLOOPBOUNDPASS_H -------------------------------------------------------------------------------- /include/profile_h/auxiliary.h: -------------------------------------------------------------------------------- 1 | #ifndef AUXILIARY_H 2 | #define AUXILIARY_H 3 | 4 | #include "llvm/Support/Timer.h" 5 | #include "llvm/IR/BasicBlock.h" 6 | #define ENABLE_TIMER 7 | 8 | #include 9 | #include 10 | 11 | #ifdef ENABLE_BTREE_MAP 12 | #include "profile_h/btree_map.h" 13 | #endif // End of ENABLE_BTREE_MAP 14 | 15 | #define READ_PORT_PER_PARTITION 2 16 | #define WRITE_PORT_PER_PARTITION 1 17 | #define MAX_WRITE_PORT_PER_PARTITION (WRITE_PORT_PER_PARTITION+1) 18 | 19 | #define INFINITE_HARDWARE 999999999 20 | 21 | extern std::string inputFileName; 22 | extern std::string inputPath; 23 | extern std::string outputPath; 24 | extern std::string config_filename; 25 | extern std::vector kernel_names; 26 | extern bool enable_profiling_time_only; 27 | extern bool memory_trace_gen; 28 | extern bool enable_no_trace; 29 | extern bool show_cfg_detailed; 30 | extern bool show_cfg_only; 31 | extern bool show_dddg_bf_opt; 32 | extern bool show_dddg_af_opt; 33 | extern bool verbose_print; 34 | extern bool enable_store_buffer; 35 | extern bool enable_shared_load_removal; 36 | extern bool disable_shared_load_removal; 37 | extern bool enable_repeated_store_removal; 38 | extern bool enable_memory_disambiguation; 39 | extern bool enable_tree_height_reduction_float; 40 | extern bool enable_tree_height_reduction_integer; 41 | extern bool increase_load_latency; 42 | extern bool disable_fp_unit_threshold; 43 | extern bool enable_extra_scalar; 44 | extern bool enable_rw_rw_memory; 45 | extern bool target_vc707; 46 | extern std::vector target_loops; 47 | extern std::ofstream summary; 48 | 49 | typedef std::map getElementPtrName2arrayNameMapTy; 50 | extern getElementPtrName2arrayNameMapTy getElementPtrName2arrayNameMap; 51 | 52 | #define VERBOSE_PRINT(X) \ 53 | do { if (verbose_print) { X; } \ 54 | } while (0) 55 | 56 | namespace llvm { 57 | typedef std::pair fn_lpNamePairTy; 58 | 59 | /// FunctionName --> number of loops inside it 60 | typedef std::map funcName2loopNumMapTy; 61 | extern funcName2loopNumMapTy funcName2loopNumMap; 62 | 63 | /// Loop Basic Block ID --> (the corresponding Loop Header BB id, loop depth) 64 | #ifdef ENABLE_BTREE_MAP 65 | typedef btree::btree_map > loopBBid2HeaderAndloopDepthPairMapTy; 66 | #else 67 | typedef std::map > loopBBid2HeaderAndloopDepthPairMapTy; 68 | #endif // End of ENABLE_BTREE_MAP 69 | extern loopBBid2HeaderAndloopDepthPairMapTy loopBBid2HeaderAndloopDepthPairMap; 70 | 71 | /// headerID_list_vec contains a vector of headerID_list 72 | /// headerID_list: The header BB id of the innermost loop --> The header BB id of the outermost loop 73 | typedef std::vector > headerID_list_vecTy; 74 | extern headerID_list_vecTy headerID_list_vec; 75 | 76 | typedef std::map funcName2headIDlistVecMapTy; 77 | extern funcName2headIDlistVecMapTy funcName2headIDlistVecMap; 78 | 79 | //typedef std::map > > loop2subloopMapTy; 80 | /// loopName --> subloop map 81 | typedef std::map > loop2subloopMapTy; 82 | 83 | typedef std::map func2loopInfoMapTy; 84 | extern func2loopInfoMapTy func2loopInfoMap; 85 | 86 | typedef std::map > funcName2loopsMapTy; 87 | extern funcName2loopsMapTy funcName2loopsMap; 88 | 89 | /// loopName2BoundList: the whole loop name -> loop bounds list 90 | /// Loop bounds sequence: 91 | /// The top-level loop -> lower-level loop -> ... -> the innermost-level loop 92 | typedef std::map > loopName2BoundListTy; 93 | typedef std::map funcName2loopBoundsTy; 94 | extern funcName2loopBoundsTy funcName2loopBounds; 95 | 96 | /// Used to recognize the relationship between basic block ids and loop name 97 | typedef std::map BBids2loopNameMapTy; 98 | extern BBids2loopNameMapTy BBids2loopNameMap; 99 | 100 | typedef std::map BB2loopNameMapTy; 101 | extern BB2loopNameMapTy BB2loopNameMap; 102 | 103 | typedef std::map funcName2loopInfoMapTy; 104 | extern funcName2loopInfoMapTy funcName2loopInfoMap; 105 | 106 | #ifdef ENABLE_BTREE_MAP 107 | typedef btree::btree_map > lpBBid2EvalIterIndxMapTy; 108 | #else 109 | typedef std::map > lpBBid2EvalIterIndxMapTy; 110 | #endif // End of ENABLE_BTREE_MAP 111 | extern lpBBid2EvalIterIndxMapTy lpBBid2EvalIterIndxMap; 112 | 113 | /// Header Basic Block ID --> loop bound Map 114 | typedef std::map BBheaderID2loopBoundMapTy; 115 | extern BBheaderID2loopBoundMapTy BBheaderID2loopBoundMap; 116 | 117 | typedef std::pair bbFuncNamePairTy; 118 | typedef std::pair lpNameLevelPairTy; 119 | typedef std::map LpName2numLevelMapTy; 120 | typedef std::map bbFuncNamePair2lpNameLevelPairMapTy; 121 | 122 | extern bbFuncNamePair2lpNameLevelPairMapTy bbFuncNamePair2lpNameLevelPairMap; 123 | extern bbFuncNamePair2lpNameLevelPairMapTy headerBBFuncnamePair2lpNameLevelPairMap; 124 | extern bbFuncNamePair2lpNameLevelPairMapTy exitBBFuncnamePair2lpNameLevelPairMap; 125 | extern LpName2numLevelMapTy LpName2numLevelMap; 126 | 127 | } 128 | 129 | #endif // End of AUXILIARY_H -------------------------------------------------------------------------------- /include/profile_h/btree_map.h: -------------------------------------------------------------------------------- 1 | // Copyright 2013 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // A btree_map<> implements the STL unique sorted associative container 16 | // interface and the pair associative container interface (a.k.a map<>) using a 17 | // btree. A btree_multimap<> implements the STL multiple sorted associative 18 | // container interface and the pair associtive container interface (a.k.a 19 | // multimap<>) using a btree. See btree.h for details of the btree 20 | // implementation and caveats. 21 | 22 | #ifndef UTIL_BTREE_BTREE_MAP_H__ 23 | #define UTIL_BTREE_BTREE_MAP_H__ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "btree.h" 33 | #include "btree_container.h" 34 | 35 | namespace btree { 36 | 37 | // The btree_map class is needed mainly for its constructors. 38 | template , 40 | typename Alloc = std::allocator >, 41 | int TargetNodeSize = 256> 42 | class btree_map : public btree_map_container< 43 | btree > > { 44 | 45 | typedef btree_map self_type; 46 | typedef btree_map_params< 47 | Key, Value, Compare, Alloc, TargetNodeSize> params_type; 48 | typedef btree btree_type; 49 | typedef btree_map_container super_type; 50 | 51 | public: 52 | typedef typename btree_type::key_compare key_compare; 53 | typedef typename btree_type::allocator_type allocator_type; 54 | 55 | public: 56 | // Default constructor. 57 | btree_map(const key_compare &comp = key_compare(), 58 | const allocator_type &alloc = allocator_type()) 59 | : super_type(comp, alloc) { 60 | } 61 | 62 | // Copy constructor. 63 | btree_map(const self_type &x) 64 | : super_type(x) { 65 | } 66 | 67 | // Range constructor. 68 | template 69 | btree_map(InputIterator b, InputIterator e, 70 | const key_compare &comp = key_compare(), 71 | const allocator_type &alloc = allocator_type()) 72 | : super_type(b, e, comp, alloc) { 73 | } 74 | 75 | // At function 76 | const Value& at(const Key& key) const { 77 | auto begin_iter = super_type::equal_range(key).first; 78 | if (begin_iter != super_type::end()) { 79 | return begin_iter->second; 80 | } 81 | else { 82 | throw std::out_of_range("btree_map::at"); 83 | } 84 | } 85 | Value& at(const Key& key) { 86 | auto begin_iter = super_type::equal_range(key).first; 87 | if (begin_iter != super_type::end()) { 88 | return begin_iter->second; 89 | } 90 | else { 91 | throw std::out_of_range("btree_map::at"); 92 | } 93 | } 94 | }; 95 | 96 | template 97 | inline void swap(btree_map &x, 98 | btree_map &y) { 99 | x.swap(y); 100 | } 101 | 102 | // The btree_multimap class is needed mainly for its constructors. 103 | template , 105 | typename Alloc = std::allocator >, 106 | int TargetNodeSize = 256> 107 | class btree_multimap : public btree_multi_container< 108 | btree > > { 109 | 110 | typedef btree_multimap self_type; 111 | typedef btree_map_params< 112 | Key, Value, Compare, Alloc, TargetNodeSize> params_type; 113 | typedef btree btree_type; 114 | typedef btree_multi_container super_type; 115 | 116 | public: 117 | typedef typename btree_type::key_compare key_compare; 118 | typedef typename btree_type::allocator_type allocator_type; 119 | typedef typename btree_type::data_type data_type; 120 | typedef typename btree_type::mapped_type mapped_type; 121 | 122 | public: 123 | // Default constructor. 124 | btree_multimap(const key_compare &comp = key_compare(), 125 | const allocator_type &alloc = allocator_type()) 126 | : super_type(comp, alloc) { 127 | } 128 | 129 | // Copy constructor. 130 | btree_multimap(const self_type &x) 131 | : super_type(x) { 132 | } 133 | 134 | // Range constructor. 135 | template 136 | btree_multimap(InputIterator b, InputIterator e, 137 | const key_compare &comp = key_compare(), 138 | const allocator_type &alloc = allocator_type()) 139 | : super_type(b, e, comp, alloc) { 140 | } 141 | }; 142 | 143 | template 144 | inline void swap(btree_multimap &x, 145 | btree_multimap &y) { 146 | x.swap(y); 147 | } 148 | 149 | } // namespace btree 150 | 151 | #endif // UTIL_BTREE_BTREE_MAP_H__ 152 | -------------------------------------------------------------------------------- /lib/Profile/AssignBasicBlockID.cpp: -------------------------------------------------------------------------------- 1 | #include "profile_h/AssignBasicBlockIDPass.h" 2 | 3 | #define DEBUG_TYPE "assign-bb-id" 4 | using namespace llvm; 5 | 6 | static const char *mdKindName = "recordBBid"; // Record Basic Block ID 7 | 8 | funcBBNmPair2numInstInBBMapTy funcBBNmPair2numInstInBBMap; 9 | getElementPtrName2arrayNameMapTy getElementPtrName2arrayNameMap; 10 | 11 | AssignBasicBlockID::AssignBasicBlockID() : ModulePass(ID) { 12 | errs() << "===========================\n"; 13 | errs() << "DEBUG-INFO: [static-analysis_bb-info-extraction] Extracting basic block information\n"; 14 | errs() << "===========================\n"; 15 | counter = 0; 16 | DEBUG(dbgs() << "Initialize AssignBasicBlockID pass\n"); 17 | initializeAssignBasicBlockIDPass(*PassRegistry::getPassRegistry()); 18 | } 19 | 20 | void AssignBasicBlockID::getAnalysisUsage(AnalysisUsage &AU) const { 21 | //AU.addRequiredID(LoopSimplifyID); 22 | //AU.addPreservedID(LoopSimplifyID); 23 | 24 | //AU.addRequiredID(LCSSAID); 25 | //AU.addPreservedID(LCSSAID); 26 | 27 | AU.setPreservesCFG(); 28 | } 29 | 30 | bool AssignBasicBlockID::runOnModule(Module &M) { 31 | DEBUG(dbgs() << "\n\nBegin AssignBasicBlockID Pass :\n"); 32 | // Create a named Metadata node: 33 | NamedMDNode *NMD = M.getOrInsertNamedMetadata(mdKindName); 34 | 35 | // Initialize BB ID 36 | counter = 0; 37 | 38 | // Scan through all basic block in the module and assign unique ID 39 | Module::iterator FI, FE; 40 | Function::iterator BI, BE; 41 | BasicBlock::iterator bbit, bbie; 42 | for (FI = M.begin(), FE = M.end(); FI != FE; ++FI) { 43 | //runOnFunction(*FI); 44 | if (FI->isDeclaration()) { 45 | continue; 46 | } 47 | 48 | std::vector::iterator it; 49 | it = std::find(kernel_names.begin(), kernel_names.end(), FI->getName()); 50 | if (it == kernel_names.end()) { 51 | // We are not interested in this function 52 | continue; 53 | } 54 | 55 | std::string func_name = FI->getName(); 56 | DEBUG(dbgs() << "Function name = " << func_name << "\n"); 57 | for (BI = FI->begin(), BE = FI->end(); BI != BE; ++BI) { 58 | NMD->addOperand(assignID(BI, counter)); 59 | counter++; 60 | 61 | // Count instructions inside a basic block 62 | unsigned num_inst = 0; 63 | std::string bb_name = BI->getName(); 64 | DEBUG(dbgs() << "BB name = " << bb_name << "\n"); 65 | for (bbit = BI->begin(), bbie = BI->end(); bbit != bbie; ++bbit) { 66 | if (CallInst* CI = dyn_cast(bbit)) { 67 | if (CI->isTailCall() == false) { 68 | num_inst++; 69 | } 70 | else { 71 | // Do not count for tail call instructions. 72 | //errs() << "This call instruction is a tail call\n"; 73 | } 74 | } 75 | else { 76 | //errs() << *bbit << "\n"; 77 | num_inst++; 78 | } 79 | 80 | if (GetElementPtrInst* getElePtrInst = dyn_cast(bbit)) { 81 | std::string getElementPtrName = getElePtrInst->getName().str(); 82 | std::string arrayName = getElePtrInst->getOperand(0)->getName().str(); 83 | getElementPtrName2arrayNameMapTy::iterator it_arrayName = getElementPtrName2arrayNameMap.find(getElementPtrName); 84 | if (it_arrayName == getElementPtrName2arrayNameMap.end()) { 85 | getElementPtrName2arrayNameMap.insert(std::make_pair(getElementPtrName, arrayName)); 86 | } 87 | } 88 | } 89 | //errs() << "num inst = " << num_inst << "\n"; 90 | funcBBNmPair2numInstInBBMap.insert(std::make_pair(std::make_pair(func_name, bb_name), num_inst)); 91 | } 92 | } 93 | 94 | // Check how many basic blocks 95 | DEBUG(dbgs() << "\tBasic Block number: " << counter << "\n"); 96 | 97 | //Verify the module 98 | std::string ErrorStr; 99 | raw_string_ostream OS(ErrorStr); 100 | if (verifyModule(M, &OS)){ 101 | errs() << OS.str() << "\n"; 102 | return false; 103 | } 104 | 105 | DEBUG(dbgs() << "End AssignBasicBlockID Pass\n\n"); 106 | return true; 107 | } 108 | 109 | MDNode* AssignBasicBlockID::assignID(BasicBlock *BB, unsigned id) { 110 | // Fetch the context in which the enclosing module was defined 111 | LLVMContext &Context = BB->getContext(); 112 | std::string BBname = BB->getName(); 113 | std::string func_name = BB->getParent()->getName(); 114 | 115 | // Create a metadata node that contains ID as a constant: 116 | Value* ID[]{ 117 | MDString::get(Context, func_name), 118 | MDString::get(Context, BBname), 119 | ConstantInt::get(Type::getInt32Ty(Context), id) 120 | }; 121 | 122 | return MDNode::getWhenValsUnresolved(Context, ArrayRef(ID, 3), false); 123 | } 124 | /* 125 | MDNode* assignID (Instruction *I, unsigned id) { 126 | // Fetch the context in which the enclosing module was defined 127 | LLVMContext &Context = I->getContext(); 128 | 129 | // Create a metadata node that contains ID as a constant: 130 | Value* ID[]{ 131 | MDString::get(Context, I->getParent()->getName()), 132 | ConstantInt::get(Type::getInt32Ty(Context), id) 133 | }; 134 | 135 | return MDNode::getWhenValsUnresolved(Context, ArrayRef(ID, 2), true); 136 | }*/ 137 | 138 | char AssignBasicBlockID::ID = 0; 139 | 140 | INITIALIZE_PASS(AssignBasicBlockID, "assignBBid", 141 | "This pass is used to assign unique id for each basic block", 142 | false, 143 | true 144 | ) 145 | 146 | /* 147 | INITIALIZE_PASS_BEGIN(AssignBasicBlockID, "assignBBid", 148 | "This pass is used to assign unique id for each basic block", 149 | false, 150 | true 151 | ) 152 | INITIALIZE_PASS_DEPENDENCY(LoopInfo) 153 | INITIALIZE_PASS_DEPENDENCY(LoopSimplify) 154 | INITIALIZE_PASS_END(AssignBasicBlockID, "assignBBid", 155 | "This pass is used to assign unique id for each basic block", 156 | false, 157 | true 158 | ) 159 | */ 160 | 161 | ModulePass *llvm::createAssignBasicBlockIDPass() { 162 | return new AssignBasicBlockID(); 163 | } -------------------------------------------------------------------------------- /include/profile_h/AnalysisProfilingPass.h: -------------------------------------------------------------------------------- 1 | #ifndef ANALYSISPROFILINGPASS_H 2 | #define ANALYSISPROFILINGPASS_H 3 | 4 | #include "llvm/Pass.h" 5 | #include "llvm/IR/Module.h" 6 | #include "llvm/IR/Function.h" 7 | #include "llvm/IR/BasicBlock.h" 8 | #include "llvm/Analysis/LoopInfo.h" 9 | 10 | #include "profile_h/lin-profile.h" 11 | #include "profile_h/QueryBasicBlockIDPass.h" 12 | #include "profile_h/QueryLoadStoreIDPass.h" 13 | #include "profile_h/ExtractLoopInfoPass.h" 14 | #include "profile_h/TraceDataStructure.h" 15 | #include "profile_h/CodeInstrumentPass.h" 16 | #include "profile_h/Passes.h" 17 | #include "profile_h/auxiliary.h" 18 | 19 | namespace llvm{ 20 | 21 | class AnalysisProfiling : public ModulePass { 22 | 23 | public: 24 | static char ID; 25 | AnalysisProfiling(); 26 | void getAnalysisUsage(AnalysisUsage &AU) const; 27 | bool runOnModule(Module &M); 28 | uint64_t getBBFreq(BasicBlock* BB) const; 29 | uint64_t getBranchFreq(BasicBlock* Src, BasicBlock* Dest) const; 30 | 31 | bool testbbIDpass(Module &M); 32 | 33 | private: 34 | QueryBasicBlockID* bbIDpass; 35 | QueryLoadStoreID* lsIDpass; 36 | 37 | /// Used in VerifyProfile() 38 | BBFreqMap BBFreq; 39 | BranchFreqMap BranchFreq; 40 | 41 | //typedef std::map > > loop2subloopMapTy; 42 | /// loopName --> subloop map 43 | /// Move to auxiliary.h 44 | //typedef std::map > loop2subloopMapTy; 45 | loop2subloopMapTy loop2subloopMap; 46 | std::map subloopDepthandLoopBound; 47 | 48 | ///Move to auxiliary.h 49 | //typedef std::map > funcName2loopsMapTy; 50 | //funcName2loopsMapTy funcName2loopsMap; 51 | 52 | /// loopName2BoundList: the whole loop name -> loop bounds list 53 | /// Loop bounds sequence: 54 | /// The top-level loop -> lower-level loop -> ... -> the innermost-level loop 55 | /// Move to auxiliary.h 56 | //typedef std::map > loopName2BoundListTy; 57 | //typedef std::map funcName2loopBoundsTy; 58 | //funcName2loopBoundsTy funcName2loopBounds; 59 | 60 | /// Move to auxiliary.h 61 | //typedef std::map func2loopInfoMapTy; 62 | //func2loopInfoMapTy func2loopInfoMap; 63 | 64 | /// Used to recognize the relationship between basic block ids and loop name 65 | /// Move to auxiliary.h 66 | //typedef std::map BBids2loopNameMapTy; 67 | //BBids2loopNameMapTy BBids2loopNameMap; 68 | 69 | /// Move to auxiliary.h 70 | //typedef std::map funcName2loopInfoMapTy; 71 | /// Move to GetLoopBound.h 72 | //funcName2loopInfoMapTy funcName2loopInfoMap; 73 | 74 | /// vector used to store all loops' basic block IDs 75 | //std::vector bbID_for_loops_vec; 76 | 77 | std::map loopDepth2BoundMap; 78 | 79 | void VerifyProfile(); 80 | void extract_loopInfo_inFunc(Module &M); 81 | 82 | void calculateLoopBound(Function* func); 83 | void modifyTrace_EvalIterationIndex(); 84 | void trace_eval_iteration_index(Function* func); 85 | 86 | void analyze_Dynamic_DataDep(); 87 | void analyze_Arithmetic_Intensity(); 88 | 89 | // Write information of dynamic data dependence and arithmetic intensity of loops into a file 90 | void write_dynDataDep_ArithIntensity_file(); 91 | 92 | // vector of (load/store address, trace_entry ID) pair 93 | //typedef std::vector > lsAddrTraceIDpairVecTy; 94 | //typedef std::list > lsAddrTraceIDpairListTy; 95 | typedef std::map lsAddrTraceIDpairMapTy; 96 | typedef lsAddrTraceIDpairMapTy::iterator iterator_t; 97 | iterator_t findEntryInlsAddrTraceIDpairVec(lsAddrTraceIDpairMapTy &lsAddrTraceIDpairVec, uintptr_t ls_addr); 98 | 99 | std::map loopHeaderBBid2loopDepthMap; 100 | 101 | //typedef std::multimap loopName2Trace_fMMapTy; 102 | 103 | //typedef std::multimap funcN2loopNToTrace_fMMapTy; 104 | //funcN2loopNToTrace_fMMapTy funcN2loopNToTrace_fMMap; 105 | typedef std::multimap funcName2Trace_entryMMapTy; 106 | funcName2Trace_entryMMapTy funcName2Trace_entryMMap; 107 | 108 | // loopName --> subTrace_f_entry Map 109 | //typedef std::map loopName2subTraceMapTy; 110 | typedef std::pair funcLoopNamePairTy; 111 | // (funcionName, loopName) --> loopName2subTraceMapTy Map 112 | typedef std::multimap funcName2loopTraceMMapTy; 113 | funcName2loopTraceMMapTy funcName2loopTraceMMap; 114 | 115 | // (functionName, loopName) -> number of binary operators executed 116 | typedef std::map, uint64_t> fnlpName2BinaryOpNumMapTy; 117 | fnlpName2BinaryOpNumMapTy fnlpName2BinaryOpNumMap; 118 | 119 | // (functionName, loopName) -> number of memory bytes transferred 120 | typedef std::map, uint64_t> fnlpName2MemByteMapTy; 121 | fnlpName2MemByteMapTy fnlpName2MemByteMap; 122 | 123 | // (functionName, loopName) -> arithmetic intensity 124 | typedef std::map, float> fnlpName2ArithIntensityMapTy; 125 | fnlpName2ArithIntensityMapTy fnlpName2ArithIntensityMap; 126 | 127 | // Loop Basic Block ID -> the corresponding loop depth 128 | typedef std::map loopBBid2loopDepthMapTy; 129 | loopBBid2loopDepthMapTy loopBBid2loopDepthMap; 130 | void getloopBBid2loopDepthMap(Function* func); 131 | }; 132 | 133 | /// Write the trace into a file 134 | void write_trace_file(TraceType& trace, std::string fname); 135 | 136 | } // End namespace llvm 137 | 138 | #endif // End of ANALYSISPROFILINGPASS_H -------------------------------------------------------------------------------- /testsuite/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(TEST_POLYBENCH_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}) 4 | set(TEST_POLYBENCH_BIN_DIR ${CMAKE_CURRENT_BINARY_DIR}) 5 | MESSAGE(STATUS "TEST_POLYBENCH_SRC_DIR: ${TEST_POLYBENCH_SRC_DIR}") 6 | 7 | SET(LLVM_BUILD_BIN_DIR ${LLVM_BINARY_DIR}/bin) 8 | MESSAGE(STATUS "LLVM_BUILD_BIN_DIR: ${LLVM_BUILD_BIN_DIR}") 9 | 10 | #set up LLVM binary 11 | set(CLANG ${LLVM_BUILD_BIN_DIR}/clang) 12 | #set(CLANG ${LLVM_BINARY_DIR}/bin/clang) 13 | set(OPT ${LLVM_BUILD_BIN_DIR}/opt) 14 | #set(OPT ${LLVM_BINARY_DIR}/bin/opt) 15 | set(LLC ${LLVM_BUILD_BIN_DIR}/llc) 16 | #set(LLVM ${LLVM_BINARY_DIR}/bin/llc) 17 | set(LLI ${LLVM_BUILD_BIN_DIR}/lli) 18 | #set(LLI ${LLVM_BINARY_DIR}/bin/lli) 19 | set(LLVM_LINK ${LLVM_BUILD_BIN_DIR}/llvm-link) 20 | #set(LLVM_LINK ${LLVM_BINARY_DIR}/bin/llvm-link) 21 | 22 | #set up lin-analyzer binary in cmake/ folder 23 | set(LIN_PROFILER ${LLVM_BUILD_BIN_DIR}/lin-analyzer) 24 | 25 | #Add path for custom modules 26 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${TEST_POLYBENCH_SRC_DIR}/cmake") 27 | MESSAGE(STATUS "CMAKE_MODULE_PATH: ${CMAKE_MODULE_PATH}") 28 | 29 | #set(BENCHSUITE_NAME "polybench") 30 | add_custom_target(generating_llvm_ir 31 | COMMENT "Compiling all polybench benchmarks into llvm ir" 32 | ) 33 | 34 | add_custom_target(generating_linked_llvm_ir 35 | COMMENT "Linking all llvm IRs into a single llvm IR" 36 | ) 37 | 38 | add_custom_target(clean_temp_bin_bc_files 39 | COMMENT "Clean all llvm temp IRs" 40 | ) 41 | 42 | add_custom_target(run_polybench 43 | COMMENT "Running polybench with lin-analyzer" 44 | ) 45 | 46 | add_custom_target(polybench 47 | COMMENT "Finish Polybench testing" 48 | ) 49 | 50 | add_dependencies(generating_llvm_ir clean_temp_bin_bc_files) 51 | add_dependencies(generating_linked_llvm_ir generating_llvm_ir) 52 | add_dependencies(run_polybench generating_linked_llvm_ir lin-analyzer) 53 | add_dependencies(polybench run_polybench) 54 | 55 | macro(compile_polybench test_file kernel_func postfix) 56 | set(TEST_NAME ${test_file}) 57 | set(KERNEL_FUNC_NAME ${kernel_func}) 58 | 59 | set(TESTSUITE_SRC_ROOT ${CMAKE_CURRENT_SOURCE_DIR}) 60 | set(TESTSUITE_BIN_ROOT ${CMAKE_CURRENT_BINARY_DIR}) 61 | 62 | set(TESTSUITE_SRC_BC_DIR ${TESTSUITE_BIN_ROOT}) 63 | 64 | set(INPUT_SRC "${TESTSUITE_SRC_ROOT}/${test_file}.${postfix}") 65 | set(OUTPUT_BC "${TESTSUITE_SRC_BC_DIR}/${test_file}.bc") 66 | 67 | #if (TESTSUITE_SRC_ROOT AND TESTSUITE_BIN_ROOT) 68 | #MESSAGE(STATUS "TESTSUITE_SRC_ROOT: " ${TESTSUITE_SRC_ROOT}) 69 | #MESSAGE(STATUS "TESTSUITE_BIN_ROOT: " ${TESTSUITE_BIN_ROOT}) 70 | #endif (TESTSUITE_SRC_ROOT AND TESTSUITE_BIN_ROOT) 71 | #MESSAGE(STATUS "INPUT_SRC: ${INPUT_SRC}") 72 | #MESSAGE(STATUS "OUTPUT_BC: ${OUTPUT_BC}") 73 | add_custom_command(OUTPUT ${OUTPUT_BC} 74 | COMMAND ${CLANG} -g -O1 -emit-llvm 75 | -c ${INPUT_SRC} -o ${OUTPUT_BC} 76 | DEPENDS ${INPUT_SRC} ${CLANG} 77 | WORKING_DIRECTORY ${TESTSUITE_SRC_BC_DIR} 78 | COMMENT "Compiling ${test_file}.${postfix} to ${OUTPUT_BC}" 79 | ) 80 | add_custom_target(${test_file}_${KERNEL_FUNC_NAME}_ir DEPENDS ${OUTPUT_BC}) 81 | add_dependencies(generating_llvm_ir ${test_file}_${KERNEL_FUNC_NAME}_ir) 82 | 83 | endmacro(compile_polybench) 84 | 85 | macro(link_polybench kernelName bc_files) 86 | get_filename_component(kernelNameWOpostfix ${kernelName} NAME_WE) 87 | set(KERNEL_NAME ${kernelNameWOpostfix}) 88 | set(TESTSUITE_LINK_SRC_ROOT ${CMAKE_CURRENT_SOURCE_DIR}) 89 | set(TESTSUITE_LINK_BIN_ROOT ${CMAKE_CURRENT_BINARY_DIR}) 90 | #MESSAGE(STATUS "kernel_func name: ${KERNEL_NAME}") 91 | set(KERNEL_BC "${KERNEL_NAME}.bc") 92 | set(ABSTRACT_KERNEL_BC "abstract_kernel.bc") 93 | set(MAIN_BC "main.bc") 94 | set(LINKED_BC "${TESTSUITE_LINK_BIN_ROOT}/${KERNEL_NAME}_linked.bc") 95 | set(OPT_BC "${TESTSUITE_LINK_BIN_ROOT}/${KERNEL_NAME}_linked_opt.bc") 96 | set(OPT_FLAGS -mem2reg -instnamer -lcssa -indvars) 97 | 98 | MESSAGE(STATUS "LINKED_BC: ${LINKED_BC}") 99 | add_custom_command(OUTPUT ${LINKED_BC} 100 | #COMMAND ${LLVM_LINK} ${bc_files} -o ${LINKED_BC} 101 | COMMAND ${LLVM_LINK} ${MAIN_BC} ${ABSTRACT_KERNEL_BC} ${KERNEL_BC} -o ${LINKED_BC} 102 | DEPENDS ${bc_files} ${LLVM_LINK} 103 | WORKING_DIRECTORY ${TESTSUITE_LINK_BIN_ROOT} 104 | COMMENT "linking all *.bc into ${KERNEL_NAME}_linked.bc" 105 | ) 106 | add_custom_command(OUTPUT ${OPT_BC} 107 | COMMAND ${OPT} ${OPT_FLAGS} ${LINKED_BC} -o ${OPT_BC} 108 | DEPENDS ${LINKED_BC} ${OPT} 109 | WORKING_DIRECTORY ${TESTSUITE_LINK_BIN_ROOT} 110 | COMMENT "opting the ${KERNEL_NAME}_linked.bc into ${KERNEL_NAME}_linked_opt.bc" 111 | ) 112 | add_custom_target(${KERNEL_NAME}_opt_ir DEPENDS ${OPT_BC}) 113 | add_dependencies(generating_linked_llvm_ir ${KERNEL_NAME}_opt_ir generating_llvm_ir) 114 | endmacro(link_polybench) 115 | 116 | #macro(remove_bin_bc_files kernelName) 117 | # file(GLOB temp_bin_bc_files RELATIVE "${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/*.bc") 118 | # foreach(temp_file ${temp_bin_bc_files}) 119 | # file(REMOVE ${temp_file}) 120 | # endforeach(temp_file) 121 | # add_custom_target(${kernelName}_clean ${temp_bin_bc_files}) 122 | # add_dependencies(clean_temp_bin_bc_files ${kernelName}_clean) 123 | #endmacro(remove_bin_bc_files) 124 | 125 | macro(test_polybench kernelName) 126 | set(BC_PATH "${CMAKE_CURRENT_BINARY_DIR}/") 127 | get_filename_component(NameWOpostfix ${kernelName} NAME_WE) 128 | set(Kernel_Name "${NameWOpostfix}") 129 | set(INPUT_BC "${CMAKE_CURRENT_BINARY_DIR}/${Kernel_Name}_linked_opt.bc") 130 | 131 | set(DYNAMIC_TRACE "${CMAKE_CURRENT_BINARY_DIR}/dynamic_trace.gz") 132 | set(INSTRUMENTED_BC "${Kernel_Name}_linked_opt_trace.bc") 133 | 134 | add_custom_command(OUTPUT ${DYNAMIC_TRACE} ${INSTRUMENTED_BC} 135 | COMMAND ${LIN_PROFILER} ${INPUT_BC} ${BC_PATH} ${Kernel_Name} 136 | DEPENDS ${INPUT_BC} ${LIN_PROFILER} 137 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} 138 | COMMENT "Testing ${Kernel_Name} with lin-analyzer" 139 | ) 140 | add_custom_target(${Kernel_Name}_lin-analyzer Depends ${DYNAMIC_TRACE} ${INSTRUMENTED_BC}) 141 | add_dependencies(run_polybench ${Kernel_Name}_lin-analyzer) 142 | endmacro(test_polybench) 143 | 144 | add_subdirectory(Ecobench) 145 | 146 | -------------------------------------------------------------------------------- /include/profile_h/TraceDataStructure.h: -------------------------------------------------------------------------------- 1 | #ifndef TRACEDATASTRUCTURE_H 2 | #define TRACEDATASTRUCTURE_H 3 | 4 | #include "llvm/Pass.h" 5 | #include "llvm/IR/BasicBlock.h" 6 | #include "llvm/IR/Function.h" 7 | #include "llvm/Support/raw_ostream.h" 8 | 9 | #include 10 | #include 11 | 12 | //#include "profile_h/ExtractLoopInfoPass.h" 13 | #include "profile_h/auxiliary.h" 14 | #include "profile_h/Passes.h" 15 | 16 | #define USE_LIST_FOR_TRACE_F 17 | #define USE_LIST_FOR_RECORDLS 18 | #define USE_LIST_FOR_DATADEPTYPE 19 | 20 | namespace llvm { 21 | 22 | enum class RecordType : unsigned { 23 | NOType = 'NA', // Not a type 24 | LOADType = 'L', // Load record 25 | STOREType = 'S', // Store record 26 | }; 27 | 28 | enum class DepType : unsigned { 29 | INITType = 'IT', // Initial Type 30 | RAWType = 'RAW', // RAW Dependence; flow (aka true) dependences, leading from a store to a load 31 | WARType = 'WAR', // WAR Dependence; anti dependences, leading from a load to a store 32 | WAWType = 'WAW' // WAW Dependence; output dependences, leading from stores to stores 33 | }; 34 | 35 | /// The class below is used to record information of 36 | /// load or store instructions at runtime 37 | class RecordLoadStore 38 | { 39 | public: 40 | //RecordLoadStore() { errs() << "ERROR! Designers should send arguments to RecordLoadStore class! \n"; } 41 | RecordLoadStore(); 42 | RecordLoadStore(RecordType ls_type, uint64_t lsid, unsigned char* ptr, uint64_t size); 43 | 44 | RecordLoadStore& operator=(RecordLoadStore const &rhs); 45 | 46 | // Access function members for querying 47 | RecordType getlsRecordType() const; 48 | uint64_t getlsID() const; 49 | uintptr_t getls_address() const; 50 | uint64_t getls_size() const; 51 | unsigned char* getls_ptr() const; 52 | 53 | void setEval_Iteration_Index(std::list evalIterList); 54 | std::list getEval_Iteration_Index() const; 55 | //void setLSinst(Instruction* inst); 56 | //Instruction* getLSinst() const; 57 | 58 | ~RecordLoadStore() {} 59 | 60 | private: 61 | //Instruction* Inst; 62 | RecordType record_type; 63 | uint64_t lsID; 64 | unsigned char* ls_ptr; 65 | uint64_t ls_size; 66 | uintptr_t ls_address; // Load/store address 67 | /// Evaluation Iteration Index sequence : The top-level -> lower-level -> the innermost-level loop 68 | std::list eval_Iteration_Index; 69 | }; 70 | /// End of the record class declaration 71 | 72 | /// Record the trace: 73 | class RecordTrace 74 | { 75 | public: 76 | RecordTrace(); 77 | RecordTrace(RecordLoadStore lsRecord, unsigned lineid, BasicBlock* BB, uint64_t traceID); 78 | 79 | // Set recordTrace 80 | void setRecordTrace(RecordLoadStore lsRecord, unsigned lineid, BasicBlock* BB, uint64_t BBid, uint64_t traceID); 81 | 82 | // Access function members for querying 83 | uint64_t getlsID() const; 84 | unsigned getlineID() const; 85 | uintptr_t getls_address() const; 86 | uint64_t getls_size() const; 87 | std::string getRecordType() const; 88 | RecordLoadStore getls_record() const; 89 | 90 | //Instruction* getRecordInst() const; 91 | BasicBlock* getBelongedBB() const; 92 | uint64_t getBelongedBBid() const; 93 | Function* getBelongedFunc() const; 94 | uint64_t getTraceID() const; 95 | fn_lpNamePairTy getfn_lpNamePair() const; 96 | 97 | void setEval_Iteration_Index(std::list eval_list); 98 | 99 | ~RecordTrace() {} 100 | 101 | private: 102 | RecordLoadStore ls_record; 103 | uint64_t lineID; 104 | unsigned iteration; 105 | BasicBlock* belongedBB; 106 | uint64_t belongedBBid; 107 | uint64_t trace_id; 108 | std::string funcName; 109 | std::string loopName; 110 | }; // End of RecordTrace class 111 | 112 | /// Record dynamic data dependence 113 | class DynDataDep 114 | { 115 | public: 116 | DynDataDep(); 117 | DynDataDep(DepType depTy, uint64_t srclsid, uint64_t dstlsid, std::vector depDis, \ 118 | fn_lpNamePairTy src_fn_lpNamePair, fn_lpNamePairTy dst_fn_lpNamePair, bool inter_loop, bool inter_func); 119 | std::pair getDepPair() const; 120 | std::vector getDepDistance() const; 121 | std::string getsrcFuncName() const; 122 | std::string getsrcLoopName() const; 123 | std::string getdstFuncName() const; 124 | std::string getdstLoopName() const; 125 | std::string getDepType() const; 126 | bool isLoopIndependent() const; 127 | bool isCrossLevel() const; 128 | bool isloopcarrieddependent() const; 129 | bool isinterloopdependent() const; 130 | bool isinterfuncdependent() const; 131 | void setSrcLSid(uint64_t src_lsid); 132 | void setDstLSid(uint64_t dst_lsid); 133 | void setDepType(DepType depTy); 134 | 135 | private: 136 | DepType depType; 137 | std::vector depDistance; 138 | uint64_t srcLSID; 139 | uint64_t dstLSID; 140 | unsigned loop_level; 141 | bool loop_independent; 142 | bool cross_level; 143 | bool loop_carried_dependency; 144 | bool inter_loop_dependency; 145 | bool inter_function_dependency; 146 | /* 147 | std::string funcName; 148 | std::string loopName; 149 | */ 150 | 151 | fn_lpNamePairTy srcfn_lpNamePair; 152 | fn_lpNamePairTy dstfn_lpNamePair; 153 | }; 154 | 155 | #ifndef USE_LIST_FOR_TRACE_F 156 | typedef std::vector TraceType; 157 | #else 158 | typedef std::list TraceType; 159 | #endif // End of USE_LIST_FOR_TRACE_F 160 | extern TraceType Trace_f; 161 | 162 | // Vector used to record load/store information at runtime 163 | #ifndef USE_LIST_FOR_RECORDLS 164 | extern std::vector recordls; 165 | #else 166 | extern std::list recordls; 167 | #endif // End of USE_LIST_FOR_RECORDLS 168 | 169 | //typedef std::vector lsAddressVecTy; 170 | //extern lsAddressVecTy lsAddressVec; 171 | 172 | #ifndef USE_LIST_FOR_DATADEPTYPE 173 | typedef std::vector DataDepType; 174 | #else 175 | typedef std::list DataDepType; 176 | #endif // End of USE_LIST_FOR_DATADEPTYPE 177 | extern DataDepType DynDataDepVec; 178 | extern DataDepType RefinedDynDataDepVec; 179 | extern DataDepType RefinedInterDynDataDepVec; 180 | } 181 | #endif // End of TRACEDATASTRUCTURE_H -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Lin-Analyzer 2 | 3 | A high-level performance analysis tool for FPGA-based accelerator. 4 | 5 | ## Installation 6 | ### Linux Installation 7 | 8 | Assume you have the following directory structure (windows setup is similar): 9 | ``` 10 | $HOME 11 | ~/llvm 12 | ~/llvm/tools/clang 13 | ~/llvm/tools/lin-analyzer 14 | ~/build 15 | ~/boost_1_57_0 16 | ``` 17 | 18 | * LLVM and clang 3.5: 19 | 20 | ``` 21 | wget http://llvm.org/releases/3.5.0/llvm-3.5.0.src.tar.xz 22 | wget http://llvm.org/releases/3.5.0/cfe-3.5.0.src.tar.xz 23 | tar -xvf llvm-3.5.0.src.tar.xz 24 | mv llvm-3.5.0.src llvm 25 | tar -xvf cfe-3.5.0.src.tar.xz 26 | mv cfe-3.5.0.src clang 27 | cp -r clang llvm/tools 28 | ``` 29 | 30 | * Lin-Analyzer: 31 | 32 | ``` 33 | cd ~/llvm/tools 34 | git clone git@github.com:zhguanw/lin-analyzer.git 35 | open ~/llvm/tools/CMakeLists.txt and add "add_llvm_tool_subdirectory(lin-analyzer)" to it 36 | open ~/llvm/CMakeLists.txt and add "set(LLVM_REQUIRES_RTTI 1)" to enable RTTI feature 37 | ``` 38 | 39 | * Boost graph library: 40 | 41 | ``` 42 | cd ~ 43 | wget http://softlayer-sng.dl.sourceforge.net/project/boost/boost/1.57.0/boost_1_57_0.tar.gz 44 | tar -xvf boost_1_57_0.tar.gz 45 | ``` 46 | 47 | * zlib library, version 1.2.8 48 | 49 | ``` 50 | sudo apt-get install zlib1g-dev 51 | ``` 52 | 53 | * cmake 54 | 55 | ``` 56 | sudo apt-get install cmake 57 | ``` 58 | (I use version 2.8.12.2, higher version should be fine) 59 | 60 | * Install Lin-Analyzer 61 | ``` 62 | cd ~ 63 | mkdir build 64 | cd ~/build 65 | cmake ~/llvm -DBOOST_INCLUDE_DIR=/your-path-to/boost_1_57_0 -DZLIB_INCLUDE_DIRS=/usr/include -DZLIB_LIBRARY=/usr/lib/x86_64-linux-gnu/libz.so 66 | ``` 67 | 68 | ### Windows Installation 69 | I use cygwin, so the first three steps above are the same. 70 | 71 | * Install Visual Studio 2013 (32-bit or 64-bit) 72 | * zlib 1.2.8: 73 | ``` 74 | (a). Download zlib from http://zlib.net/zlib-1.2.8.tar.gz and uncompress it 75 | (b). vim your_path_to\zlib-1.2.8\contrib\masmx86\bld_ml32.bat 76 | ml.exe /coff /Zi /c /Flmatch686.lst match686.asm 77 | ml.exe /coff /Zi /c /Flinffas32.lst inffas32.asm 78 | (c). Set Visual Studio to the system environment: 79 | PATH = %PATH:your_path_to\Microsoft Visual Studio 13.0\VC\bin 80 | (d). Open zlibvc.sln using vs2013 located at your_path_to\zlib-1.2.8\contrib\vstudio\vc11 81 | (e). Open properties of zlibstat project and remove "ZLIB_WINAPI;" from "Configuration Properties -> C/C++ -> Preprocessor -> Preprocessor Definitions" 82 | (f). If you generate 64-bit lin-analyzer, then you also need to generate 64-bit zlib library. To do this, you need to Open "Configuration Manager" and change "Win32" to "x64" under "Platform" 83 | (g). Build the static library. 84 | (h). After successfully building the zlib static library, you need to specify its absolute path for ZLIB_INCLUDE_DIRS and ZLIB_LIBRARY variables in cmake. 85 | ``` 86 | 87 | * Install cmake 2.8.12.2 88 | ``` 89 | Use cmake to compile llvm and setup Visual Studio project files 90 | Will update detailed instructions soon... 91 | ``` 92 | 93 | ## Getting started 94 | * Lin-Analyzer options 95 | ``` 96 | Usage: lin-analyzer [file.bc] -Ipath=[path] -config=[filename] [kernel-name] -Opath=[path] -TargetLoops=[index] [options] 97 | Options: 98 | -h, --help Help information. 99 | -profiling-time Profile kernels without FPGA estimation. 100 | -mem-trace Obtain memory trace for access pattern analysis without FPGA estimation. This 101 | option should be used with -profiling-time together. 102 | -no-trace Disable dynamic trace generation. 103 | -TargetLoops Specify target loops focused. Eg., -TargetLoops=2,3: only analyse loop 2 and 3. 104 | -cfg-detailed Show CFG with detailed instructions. 105 | -cfg-only Show CFG only with basic blocks. 106 | -dddg-bf-opt Show DDDG before optimization. May slow down program if input size is large 107 | -dddg-af-opt Show DDDG after optimization. May slow down program if input size is large 108 | -verbose Verbose mode, print more information. 109 | -dis-store-buffer Disable store-buffer optimization. 110 | -shared-load-removal Enable shared-load-removal optimization. 111 | -dis-shared-load-removal Disable shared-load-removal opt., even for completely unrolling config. 112 | -dis-rp-store-removal Disable repeated-store-removal optimization. 113 | -THR-float Enable tree height reduction optimization for floating point operations. 114 | -THR-integer Enable tree height reduction optimization for integer operations. 115 | -memory-disambig Enable memory disambiguation optimization. 116 | -dis-fp-threshold Disable floating point unit threshold and area budget is unlimited. 117 | -en-extra-scalar Sometimes, result might be shifted, this option is used to improve prediction. 118 | -en-rw-rw-memory Use memory with two ports and each supports read and write operation. Default is 119 | read-only and read-write. 120 | -vc707 Target for Xilinx Virtex7 VC707. Default is Xilinx Zedboard or ZC702 121 | ``` 122 | 123 | 2. Design Space Exploration 124 | ``` 125 | export BOOST_ROOT=~/boost_1_57_0 126 | export LD_LIBRARY_PATH=~/build/bin/lib 127 | export LLVM_BIN_HOME=~/build/bin 128 | export LLVM_SRC=~/llvm 129 | export TESTBENCH_HOME=~/llvm/tools/lin-analyzer/testsuite/Ecobench 130 | cd ~/llvm/tools/lin-analyzer/testsuite/Ecobench/scripts 131 | python run_dse.py 132 | ``` 133 | 134 | 3. Windows 135 | ``` 136 | Similar to Linux command, but use Visual Studio; 137 | Will update it soon... 138 | ``` 139 | 140 | ## License 141 | 142 | Lin-Analyzer is licensed under the GPL-3.0 license. 143 | 144 | Dynamic data graph generation (DDDG) and few of optimization functions in Lin-Analyzer are modified from Aladdin project and Lin-Analyzer is also followed Aladdin's license. For more information, please visit Aladdin's website: https://github.com/ysshao/ALADDIN 145 | 146 | ## Citation 147 | 148 | If you use Lin-Analyzer in your research, please cite 149 | 150 | Lin-Analyzer: A High-level Performance Analysis Tool for FPGA-based Accelerators, 151 | Guanwen Zhong, Alok Prakash,Yun Liang, Tulika Mitra, Smail Niar, 152 | 53rd ACM/IEEE Design Automation Conference, June 2016 153 | 154 | ========================== 155 | 156 | Guanwen (Henry) Zhong, 157 | 158 | guanwen@comp.nus.edu.sg 159 | 160 | National University of Singapore, 2016 161 | -------------------------------------------------------------------------------- /lib/Build_DDDG/opcode_func.cpp: -------------------------------------------------------------------------------- 1 | #include "profile_h/opcode_func.h" 2 | #include "profile_h/InstrumentForDDDGPass.h" 3 | #include "profile_h/auxiliary.h" 4 | 5 | extern bool increase_load_latency; 6 | 7 | bool is_associative(unsigned microop) 8 | { 9 | if (microop == LLVM_IR_Add ) 10 | return true; 11 | return false; 12 | } 13 | 14 | bool is_fassociative(unsigned microop) 15 | { 16 | if (microop == LLVM_IR_FAdd) 17 | return true; 18 | return false; 19 | } 20 | 21 | bool is_memory_op(unsigned microop) 22 | { 23 | if (microop == LLVM_IR_Load || microop == LLVM_IR_Store) 24 | return true; 25 | return false; 26 | } 27 | 28 | bool is_compute_op(unsigned microop) 29 | { 30 | switch(microop) 31 | { 32 | case LLVM_IR_Add : case LLVM_IR_FAdd : case LLVM_IR_Sub : case LLVM_IR_FSub : 33 | case LLVM_IR_Mul : case LLVM_IR_FMul : case LLVM_IR_UDiv : case LLVM_IR_SDiv : 34 | case LLVM_IR_FDiv : case LLVM_IR_URem : case LLVM_IR_SRem : case LLVM_IR_FRem : 35 | case LLVM_IR_Shl : case LLVM_IR_LShr : case LLVM_IR_AShr : case LLVM_IR_And : 36 | case LLVM_IR_Or: case LLVM_IR_Xor: case LLVM_IR_ICmp : case LLVM_IR_FCmp : 37 | return true; 38 | default: 39 | return false; 40 | } 41 | } 42 | 43 | bool is_store_op(unsigned microop) 44 | { 45 | if (microop == LLVM_IR_Store) 46 | return true; 47 | return false; 48 | } 49 | 50 | bool is_load_op(unsigned microop) 51 | { 52 | if (microop == LLVM_IR_Load) 53 | return true; 54 | return false; 55 | } 56 | 57 | bool is_bit_op(unsigned microop) 58 | { 59 | switch (microop) 60 | { 61 | case LLVM_IR_Shl: case LLVM_IR_LShr: case LLVM_IR_AShr : 62 | case LLVM_IR_And : case LLVM_IR_Or: case LLVM_IR_Xor : 63 | return true; 64 | default: 65 | return false; 66 | } 67 | } 68 | 69 | bool is_control_op (unsigned microop) 70 | { 71 | if (microop == LLVM_IR_PHI) 72 | return true; 73 | return is_branch_op(microop); 74 | } 75 | 76 | bool is_phi_op (unsigned microop) { 77 | return (microop == LLVM_IR_PHI) ? true : false; 78 | } 79 | 80 | bool is_branch_op (unsigned microop) 81 | { 82 | if (microop == LLVM_IR_Br || microop == LLVM_IR_Switch) 83 | return true; 84 | return is_call_op(microop); 85 | } 86 | 87 | bool is_call_op(unsigned microop) 88 | { 89 | if (microop == LLVM_IR_Call) 90 | return true; 91 | return is_dma_op(microop); 92 | } 93 | 94 | bool is_index_op (unsigned microop) 95 | { 96 | if (microop == LLVM_IR_IndexAdd || microop == LLVM_IR_IndexSub) 97 | return true; 98 | return false; 99 | } 100 | 101 | bool is_dma_load(unsigned microop) 102 | { 103 | return microop == LLVM_IR_DMALoad ; 104 | } 105 | 106 | bool is_dma_store(unsigned microop) 107 | { 108 | return microop == LLVM_IR_DMAStore ; 109 | } 110 | 111 | bool is_dma_op(unsigned microop) 112 | { 113 | return is_dma_load(microop) || is_dma_store(microop); 114 | } 115 | 116 | bool is_mul_op(unsigned microop) 117 | { 118 | switch(microop) 119 | { 120 | case LLVM_IR_Mul: case LLVM_IR_UDiv: case LLVM_IR_FMul : case LLVM_IR_SDiv : 121 | case LLVM_IR_FDiv : case LLVM_IR_URem : case LLVM_IR_SRem : case LLVM_IR_FRem: 122 | return true; 123 | default: 124 | return false; 125 | } 126 | } 127 | 128 | bool is_add_op(unsigned microop) 129 | { 130 | if (microop == LLVM_IR_Add || microop == LLVM_IR_Sub) 131 | return true; 132 | return false; 133 | } 134 | 135 | bool is_fadd_op(unsigned microop){ 136 | return ( (microop == LLVM_IR_FAdd) ? 1 : 0 ); 137 | } 138 | 139 | bool is_fsub_op(unsigned microop){ 140 | return ((microop == LLVM_IR_FSub) ? 1 : 0); 141 | } 142 | 143 | bool is_fmul_op(unsigned microop){ 144 | return ((microop == LLVM_IR_FMul) ? 1 : 0); 145 | } 146 | 147 | bool is_fdiv_op(unsigned microop){ 148 | return ((microop == LLVM_IR_FDiv) ? 1 : 0); 149 | } 150 | 151 | bool is_fcmp_op(unsigned microop){ 152 | return ((microop == LLVM_IR_FCmp) ? 1 : 0); 153 | } 154 | 155 | bool is_float_op(unsigned microop) { 156 | bool flag = (microop == LLVM_IR_FAdd || microop == LLVM_IR_FSub || microop == LLVM_IR_FMul || microop == LLVM_IR_FDiv); 157 | return (flag ? 1 : 0); 158 | } 159 | 160 | unsigned fpga_node_latency (unsigned microop) 161 | { 162 | switch (microop) { 163 | case LLVM_IR_Shl: 164 | case LLVM_IR_LShr: 165 | case LLVM_IR_AShr: 166 | case LLVM_IR_And: 167 | case LLVM_IR_Or: 168 | case LLVM_IR_Xor: 169 | case LLVM_IR_ICmp: 170 | case LLVM_IR_Br: 171 | case LLVM_IR_IndexAdd: 172 | case LLVM_IR_IndexSub: 173 | return 0; 174 | case LLVM_IR_Add: 175 | case LLVM_IR_Sub: 176 | return ADDSUB_LATENCY; 177 | case LLVM_IR_Call: 178 | return 0; 179 | case LLVM_IR_Store: 180 | return STORE_LATENCY; 181 | case LLVM_IR_SilentStore: 182 | return 0; 183 | case LLVM_IR_Load: 184 | // Observation from Vivado HLS: 185 | // 1. When enabling partitioning without pipelining, a load operation 186 | // from BRAM needs 2 access latency 187 | // 2. When no partitioning, a load operation from BRAM needs 1 access 188 | // latency 189 | // FIXME: In current implementation, we apply 2 load latency to all arrays 190 | // for simplicity. But to further improving accuracy, it is better 191 | // to ONLY associate 2 load latency with partitioned arrays and use 192 | // 1 load latency for normal arrays. 193 | if (increase_load_latency == true) { 194 | return LOAD_LATENCY; 195 | } 196 | else { 197 | return LOAD_LATENCY - 1; 198 | } 199 | case LLVM_IR_Mul: 200 | // 64 bits -- 18 cycles 201 | // 50 bits -- 11 cycles 202 | // 32 bits -- 6 cycles 203 | // 24 bits -- 3 cycles 204 | // 20 bits -- 3 cycles 205 | // 18 bits -- 1 cycles 206 | // 16 bits -- 1 cycles 207 | // 10 bits -- 1 cycles 208 | // 8 bits -- 1 cycles 209 | // Currently, we only consider 32-bit applications 210 | return MUL32BIT_LATENCY; 211 | case LLVM_IR_UDiv: 212 | case LLVM_IR_SDiv: 213 | // 64 bits -- 68 cycles 214 | // 50 bits -- 54 cycles 215 | // 32 bits -- 36 cycles 216 | // 24 bits -- 28 cycles 217 | // 16 bits -- 20 cycles 218 | // 10 bits -- 14 cycles 219 | // 8 bits -- 12 cycles 220 | // Currently, we only consider 32-bit applications 221 | return DIV32BIT_LATENCY; 222 | case LLVM_IR_FAdd: 223 | case LLVM_IR_FSub: 224 | // 32/64 bits -- 5 cycles 225 | return FADDSUB32BIT_LATENCY; 226 | case LLVM_IR_FMul: 227 | // 64 bits -- 6 cycles 228 | // 32 bits -- 4 cycles 229 | return FMUL32BIT_LATENCY; 230 | case LLVM_IR_FDiv: 231 | // 64 bits -- 31 cycles 232 | // 32 bits -- 16 cycles 233 | return FDIV32BIT_LATENCY; 234 | case LLVM_IR_FCmp: 235 | return FCMP_LATENCY; 236 | default: 237 | return 0; 238 | } 239 | } 240 | -------------------------------------------------------------------------------- /lib/Build_DDDG/file_func.cpp: -------------------------------------------------------------------------------- 1 | #include "profile_h/file_func.h" 2 | 3 | void read_file(string file_name, vector &output) 4 | { 5 | ifstream file; 6 | #ifdef DDEBUG 7 | cerr << file_name << endl; 8 | #endif 9 | file.open(file_name.c_str()); 10 | string wholeline; 11 | if (file.is_open()) 12 | { 13 | while (!file.eof()) 14 | { 15 | getline(file, wholeline); 16 | if (wholeline.size() == 0) 17 | break; 18 | output.push_back(atoi(wholeline.c_str())); 19 | } 20 | file.close(); 21 | } 22 | else 23 | { 24 | cerr << "file not open " << file_name << endl; 25 | exit(0); 26 | } 27 | } 28 | 29 | void read_gzip_string_file ( string gzip_file_name, unsigned size, 30 | vector &output) 31 | { 32 | gzFile gzip_file; 33 | gzip_file = gzopen(gzip_file_name.c_str(), "r"); 34 | 35 | #ifdef DDEBUG 36 | cerr << gzip_file_name << endl; 37 | #endif 38 | unsigned i = 0; 39 | while(!gzeof(gzip_file) && i< size) 40 | { 41 | char buffer[256]; 42 | gzgets(gzip_file, buffer, 256); 43 | string s(buffer); 44 | output.at(i) = s.substr(0,s.size()-1); 45 | i++; 46 | } 47 | gzclose(gzip_file); 48 | if (i == 0) 49 | { 50 | cerr << "file not open " << gzip_file_name << endl; 51 | exit(0); 52 | } 53 | } 54 | 55 | /*Read gz file into vector 56 | Input: gzip-file-name, size of elements, vector to write to 57 | */ 58 | void read_gzip_file(string gzip_file_name, unsigned size, std::vector &output) 59 | { 60 | gzFile gzip_file; 61 | #ifdef DDEBUG 62 | std::cerr << gzip_file_name << std::endl; 63 | #endif 64 | if (fileExists(gzip_file_name)) 65 | { 66 | gzip_file = gzopen(gzip_file_name.c_str(), "r"); 67 | unsigned i = 0; 68 | while(!gzeof(gzip_file) && i< size) 69 | { 70 | char buffer[256]; 71 | gzgets(gzip_file, buffer, 256); 72 | output.at(i) = strtol(buffer, NULL, 10); 73 | i++; 74 | } 75 | gzclose(gzip_file); 76 | #ifdef DDEBUG 77 | std::cerr << "end of reading file" << gzip_file_name << std::endl; 78 | #endif 79 | } 80 | else 81 | { 82 | cerr << "no such file " << gzip_file_name << endl; 83 | } 84 | } 85 | void read_gzip_unsigned_file(string gzip_file_name, unsigned size, 86 | vector &output) 87 | { 88 | gzFile gzip_file; 89 | #ifdef DDEBUG 90 | cerr << gzip_file_name << endl; 91 | #endif 92 | gzip_file = gzopen(gzip_file_name.c_str(), "r"); 93 | unsigned i = 0; 94 | while(!gzeof(gzip_file) && i< size) 95 | { 96 | char buffer[256]; 97 | gzgets(gzip_file, buffer, 256); 98 | output.at(i) = (unsigned)strtol(buffer, NULL, 10); 99 | i++; 100 | } 101 | gzclose(gzip_file); 102 | } 103 | 104 | /*Read gz file into vector 105 | Input: gzip-file-name, size of elements, vector to write to 106 | */ 107 | void read_gzip_file_no_size(string gzip_file_name, vector &output) 108 | { 109 | gzFile gzip_file; 110 | #ifdef DDEBUG 111 | cerr << gzip_file_name << endl; 112 | #endif 113 | gzip_file = gzopen(gzip_file_name.c_str(), "r"); 114 | unsigned i = 0; 115 | while(!gzeof(gzip_file) ) 116 | { 117 | char buffer[256]; 118 | gzgets(gzip_file, buffer, 256); 119 | int value; 120 | sscanf(buffer, "%d", &value); 121 | output.push_back(value); 122 | i++; 123 | } 124 | gzclose(gzip_file); 125 | 126 | if (i == 0) 127 | { 128 | cerr << "file not open " << gzip_file_name << endl; 129 | exit(0); 130 | } 131 | } 132 | 133 | /*Read gz with two element file into vector 134 | Input: gzip-file-name, size of elements, vector to write to 135 | */ 136 | void read_gzip_2_unsigned_file(string gzip_file_name, unsigned size, 137 | vector< pair > &output) 138 | { 139 | gzFile gzip_file; 140 | #ifdef DDEBUG 141 | cerr << gzip_file_name << endl; 142 | #endif 143 | gzip_file = gzopen(gzip_file_name.c_str(), "r"); 144 | unsigned i = 0; 145 | while(!gzeof(gzip_file) && i< size) 146 | { 147 | char buffer[256]; 148 | gzgets(gzip_file, buffer, 256); 149 | unsigned element1, element2; 150 | sscanf(buffer, "%d,%d", &element1, &element2); 151 | output.at(i).first = element1; 152 | output.at(i).second = element2; 153 | i++; 154 | } 155 | gzclose(gzip_file); 156 | 157 | if (i == 0) 158 | { 159 | cerr << "file not open " << gzip_file_name << endl; 160 | exit(0); 161 | } 162 | } 163 | 164 | void read_gzip_1in2_unsigned_file(string gzip_file_name, unsigned size, 165 | vector &output) 166 | { 167 | gzFile gzip_file; 168 | #ifdef DDEBUG 169 | cerr << gzip_file_name << "," << size << endl; 170 | #endif 171 | gzip_file = gzopen(gzip_file_name.c_str(), "r"); 172 | unsigned i = 0; 173 | while(!gzeof(gzip_file) && i< size) 174 | { 175 | char buffer[256]; 176 | gzgets(gzip_file, buffer, 256); 177 | unsigned element1, element2; 178 | sscanf(buffer, "%d,%d", &element1, &element2); 179 | output.at(i) = element1; 180 | i++; 181 | } 182 | gzclose(gzip_file); 183 | if (i == 0) 184 | { 185 | cerr << "file not open " << gzip_file_name << endl; 186 | exit(0); 187 | } 188 | } 189 | 190 | void write_gzip_file(string gzip_file_name, unsigned size, vector &output) 191 | { 192 | gzFile gzip_file; 193 | #ifdef DDEBUG 194 | cerr << gzip_file_name << endl; 195 | #endif 196 | gzip_file = gzopen(gzip_file_name.c_str(), "w"); 197 | for (unsigned i = 0; i < size; ++i) 198 | gzprintf(gzip_file, "%d\n", output.at(i)); 199 | gzclose(gzip_file); 200 | } 201 | 202 | void write_gzip_bool_file(std::string gzip_file_name, unsigned size, std::vector &output) 203 | { 204 | gzFile gzip_file; 205 | #ifdef DDEBUG 206 | cerr << gzip_file_name << endl; 207 | #endif 208 | gzip_file = gzopen(gzip_file_name.c_str(), "w"); 209 | for (unsigned i = 0; i < size; ++i) 210 | gzprintf(gzip_file, "%d\n", output.at(i) ? 1 : 0); 211 | gzclose(gzip_file); 212 | } 213 | 214 | void write_gzip_unsigned_file(string gzip_file_name, unsigned size, 215 | vector &output) 216 | { 217 | gzFile gzip_file; 218 | #ifdef DDEBUG 219 | cerr << gzip_file_name << endl; 220 | #endif 221 | gzip_file = gzopen(gzip_file_name.c_str(), "w"); 222 | for (unsigned i = 0; i < size; ++i) 223 | gzprintf(gzip_file, "%u\n", output.at(i)); 224 | gzclose(gzip_file); 225 | } 226 | 227 | void write_string_file(string file_name, unsigned size, vector &output) 228 | { 229 | ofstream file; 230 | file.open(file_name.c_str()); 231 | for (unsigned i = 0; i < size; ++i) 232 | file << output.at(i) << endl; 233 | file.close(); 234 | } 235 | 236 | void write_gzip_string_file(string gzip_file_name, unsigned size, vector &output) 237 | { 238 | gzFile gzip_file; 239 | gzip_file = gzopen(gzip_file_name.c_str(), "w"); 240 | #ifdef DDEBUG 241 | cerr << gzip_file_name << endl; 242 | #endif 243 | for (unsigned i = 0; i < size; ++i) 244 | gzprintf(gzip_file, "%s\n", output.at(i).c_str()); 245 | gzclose(gzip_file); 246 | } 247 | 248 | bool fileExists (const string file_name) 249 | { 250 | struct stat buf; 251 | if (stat(file_name.c_str(), &buf) != -1) 252 | return true; 253 | return false; 254 | } 255 | -------------------------------------------------------------------------------- /include/profile_h/fpga_resources.h: -------------------------------------------------------------------------------- 1 | #ifndef FPGA_RESOURCES_H 2 | #define FPGA_RESOURCES_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | //#include "profile_h/lin-profile.h" 10 | #include "profile_h/generic_func.h" 11 | #include "profile_h/auxiliary.h" 12 | 13 | /// Define FPGA chip we use 14 | //#define __XILINX_ZYNQ7000_ZC702__ 15 | //#define __XILINX_VIRTEX7_VC707__ 16 | 17 | /// Array name --> Array partition number 18 | typedef std::map arrayName2NumPartTy; 19 | typedef std::map arrayName2NumPortPerPartTy; 20 | /// Array name --> (Array partition number, Total Array Size in Byte, Word size in Byte) Map 21 | /// If an array is completely partitioned, then its Array partition number is 0. 22 | typedef std::map > > arrayName2arrayConfigTy; 23 | /// Array name --> memory inefficiency per partition 24 | typedef std::map arrayName2memEfficiencyTy; 25 | 26 | class FPGA_ResClass { 27 | public: 28 | FPGA_ResClass(): dsp(0), bram18k(0), ff(0), lut(0) {} 29 | FPGA_ResClass(unsigned n_dsp, unsigned n_bram, unsigned n_ff, unsigned n_lut) : dsp(n_dsp), bram18k(n_bram), ff(n_ff), lut(n_lut) {} 30 | virtual ~FPGA_ResClass() {} 31 | 32 | unsigned getDSP() const { return dsp; } 33 | unsigned getBRAM18K() const { return bram18k; } 34 | unsigned getFF() const { return ff; } 35 | unsigned getLUT() const { return lut; } 36 | 37 | void setDSP(unsigned num) { dsp = num; } 38 | void setBRAM18K(unsigned num) { bram18k = num; } 39 | void setFF(unsigned num) { ff = num; } 40 | void setLUT(unsigned num) { lut = num; } 41 | 42 | private: 43 | unsigned dsp; 44 | unsigned bram18k; 45 | unsigned ff; 46 | unsigned lut; 47 | }; 48 | 49 | class UsedFPGA_ResClass : public FPGA_ResClass { 50 | public: 51 | ///FIXME: The resources used by fadd/sub, fmul, fdiv here are also related to its bitwidth, 52 | /// But we assume all are 32-bit floating point operation, later we need to change here. 53 | UsedFPGA_ResClass() : num_fadd(0), num_fsub(0), num_fmul(0), num_fdiv(0) {} 54 | 55 | void increaseFadd() { updateUsedFadd_sub(); num_fadd++; } 56 | void increaseFsub() { updateUsedFadd_sub(); num_fsub++; } 57 | void increaseFmul() { updateUsedFmul(); num_fmul++; } 58 | void increaseFdiv() { updateUsedFdiv(); num_fdiv++; } 59 | void increaseArrayPart(std::string arrayName); 60 | 61 | void setArrayPartNum(std::string arrayName, unsigned partNum); 62 | 63 | unsigned getNumFadd() const { return num_fadd; } 64 | unsigned getNumFsub() const { return num_fsub; } 65 | unsigned getNumFmul() const { return num_fmul; } 66 | unsigned getNumFdiv() const { return num_fdiv; } 67 | unsigned getArrayPartitionNum(std::string arrayName); 68 | arrayName2NumPartTy getArrayName2NumPartMap() const; 69 | 70 | const unsigned faddsub_DSP = 2; 71 | const unsigned faddsub_FF = 205; 72 | const unsigned faddsub_LUT = 390; 73 | const unsigned fmul_DSP = 3; 74 | const unsigned fmul_FF = 143; 75 | const unsigned fmul_LUT = 321; 76 | const unsigned fdiv_DSP = 0; 77 | const unsigned fdiv_FF = 761; 78 | const unsigned fdiv_LUT = 994; 79 | 80 | private: 81 | void updateUsedFadd_sub(); 82 | void updateUsedFmul(); 83 | void updateUsedFdiv(); 84 | 85 | unsigned num_fadd; 86 | unsigned num_fsub; 87 | unsigned num_fmul; 88 | unsigned num_fdiv; 89 | arrayName2NumPartTy array2numPart; 90 | }; 91 | 92 | /// Currently, we focus on a FPGA chip on Xilinx ZC702 development board. The resource limitations are 93 | /// defined inside the following class. 94 | class UsedFPGA_Res_With_Constraint : public UsedFPGA_ResClass { 95 | public: 96 | explicit UsedFPGA_Res_With_Constraint(arrayName2arrayConfigTy& arrayName2arrayCfg); 97 | // If an array partition only contains bits less than or equal to bram_sizeInbit_threshold, 98 | // then it will be implemented with distributed RAM instead of BRAM. 99 | const float bram_sizeInbit_threshold = 512; 100 | 101 | // Default is the available resource of Xilinx Zedboard or ZC702 102 | unsigned max_dsp = 220; 103 | unsigned max_bram18k = 280; 104 | unsigned max_ff = 106400; 105 | unsigned max_lut = 53200; 106 | 107 | /* 108 | #if defined(__XILINX_ZYNQ7000_ZC702__) 109 | const unsigned max_dsp = 220; 110 | const unsigned max_bram18k = 280; 111 | const unsigned max_ff = 106400; 112 | const unsigned max_lut = 53200; 113 | #elif defined(__XILINX_VIRTEX7_VC707__) 114 | const unsigned max_dsp = 2800; 115 | const unsigned max_bram18k = 2060; 116 | const unsigned max_ff = 607200; 117 | const unsigned max_lut = 303600; 118 | #else 119 | const unsigned max_dsp = 220; 120 | const unsigned max_bram18k = 280; 121 | const unsigned max_ff = 106400; 122 | const unsigned max_lut = 53200; 123 | #endif 124 | */ 125 | 126 | const unsigned size_BRAM18K_in_bit = 18432; 127 | bool check_resources_limitation(unsigned bram18k_usage, unsigned dsp_usage, unsigned ff_usage, unsigned lut_usage); 128 | arrayName2memEfficiencyTy getMemoryEfficiency() const; 129 | arrayName2NumPartTy getArrayName2Bram18k_used() const; 130 | unsigned getTotalBram18k_usage() const; 131 | unsigned getArrayWritePortNumPerPart(std::string original_array_name); 132 | unsigned getArrayPartNameWritePortNum(std::string array_name); 133 | 134 | /// try_to_occupy_one_*(): 135 | /// return: false -- resource constraint, need to wait; 136 | /// true -- user successfully occupies one compute unit or memory read/write port. 137 | bool try_to_occupy_one_fadd(); 138 | bool try_to_occupy_one_fsub(); 139 | bool try_to_occupy_one_fmul(); 140 | bool try_to_occupy_one_fdiv(); 141 | bool try_to_occupy_one_read_port(std::string arrayName); 142 | bool try_to_occupy_one_write_port(std::string arrayName); 143 | 144 | void release_one_fadd(); 145 | void release_one_fsub(); 146 | void release_one_fmul(); 147 | void release_one_fdiv(); 148 | void release_one_read_port(std::string arrayName); 149 | void release_one_write_port(std::string arrayName); 150 | 151 | void set_floating_unit_threshold(unsigned fadd_limited, unsigned fsub_limited, unsigned fmul_limited, unsigned fdiv_limited); 152 | std::vector get_constrained_fop_unit_type(); 153 | 154 | private: 155 | void setBRAM18K_usage(); 156 | bool askForMore_Fadd(); 157 | bool askForMore_Fsub(); 158 | bool askForMore_Fmul(); 159 | bool askForMore_Fdiv(); 160 | 161 | arrayName2arrayConfigTy arrayName2arrayConfig; 162 | arrayName2NumPartTy arrayName2bram18k_used; 163 | arrayName2memEfficiencyTy arrayName2memEfficiency; 164 | arrayName2NumPartTy arrayPartName2readPort; 165 | arrayName2NumPartTy arrayPartName2writePort; 166 | unsigned bram18k_total_used; 167 | unsigned fadd_used; 168 | unsigned fsub_used; 169 | unsigned fmul_used; 170 | unsigned fdiv_used; 171 | arrayName2NumPartTy arrayPartName2readPort_used; 172 | arrayName2NumPartTy arrayPartName2writePort_used; 173 | arrayName2NumPortPerPartTy arrayName2NumWritePortPerPart; 174 | 175 | bool set_unit_threshold_flag; 176 | unsigned threshold_fadd_num; 177 | unsigned threshold_fsub_num; 178 | unsigned threshold_fmul_num; 179 | unsigned threshold_fdiv_num; 180 | 181 | bool dsp_resource_limited; 182 | bool fadd_limited_flag; 183 | bool fsub_limited_flag; 184 | bool fmul_limited_flag; 185 | bool fdiv_limited_flag; 186 | }; 187 | #endif // End of FPGA_RESOURCES_H -------------------------------------------------------------------------------- /lib/Profile/GetInstDistributionPass.cpp: -------------------------------------------------------------------------------- 1 | #include "profile_h/GetInstDistributionPass.h" 2 | 3 | #define DEBUG_TYPE "get-inst-distribution" 4 | using namespace llvm; 5 | 6 | STATISTIC(NumTotalInst, "The number of total instructions: #"); 7 | /// StoreInst and LoadInst 8 | STATISTIC(NumMemInst, "The number of load/store instructions: #"); 9 | /// TerminatorInst 10 | STATISTIC(NumBranch, "The number of branch instructions: #"); 11 | /// CmpInst and BinaryOperator 12 | STATISTIC(NumComputation, "The number of computing operations: #"); 13 | /// Others, eg. PHINode, CallInst, CastInst, etc. 14 | STATISTIC(NumOthers, "The number of other instructions: #"); 15 | /// LoadInst 16 | STATISTIC(NumLoadInst, "The number of load instructions: #"); 17 | /// StoreInst 18 | STATISTIC(NumStoreInst, "The number of store instructions: #"); 19 | 20 | GetInstDistribution::GetInstDistribution() : ModulePass(ID) { 21 | errs() << "\n---------------------------------------\n"; 22 | errs() << "\n\tInitialize GetInstDistribution pass\n"; 23 | initializeGetInstDistributionPass(*PassRegistry::getPassRegistry()); 24 | } 25 | 26 | void GetInstDistribution::getAnalysisUsage(AnalysisUsage &AU) const { 27 | //AU.addRequiredID(LoopSimplifyID); 28 | //AU.addPreservedID(LoopSimplifyID); 29 | 30 | //AU.addRequiredID(LCSSAID); 31 | //AU.addPreservedID(LCSSAID); 32 | 33 | AU.addRequired(); 34 | 35 | AU.setPreservesCFG(); 36 | } 37 | 38 | bool GetInstDistribution::runOnModule(Module &M) { 39 | 40 | /// To get the instruction distribution of kernels, there are three steps 41 | /// before we get the final result. 42 | /// 1. Get the basic block frequency by the Embedded Execution Engine 43 | /// 2. Get the instruction distribution of each basic block of the kernel 44 | /// 3. Multiply instruction distribution per basic block by basic block frequency 45 | /// Done 46 | 47 | /// Make sure basic block frequency is available 48 | if (BBidFreq.size() == 0 || BranchIDFreq.size() == 0) { 49 | errs() << "BBidFreq and BranchIDFreq are empty! Error!\n"; 50 | return false; 51 | } 52 | 53 | /// Collect instruction distribution information per basic block 54 | bbIDpass = &getAnalysis(); 55 | Module::iterator FI, FE; 56 | Function::iterator BI, BE; 57 | BasicBlock::iterator I, E; 58 | 59 | std::vector::iterator it_name; 60 | std::string Fun_Name; 61 | for (FI = M.begin(), FE = M.end(); FI != FE; ++FI) { 62 | it_name = std::find(kernel_names.begin(), kernel_names.end(), FI->getName()); 63 | Fun_Name = FI->getName().str(); 64 | if (it_name != kernel_names.end()) { 65 | errs() << "\tFunction Name = " << FI->getName() << "\n"; 66 | // Explore instructions within a kernel 67 | for (BI = FI->begin(), BE = FI->end(); BI != BE; ++BI) { 68 | instDis instDisBB; 69 | instDisBB.meminst = 0; 70 | instDisBB.ldinst = 0; 71 | instDisBB.stinst = 0; 72 | instDisBB.brinst = 0; 73 | instDisBB.compinst = 0; 74 | instDisBB.others = 0; 75 | 76 | for (I = BI->begin(), E = BI->end(); I != E; ++I) { 77 | Instruction* inst = &*I; 78 | //NumTotalInst++; 79 | if (isa(inst)) { 80 | //NumMemInst++; 81 | //NumLoadInst++; 82 | instDisBB.meminst++; 83 | instDisBB.ldinst++; 84 | } 85 | else if (isa(inst)) { 86 | //NumMemInst++; 87 | //NumStoreInst; 88 | instDisBB.meminst++; 89 | instDisBB.stinst++; 90 | } 91 | else if (isa(inst)) { 92 | //NumBranch++; 93 | instDisBB.brinst++; 94 | } 95 | else if (isa(inst) || isa(inst)) { 96 | //NumComputation++; 97 | instDisBB.compinst++; 98 | } 99 | else { 100 | //NumOthers++; 101 | instDisBB.others++; 102 | } 103 | 104 | } // Get the instruction distribution of a basic block now 105 | 106 | // Store instruction distribution per basic block into bbID2instDisMap 107 | uint64_t bbid = bbIDpass->getBBid(BI); 108 | bbID2instDisMap.insert(std::make_pair(bbid, instDisBB)); 109 | } 110 | } 111 | } 112 | 113 | /// Calculate instruction distribution of the kernel 114 | NumTotalInst = 0; 115 | NumMemInst = 0; 116 | NumLoadInst = 0; 117 | NumStoreInst = 0; 118 | NumBranch = 0; 119 | NumComputation = 0; 120 | NumOthers = 0; 121 | bbID2instDisMapTy::iterator it, ie; 122 | for (it = bbID2instDisMap.begin(), ie = bbID2instDisMap.end(); it != ie; it++) { 123 | uint64_t bb_id = it->first; 124 | errs() << "bb_id = " << bb_id << "\n"; 125 | assert( (BBidFreq.find(bb_id) != BBidFreq.end()) && "Can not find bb_id in BBidFreq! Error\n"); 126 | uint64_t freqbbid = BBidFreq.at(bb_id); 127 | NumLoadInst += it->second.ldinst * freqbbid; 128 | NumStoreInst += it->second.stinst * freqbbid; 129 | NumBranch += it->second.brinst * freqbbid; 130 | NumComputation += it->second.compinst * freqbbid; 131 | NumOthers += it->second.others * freqbbid; 132 | } 133 | NumMemInst += NumLoadInst + NumStoreInst; 134 | NumTotalInst += NumMemInst + NumBranch + NumComputation + NumOthers; 135 | 136 | /// Write the instruction distribution information into a file 137 | std::string instDis_fileName; 138 | if (instDis_fileName.empty()) { 139 | if (inputFileName == "-") { 140 | instDis_fileName = "-"; 141 | } 142 | else { 143 | const std::string &IFN = inputFileName; 144 | int Len = IFN.length(); 145 | // If the source ends in .bc, strip it off 146 | if (IFN[Len - 3] == '.' && IFN[Len - 2] == 'b' && IFN[Len - 1] == 'c') { 147 | instDis_fileName = std::string(IFN.begin(), IFN.end() - 3) + ".instdis"; 148 | } 149 | } 150 | } 151 | 152 | std::ofstream instdisFile; 153 | instdisFile.open(instDis_fileName); 154 | instdisFile << "Instruction Distribution of kernel " << Fun_Name << "\n"; 155 | instdisFile << "NumMemInst;NumComputation;NumBranch;NumOthers;"; 156 | instdisFile << "NumTotalInst;NumLoadInst;NumStoreInst\n"; 157 | instdisFile << NumMemInst << ";" << NumComputation << ";" << NumBranch << ";"; 158 | instdisFile << NumOthers << ";" << NumTotalInst << ";" << NumLoadInst << ";" << NumStoreInst << "\n"; 159 | instdisFile << "Finished!\n"; 160 | instdisFile.close(); 161 | 162 | /// Print the information below 163 | errs() << "\n\tPrinting instruction distribution below:\n"; 164 | errs() << "\t Memory instructions: \t# " << NumMemInst << "\n"; 165 | errs() << "\t\t Load instructions: \t# " << NumLoadInst << "\n"; 166 | errs() << "\t\t Store instructions: \t# " << NumStoreInst << "\n"; 167 | errs() << "\t Computation instructions: \t# " << NumComputation << "\n"; 168 | errs() << "\t Branch instructions: \t# " << NumBranch << "\n"; 169 | errs() << "\t Other instructions: \t# " << NumOthers << "\n"; 170 | errs() << "\t -----------\n"; 171 | errs() << "\t Total instructions: \t# " << NumTotalInst << "\n"; 172 | errs() << "\t End\n"; 173 | 174 | errs() << "\n\tFinish GetInstDistribution Pass!\n"; 175 | errs() << "\n---------------------------------------\n"; 176 | 177 | // Clear BBidFreq, BranchIDFreq 178 | BBidFreq.clear(); 179 | BranchIDFreq.clear(); 180 | 181 | return false; 182 | } 183 | 184 | 185 | char GetInstDistribution::ID = 0; 186 | 187 | INITIALIZE_PASS(GetInstDistribution, "getInstDist", 188 | "This pass is used to get instruction distribution of kernels", 189 | false, 190 | false 191 | ) 192 | 193 | 194 | ModulePass *llvm::createGetInstDistributionPass() { 195 | return new GetInstDistribution(); 196 | } -------------------------------------------------------------------------------- /lib/Profile/QueryLoadStoreID.cpp: -------------------------------------------------------------------------------- 1 | #include "profile_h/QueryLoadStoreIDPass.h" 2 | 3 | #define DEBUG_TYPE "query-laodstore-id" 4 | using namespace llvm; 5 | 6 | static const char *mdKindName = "recordLoadStoreID"; // Record Load/Store ID 7 | 8 | STATISTIC(NumInst, "The number of total instructions: #"); 9 | STATISTIC(NumLoadInst, "The number of load instructions: #"); 10 | STATISTIC(NumStoreInst, "The number of store instructions: #"); 11 | 12 | QueryLoadStoreID::QueryLoadStoreID() : ModulePass(ID) { 13 | DEBUG(dbgs() << "Initialize QueryLoadStoreID pass\n"); 14 | initializeQueryLoadStoreIDPass(*PassRegistry::getPassRegistry()); 15 | } 16 | 17 | void QueryLoadStoreID::getAnalysisUsage(AnalysisUsage &AU) const{ 18 | //AU.addRequired(); 19 | //AU.setPreservesCFG(); 20 | AU.setPreservesAll(); 21 | } 22 | 23 | /* 24 | unsigned QueryLoadStoreID::getLoadStoreid(Instruction* I) const{ 25 | std::map::const_iterator it; 26 | it = INST2IDMap.find(I); 27 | if (it != INST2IDMap.end()) { 28 | return INST2IDMap.at(I); 29 | } 30 | else { 31 | errs() << "Basic Block is not in the BB2IDMap, ERROR\n"; 32 | return false; 33 | } 34 | } 35 | 36 | Instruction* QueryLoadStoreID::getLoadStorebyID(unsigned id) const{ 37 | std::map::const_iterator it; 38 | it = ID2INSTMap.find(id); 39 | if (it != ID2INSTMap.end()) { 40 | return ID2INSTMap.at(id); 41 | } 42 | else { 43 | errs() << "Can not find ID of the Basic Block, error!\n"; 44 | return NULL; 45 | } 46 | }*/ 47 | 48 | bool QueryLoadStoreID::runOnModule(Module &M) { 49 | DEBUG(dbgs() << "\n\nBegin QueryLoadStoreID Pass :\n"); 50 | // Store all instructions in a worklist; 51 | Module::iterator FI, FE; 52 | std::vector::iterator fn_it; 53 | 54 | unsigned instid = 0; 55 | unsigned counter = 0; 56 | for (FI = M.begin(), FE = M.end(); FI != FE; ++FI) { 57 | if (FI->isDeclaration()) { 58 | continue; 59 | } 60 | fn_it = std::find(kernel_names.begin(), kernel_names.end(), FI->getName()); 61 | if (fn_it == kernel_names.end()) { 62 | // Ignore uninteresting functions 63 | continue; 64 | } 65 | 66 | for (inst_iterator I = inst_begin(FI), E = inst_end(FI); I != E; ++I) { 67 | worklist.push_back(&*I); 68 | if (isa(&*I) || isa(&*I)) { 69 | counter++; 70 | } 71 | instid++; 72 | } 73 | } 74 | 75 | // Print number of instructions in the module: 76 | NumInst = worklist.size(); 77 | DEBUG(dbgs() << "\tNumber of the total instructions in the kernal functions: " << NumInst << "\n\n"); 78 | 79 | // Create a named Metadata node: 80 | NamedMDNode *NMD = M.getNamedMetadata(mdKindName); 81 | 82 | // Scan the NamedMDNode we get and extract its BB-ID pairs 83 | for (unsigned i = 0; i < NMD->getNumOperands(); i++) { 84 | MDNode* node = NMD->getOperand(i); 85 | MDString* Instmdstr = dyn_cast(node->getOperand(0)); 86 | std::string Inststr = Instmdstr->getString(); 87 | 88 | ConstantInt* lineID = dyn_cast(node->getOperand(1)); 89 | unsigned lineid = static_cast (lineID->getZExtValue()); 90 | 91 | ConstantInt* lsID = dyn_cast(node->getOperand(2)); 92 | unsigned lsid = static_cast (lsID->getZExtValue()); 93 | 94 | Instruction* inst = worklist[lineid]; 95 | //errs() << "Instruction = " << Instmdstr->getString() << " -> ID = " \ 96 | // << *ID << "\n"; 97 | if (Inststr == "LoadInst") { 98 | NumLoadInst++; 99 | } 100 | else if (Inststr == "StoreInst") { 101 | NumStoreInst++; 102 | } 103 | else { 104 | // Do nothing 105 | } 106 | 107 | lsID2lsInstMap.insert(std::make_pair(lsid, inst)); 108 | lsInst2lsIDMap.insert(std::make_pair(inst, std::make_pair(lineid, lsid))); 109 | } 110 | 111 | // Check how many load/store instructions 112 | DEBUG(dbgs() << "\tLoad/Store instruction number: " << counter << "\n"); 113 | DEBUG(dbgs() << "\tLoad instruction number: " << NumLoadInst << "\n"); 114 | DEBUG(dbgs() << "\tStore instruction number: " << NumStoreInst << "\n"); 115 | 116 | unsigned num_LoadStore = lsID2lsInstMap.size(); 117 | if (num_LoadStore != counter) { 118 | assert(false && "Error: Number of Load/Store instructions is wrong\n"); 119 | } 120 | 121 | //Verify the module 122 | std::string ErrorStr; 123 | raw_string_ostream OS(ErrorStr); 124 | if (verifyModule(M, &OS)){ 125 | errs() << OS.str() << "\n"; 126 | return false; 127 | } 128 | 129 | DEBUG(dbgs() << "\nEnd QueryLoadStoreID Pass\n\n"); 130 | return false; 131 | } 132 | 133 | unsigned QueryLoadStoreID::getlsID(Instruction* I) const { 134 | if (isa(I) || isa(I)) { 135 | std::map>::const_iterator it; 136 | it = lsInst2lsIDMap.find(I); 137 | if (it != lsInst2lsIDMap.end()) { 138 | return lsInst2lsIDMap.at(I).second; 139 | } 140 | else { 141 | DEBUG(dbgs() << "The instruction caused the problem: " << *I << "\n"); 142 | assert(false && "Error: The instruction is not a Load or store instruction\n"); 143 | return 1; 144 | } 145 | } 146 | else { 147 | DEBUG(dbgs() << "The instruction caused the problem: " << *I << "\n"); 148 | assert(false && "Error: The instruction is not a Load or store instruction\n"); 149 | return 1; 150 | } 151 | } 152 | 153 | Instruction* QueryLoadStoreID::getlsbylsID(unsigned lsid) const { 154 | LSIDToLSinstMapTy::const_iterator it; 155 | it = lsID2lsInstMap.find(lsid); 156 | if (it != lsID2lsInstMap.end()) { 157 | return lsID2lsInstMap.at(lsid); 158 | } 159 | else { 160 | assert(false && "Error: Could not find the lsID\n"); 161 | return NULL; 162 | } 163 | } 164 | 165 | unsigned QueryLoadStoreID::getlsLineID(Instruction* I) const { 166 | if (isa(I) || isa(I)) { 167 | std::map>::const_iterator it; 168 | it = lsInst2lsIDMap.find(I); 169 | if (it != lsInst2lsIDMap.end()) { 170 | return lsInst2lsIDMap.at(I).first; 171 | } 172 | else { 173 | DEBUG(dbgs() << "The instruction caused the problem: " << *I << "\n"); 174 | assert(false && "Error: The instruction is not a Load or store instruction\n"); 175 | return 1; 176 | } 177 | } 178 | else { 179 | assert(false && "Error: The instruction is not a Load or store instruction\n"); 180 | return 1; 181 | } 182 | } 183 | 184 | unsigned QueryLoadStoreID::getInstLineID(Instruction* I) const { 185 | if (isa(I)) { 186 | std::map>::const_iterator it; 187 | it = lsInst2lsIDMap.find(I); 188 | if (it != lsInst2lsIDMap.end()) { 189 | return lsInst2lsIDMap.at(I).first; 190 | } 191 | else { 192 | DEBUG(dbgs() << "The instruction caused the problem: " << *I << "\n"); 193 | assert(false && "Error: The instruction is not a Load or store instruction\n"); 194 | return 1; 195 | } 196 | } 197 | else { 198 | assert(false && "Error: The instruction is not a Load or store instruction\n"); 199 | return 1; 200 | } 201 | } 202 | 203 | Instruction* QueryLoadStoreID::getInstbyInstLineID(unsigned instLineid) const { 204 | 205 | if (instLineid < worklist.size()) { 206 | return worklist.at(instLineid); 207 | } 208 | else { 209 | assert(false && "Error: Could not find the line ID\n"); 210 | return NULL; 211 | } 212 | } 213 | 214 | BasicBlock* QueryLoadStoreID::getBBbylsID(unsigned lsid) const { 215 | Instruction* inst = getlsbylsID(lsid); 216 | return inst->getParent(); 217 | } 218 | 219 | char QueryLoadStoreID::ID = 0; 220 | INITIALIZE_PASS(QueryLoadStoreID, "queryLoadStoreid", 221 | "This pass is used to get the unique id of specific Load/Store", 222 | false, 223 | false 224 | ) 225 | 226 | ModulePass *llvm::createQueryLoadStoreIDPass() { 227 | return new QueryLoadStoreID(); 228 | } --------------------------------------------------------------------------------