Skip to content

Commit

Permalink
Merge branch 'master' into 2845_inline_symbol_bug
Browse files Browse the repository at this point in the history
  • Loading branch information
arporter authored Jan 27, 2025
2 parents dbce296 + 10a3a6e commit edf4556
Show file tree
Hide file tree
Showing 111 changed files with 2,018 additions and 723 deletions.
15 changes: 15 additions & 0 deletions changelog
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,21 @@
11) PR #2814 for #2704. Adds backward accesses capabilities to the
DefinitionUseChain tool.

12) PR #2509 for #2394. Adds support for logical and character types
to the PSyData tooling.

13) PR #2862 for #2858. Change to PSyIR frontend and backend to ensure
existing parentheses in expressions are preserved.

14) PR #2825 for #2278 and #2849. Signatures AccessType now indentifies
INQUIRY and TYPE_INFO, for inquiry intrinsic accesses and precision symbols.

15) PR #2855 for #2853. Allows the Fortran standard used by fparser to
be set in the config file and ensure it is used consistently.

16) PR #2857 for 2854. Excludes character assignments from ACC KERNELS
regions to avoid issues in NEMO.

release 3.0.0 6th of December 2024

1) PR #2477 for #2463. Add support for Fortran Namelist statements.
Expand Down
4 changes: 4 additions & 0 deletions config/psyclone.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ OCL_DEVICES_PER_NODE = 1
# and will not produce a warning message if they cannot be found.
IGNORE_MODULES = netcdf, mpi

# The Fortran standard to use when parsing files. This value is passed
# to fparser. Valid values are f2003 and f2008
FORTRAN_STANDARD = f2008

# Settings specific to the LFRic API
# ==================================
[lfric]
Expand Down
46 changes: 20 additions & 26 deletions doc/developer_guide/dependency.rst
Original file line number Diff line number Diff line change
Expand Up @@ -263,16 +263,17 @@ DataAccess class i.e. the `_field_write_arguments()` and
Variable Accesses
=================

Especially in the NEMO API, it is not possible to rely on pre-defined
kernel information to determine dependencies between loops. So an additional,
somewhat lower-level API has been implemented that can be used to determine
variable accesses (READ, WRITE etc.), which is based on the PSyIR information.
The only exception to this is if a kernel is called, in which case the
metadata for the kernel declaration will be used to determine the variable
accesses for the call statement. The information about all variable usage
of a PSyIR node or a list of nodes can be gathered by creating an object of
type `psyclone.core.VariablesAccessInfo`.
This class uses a `Signature` object to keep track of the variables used.
When using PSyclone with generic Fortran code, it is not possible to
rely on pre-defined kernel information to determine dependencies
between loops. So an additional, somewhat lower-level API has been
implemented that can be used to determine variable accesses (READ,
WRITE etc.), which is based on the PSyIR information. The only
exception to this is if a kernel is called, in which case the metadata
for the kernel declaration will be used to determine the variable
accesses for the call statement. The information about all variable
usage of a PSyIR node or a list of nodes can be gathered by creating
an object of type `psyclone.core.VariablesAccessInfo`. This class
uses a `Signature` object to keep track of the variables used.

Signature
---------
Expand All @@ -289,6 +290,14 @@ a single component.
:members:
:special-members: __hash__, __eq__, __lt__

AccessType
----------

An individual access to a ``Signature`` is described by an instance of the
``AccessType`` enumeration:

.. autoclass:: psyclone.core.access_type.AccessType
:members:

VariablesAccessInfo
-------------------
Expand Down Expand Up @@ -319,22 +328,7 @@ instance is holding information about.
VariablesAccessInfo Options
+++++++++++++++++++++++++++

By default, `VariablesAccessInfo` will not report the first argument of
the PSyIR operators `lbound`, `ubound`, or `size` as read accesses,
since these functions do not actually access the content of the array,
they only query the size. If these accesses are required (e.g. in kernel
extraction this could be important if an array is only used in these
intrinsic - a driver would still need these arrays in order to query
the size), the optional `options` parameter of the `VariablesAccessInfo`
constructor can be used: add the key
`COLLECT-ARRAY-SHAPE-READS` and set it to true::

vai = VariablesAccessInfo(options={'COLLECT-ARRAY-SHAPE-READS': True})

In this case all arrays specified as first parameter to one of the
PSyIR operators above will be reported as read access.

Fortran also allows to rename a symbol locally when it is being imported,
Fortran allows an imported symbol to be renamed locally
(`use some_mod, only: renamed => original_name`). Depending on use case,
it might be useful to get the non-local, original name. By default,
`VariablesAccessInfo` will report the local name (i.e. the renamed name),
Expand Down
4 changes: 4 additions & 0 deletions doc/user_guide/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ section e.g.:
REPROD_PAD_SIZE = 8
PSYIR_ROOT_NAME = psyir_tmp
VALID_PSY_DATA_PREFIXES = profile, extract
FORTRAN_STANDARD = f2008

and an optional API specific section, for example for the
``lfric`` section:
Expand Down Expand Up @@ -176,6 +177,9 @@ BACKEND_CHECKS_ENABLED Optional (defaults to True). Whether or not the PSyIR
backend should validate the tree that it is passed.
Can be overridden by the ``--backend`` command-line
flag (see :ref:`backend-options`).
FORTRAN_STANDARD Optional (defaults to f2008). The Fortran standard str
that should be used by fparser. Valid values are
f2003 and f2008.
======================= ======================================================= ===========

Common Sections
Expand Down
5 changes: 3 additions & 2 deletions doc/user_guide/libraries.rst
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,9 @@ Read-only libraries check that a field declared as read-only is not
modified during a kernel call. More information can be found in the
:ref:`Read-Only Verification <psydata_read_verification>` section.

The libraries for :ref:`LFRic <lfric-api>` and
:ref:`GOcean <gocean-api>` APIs are included with PSyclone in
The libraries for :ref:`LFRic <lfric-api>`,
:ref:`GOcean <gocean-api>` APIs and generic Fortran code
are included with PSyclone in
the ``lib/read_only`` `directory
<https://github.com/stfc/PSyclone/tree/master/lib/read_only>`__.
For detailed instructions on how to build and use these libraries
Expand Down
26 changes: 23 additions & 3 deletions doc/user_guide/psy_data.rst
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ be printed at runtime, e.g.::
The transformation that adds read-only-verification to an application
can be applied for both the :ref:`LFRic <lfric-api>` and
:ref:`GOcean API <gocean-api>` - no API-specific transformations are required.
It can also be used to verify existing Fortran code.
Below is an example that searches for each loop in a PSyKAl invoke code (which
will always surround kernel calls) and applies the transformation to each one.
This code has been successfully used as a global transformation with the LFRic
Expand All @@ -136,10 +137,10 @@ Gravity Wave application (the executable is named ``gravity_wave``)
read_only_verify.apply(loop)
Besides the transformation, a library is required to do the actual
verification at runtime. There are two implementations of the
verification at runtime. There are three implementations of the
read-only-verification library included in PSyclone: one for LFRic,
and one for GOcean.
Both libraries support the environment variable ``PSYDATA_VERBOSE``.
one for GOcean, and one for generic Fortran code.
These libraries support the environment variable ``PSYDATA_VERBOSE``.
This can be used to control how much output is generated
by the read-only-verification library at runtime. If the
variable is not specified or has the value '0', warnings will only
Expand Down Expand Up @@ -230,6 +231,25 @@ An executable example for using the GOcean read-only-verification
library is included in ``examples/gocean/eg5/readonly``, see
:ref:`gocean_example_readonly`.


Read-Only-Verification Library for Generic Fortran
++++++++++++++++++++++++++++++++++++++++++++++++++

This library is contained in the ``lib/read_only/generic`` directory and
it must be compiled before linking any existing Fortran code that uses
read-only verification.

Compilation of the library is done by invoking ``make`` and setting
the required variables:

.. code-block:: shell
make F90=ifort F90FLAGS="--some-flag"
This will create a library called ``lib_read_only.a``.
An executable example for using the generic read-only-verification
library is included in ``examples/nemo/eg6/``.

.. _psydata_value_range_check:

Value Range Check
Expand Down
8 changes: 8 additions & 0 deletions doc/user_guide/tutorials_and_examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -783,6 +783,14 @@ compilation instructions are in the ``README.md`` file, including how
to switch from using the stand-alone extraction library to the NetCDF-based
one (see :ref:`extraction_libraries` for details).

Example 6: Read-only Verification
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

This example shows the use of read-only verification with PSyclone for
generic Fortran code. It instruments each kernel in a small Fortran
program with the PSyData-based read-only verification code. Detailed
compilation instructions are in the ``README.md`` file.


Scripts
^^^^^^^
Expand Down
6 changes: 6 additions & 0 deletions examples/nemo/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,3 +140,9 @@ benchmark.

Extraction of kernel data. Using the tra_adv benchmark, this example
shows the extraction of kernel input- and output-data.

## Example 6

A simple stand-alone example that shows verification that read-only data
is not modified, e.g. by out-of-bounds accesses to other variables.
This uses the PSyData interface to instrument generic Fortran code.
5 changes: 4 additions & 1 deletion examples/nemo/eg5/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,14 @@ kernels: extract_kernels.py
$(PSYCLONE) -l all -s ./extract_kernels.py -o psy.f90 ../code/tra_adv.F90

$(EXTRACT_DIR)/$(LIB_NAME):
make -C $(EXTRACT_DIR)
${MAKE} -C $(EXTRACT_DIR)

# Compilation uses the 'kernels' transformed code
psy.f90: kernels
psy.o: $(EXTRACT_DIR)/$(LIB_NAME)

%.o: %.f90
$(F90) $(F90FLAGS) -c $<

allclean: clean
${MAKE} -C ${EXTRACT_DIR} allclean
11 changes: 1 addition & 10 deletions examples/nemo/eg5/extract_kernels.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,16 +88,7 @@ def trans(psyir):
if not isinstance(kern, Loop):
continue
try:
# TODO #2080: once this is fixed, the option can be removed
# The example contains array expressions, e.g.:
# zwx(:,:,jpk) = 0.e0
# PSyclone represents this internally using Range with LBOUND
# and UBOUND intrinsics and currently this results in several
# occurrences of zws on the left hand side, which will trigger
# an exception in the dependency analysis. Therefore, disable
# the collection of read accesses for the shape of an array.
extract.apply(kern,
options={"COLLECT-ARRAY-SHAPE-READS": False})
extract.apply(kern)
except TransformationError as err:
# Typically that's caused by a kernel having a CodeBlock
# inside.
Expand Down
86 changes: 86 additions & 0 deletions examples/nemo/eg6/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# -----------------------------------------------------------------------------
# BSD 3-Clause License
#
# Copyright (c) 2023-2025, Science and Technology Facilities Council.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# * Neither the name of the copyright holder nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# ------------------------------------------------------------------------------
# Author: A. R. Porter, STFC Daresbury Lab
# Modified J. Henrichs, Bureau of Meteorology

# This example uses PSyclone (which must be installed) to generate Fortran for
# the tracer-advection benchmark. The script provided here instruments code to
# check that read-only variables are not modified.

# The compiler to use may be specified via the F90 environment variable,
# it defaults to:
# export F90=gfortran
# export F90FLAGS="-g -O0"

include ../../common.mk

TYPE ?= standalone

GENERATED_FILES += psy.f90 psy.o dummy

PSYROOT=../../..
READ_ONLY_CHECK_DIR ?= $(PSYROOT)/lib/read_only/generic

F90FLAGS += -I$(READ_ONLY_CHECK_DIR)
LIB_NAME = lib_read_only.a

.PHONY: allclean

compile: dummy

run: compile
./dummy

dummy: psy.o $(READ_ONLY_CHECK_DIR)/$(LIB_NAME)
$(F90) $(F90FLAGS) psy.o -o dummy $(READ_ONLY_CHECK_DIR)/$(LIB_NAME) $(LDFLAGS)

transform: kernels

# Need `-l all` to ensure line-lengths in generated code are less than the
# standard-mandated 132 chars.
kernels: read_only_check.py
$(PSYCLONE) -l all -s ./read_only_check.py -o psy.f90 dummy.f90

$(READ_ONLY_CHECK_DIR)/$(LIB_NAME):
$(MAKE) -C $(READ_ONLY_CHECK_DIR)

# Compilation uses the 'kernels' transformed code
psy.f90: dummy.f90 read_only_check.py kernels
psy.o: $(READ_ONLY_CHECK_DIR)/$(LIB_NAME)

%.o: %.f90
$(F90) $(F90FLAGS) -c $<

allclean: clean
${MAKE} -C $(READ_ONLY_CHECK_DIR) allclean
Loading

0 comments on commit edf4556

Please sign in to comment.