#!/usr/bin/env python
"""
OP2 source code transformation tool
This tool parses the user's original source code to produce
target-specific code to execute the user's kernel functions.
This prototype is written in Python and is directly based on the
parsing and code generation of the matlab source code transformation code
usage: ./op2.py 'file1','file2', ..., [kernel_dir]
This takes as input
file1.cpp, file2.cpp, ...
and produces as output modified versions
file1_op.cpp, file2_op.cpp, ...
then calls a number of target-specific code generators
to produce individual kernel files of the form
xxx_kernel.cpp -- for OpenMP x86 execution
xxx_kernel.cu -- for CUDA execution
plus a master kernel file of the form
file1_kernels.cpp -- for OpenMP x86 execution`
file1_kernels.cu -- for CUDA execution
If user kernel files are located in a sub-directory (e.g. 'kernel_dir'), then
this directory can be provided as argument as well.
"""
import sys
import re
import datetime
import os
# Import MPI+SEQ and MPI+autovectorised SEQ
from op2_gen_seq import op2_gen_seq
from op2_gen_mpi_vec import op2_gen_mpi_vec
# import OpenMP and CUDA code generation functions
from op2_gen_openmp_simple import op2_gen_openmp_simple
from op2_gen_openmp import op2_gen_openmp
from op2_gen_openacc import op2_gen_openacc
from op2_gen_cuda import op2_gen_cuda
from op2_gen_cuda_simple import op2_gen_cuda_simple
from op2_gen_cuda_simple_hyb import op2_gen_cuda_simple_hyb
from op2_gen_openmp4 import op2_gen_openmp4
from op2_gen_common import *
# from http://stackoverflow.com/a/241506/396967
# 这一部分去除掉源码里的注释
def comment_remover(text):
"""Remove comments from text"""
def replacer(match):
s = match.group(0)
if s.startswith('/'):
return ""
else:
return s
pattern = re.compile(
r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"',
re.DOTALL | re.MULTILINE
)
return re.sub(pattern, replacer, text)
def op_parse_calls(text):
"""Parsing for op_init/op_exit/op_partition/op_hdf5 calls"""
# remove comments just for this call
text = comment_remover(text)
inits = len(re.findall('op_init', text))
exits = len(re.findall('op_exit', text))
parts = len(re.findall('op_partition', text))
hdf5s = len(re.findall('hdf5', text))
return (inits, exits, parts, hdf5s)
def op_decl_set_parse(text):
"""Parsing for op_decl_set calls"""
sets = []
for m in re.finditer('op_decl_set\((.*)\)', text):
args = m.group(1).split(',')
# check for syntax errors
if len(args) != 2:
print 'Error in op_decl_set : must have three arguments'
return
sets.append({
'name': args[1].strip()
})
for m in re.finditer('op_decl_set_hdf5\((.*)\)', text):
args = m.group(1).split(',')
# check for syntax errors
if len(args) != 2:
print 'Error in op_decl_set : must have three arguments'
return
sets.append({
'name': args[1].strip()[1:-1]
})
return sets
def op_decl_const_parse(text):
"""Parsing for op_decl_const calls"""
consts = []
for m in re.finditer('op_decl_const\((.*)\)', text):
args = m.group(1).split(',')
# check for syntax errors
if len(args) != 3:
print 'Error in op_decl_const : must have three arguments'
return
consts.append({
'loc': m.start(),
'dim': args[0].strip(),
'type': args[1].strip(),
'name': args[2].strip(),
'name2': args[2].strip()
})
return consts
def extract_declared_globals(text):
""" Parsing for variables that have been declared 'extern' by user """
globals_found = []
global_pattern = r'[\s]*extern[\s]+[\w]+[\s]+([\w]+)'
for match in re.findall(global_pattern, text):
globals_found.append(match)
return globals_found
def arg_parse(text, j):
"""Parsing arguments in op_par_loop to find the correct closing brace"""
depth = 0
loc2 = j
while 1:
if text[loc2] == '(':
depth = depth + 1
elif text[loc2] == ')':
depth = depth - 1
if depth == 0:
return loc2
loc2 = loc2 + 1
def get_arg_dat(arg_string, j):
loc = arg_parse(arg_string, j + 1)
dat_args_string = arg_string[arg_string.find('(', j) + 1:loc]
# remove comments
dat_args_string = comment_remover(dat_args_string)
# check for syntax errors
if len(dat_args_string.split(',')) != 6:
print 'Error parsing op_arg_dat(%s): must have six arguments' \
% dat_args_string
return
# split the dat_args_string into 6 and create a struct with the elements
# and type as op_arg_dat
temp_dat = {
'type': 'op_arg_dat',
'dat': dat_args_string.split(',')[0].strip(),
'idx': dat_args_string.split(',')[1].strip(),
'map': dat_args_string.split(',')[2].strip(),
'dim': dat_args_string.split(',')[3].strip(),
'typ': dat_args_string.split(',')[4].strip(),
'acc': dat_args_string.split(',')[5].strip(),
'opt':''}
return temp_dat
def get_opt_arg_dat(arg_string, j):
loc = arg_parse(arg_string, j + 1)
dat_args_string = arg_string[arg_string.find('(', j) + 1:loc]
# remove comments
dat_args_string = comment_remover(dat_args_string)
# check for syntax errors
if len(dat_args_string.split(',')) != 7:
print 'Error parsing op_opt_arg_dat(%s): must have 7 arguments' \
% dat_args_string
return
# split the dat_args_string into 6 and create a struct with the elements
# and type as op_arg_dat
temp_dat = {
'type': 'op_opt_arg_dat',
'opt': dat_args_string.split(',')[0].strip(),
'dat': dat_args_string.split(',')[1].strip(),
'idx': dat_args_string.split(',')[2].strip(),
'map': dat_args_string.split(',')[3].strip(),
'dim': dat_args_string.split(',')[4].strip(),
'typ': dat_args_string.split(',')[5].strip(),
'acc': dat_args_string.split(',')[6].strip()}
return temp_dat
def get_arg_gbl(arg_string, k):
loc = arg_parse(arg_string, k + 1)
gbl_args_string = arg_string[arg_string.find('(', k) + 1:loc]
# remove comments
gbl_args_string = comment_remover(gbl_args_string)
# check for syntax errors
if len(gbl_args_string.split(',')) != 4:
print 'Error parsing op_arg_gbl(%s): must have four arguments' \
% gbl_args_string
return
# split the gbl_args_string into 4 and create a struct with the elements
# and type as op_arg_gbl
temp_gbl = {
'type': 'op_arg_gbl',
'data': gbl_args_string.split(',')[0].strip(),
'dim': gbl_args_string.split(',')[1].strip(),
'typ': gbl_args_string.split(',')[2].strip(),
'acc': gbl_args_string.split(',')[3].strip(),
'opt':''}
return temp_gbl
def append_init_soa(text):
text = re.sub('\\bop_init\\b\\s*\((.*)\)','op_init_soa(\\1,1)', text)
text = re.sub('\\bop_mpi_init\\b\\s*\((.*)\)','op_mpi_init_soa(\\1,1)', text)
return text
def op_par_loop_parse(text):
"""Parsing for op_par_loop calls"""
loop_args
op2.py源码阅读和注释以及工具拆分
最新推荐文章于 2025-01-20 04:22:00 发布