| //===-- Memory.td - Memory definitions for Offload ---------*- tablegen -*-===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| // | |
| // This file contains Offload API definitions related to memory allocations | |
| // | |
| //===----------------------------------------------------------------------===// | |
| def ol_alloc_type_t : Enum { | |
| let desc = "Represents the type of a memory allocation."; | |
| let etors = [ | |
| Etor<"HOST", "Host allocation">, | |
| Etor<"DEVICE", "Device allocation">, | |
| Etor<"MANAGED", "Managed allocation"> | |
| ]; | |
| } | |
| def ol_memory_register_flags_t : Typedef { | |
| let desc = "Memory registering/locking flags"; | |
| let value = "uint32_t"; | |
| } | |
| def ol_memory_register_flag_t : Enum { | |
| let desc = "Memory registering/locking flags"; | |
| let is_bit_field = 1; | |
| let etors =[ | |
| Etor<"LOCK_MEMORY", "Page-lock the memory">, | |
| Etor<"UNLOCK_MEMORY", "Page-unlock the memory">, | |
| ]; | |
| } | |
| def olMemAlloc : Function { | |
| let desc = "Creates a memory allocation on the specified device."; | |
| let details = [ | |
| "The allocation is scoped to `Context` and `Device` must belong to it.", | |
| "This function can only be used to create device or managed allocations. To create a host allocation use `olMemAllocHost`." | |
| ]; | |
| let params = [ | |
| Param<"ol_context_handle_t", "Context", "handle of the context", PARAM_IN>, | |
| Param<"ol_device_handle_t", "Device", "handle of the device to allocate on", PARAM_IN>, | |
| Param<"ol_alloc_type_t", "Type", "type of the allocation. Must be either `OL_ALLOC_TYPE_DEVICE` or `OL_ALLOC_TYPE_MANAGED`", PARAM_IN>, | |
| Param<"size_t", "Size", "size of the allocation in bytes", PARAM_IN>, | |
| Param<"void**", "AllocationOut", "output for the allocated pointer", PARAM_OUT> | |
| ]; | |
| let returns = [ | |
| Return<"OL_ERRC_INVALID_SIZE", [ | |
| "`Size == 0`" | |
| ]>, | |
| Return<"OL_ERRC_INVALID_ENUMERATION", [ | |
| "`Type == OL_ALLOC_TYPE_HOST`" | |
| ]>, | |
| Return<"OL_ERRC_INVALID_DEVICE", [ | |
| "Device does not belong to `Context`" | |
| ]> | |
| ]; | |
| } | |
| def olMemAllocHost : Function { | |
| let desc = "Creates a host memory allocation accessible from the specified device."; | |
| let details = [ | |
| "The allocation is scoped to `Context` and `Device` must belong to it." | |
| ]; | |
| let params = [ | |
| Param<"ol_context_handle_t", "Context", "handle of the context", PARAM_IN>, | |
| Param<"ol_device_handle_t", "Device", "handle of the device to allocate on", PARAM_IN>, | |
| Param<"size_t", "Size", "size of the allocation in bytes", PARAM_IN>, | |
| Param<"void**", "AllocationOut", "output for the allocated pointer", PARAM_OUT> | |
| ]; | |
| let returns = [ | |
| Return<"OL_ERRC_INVALID_SIZE", [ | |
| "`Size == 0`" | |
| ]>, | |
| Return<"OL_ERRC_INVALID_DEVICE", [ | |
| "Device does not belong to `Context`" | |
| ]> | |
| ]; | |
| } | |
| def olMemAllocAligned : Function { | |
| let desc = "Creates a memory allocation on the specified device with the specified alignment."; | |
| let details = [ | |
| "The allocation is scoped to `Context` and `Device` must belong to it.", | |
| "This function can only be used to create device or managed allocations. To create a host allocation use `olMemAllocAlignedHost`." | |
| ]; | |
| let params = [ | |
| Param<"ol_context_handle_t", "Context", "handle of the context", PARAM_IN>, | |
| Param<"ol_device_handle_t", "Device", "handle of the device to allocate on", PARAM_IN>, | |
| Param<"ol_alloc_type_t", "Type", "type of the allocation. Must be either `OL_ALLOC_TYPE_DEVICE` or `OL_ALLOC_TYPE_MANAGED`", PARAM_IN>, | |
| Param<"size_t", "Size", "size of the allocation in bytes", PARAM_IN>, | |
| Param<"size_t", "Alignment", | |
| "alignment of the allocation in bytes. Must be non-zero and a power of two", | |
| PARAM_IN>, | |
| Param<"void**", "AllocationOut", "output for the allocated pointer", PARAM_OUT> | |
| ]; | |
| let returns = [ | |
| Return<"OL_ERRC_INVALID_SIZE", [ | |
| "`Size == 0`" | |
| ]>, | |
| Return<"OL_ERRC_INVALID_ARGUMENT", [ | |
| "`Alignment == 0`" | |
| ]>, | |
| Return<"OL_ERRC_INVALID_ARGUMENT", [ | |
| "`(Alignment & (Alignment - 1)) != 0`" | |
| ]>, | |
| Return<"OL_ERRC_INVALID_ENUMERATION", [ | |
| "`Type == OL_ALLOC_TYPE_HOST`" | |
| ]>, | |
| Return<"OL_ERRC_INVALID_DEVICE", [ | |
| "Device does not belong to `Context`" | |
| ]>, | |
| ]; | |
| } | |
| def olMemAllocAlignedHost : Function { | |
| let desc = "Creates a host memory allocation with the specified alignment."; | |
| let details = [ | |
| "The allocation is scoped to `Context` and `Device` must belong to it." | |
| ]; | |
| let params = [ | |
| Param<"ol_context_handle_t", "Context", "handle of the context", PARAM_IN>, | |
| Param<"ol_device_handle_t", "Device", "handle of the device to allocate on", PARAM_IN>, | |
| Param<"size_t", "Size", "size of the allocation in bytes", PARAM_IN>, | |
| Param<"size_t", "Alignment", | |
| "alignment of the allocation in bytes. Must be non-zero and a power of two", | |
| PARAM_IN>, | |
| Param<"void**", "AllocationOut", "output for the allocated pointer", PARAM_OUT> | |
| ]; | |
| let returns = [ | |
| Return<"OL_ERRC_INVALID_SIZE", [ | |
| "`Size == 0`" | |
| ]>, | |
| Return<"OL_ERRC_INVALID_ARGUMENT", [ | |
| "`Alignment == 0`" | |
| ]>, | |
| Return<"OL_ERRC_INVALID_ARGUMENT", [ | |
| "`(Alignment & (Alignment - 1)) != 0`" | |
| ]>, | |
| Return<"OL_ERRC_INVALID_DEVICE", [ | |
| "Device does not belong to `Context`" | |
| ]>, | |
| ]; | |
| } | |
| def olMemFree : Function { | |
| let desc = "Frees a memory allocation previously made by an olMemAlloc* function."; | |
| let params = [ | |
| Param<"ol_context_handle_t", "Context", "handle of the context the allocation was made in", PARAM_IN>, | |
| Param<"void*", "Address", "address of the allocation to free", PARAM_IN>, | |
| ]; | |
| let returns = [ | |
| Return<"OL_ERRC_INVALID_CONTEXT", [ | |
| "The allocation was not made in `Context`" | |
| ]> | |
| ]; | |
| } | |
| def ol_mem_info_t : Enum { | |
| let desc = "Supported memory info."; | |
| let is_typed = 1; | |
| let etors = [ | |
| TaggedEtor<"DEVICE", "ol_device_handle_t", "The handle of the device associated with the allocation.">, | |
| TaggedEtor<"BASE", "void *", "Base address of this allocation.">, | |
| TaggedEtor<"SIZE", "size_t", "Size of this allocation in bytes.">, | |
| TaggedEtor<"TYPE", "ol_alloc_type_t", "Type of this allocation.">, | |
| ]; | |
| } | |
| def olGetMemInfo : Function { | |
| let desc = "Queries the given property of a memory allocation allocated with an olMemAlloc* function."; | |
| let details = [ | |
| "`olGetMemInfoSize` can be used to query the storage size required for the given query.", | |
| "The provided pointer can point to any location inside the allocation.", | |
| "The allocation must belong to `Context`.", | |
| ]; | |
| let params = [ | |
| Param<"ol_context_handle_t", "Context", "handle of the context the allocation was made in", PARAM_IN>, | |
| Param<"const void *", "Ptr", "pointer to the allocated memory", PARAM_IN>, | |
| Param<"ol_mem_info_t", "PropName", "type of the info to retrieve", PARAM_IN>, | |
| Param<"size_t", "PropSize", "the number of bytes pointed to by PropValue.", PARAM_IN>, | |
| TypeTaggedParam<"void*", "PropValue", "array of bytes holding the info. " | |
| "If Size is not equal to or greater to the real number of bytes needed to return the info " | |
| "then the OL_ERRC_INVALID_SIZE error is returned and pPlatformInfo is not used.", PARAM_OUT, | |
| TypeInfo<"PropName" , "PropSize">> | |
| ]; | |
| let returns = [ | |
| Return<"OL_ERRC_INVALID_SIZE", [ | |
| "`PropSize == 0`", | |
| "If `PropSize` is less than the real number of bytes needed to return the info." | |
| ]>, | |
| Return<"OL_ERRC_NOT_FOUND", ["memory was not allocated in `Context`"]> | |
| ]; | |
| } | |
| def olGetMemInfoSize : Function { | |
| let desc = "Returns the storage size of the given queue query."; | |
| let details = [ | |
| "The provided pointer can point to any location inside the allocation.", | |
| "The allocation must belong to `Context`.", | |
| ]; | |
| let params = [ | |
| Param<"ol_context_handle_t", "Context", "handle of the context the allocation was made in", PARAM_IN>, | |
| Param<"const void *", "Ptr", "pointer to the allocated memory", PARAM_IN>, | |
| Param<"ol_mem_info_t", "PropName", "type of the info to query", PARAM_IN>, | |
| Param<"size_t*", "PropSizeRet", "pointer to the number of bytes required to store the query", PARAM_OUT> | |
| ]; | |
| let returns = [ | |
| Return<"OL_ERRC_NOT_FOUND", ["memory was not allocated in `Context`"]> | |
| ]; | |
| } | |
| def olMemcpy : Function { | |
| let desc = "Enqueue a memcpy operation."; | |
| let details = [ | |
| "For host pointers, use the host device belonging to the OL_PLATFORM_BACKEND_HOST platform.", | |
| "If both pointers are on the host and a queue is specified, the memcpy is ordered with other work in the queue.", | |
| "If a queue is not specified, the memcpy happens synchronously" | |
| ]; | |
| let params = [ | |
| Param<"ol_queue_handle_t", "Queue", "handle of the queue.", PARAM_IN_OPTIONAL>, | |
| Param<"void*", "DstPtr", "pointer to copy to", PARAM_IN>, | |
| Param<"ol_device_handle_t", "DstDevice", "device that DstPtr belongs to", PARAM_IN>, | |
| Param<"const void*", "SrcPtr", "pointer to copy from", PARAM_IN>, | |
| Param<"ol_device_handle_t", "SrcDevice", "device that SrcPtr belongs to", PARAM_IN>, | |
| Param<"size_t", "Size", "size in bytes of data to copy", PARAM_IN>, | |
| ]; | |
| let returns = []; | |
| } | |
| def olMemFill : Function { | |
| let desc = "Fill memory with copies of the given pattern"; | |
| let details = [ | |
| "Filling with patterns of a different size than 1, 2 or 4 bytes may be less performant and may synchronize the queue", | |
| "The destination pointer and queue must be associated with the same device", | |
| "The fill size must be a multiple of the pattern size", | |
| ]; | |
| let params = [ | |
| Param<"ol_queue_handle_t", "Queue", "handle of the queue", PARAM_IN_OPTIONAL>, | |
| Param<"void*", "Ptr", "destination pointer to start filling at", PARAM_IN>, | |
| Param<"size_t", "PatternSize", "the size of the pattern in bytes", PARAM_IN>, | |
| Param<"const void*", "PatternPtr", "", PARAM_IN>, | |
| Param<"size_t", "FillSize", "number of bytes to fill", PARAM_IN>, | |
| ]; | |
| let returns = [ | |
| Return<"OL_ERRC_INVALID_SIZE", ["`FillSize % PatternSize != 0`"]> | |
| ]; | |
| } | |
| def olMemRegister : Function { | |
| let desc = "Register and optionally page-lock host memory so it can be accessible by the device."; | |
| let details = [ | |
| "Registers host memory and optionally page-locks it to optimize transfers and returns", | |
| "the device accessible stable pointer that devices should use for memory transfers", | |
| "involving the host pinned allocation. If the buffer intersects with other existing buffer,", | |
| "if the buffer is locked outside of this API, or Flags doesn't contain LOCK_MEMORY", | |
| "flag a new user will be registered. Partial overlapping with an already registered range is", | |
| "not allowed. The pinned pointer can be accessed both on host and device and", | |
| "no guarantees are made about consistency.", | |
| "The pinned pointer should be used to execute memory transfers", | |
| "as it is a stable pointer for memory access." | |
| ]; | |
| let params = [ | |
| Param<"ol_device_handle_t", "Device", "handle of the device", PARAM_IN>, | |
| Param<"void *", "Ptr", "host pointer", PARAM_IN>, | |
| Param<"size_t", "Size", "size of the memory in bytes", PARAM_IN>, | |
| Param<"ol_memory_register_flags_t", "Flags", "flags controlling various aspects of registration", PARAM_IN>, | |
| Param<"void**", "PinnedPtr", "pointer to the pinned memory", PARAM_OUT> | |
| ]; | |
| let returns = [ | |
| Return<"OL_ERRC_INVALID_SIZE", [ | |
| "`Size == 0`" | |
| ]> | |
| ]; | |
| } | |
| def olMemUnregister : Function { | |
| let desc = "Unregister host memory and optionally page-unlock it."; | |
| let details = [ | |
| "Unregisters host memory and optionally page-unlocks it.", | |
| "If other users are still using the buffer or Flags doesn't contain UNLOCK_MEMORY flag" | |
| "the memory is unregistered, otherwise the memory is unlocked." | |
| ]; | |
| let params = [ | |
| Param<"ol_device_handle_t", "Device", "handle of the device", PARAM_IN>, | |
| Param<"void *", "Ptr", "host pointer", PARAM_IN>, | |
| Param<"ol_memory_register_flags_t", "Flags", "flags controlling various aspects of unregistration", PARAM_IN>, | |
| ]; | |
| let returns = []; | |
| } | |
| def ol_mem_migration_flags_t : Typedef { | |
| let desc = "Memory migration flags, indicating the direction data is migrated in."; | |
| let value = "uint32_t"; | |
| } | |
| def ol_mem_migration_flag_t : Enum { | |
| let desc = "Memory migration flags, indicating the direction data is migrated in."; | |
| let is_bit_field = 1; | |
| let etors = [ | |
| Etor<"HOST_TO_DEVICE", "Migrate data from the host to the device">, | |
| Etor<"DEVICE_TO_HOST", "Migrate data from the device to the host">, | |
| ]; | |
| } | |
| def olMemPrefetch : Function { | |
| let desc = "Enqueue a command to migrate USM memory between the host and a device."; | |
| let details = [ | |
| "Prefetch is a hint that migrates a USM allocation between the host and a device " | |
| "so subsequent accesses on the target side are faster. The contents of the memory " | |
| "are unchanged - only its physical location may change.", | |
| "Prefetching may not be supported for all devices or allocation types. If it is not " | |
| "supported the prefetch is ignored and the call still returns success.", | |
| ]; | |
| let params = [ | |
| Param<"ol_queue_handle_t", "Queue", "handle of the queue", PARAM_IN>, | |
| Param<"size_t", "Count", "number of entries in `Mems` and `Sizes`. Zero is allowed and is a no-op.", PARAM_IN>, | |
| Param<"const void**", "Mems", "array of `Count` pointers, each pointing into a USM allocation to be prefetched. May be NULL if `Count` is 0.", PARAM_IN_OPTIONAL>, | |
| Param<"const size_t*", "Sizes", "array of `Count` sizes in bytes. A zero entry is allowed and is a no-op for that element. May be NULL if `Count` is 0.", PARAM_IN_OPTIONAL>, | |
| Param<"ol_mem_migration_flags_t", "Flags", "direction of the migration; exactly one of the OL_MEM_MIGRATION_FLAG_* values", PARAM_IN>, | |
| ]; | |
| let returns = [ | |
| Return<"OL_ERRC_INVALID_NULL_POINTER", [ | |
| "`Count > 0 && Mems == NULL`", | |
| "`Count > 0 && Sizes == NULL`" | |
| ]>, | |
| Return<"OL_ERRC_INVALID_ENUMERATION", [ | |
| "`(Flags & ~(OL_MEM_MIGRATION_FLAG_HOST_TO_DEVICE | OL_MEM_MIGRATION_FLAG_DEVICE_TO_HOST)) != 0`" | |
| ]>, | |
| ]; | |
| } |