Skip to content
Snippets Groups Projects
Commit 72f50343 authored by Frederik Hennig's avatar Frederik Hennig
Browse files

Documentation on buffers

parent a484bce1
No related branches found
No related tags found
1 merge request!421Refactor Field Modelling
Pipeline #69794 passed
......@@ -2,29 +2,30 @@
Abstract Syntax Tree
********************
Inheritance Diagramm
====================
API Documentation
=================
Inheritance Diagram
-------------------
.. inheritance-diagram:: pystencils.backend.ast.astnode.PsAstNode pystencils.backend.ast.structural pystencils.backend.ast.expressions pystencils.backend.extensions.foreign_ast
:top-classes: pystencils.types.PsAstNode
:parts: 1
Base Classes
============
------------
.. automodule:: pystencils.backend.ast.astnode
:members:
Structural Nodes
================
----------------
.. automodule:: pystencils.backend.ast.structural
:members:
Expressions
===========
-----------
.. automodule:: pystencils.backend.ast.expressions
:members:
......@@ -15,6 +15,7 @@ who wish to customize or extend the behaviour of the code generator in their app
translation
platforms
transformations
output
jit
extensions
......
......@@ -40,18 +40,18 @@ two `PsSymbol` instances with the same name and data type will in general *not*
In fact, most of the time, it is an error to have two identical symbol instances active.
Creating Symbols
----------------
^^^^^^^^^^^^^^^^
During kernel translation, symbols never exist in isolation, but should always be managed by a `KernelCreationContext`.
Symbols can be created and retrieved using `KernelCreationContext.add_symbol` and `KernelCreationContext.find_symbol`.
A symbol can also be duplicated using `KernelCreationContext.duplicate_symbol`, which assigns a new name to the symbol's copy.
Symbols can be created and retrieved using `add_symbol <KernelCreationContext.add_symbol>` and `find_symbol <KernelCreationContext.find_symbol>`.
A symbol can also be duplicated using `duplicate_symbol <KernelCreationContext.duplicate_symbol>`, which assigns a new name to the symbol's copy.
The `KernelCreationContext` keeps track of all existing symbols during a kernel translation run
and makes sure that no name and data type conflicts may arise.
Never call the constructor of `PsSymbol` directly unless you really know what you are doing.
Symbol Properties
-----------------
^^^^^^^^^^^^^^^^^
Symbols can be annotated with arbitrary information using *symbol properties*.
Each symbol property type must be a subclass of `PsSymbolProperty`.
......@@ -64,6 +64,7 @@ For example, this snippet defines a property type that models pointer alignment
@dataclass(frozen=True)
class AlignmentProperty(UniqueSymbolProperty)
"""Require this pointer symbol to be aligned at a particular byte boundary."""
byte_boundary: int
Inheriting from `UniqueSymbolProperty` ensures that at most one property of this type can be attached to
......@@ -77,10 +78,34 @@ It then becomes the responsibility of the runtime system embedding the kernel to
To make sure this information becomes visible, any properties attached to symbols exposed as kernel parameters will also
be added to their respective `KernelParameter` instance.
Constants and Literals
======================
Buffers
-------
Buffers, as represented by the `PsBuffer` class, represent contiguous, n-dimensional, linearized cuboid blocks of memory.
Each buffer has a fixed name and element data type,
and will be represented in the IR via three sets of symbols:
- The *base pointer* is a symbol of pointer type which points into the buffer's underlying memory area.
Each buffer has at least one, its primary base pointer, whose pointed-to type must be the same as the
buffer's element type. There may be additional base pointers pointing into subsections of that memory.
These additional base pointers may also have deviating data types, as is for instance required for
type erasure in certain cases.
To communicate its role to the code generation system,
each base pointer needs to be marked as such using the `BufferBasePtr` property,
.
- The buffer *shape* defines the size of the buffer in each dimension. Each shape entry is either a `symbol <PsSymbol>`
or a `constant <PsConstant>`.
- The buffer *strides* define the step size to go from one entry to the next in each dimension.
Like the shape, each stride entry is also either a symbol or a constant.
The shape and stride symbols must all have the same data type, which will be stored as the buffer's index data type.
Creating and Managing Buffers
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Similarily to symbols, buffers are typically managed by the `KernelCreationContext`, which associates each buffer
to a front-end `Field`. Buffers for fields can be obtained using `get_buffer <KernelCreationContext.get_buffer>`.
The context makes sure to avoid name conflicts between buffers.
API Documentation
=================
......
*********************
Code Generator Output
*********************
.. automodule:: pystencils.backend.kernelfunction
:members:
......@@ -3,7 +3,7 @@ from typing import Sequence
from itertools import chain
from dataclasses import dataclass
from ..types import PsType, PsTypeError, deconstify, PsIntegerType
from ..types import PsType, PsTypeError, deconstify, PsIntegerType, PsPointerType
from .exceptions import PsInternalCompilerError
from .constants import PsConstant
from .properties import PsSymbolProperty, UniqueSymbolProperty
......@@ -119,6 +119,19 @@ class PsBuffer:
shape: Sequence[PsSymbol | PsConstant],
strides: Sequence[PsSymbol | PsConstant],
):
bptr_type = base_ptr.get_dtype()
if not isinstance(bptr_type, PsPointerType):
raise ValueError(
f"Type of buffer base pointer {base_ptr} was not a pointer type: {bptr_type}"
)
if bptr_type.base_type != element_type:
raise ValueError(
f"Base type of primary buffer base pointer {base_ptr} "
f"did not equal buffer element type {element_type}."
)
if len(shape) != len(strides):
raise ValueError("Buffer shape and stride tuples must have the same length")
......@@ -148,30 +161,37 @@ class PsBuffer:
@property
def name(self):
"""The buffer's name"""
return self._name
@property
def base_pointer(self) -> PsSymbol:
"""Primary base pointer"""
return self._base_ptr
@property
def shape(self) -> tuple[PsSymbol | PsConstant, ...]:
"""Buffer shape symbols and/or constants"""
return self._shape
@property
def strides(self) -> tuple[PsSymbol | PsConstant, ...]:
"""Buffer stride symbols and/or constants"""
return self._strides
@property
def dim(self) -> int:
"""Dimensionality of this buffer"""
return len(self._shape)
@property
def index_type(self) -> PsIntegerType:
"""Index data type of this buffer; i.e. data type of its shape and stride symbols"""
return self._index_dtype
@property
def element_type(self) -> PsType:
"""Element type of this buffer"""
return self._element_type
def __repr__(self) -> str:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment