From 72f503433f25e6f815f015408f9d9700188890d9 Mon Sep 17 00:00:00 2001
From: Frederik Hennig <frederik.hennig@fau.de>
Date: Wed, 23 Oct 2024 13:47:59 +0200
Subject: [PATCH] Documentation on buffers

---
 docs/source/backend/ast.rst      | 15 ++++++------
 docs/source/backend/index.rst    |  1 +
 docs/source/backend/objects.rst  | 39 ++++++++++++++++++++++++++------
 docs/source/backend/output.rst   |  6 +++++
 src/pystencils/backend/memory.py | 22 +++++++++++++++++-
 5 files changed, 68 insertions(+), 15 deletions(-)
 create mode 100644 docs/source/backend/output.rst

diff --git a/docs/source/backend/ast.rst b/docs/source/backend/ast.rst
index 41f230166..44f8f2540 100644
--- a/docs/source/backend/ast.rst
+++ b/docs/source/backend/ast.rst
@@ -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:
diff --git a/docs/source/backend/index.rst b/docs/source/backend/index.rst
index b3de9dbf6..70ed684c6 100644
--- a/docs/source/backend/index.rst
+++ b/docs/source/backend/index.rst
@@ -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
 
diff --git a/docs/source/backend/objects.rst b/docs/source/backend/objects.rst
index a39f4c24b..11cf8ea5e 100644
--- a/docs/source/backend/objects.rst
+++ b/docs/source/backend/objects.rst
@@ -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
 =================
diff --git a/docs/source/backend/output.rst b/docs/source/backend/output.rst
new file mode 100644
index 000000000..9875e257b
--- /dev/null
+++ b/docs/source/backend/output.rst
@@ -0,0 +1,6 @@
+*********************
+Code Generator Output
+*********************
+
+.. automodule:: pystencils.backend.kernelfunction
+    :members:
diff --git a/src/pystencils/backend/memory.py b/src/pystencils/backend/memory.py
index ad28cd3c7..9b72a4e43 100644
--- a/src/pystencils/backend/memory.py
+++ b/src/pystencils/backend/memory.py
@@ -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:
-- 
GitLab