mirror of
https://gitlab.com/scemama/irpf90.git
synced 2024-12-22 12:23:32 +01:00
Add template. Repare OMP_Lock
This commit is contained in:
parent
982d771c61
commit
974775a9a5
@ -271,13 +271,21 @@ def create_build_remaining(f,ninja):
|
||||
|
||||
if extension.lower() in ['f', 'f90']:
|
||||
result = ["build {target_o}: compile_fortran_{irp_id} {target_i}"]
|
||||
result_make = [
|
||||
'{target_o}: {target_i}',
|
||||
'\t@printf "F: {short_target_o} -> {short_target_i}\\n"',
|
||||
"\t@$(FC) $(FCFLAGS) -c $^ -o $@", ""]
|
||||
|
||||
elif extension.lower() in ['c']:
|
||||
result = ["build {target_o}: compile_c_{irp_id} {target_i}"]
|
||||
elif extension.lower() in ['cxx', 'cpp']:
|
||||
result = ["build {target_o}: compile_cxx_{irp_id} {target_i}"]
|
||||
|
||||
result += [" short_in = {short_target_i}", " short_out = {short_target_o}", ""]
|
||||
return '\n'.join(result).format(**locals())
|
||||
|
||||
result_final = result if ninja else result_make
|
||||
|
||||
return '\n'.join(result_final).format(**locals())
|
||||
|
||||
|
||||
def create_makefile(d_flags,d_var,irpf90_flags,ninja=True):
|
||||
|
381
src/entity.py
381
src/entity.py
@ -64,7 +64,6 @@ class Entity(object):
|
||||
|
||||
self.comm_world = comm_world
|
||||
|
||||
|
||||
# ~ # ~ # ~
|
||||
# G l o b a l P r o p e r t y
|
||||
# ~ # ~ # ~
|
||||
@ -97,7 +96,6 @@ class Entity(object):
|
||||
d[type(line)] += [(i, line)]
|
||||
return d
|
||||
|
||||
|
||||
# ~ # ~ # ~
|
||||
# M u l t i p l e P r o v i d e r H a n d l e r
|
||||
# ~ # ~ # ~
|
||||
@ -114,7 +112,6 @@ class Entity(object):
|
||||
'''
|
||||
return self.name == self.same_as
|
||||
|
||||
|
||||
@irpy.lazy_property
|
||||
def prototype(self):
|
||||
# () -> Line
|
||||
@ -128,13 +125,14 @@ class Entity(object):
|
||||
'''
|
||||
|
||||
d = self.d_type_lines
|
||||
return next(line for _,line in d[Begin_provider]+d[Cont_provider] if line.filename[1] == self.name)
|
||||
return next(line for _, line in d[Begin_provider] + d[Cont_provider]
|
||||
if line.filename[1] == self.name)
|
||||
|
||||
@irpy.lazy_property
|
||||
def l_name(self):
|
||||
# () -> List[str]
|
||||
d = self.d_type_lines
|
||||
return [line.filename[1] for _,line in d[Begin_provider]+d[Cont_provider] ]
|
||||
return [line.filename[1] for _, line in d[Begin_provider] + d[Cont_provider]]
|
||||
|
||||
@irpy.lazy_property
|
||||
def l_others_name(self):
|
||||
@ -142,11 +140,10 @@ class Entity(object):
|
||||
'''Extract the other entity-name defined'''
|
||||
return [name for name in self.l_name if not name == self.name]
|
||||
|
||||
|
||||
@irpy.lazy_property
|
||||
def doc(self):
|
||||
# () -> List[str]
|
||||
doc = [line.text.lstrip()[1:] for _,line in self.d_type_lines[Doc]]
|
||||
doc = [line.text.lstrip()[1:] for _, line in self.d_type_lines[Doc]]
|
||||
if not doc:
|
||||
logger.warning("Entity '%s' is not documented" % (self.name))
|
||||
return doc
|
||||
@ -278,12 +275,12 @@ class Entity(object):
|
||||
def includes(self):
|
||||
# () -> str
|
||||
'''Extract the name of include who need be to be include in this Entity'''
|
||||
return [line.filename for _,line in self.d_type_lines[Include]]
|
||||
return [line.filename for _, line in self.d_type_lines[Include]]
|
||||
|
||||
@irpy.lazy_property
|
||||
def uses(self):
|
||||
'''Extract the name of module who are used in this Entity'''
|
||||
return [line.filename for _,line in self.d_type_lines[Use]]
|
||||
return [line.filename for _, line in self.d_type_lines[Use]]
|
||||
|
||||
@irpy.lazy_property
|
||||
def calls(self):
|
||||
@ -292,7 +289,7 @@ class Entity(object):
|
||||
def extract_name(line):
|
||||
return line.text.split('(', 1)[0].split()[1].lower()
|
||||
|
||||
return [extract_name(line) for _,line in self.d_type_lines[Call] ]
|
||||
return [extract_name(line) for _, line in self.d_type_lines[Call]]
|
||||
|
||||
# ~ # ~ # ~
|
||||
# Array Dimension
|
||||
@ -324,7 +321,6 @@ class Entity(object):
|
||||
else:
|
||||
return map(str.strip, x[1:-1].split(','))
|
||||
|
||||
|
||||
@irpy.lazy_property
|
||||
def allocate(self):
|
||||
# () -> List[Str]
|
||||
@ -338,6 +334,9 @@ class Entity(object):
|
||||
# ~ # ~ # ~
|
||||
# D e c l a r a t i o n
|
||||
# ~ # ~ # ~
|
||||
@irpy.lazy_property
|
||||
def is_protected(self):
|
||||
return self.text[0].lower.startswith('begin_provider_immu')
|
||||
|
||||
@irpy.lazy_property
|
||||
def type(self):
|
||||
@ -347,7 +346,7 @@ class Entity(object):
|
||||
type_ = self.prototype.text.split(',')[0].split('[')[1].strip()
|
||||
|
||||
if not type_:
|
||||
logger.error( "Error in definition of %s." % (self.name))
|
||||
logger.error("Error in definition of %s." % (self.name))
|
||||
sys.exit(1)
|
||||
|
||||
if self.dim:
|
||||
@ -356,29 +355,18 @@ class Entity(object):
|
||||
return type_
|
||||
|
||||
@irpy.lazy_property
|
||||
def header(self):
|
||||
def d_header(self):
|
||||
# () -> List[str]
|
||||
'''Compute all the code needed to inistanticant the entity'''
|
||||
|
||||
|
||||
name = self.name
|
||||
str_ = " {type_} :: {name} {dim}".format(type_=self.type, name=name, dim=build_dim(self.dim, colons=True))
|
||||
|
||||
if command_line.coarray:
|
||||
if not self.dim:
|
||||
str_ += " [*]"
|
||||
else:
|
||||
str_ += " [:]"
|
||||
|
||||
l = [str_]
|
||||
if self.dim and command_line.align != '1':
|
||||
l += [" !DIR$ ATTRIBUTES ALIGN: %s :: %s" % (command_line.align, name)]
|
||||
|
||||
if self.is_main:
|
||||
l += [" logical :: %s_is_built = .False." % (name)]
|
||||
|
||||
return l
|
||||
|
||||
import util
|
||||
d_template = {
|
||||
'name': self.name,
|
||||
'type': self.type,
|
||||
'main': self.is_main,
|
||||
'dim': build_dim(self.dim,colons=True),
|
||||
'protected': '\n'.join(self.allocater+self.builder) if self.is_protected else False}
|
||||
return d_template
|
||||
|
||||
############################################################
|
||||
@irpy.lazy_property
|
||||
@ -401,118 +389,35 @@ class Entity(object):
|
||||
# ~ # ~ # ~
|
||||
|
||||
@irpy.lazy_property
|
||||
def toucher(self):
|
||||
def d_touche_template(self):
|
||||
# () -> List[str]
|
||||
'''Fabric the f90 routine who handle the cache invalidation'''
|
||||
|
||||
# Only one by EntityColleciton
|
||||
if not self.is_main:
|
||||
return []
|
||||
|
||||
template = '''
|
||||
SUBROUTINE touch_{name}
|
||||
|
||||
{#l_module}
|
||||
{name}
|
||||
{/l_module}
|
||||
|
||||
IMPLICIT NONE
|
||||
{?do_debug}
|
||||
CHARACTER*(6+{@size key=name/}),PARAMETER :: irp_here = 'touch_{name}'
|
||||
{/do_debug}
|
||||
|
||||
{?do_debug}
|
||||
CALL irp_enter(irp_here)
|
||||
{/do_debug}
|
||||
|
||||
{#l_ancestor}
|
||||
{name}_is_built = .FALSE.
|
||||
{/l_ancestor}
|
||||
|
||||
{name}_is_built = .TRUE.
|
||||
|
||||
{?do_debug}
|
||||
CALL irp_leave(irp_here)
|
||||
{/do_debug}
|
||||
|
||||
END SUBROUTINE touch_{name}
|
||||
'''
|
||||
|
||||
# Only one by EntityColleciton
|
||||
if not self.is_main:
|
||||
return []
|
||||
return {}
|
||||
|
||||
from util import mangled
|
||||
l_parents = [{'name':n} for n in mangled(self.parents,self.d_entity)]
|
||||
name = self.name
|
||||
l_module= [ {'name':n} for n in build_use(self.parents+[name],self.d_entity)]
|
||||
|
||||
from ashes import AshesEnv
|
||||
ashes_env = AshesEnv()
|
||||
ashes_env.register_source('touch',template)
|
||||
|
||||
l = ashes_env.render('touch', {'name': name,
|
||||
'l_module':l_module,
|
||||
'l_ancestor':l_parents,
|
||||
'do_debug':command_line.do_debug})
|
||||
return [i for i in l.split('\n') if i]
|
||||
return {
|
||||
'name': self.name,
|
||||
'l_module': [n for n in build_use(self.parents + [self.name], self.d_entity,use=False)],
|
||||
'l_ancestor': [n for n in mangled(self.parents, self.d_entity)]}
|
||||
|
||||
##########################################################
|
||||
@irpy.lazy_property
|
||||
def locker(self):
|
||||
if not command_line.do_openmp:
|
||||
return []
|
||||
|
||||
name = self.name
|
||||
result = ["subroutine irp_lock_%s(set)" % (name)]
|
||||
result += [
|
||||
" use omp_lib",
|
||||
" implicit none",
|
||||
" logical, intent(in) :: set",
|
||||
" integer(kind=omp_nest_lock_kind),save :: %s_lock" % (name),
|
||||
" integer,save :: ifirst",
|
||||
]
|
||||
if command_line.do_debug:
|
||||
length = str(len("irp_lock_%s" % (name)))
|
||||
result += [
|
||||
" character*(%s) :: irp_here = 'irp_lock_%s'" % (length, name),
|
||||
" call irp_enter(irp_here)"
|
||||
]
|
||||
|
||||
result += [
|
||||
" if (ifirst == 0) then",
|
||||
" ifirst = 1",
|
||||
" call omp_init_nest_lock(%s_lock)" % (name),
|
||||
" endif",
|
||||
" if (set) then",
|
||||
" call omp_set_nest_lock(%s_lock)" % (name),
|
||||
" else",
|
||||
" call omp_unset_nest_lock(%s_lock)" % (name),
|
||||
" endif",
|
||||
]
|
||||
if command_line.do_debug:
|
||||
result.append(" call irp_leave(irp_here)")
|
||||
result.append("end subroutine irp_lock_%s" % (name))
|
||||
result.append("")
|
||||
return result
|
||||
|
||||
##########################################################
|
||||
@irpy.lazy_property
|
||||
def free(self):
|
||||
# () -> List[ str ]
|
||||
'''Compute an part of a subroutine used to free a variable'''
|
||||
|
||||
name = self.name
|
||||
result = ["!",
|
||||
"! >>> FREE %s" % (name),
|
||||
" %s_is_built = .False." % (self.same_as)]
|
||||
result = ["!", "! >>> FREE %s" % (name), " %s_is_built = .False." % (self.same_as)]
|
||||
|
||||
if self.dim:
|
||||
result += [
|
||||
" if (allocated(%s)) then"%(name),
|
||||
" deallocate (%s)"%(name)]
|
||||
result += [" if (allocated(%s)) then" % (name), " deallocate (%s)" % (name)]
|
||||
if command_line.do_memory:
|
||||
result += " print *, 'Deallocating %s'"%(name)
|
||||
result += " print *, 'Deallocating %s'" % (name)
|
||||
|
||||
result += [" endif"]
|
||||
|
||||
@ -528,183 +433,52 @@ END SUBROUTINE touch_{name}
|
||||
if not self.is_main:
|
||||
return []
|
||||
|
||||
from ashes import AshesEnv
|
||||
template = '''
|
||||
{#l_allocate}
|
||||
{subroutine|s}
|
||||
{/l_allocate}
|
||||
|
||||
{?inline}
|
||||
!DEC$ ATTRIBUTES FORCEINLINE :: provide_{name}
|
||||
{/inline}
|
||||
SUBROUTINE provide_{name}
|
||||
|
||||
{?do_openmp}
|
||||
use omp_lib
|
||||
{/do_openmp}
|
||||
|
||||
{#l_module}
|
||||
{name}
|
||||
{/l_module}
|
||||
|
||||
implicit none
|
||||
{?do_debug}
|
||||
character*(8+{@size key=name/}),parameter :: irp_here = 'provide_{name}'
|
||||
{/do_debug}
|
||||
|
||||
{?do_openmp}
|
||||
CALL irp_lock_{name}(.TRUE.)
|
||||
{/do_openmp}
|
||||
|
||||
{?do_debug}
|
||||
CALL irp_enter(irp_here)
|
||||
{/do_debug}
|
||||
|
||||
{#l_children}
|
||||
IF (.NOT.{name}_is_built) THEN
|
||||
CALL provide_{name}
|
||||
ENDIF
|
||||
{/l_children}
|
||||
|
||||
{#do_task}
|
||||
!$OMP TASK DEFAULT(shared) {depend}
|
||||
{/do_task}
|
||||
|
||||
{#l_allocate}
|
||||
CALL allocate_{name}
|
||||
{/l_allocate}
|
||||
|
||||
CALL bld_{name}
|
||||
|
||||
{?do_task}
|
||||
!$OMP END TASK
|
||||
{/do_task}
|
||||
|
||||
{name}_is_built = .TRUE.
|
||||
|
||||
{?do_openmp}
|
||||
CALL irp_lock_{name}(.FALSE.)
|
||||
{/do_openmp}
|
||||
|
||||
{?do_debug}
|
||||
CALL irp_leave(irp_here)
|
||||
{/do_debug}
|
||||
|
||||
END SUBROUTINE provide_{name}
|
||||
'''
|
||||
from util import mangled
|
||||
|
||||
import util
|
||||
name = self.name
|
||||
var = self.d_entity[name]
|
||||
l_module = [ {'name':x} for x in build_use([self.name] + self.to_provide, self.d_entity)]
|
||||
l_allocate = [ {'name':n, 'subroutine':self.build_alloc(n)} for n in self.l_name if self.d_entity[n].dim]
|
||||
l_children = [ {'name':x} for x in mangled(self.to_provide, self.d_entity) ]
|
||||
l_module = [x for x in build_use([self.name] + self.to_provide, self.d_entity,use=False)]
|
||||
l_children = [x for x in mangled(self.to_provide, self.d_entity)]
|
||||
|
||||
in_ = ['depend(in: %s)' % n for n in self.to_provide]
|
||||
out_ = ['depend(out: %s)' % n for n in self.l_name]
|
||||
do_task = [ {'depend':' '.join(in_ + out_) } ] if command_line.do_Task else []
|
||||
|
||||
ashes_env = AshesEnv()
|
||||
ashes_env.register_source('provide',template)
|
||||
|
||||
l = ashes_env.render('provide', {'name': name,
|
||||
'l_module':l_module,
|
||||
'l_allocate':l_allocate,
|
||||
'l_children':l_children,
|
||||
'do_debug':command_line.do_debug,
|
||||
'do_openmp':command_line.do_openmp,
|
||||
'do_task':do_task})
|
||||
l = ashes_env.render('provider.f90', {
|
||||
'name': name,
|
||||
'l_module': l_module,
|
||||
'l_children_static': l_children,
|
||||
'do_debug': command_line.do_debug,
|
||||
'do_openmp': command_line.do_openmp,
|
||||
'do_task': command_line.do_Task,
|
||||
'do_corray': command_line.do_coarray,
|
||||
'dim': ','.join(self.dim),
|
||||
})
|
||||
return [i for i in l.split('\n') if i.strip()]
|
||||
|
||||
def build_alloc(self,name):
|
||||
var = self.d_entity[name]
|
||||
from ashes import AshesEnv
|
||||
template = ("""
|
||||
@irpy.lazy_property
|
||||
def allocater(self):
|
||||
if not self.is_main:
|
||||
return []
|
||||
|
||||
subroutine allocate_{name}
|
||||
from util import mangled
|
||||
|
||||
{#l_module}
|
||||
{name}
|
||||
{/l_module}
|
||||
import util
|
||||
name = self.name
|
||||
l_module = [x for x in build_use([self.name] + self.to_provide, self.d_entity,use=False)]
|
||||
if self.is_protected:
|
||||
l_module.remove(self.fmodule)
|
||||
|
||||
|
||||
character*(9+{@size key=name/}),parameter :: irp_here = 'allocate_{name}'
|
||||
integer :: irp_err
|
||||
l_dim = [{'name': name, 'rank': i + 1, 'value': dimsize(k)} for i, k in enumerate(self.dim)]
|
||||
|
||||
if ( allocated({name}) .AND.( &
|
||||
{#l_dim}
|
||||
( SIZE({name},{rank}) /= {value} ) {@sep}.OR.{/sep} &
|
||||
{/l_dim}
|
||||
)) then
|
||||
|
||||
{?do_memory}
|
||||
print *, irp_here//': Deallocated {name}'
|
||||
{/do_memory}
|
||||
l = ashes_env.render('allocater.f90', {
|
||||
'name': name,
|
||||
'l_module': l_module,
|
||||
'do_debug': command_line.do_debug,
|
||||
'do_corray': command_line.do_coarray,
|
||||
'dim': ','.join(self.dim),
|
||||
'l_dim': l_dim
|
||||
})
|
||||
return [i for i in l.split('\n') if i.strip()]
|
||||
|
||||
deallocate( {name}, stat=irp_err )
|
||||
|
||||
if (irp_err /= 0) then
|
||||
print *, irp_here//': Deallocation failed: {name}'
|
||||
print *,' size: {dim}'
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
if ( .NOT. allocated({name}) ) then
|
||||
|
||||
{?do_memory}
|
||||
print *, irp_here//': Allocate {name} ({dim})'
|
||||
{/do_memory}
|
||||
|
||||
{^corray}
|
||||
allocate({name} ({dim}), stat=irp_err)
|
||||
{:else}
|
||||
allocate({name} ({dim}[*]), stat=irp_err)
|
||||
{/corray}
|
||||
if (irp_err /= 0) then
|
||||
print *, irp_here//': Allocation failed: {name}'
|
||||
print *,' size: {dim}'
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
end subroutine
|
||||
|
||||
""")
|
||||
|
||||
def dimsize(x):
|
||||
# (str) -> str
|
||||
'''Compute the number of element in the array'''
|
||||
try:
|
||||
b0, b1 = x.split(':')
|
||||
except ValueError:
|
||||
return x
|
||||
|
||||
b0_is_digit = b0.replace('-', '').isdigit()
|
||||
b1_is_digit = b1.replace('-', '').isdigit()
|
||||
|
||||
if b0_is_digit and b1_is_digit:
|
||||
size = str(int(b1) - int(b0) + 1)
|
||||
elif b0_is_digit:
|
||||
size = "(%s) - (%d)" % (b1, int(b0) - 1)
|
||||
elif b1_is_digit:
|
||||
size = "(%d) - (%s)" % (int(b1) + 1, b0)
|
||||
else:
|
||||
size = "(%s) - (%s) + 1" % (b1, b0)
|
||||
return size
|
||||
|
||||
l_dim = [{'name':name, 'rank':i+1, 'value':dimsize(k)} for i, k in enumerate(var.dim)]
|
||||
l_module = [ {'name':x} for x in build_use([var.name] + var.needs, self.d_entity) ]
|
||||
|
||||
ashes_env = AshesEnv()
|
||||
ashes_env.register_source('hello',template)
|
||||
|
||||
return ashes_env.render('hello', {'name': name,
|
||||
'dim':','.join(var.dim),
|
||||
'corray': command_line.coarray,
|
||||
'l_dim': l_dim,
|
||||
'l_module':l_module,
|
||||
'do_memory':command_line.do_memory})
|
||||
|
||||
##########################################################
|
||||
@irpy.lazy_property
|
||||
@ -717,9 +491,12 @@ end subroutine
|
||||
# ~#~#~#~#~#
|
||||
|
||||
#Next return the first element of the iterator
|
||||
ps_text = next(text for filename, text in self.cm_t_filename_parsed_text if self.prototype.filename[0].startswith(filename))
|
||||
begin = next(i for i, (_, line) in enumerate(ps_text) if isinstance(line, Begin_provider) if line.filename[1] == self.same_as)
|
||||
end = next(begin + i for i, (_, line) in enumerate(ps_text[begin:]) if isinstance(line, End_provider))
|
||||
ps_text = next(text for filename, text in self.cm_t_filename_parsed_text
|
||||
if self.prototype.filename[0].startswith(filename))
|
||||
begin = next(i for i, (_, line) in enumerate(ps_text)
|
||||
if isinstance(line, Begin_provider) if line.filename[1] == self.same_as)
|
||||
end = next(begin + i for i, (_, line) in enumerate(ps_text[begin:])
|
||||
if isinstance(line, End_provider))
|
||||
|
||||
# Now we now that the text is betern ps_text[begin:end]
|
||||
_, line_prototype = ps_text[begin]
|
||||
@ -736,23 +513,13 @@ end subroutine
|
||||
text.append(([], Simple_line(line_prototype.i, " irp_rdtsc1 = irp_rdtsc()",
|
||||
line_prototype.filename)))
|
||||
|
||||
remove = 1
|
||||
for vars, line in ps_text[begin + 1:end]:
|
||||
|
||||
if 'call touch' in line.lower:
|
||||
text += [([], Simple_line(line.i, '!$OMP TASKGROUP', line.filename))]
|
||||
remove = -1
|
||||
|
||||
text.append((vars, line))
|
||||
text += map(lambda x: ([], Simple_line(line.i, x, line.filename)),
|
||||
build_call_provide(vars, self.d_entity))
|
||||
|
||||
|
||||
if remove == 0:
|
||||
text += [([], Simple_line(line.i, '!$OMP END TASKGROUP', line.filename))]
|
||||
|
||||
remove +=1
|
||||
|
||||
# ~#~#~#~#~#
|
||||
# Create the subroutine.
|
||||
# ~#~#~#~#~#
|
||||
@ -763,13 +530,19 @@ end subroutine
|
||||
|
||||
# Add the use statement
|
||||
result += ["subroutine bld_%s" % (self.name)]
|
||||
result += build_use([self.name] + self.needs, self.d_entity)
|
||||
|
||||
l_use = build_use([self.name] + self.needs, self.d_entity,use=False)
|
||||
if self.is_protected:
|
||||
l_use.remove(self.fmodule)
|
||||
|
||||
result += ['USE %s'%n for n in l_use]
|
||||
|
||||
import parsed_text
|
||||
# Move the variable to top, and add the text
|
||||
parsed_text.move_to_top_list(text, [Declaration, Implicit, Use])
|
||||
|
||||
result.extend( line.text for _,line in text if not isinstance(line, (Begin_doc, End_doc, Doc, Cont_provider)))
|
||||
result.extend(line.text for _, line in text
|
||||
if not isinstance(line, (Begin_doc, End_doc, Doc, Cont_provider)))
|
||||
|
||||
if command_line.do_profile:
|
||||
result += [
|
||||
@ -821,5 +594,3 @@ end subroutine
|
||||
error.fail(self.prototype, "Cyclic dependencies:\n%s" % (str(self._parents)))
|
||||
|
||||
return result
|
||||
|
||||
|
||||
|
@ -286,7 +286,7 @@ class Irpy_comm_world(object):
|
||||
# Module data
|
||||
if m.has_irp_module:
|
||||
filename = os.path.join(irpdir, '%s.irp.module.F90' % m.filename)
|
||||
text = '\n'.join(m.header + m.head)
|
||||
text = '\n'.join(m.head)
|
||||
lazy_write_file(filename, '%s\n' % text)
|
||||
|
||||
# Subroutines
|
||||
@ -312,17 +312,8 @@ class Irpy_comm_world(object):
|
||||
|
||||
def create_lock(self):
|
||||
from util import lazy_write_file
|
||||
l = sorted(self.d_entity.keys())
|
||||
|
||||
out = []
|
||||
for v in l:
|
||||
out += self.d_entity[v].locker
|
||||
|
||||
out += ["subroutine irp_init_locks_%s()" % (irpf90_t.irp_id), " implicit none"]
|
||||
for v in l:
|
||||
out += [" call irp_lock_%s(.True.)" % v]
|
||||
out += [" call irp_lock_%s(.False.)" % v]
|
||||
out += ["end subroutine", ""]
|
||||
from util import ashes_env
|
||||
|
||||
str_ = ashes_env.render('irp_lock.F90', {'entity':sorted(self.d_entity)})
|
||||
filename = os.path.join(irpf90_t.irpdir, 'irp_locks.irp.F90')
|
||||
lazy_write_file(filename, '\n'.join(out))
|
||||
lazy_write_file(filename, str_)
|
||||
|
@ -74,19 +74,17 @@ class Fmodule(object):
|
||||
@irpy.lazy_property
|
||||
def head(self):
|
||||
'''The module who containt the declaration of the entity'''
|
||||
body = list(self.use)
|
||||
body += list(self.dec)
|
||||
body += [header for var in self.l_entity for header in var.header]
|
||||
|
||||
if self.use or self.dec or self.l_entity:
|
||||
|
||||
if body:
|
||||
result = ["module %s" % (self.name)]
|
||||
result += body
|
||||
result += ["end module %s" % (self.name)]
|
||||
d_template = {'name' : self.name,
|
||||
'use':list(self.use),'usr_declaration':list(self.dec),
|
||||
'irp_declaration':[e.d_header for e in self.l_entity],
|
||||
'coarray': command_line.coarray,
|
||||
'align': False if command_line.align == 1 else command_line.align}
|
||||
return [i for i in ashes_env.render('module.f90', d_template).split('\n') if i]
|
||||
else:
|
||||
result = []
|
||||
|
||||
return result
|
||||
return []
|
||||
|
||||
@irpy.lazy_property
|
||||
def has_irp_module(self):
|
||||
@ -106,7 +104,9 @@ class Fmodule(object):
|
||||
result = []
|
||||
for var in self.l_entity:
|
||||
result += var.provider
|
||||
if not var.is_protected:
|
||||
result += var.builder
|
||||
result += var.allocater
|
||||
if var.is_read:
|
||||
result += var.reader
|
||||
if var.is_written:
|
||||
@ -213,14 +213,14 @@ class Fmodule(object):
|
||||
Because user can define F90 Type, we need to keep the correct order.
|
||||
|
||||
Warning:
|
||||
If we uniquify that can cause a problem with the type in guess.
|
||||
```type toto
|
||||
integer :: n
|
||||
end type toto
|
||||
integer :: n
|
||||
If we uniquify that can cause a problem.
|
||||
```TYPE toto
|
||||
INTEGER :: n
|
||||
END TYPE toto
|
||||
INTEGER :: n
|
||||
```
|
||||
Fix:
|
||||
We need to support Type keyword.
|
||||
We need to support TYPE keyword.
|
||||
|
||||
'''
|
||||
|
||||
|
@ -57,8 +57,10 @@ simple_dict = {
|
||||
"subst": Subst,
|
||||
"end_doc": End_doc,
|
||||
"begin_provider": Begin_provider,
|
||||
"begin_provider_immu": Begin_provider,
|
||||
"&begin_provider": Cont_provider,
|
||||
"end_provider": End_provider,
|
||||
"end_provider_immu": End_provider,
|
||||
"assert": Assert,
|
||||
"touch": Touch,
|
||||
"soft_touch": SoftTouch,
|
||||
@ -674,8 +676,10 @@ def irp_simple_statements(text):
|
||||
|
||||
if command_line.do_profile:
|
||||
temp += [Simple_line(0, "call irp_init_timer()", line.filename)]
|
||||
if command_line.do_openmp:
|
||||
temp += [Simple_line(0, " call irp_init_locks_%s()" % (irp_id), line.filename)]
|
||||
# Need to choose between lazy lock or are big full initialization
|
||||
# if command_line.do_openmp:
|
||||
# temp += [Simple_line(0, " call irp_init_locks_%s()" % (irp_id), line.filename)]
|
||||
|
||||
temp += [Call(0, " call %s" % (program_name), line.filename)]
|
||||
if command_line.do_profile:
|
||||
temp += [Simple_line(0, "call irp_print_timer()", line.filename)]
|
||||
|
47
src/templates/allocater.f90
Normal file
47
src/templates/allocater.f90
Normal file
@ -0,0 +1,47 @@
|
||||
{?dim}
|
||||
SUBROUTINE allocate_{name}
|
||||
|
||||
{#l_module}
|
||||
USE {.}
|
||||
{/l_module}
|
||||
|
||||
IMPLICIT NONE
|
||||
|
||||
CHARACTER*(9+{@size key=name/}),PARAMETER :: irp_here = 'allocate_{name}'
|
||||
INTEGER :: irp_err
|
||||
|
||||
IF ( ALLOCATED({name}) .AND.( &
|
||||
{#l_dim}
|
||||
( SIZE({name},{rank}) /= {value} ) {@sep}.OR.{/sep} &
|
||||
{/l_dim})) THEN
|
||||
|
||||
{?do_memory} PRINT*, irp_here//': Deallocated {name}' {/do_memory}
|
||||
DEALLOCATE({name},STAT=irp_err)
|
||||
|
||||
IF (irp_err /= 0) THEN
|
||||
PRINT*, irp_here//': Deallocation failed: {name}'
|
||||
PRINT*,' size: {dim}'
|
||||
ENDIF
|
||||
|
||||
GO TO 666
|
||||
ELSE IF (.NOT.ALLOCATED({name})) THEN
|
||||
GO TO 666
|
||||
ELSE
|
||||
RETURN
|
||||
ENDIF
|
||||
|
||||
666 CONTINUE
|
||||
{?do_memory} PRINT*, irp_here//': Allocate {name} ({dim})'{/do_memory}
|
||||
|
||||
{^do_corray}
|
||||
ALLOCATE({name} ({dim}), STAT=irp_err)
|
||||
{:else}
|
||||
ALLOCATE({name} ({dim}[*]), STAT=irp_err)
|
||||
{/do_corray}
|
||||
|
||||
IF (irp_err /= 0) then
|
||||
PRINT*, irp_here//': Allocation failed: {name}'
|
||||
PRINT*,' size: {dim}'
|
||||
ENDIF
|
||||
END SUBROUTINE allocate_{name}
|
||||
{/dim}
|
13
src/templates/finalize.f90
Normal file
13
src/templates/finalize.f90
Normal file
@ -0,0 +1,13 @@
|
||||
SUBROUTINE irp_finalize_{id}
|
||||
{#use}
|
||||
USE {.}
|
||||
{/use}
|
||||
|
||||
IMPLICIT NONE
|
||||
{#entity_array}
|
||||
IF (ALLOCATED({name})) THEN
|
||||
{name_root}_is_built = .FALSE.
|
||||
! DEALLOCATE({name})
|
||||
ENDIF
|
||||
{/entity_array}
|
||||
END SUBROUTINE irp_finalize_{id}
|
31
src/templates/irp_lock.f90
Normal file
31
src/templates/irp_lock.f90
Normal file
@ -0,0 +1,31 @@
|
||||
{#entity}
|
||||
SUBROUTINE irp_lock_{.}(set)
|
||||
|
||||
USE omp_lib
|
||||
IMPLICIT NONE
|
||||
LOGICAL, INTENT(in) :: set
|
||||
INTEGER(KIND=omp_lock_kind),SAVE :: {.}_lock
|
||||
INTEGER, SAVE :: ifirst = 0
|
||||
|
||||
{?do_debug}
|
||||
CHARACTER*(9+{@size key={.}/}),PARAMETER :: irp_here = 'irp_lock_{name}'
|
||||
{/do_debug}
|
||||
|
||||
{?do_debug} CALL irp_enter(irp_here) {/do_debug}
|
||||
|
||||
IF (ifirst == 0) then
|
||||
ifirst = 1
|
||||
CALL omp_init_lock({.}_lock)
|
||||
ENDIF
|
||||
|
||||
IF (set) THEN
|
||||
CALL omp_set_lock({.}_lock)
|
||||
ELSE
|
||||
CALL omp_unset_lock({.}_lock)
|
||||
ENDIF
|
||||
|
||||
{?do_debug} CALL irp_leach(irp_here) {/do_debug}
|
||||
|
||||
END SUBROUTINE irp_lock_{.}
|
||||
{/entity}
|
||||
|
40
src/templates/module.f90
Normal file
40
src/templates/module.f90
Normal file
@ -0,0 +1,40 @@
|
||||
! -*- F90 -*-
|
||||
!
|
||||
!-----------------------------------------------!
|
||||
! This file was generated with the irpf90 tool. !
|
||||
! !
|
||||
! DO NOT MODIFY IT BY HAND !
|
||||
!-----------------------------------------------!
|
||||
|
||||
|
||||
MODULE {name}
|
||||
|
||||
{#use}
|
||||
USE {.}
|
||||
{/use}
|
||||
|
||||
{#usr_declaration}
|
||||
{.}
|
||||
{/usr_declaration}
|
||||
|
||||
{#irp_declaration}
|
||||
|
||||
{^dim}
|
||||
{type} {?protected}, PROTECTED {/protected} :: {name} {?coarray} [*] {/coarray}
|
||||
{:else}
|
||||
|
||||
{?align} !DIR$ ATTRIBUTES ALIGN: {align} :: {name} {/align}
|
||||
{type} {?protected}, PROTECTED {/protected} :: {name} {dim} {?coarray} [:] {/coarray}
|
||||
{/dim}
|
||||
|
||||
{?main}
|
||||
LOGICAL :: {name}_is_built = .FALSE.
|
||||
{/main}
|
||||
{/irp_declaration}
|
||||
|
||||
CONTAINS
|
||||
{#irp_declaration}
|
||||
{protected|s}
|
||||
{/irp_declaration}
|
||||
|
||||
END MODULE {name}
|
43
src/templates/provider.f90
Normal file
43
src/templates/provider.f90
Normal file
@ -0,0 +1,43 @@
|
||||
{?inline}!DEC$ ATTRIBUTES FORCEINLINE :: provide_{name}{/inline}
|
||||
SUBROUTINE provide_{name}
|
||||
|
||||
{#l_module}
|
||||
USE {.}
|
||||
{/l_module}
|
||||
|
||||
IMPLICIT NONE
|
||||
|
||||
{?do_debug}
|
||||
CHARACTER*(8+{@size key=name/}),PARAMETER :: irp_here = 'provide_{name}'
|
||||
{/do_debug}
|
||||
|
||||
{?do_debug} CALL irp_enter(irp_here) {/do_debug}
|
||||
|
||||
{?do_openmp}
|
||||
CALL irp_lock_{name}(.TRUE.)
|
||||
IF (.NOT.{name}_is_built) THEN
|
||||
{/do_openmp}
|
||||
|
||||
{#l_children_static}
|
||||
{@first} {?do_task}!$OMP TASKGROUP{/do_task} {/first}
|
||||
{?do_openmp}!$OMP flush({.}_is_built){/do_openmp}
|
||||
IF (.NOT.{.}_is_built) THEN
|
||||
{?do_task}!$OMP TASK{/do_task}
|
||||
CALL provide_{.}
|
||||
{?do_task}!$OMP END TASK{/do_task}
|
||||
ENDIF
|
||||
{@last} {?do_task}!$OMP END TASKGROUP{/do_task} {/last}
|
||||
{/l_children_static}
|
||||
|
||||
{?dim} CALL allocate_{name} {/dim}
|
||||
|
||||
CALL bld_{name}
|
||||
|
||||
{?do_debug} CALL irp_enter(irp_here) {/do_debug}
|
||||
|
||||
{?do_openmp}
|
||||
ENDIF
|
||||
CALL irp_lock_{name}(.FALSE.)
|
||||
{/do_openmp}
|
||||
|
||||
END SUBROUTINE provide_{name}
|
26
src/templates/touch.f90
Normal file
26
src/templates/touch.f90
Normal file
@ -0,0 +1,26 @@
|
||||
{#entity}
|
||||
|
||||
SUBROUTINE touch_{name}
|
||||
|
||||
{#l_module}
|
||||
USE {.}
|
||||
{/l_module}
|
||||
|
||||
IMPLICIT NONE
|
||||
{?do_debug}
|
||||
CHARACTER*(6+{@size key=name/}),PARAMETER :: irp_here = 'touch_{name}'
|
||||
{/do_debug}
|
||||
|
||||
{?do_debug} CALL irp_enter(irp_here) {/do_debug}
|
||||
|
||||
{#l_ancestor}
|
||||
{.}_is_built = .FALSE.
|
||||
{/l_ancestor}
|
||||
|
||||
{name}_is_built = .TRUE.
|
||||
|
||||
{?do_debug} CALL irp_leave(irp_here) {/do_debug}
|
||||
|
||||
END SUBROUTINE touch_{name}
|
||||
|
||||
{/entity}
|
@ -26,39 +26,28 @@
|
||||
|
||||
from irpf90_t import irp_id,irpdir
|
||||
import os
|
||||
from util import lazy_write_file
|
||||
from command_line import command_line
|
||||
|
||||
def create(modules,variables):
|
||||
# (Dict[str,Module]. Dict[str, Variable]) -> None
|
||||
'''Create the fortran90 finalize subroutine and the touched one'''
|
||||
|
||||
|
||||
finalize = "subroutine irp_finalize_%s\n"%(irp_id)
|
||||
for m in filter(lambda x: not modules[x].is_main and modules[x].has_irp_module, modules):
|
||||
finalize += " use %s\n"%(modules[m].name)
|
||||
|
||||
main_modules_name =[ m.name for m in modules.values() if m.is_main]
|
||||
|
||||
out = []
|
||||
for v,var in variables.iteritems():
|
||||
d_template_finalize = {'id':irp_id,
|
||||
'use':[m.name for m in modules.values() if not m.is_main and m.has_irp_module],
|
||||
'entity_array':
|
||||
[{'name':e.name,'name_root':e.same_as} for e in variables.values() if e.fmodule not in main_modules_name and e.dim]}
|
||||
|
||||
if var.fmodule not in main_modules_name:
|
||||
out += var.toucher
|
||||
if var.dim:
|
||||
finalize += " if (allocated(%s)) then\n"%v
|
||||
finalize += " %s_is_built = .False.\n"%var.same_as
|
||||
finalize += " deallocate(%s)\n"%v
|
||||
finalize += " endif\n"
|
||||
|
||||
finalize += "end\n"
|
||||
d_template_touch = {'do_debug': command_line.do_debug,
|
||||
'entity':[e.d_touche_template for e in variables.values() if e.fmodule not in main_modules_name]}
|
||||
|
||||
if out:
|
||||
out = map(lambda x: "%s\n"%(x),out)
|
||||
|
||||
out += finalize
|
||||
import util
|
||||
str_out = util.ashes_env.render('touch.f90', d_template_touch) + util.ashes_env.render('finalize.f90', d_template_finalize)
|
||||
|
||||
filename=os.path.join(irpdir,'irp_touches.irp.F90')
|
||||
lazy_write_file(filename,''.join(out))
|
||||
util.lazy_write_file(filename,'%s\n'% util.remove_empy_lines(str_out))
|
||||
|
||||
if __name__ == '__main__':
|
||||
create()
|
||||
|
43
src/util.py
43
src/util.py
@ -42,6 +42,17 @@ logging.basicConfig(level=logging.INFO)
|
||||
logger = logging.getLogger('Irpf90')
|
||||
logger.setLevel(30)
|
||||
|
||||
|
||||
# ~#~#~#~#~#
|
||||
# A S H E S _ T E M P L A T E S
|
||||
# ~#~#~#~#~#
|
||||
from ashes import AshesEnv
|
||||
import os
|
||||
ashes_env = AshesEnv([os.path.join(os.path.dirname(__file__),'templates')])
|
||||
|
||||
def remove_empy_lines(text):
|
||||
return os.linesep.join([s for s in text.splitlines() if s.strip()])
|
||||
|
||||
# ~#~#~#~#~#
|
||||
# / / _ R E L A T E D
|
||||
# ~#~#~#~#~#
|
||||
@ -277,6 +288,28 @@ def flatten(l_2d):
|
||||
# ~#~#~#~#~#
|
||||
# I R P _ R E L A T E D
|
||||
# ~#~#~#~#~#
|
||||
def dimsize(x):
|
||||
# (str) -> str
|
||||
'''Compute the number of element in the array'''
|
||||
try:
|
||||
b0, b1 = x.split(':')
|
||||
except ValueError:
|
||||
return x
|
||||
|
||||
b0_is_digit = b0.replace('-', '').isdigit()
|
||||
b1_is_digit = b1.replace('-', '').isdigit()
|
||||
|
||||
if b0_is_digit and b1_is_digit:
|
||||
size = str(int(b1) - int(b0) + 1)
|
||||
elif b0_is_digit:
|
||||
size = "(%s) - (%d)" % (b1, int(b0) - 1)
|
||||
elif b1_is_digit:
|
||||
size = "(%d) - (%s)" % (int(b1) + 1, b0)
|
||||
else:
|
||||
size = "(%s) - (%s) + 1" % (b1, b0)
|
||||
return size
|
||||
|
||||
|
||||
def build_dim(l_dim, colons=False):
|
||||
# (List[str],bool) -> str
|
||||
'''Contruct a valid fortran90 array dimension code from a list dimension
|
||||
@ -298,10 +331,16 @@ def mangled(l_ent, d_ent):
|
||||
'''Create a uniq list of providier (merge the multione) '''
|
||||
return OrderedUniqueList(d_ent[name].same_as for name in l_ent)
|
||||
|
||||
def build_use(l_ent, d_ent):
|
||||
def build_use(l_ent, d_ent,use=True):
|
||||
# (List, Dict[str,Entity]) -> list
|
||||
'''Contruct the fortran90 'use' statement for the list of entity'''
|
||||
return OrderedUniqueList(" use %s" % d_ent[x].fmodule for x in l_ent)
|
||||
|
||||
l_name = OrderedUniqueList(d_ent[x].fmodule for x in l_ent)
|
||||
if not use:
|
||||
return l_name
|
||||
else:
|
||||
return [" use %s" % n for n in l_name]
|
||||
|
||||
|
||||
def build_call_provide(l_ent, d_ent):
|
||||
# (List, Dict[str,Entity]) -> list
|
||||
|
Loading…
Reference in New Issue
Block a user