diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 00000000000..152f6d6b86e --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,6 @@ +[workspace] + +members = [ + "src/Simulation/qdk_sim_rs", + "src/Qir/microsoft-quantum-qir-runtime-sys", +] \ No newline at end of file diff --git a/build/e2e.yml b/build/e2e.yml index 1a56ac89ab3..975952e7418 100644 --- a/build/e2e.yml +++ b/build/e2e.yml @@ -1,4 +1,4 @@ -name: $(Build.Major).$(Build.Minor).$(date:yyMM).$(BuildId) +name: $(Build.Major).$(Build.Minor).$(BuildId) parameters: - name: validation_level diff --git a/build/pack.ps1 b/build/pack.ps1 index 6bb5edcdf49..37882ee7581 100644 --- a/build/pack.ps1 +++ b/build/pack.ps1 @@ -129,10 +129,10 @@ function Pack-Crate() { $OutPath = Resolve-Path (Join-Path $PSScriptRoot $OutPath); } Push-Location (Join-Path $PSScriptRoot $PackageDirectory) - cargo package; - # Copy only the .crate file, since we don't need all the intermediate - # artifacts brought in by the full folder under target/package. - Copy-Item -Force (Join-Path . "target" "package" "*.crate") $OutPath; + cargo package; + # Copy only the .crate file, since we don't need all the intermediate + # artifacts brought in by the full folder under target/package. + Copy-Item -Force (Join-Path $PSScriptRoot .. "target" "package" "*.crate") $OutPath; Pop-Location } diff --git a/build/steps-codecheck.yml b/build/steps-codecheck.yml index 8a25efe684f..fe474e3ccbf 100644 --- a/build/steps-codecheck.yml +++ b/build/steps-codecheck.yml @@ -10,7 +10,7 @@ steps: # QIR Runtime: - pwsh: src/Qir/Runtime/prerequisites.ps1 - displayName: "Install QIR Runtime Prerequisistes" + displayName: "Install QIR Runtime Prerequisites" workingDirectory: $(System.DefaultWorkingDirectory) - pwsh: src/Qir/Runtime/build-qir-runtime.ps1 diff --git a/src/Azure/Azure.Quantum.Client.Test/WorkspaceTest.cs b/src/Azure/Azure.Quantum.Client.Test/WorkspaceTest.cs index 9f8a6935233..ecca60b212c 100644 --- a/src/Azure/Azure.Quantum.Client.Test/WorkspaceTest.cs +++ b/src/Azure/Azure.Quantum.Client.Test/WorkspaceTest.cs @@ -7,10 +7,12 @@ using System.IO.Compression; using System.Linq; using System.Net; +using System.Reflection; using System.Threading; using System.Threading.Tasks; - +using Azure.Identity; using Azure.Quantum; +using Azure.Quantum.Jobs; using Azure.Quantum.Jobs.Models; using Microsoft.Azure.Quantum.Exceptions; @@ -176,6 +178,100 @@ public async Task ListProviderStatusTest() Assert.AreEqual(0, max); } + [TestMethod] + [TestCategory("Local")] + public async Task ApplicationIdTest() + { + const string ENV_VAR_APPID = "EnvVarAppId"; + const string OPTIONS_APPID = "OptionAppId"; + const string LONG_ENV_VAR_APPID = "LongEnvVarAppId"; + const string LONG_OPTIONS_APPID = "LongOptionAppId"; + const string VERY_LONG_ENV_VAR_APPID = "VeryVeryVeryVeryVeryVeryLongEnvVarAppId"; + const string VERY_LONG_OPTIONS_APPID = "VeryVeryVeryVeryVeryVeryLongOptionAppId"; + const string APPID_ENV_VAR_NAME = "AZURE_QUANTUM_NET_APPID"; + + Func createWorkspace = (QuantumJobClientOptions options) => + { + var credential = new ClientSecretCredential(tenantId: "72f988bf-86f1-41af-91ab-2d7cd011db47", + clientId: "00000000-0000-0000-0000-000000000000", + clientSecret: "PLACEHOLDER"); + return new Workspace(subscriptionId: "SubscriptionId", + resourceGroupName: "ResourceGroupName", + workspaceName: "WorkspaceName", + location: "WestUs", + options: options, + credential: credential); + }; + + var originalEnvironmentAppId = Environment.GetEnvironmentVariable(APPID_ENV_VAR_NAME); + try + { + + // Test with no Environment AppId and no Options AppId + Environment.SetEnvironmentVariable(APPID_ENV_VAR_NAME, null); + var workspace = createWorkspace(null); + Assert.IsNotNull(workspace.ClientOptions); + Assert.IsNotNull(workspace.ClientOptions.Diagnostics); + Assert.AreEqual("", workspace.ClientOptions.Diagnostics.ApplicationId); + + // Test with Environment AppId and no Options AppId + Environment.SetEnvironmentVariable(APPID_ENV_VAR_NAME, ENV_VAR_APPID); + workspace = createWorkspace(null); + Assert.IsNotNull(workspace.ClientOptions); + Assert.IsNotNull(workspace.ClientOptions.Diagnostics); + Assert.AreEqual(ENV_VAR_APPID, workspace.ClientOptions.Diagnostics.ApplicationId); + + // Test with no Environment AppId and with Options AppId + Environment.SetEnvironmentVariable(APPID_ENV_VAR_NAME, null); + var options = new QuantumJobClientOptions(); + options.Diagnostics.ApplicationId = OPTIONS_APPID; + workspace = createWorkspace(options); + Assert.IsNotNull(workspace.ClientOptions); + Assert.IsNotNull(workspace.ClientOptions.Diagnostics); + Assert.AreEqual(OPTIONS_APPID, workspace.ClientOptions.Diagnostics.ApplicationId); + + // Test with Environment AppId and with Options AppId + Environment.SetEnvironmentVariable(APPID_ENV_VAR_NAME, ENV_VAR_APPID); + options = new QuantumJobClientOptions(); + options.Diagnostics.ApplicationId = OPTIONS_APPID; + workspace = createWorkspace(options); + Assert.IsNotNull(workspace.ClientOptions); + Assert.IsNotNull(workspace.ClientOptions.Diagnostics); + Assert.AreEqual($"{OPTIONS_APPID}-{ENV_VAR_APPID}", workspace.ClientOptions.Diagnostics.ApplicationId); + + // Test with long (>24 chars) combination of Environment AppId and Options AppId + Environment.SetEnvironmentVariable(APPID_ENV_VAR_NAME, LONG_ENV_VAR_APPID); + options = new QuantumJobClientOptions(); + options.Diagnostics.ApplicationId = LONG_OPTIONS_APPID; + workspace = createWorkspace(options); + Assert.IsNotNull(workspace.ClientOptions); + Assert.IsNotNull(workspace.ClientOptions.Diagnostics); + var truncatedAppId = $"{LONG_OPTIONS_APPID}-{LONG_ENV_VAR_APPID}".Substring(0, 24); + Assert.AreEqual(truncatedAppId, workspace.ClientOptions.Diagnostics.ApplicationId); + + // Test with long (>24 chars) Environment AppId and no Options AppId + Environment.SetEnvironmentVariable(APPID_ENV_VAR_NAME, VERY_LONG_ENV_VAR_APPID); + workspace = createWorkspace(null); + Assert.IsNotNull(workspace.ClientOptions); + Assert.IsNotNull(workspace.ClientOptions.Diagnostics); + Assert.AreEqual(VERY_LONG_ENV_VAR_APPID.Substring(0, 24), workspace.ClientOptions.Diagnostics.ApplicationId); + + // Test with long (>24 chars) Options AppId and no Environment AppId + Environment.SetEnvironmentVariable(APPID_ENV_VAR_NAME, null); + options = new QuantumJobClientOptions(); + Assert.ThrowsException(() => + options.Diagnostics.ApplicationId = VERY_LONG_OPTIONS_APPID); + } + finally + { + // restore original env var AZURE_QUANTUM_NET_APPID + if (originalEnvironmentAppId != null) + { + Environment.SetEnvironmentVariable(APPID_ENV_VAR_NAME, originalEnvironmentAppId); + } + } + } + private static void AssertJob(CloudJob job) { Assert.IsNotNull(job); diff --git a/src/Azure/Azure.Quantum.Client/JobManagement/Workspace.cs b/src/Azure/Azure.Quantum.Client/JobManagement/Workspace.cs index e4015ee75e8..e431b2fd8ca 100644 --- a/src/Azure/Azure.Quantum.Client/JobManagement/Workspace.cs +++ b/src/Azure/Azure.Quantum.Client/JobManagement/Workspace.cs @@ -10,7 +10,6 @@ namespace Microsoft.Azure.Quantum using System.Threading; using System.Threading.Tasks; using global::Azure.Core; - using global::Azure.Identity; using global::Azure.Quantum; using global::Azure.Quantum.Jobs; using global::Azure.Quantum.Jobs.Models; @@ -50,9 +49,10 @@ public Workspace( // Optional parameters: credential ??= CredentialFactory.CreateCredential(CredentialType.Default, subscriptionId); - options ??= new QuantumJobClientOptions(); - options.Diagnostics.ApplicationId = options.Diagnostics.ApplicationId - ?? Environment.GetEnvironmentVariable("AZURE_QUANTUM_NET_APPID"); + + // Make sure use the property Setter as we have some logic + // tto apply here + this.ClientOptions = options; this.ResourceGroupName = resourceGroupName; this.WorkspaceName = workspaceName; @@ -65,7 +65,7 @@ public Workspace( workspaceName, location, credential, - options); + this.ClientOptions); } public string ResourceGroupName { get; } @@ -81,6 +81,34 @@ public Workspace( /// public QuantumJobClient Client { get; } + /// + /// The options used to create the client to communicate with the service. + /// + public QuantumJobClientOptions ClientOptions + { + get => this.clientOptions; + set + { + // Set the ApplicationId that will be added as a UserAgent prefix + // in calls to the Azure Quantum API. + var applicationId = string.Join('-', + value?.Diagnostics?.ApplicationId?.Trim(), + Environment.GetEnvironmentVariable("AZURE_QUANTUM_NET_APPID")?.Trim() + )?.Trim('-', ' '); + if (applicationId?.Length > 24) + { + applicationId = applicationId?.Substring(0, 24); + } + + value ??= new QuantumJobClientOptions(); + value.Diagnostics.ApplicationId = applicationId; + + this.clientOptions = value; + } + } + + private QuantumJobClientOptions clientOptions; + /// /// Submits the job. /// diff --git a/src/Azure/Azure.Quantum.Client/Machine/QuantumMachineFactory.cs b/src/Azure/Azure.Quantum.Client/Machine/QuantumMachineFactory.cs index 3e4fac8dddb..be9c1b2b0e2 100644 --- a/src/Azure/Azure.Quantum.Client/Machine/QuantumMachineFactory.cs +++ b/src/Azure/Azure.Quantum.Client/Machine/QuantumMachineFactory.cs @@ -23,14 +23,17 @@ public static class QuantumMachineFactory public static IQuantumMachine? CreateMachine( IWorkspace workspace, string targetName, string? storageConnectionString = null) { + // We normalize the case of the provided target name to lower. + var targetNameNormalized = targetName?.ToLowerInvariant(); + var machineName = - targetName is null + targetNameNormalized is null ? null - : targetName.StartsWith("qci.") + : targetNameNormalized.StartsWith("qci.") ? "Microsoft.Quantum.Providers.QCI.Targets.QCIQuantumMachine, Microsoft.Quantum.Providers.QCI" - : targetName.StartsWith("ionq.") + : targetNameNormalized.StartsWith("ionq.") ? "Microsoft.Quantum.Providers.IonQ.Targets.IonQQuantumMachine, Microsoft.Quantum.Providers.IonQ" - : targetName.StartsWith("honeywell.") + : targetNameNormalized.StartsWith("honeywell.") ? "Microsoft.Quantum.Providers.Honeywell.Targets.HoneywellQuantumMachine, Microsoft.Quantum.Providers.Honeywell" : null; @@ -54,7 +57,7 @@ targetName is null ? null : (IQuantumMachine)Activator.CreateInstance( machineType, - targetName, + targetNameNormalized, workspace, storageConnectionString); } diff --git a/src/Azure/Azure.Quantum.Client/Microsoft.Azure.Quantum.Client.csproj b/src/Azure/Azure.Quantum.Client/Microsoft.Azure.Quantum.Client.csproj index 5585bc6f1b4..03d29f4fc36 100644 --- a/src/Azure/Azure.Quantum.Client/Microsoft.Azure.Quantum.Client.csproj +++ b/src/Azure/Azure.Quantum.Client/Microsoft.Azure.Quantum.Client.csproj @@ -20,10 +20,10 @@ - + - + all diff --git a/src/Azure/Azure.Quantum.Client/Storage/IJobStorageHelper.cs b/src/Azure/Azure.Quantum.Client/Storage/IJobStorageHelper.cs index 30e058779ed..015b7809076 100644 --- a/src/Azure/Azure.Quantum.Client/Storage/IJobStorageHelper.cs +++ b/src/Azure/Azure.Quantum.Client/Storage/IJobStorageHelper.cs @@ -29,6 +29,22 @@ public interface IJobStorageHelper Stream input, CancellationToken cancellationToken = default); + /// + /// Uploads the job input. + /// + /// The job id. + /// The input. + /// The MIME type indicating the content of the payload. + /// A flag to indicate if the payload should be uploaded compressed to storage. + /// The cancellation token. + /// Container uri + Input uri. + Task<(string containerUri, string inputUri)> UploadJobInputAsync( + string jobId, + Stream input, + string contentType, + bool compress, + CancellationToken cancellationToken = default); + /// /// Uploads the job program output mapping. /// diff --git a/src/Azure/Azure.Quantum.Client/Storage/IStorageHelper.cs b/src/Azure/Azure.Quantum.Client/Storage/IStorageHelper.cs index 54b7ae589fa..4bae7c272bd 100644 --- a/src/Azure/Azure.Quantum.Client/Storage/IStorageHelper.cs +++ b/src/Azure/Azure.Quantum.Client/Storage/IStorageHelper.cs @@ -1,6 +1,8 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +#nullable enable + namespace Microsoft.Azure.Quantum.Storage { using System; @@ -32,14 +34,32 @@ Task DownloadBlobAsync( /// Container client. /// Name of the BLOB. /// The input. + /// The MIME type indicating the content of the payload. + /// The blob encoding. /// The cancellation token. /// async task. Task UploadBlobAsync( BlobContainerClient containerClient, string blobName, Stream input, + string? contentType, + string? contentEncoding, CancellationToken cancellationToken = default); + /// + /// Uploads the BLOB. + /// + /// Container client. + /// Name of the BLOB. + /// The input. + /// The cancellation token. + /// async task. + Task UploadBlobAsync( + BlobContainerClient containerClient, + string blobName, + Stream input, + CancellationToken cancellationToken = default) => this.UploadBlobAsync(containerClient, blobName, input, null, null, cancellationToken); + /// /// Gets the BLOB sas URI. /// diff --git a/src/Azure/Azure.Quantum.Client/Storage/JobStorageHelper.cs b/src/Azure/Azure.Quantum.Client/Storage/JobStorageHelper.cs index 63234851d42..046cff470ca 100644 --- a/src/Azure/Azure.Quantum.Client/Storage/JobStorageHelper.cs +++ b/src/Azure/Azure.Quantum.Client/Storage/JobStorageHelper.cs @@ -37,28 +37,34 @@ public JobStorageHelper(string connectionString) } } - /// - /// Uploads the job input. - /// - /// The job id. - /// The input. - /// The cancellation token. - /// - /// Container uri + Input uri. - /// + /// public override async Task<(string containerUri, string inputUri)> UploadJobInputAsync( string jobId, Stream input, + string contentType, + bool compress, CancellationToken cancellationToken = default) { string containerName = GetContainerName(jobId); + string encoding = null; + Stream data = input; + + if (compress) + { + var compressedInput = new MemoryStream(); + await Compression.Compress(input, compressedInput); + data = compressedInput; + encoding = "gzip"; + } BlobContainerClient containerClient = await this.GetContainerClient(containerName); await this.StorageHelper.UploadBlobAsync( containerClient, Constants.Storage.InputBlobName, - input, + input: data, + contentType: contentType, + contentEncoding: encoding, cancellationToken); string containerUri = this.StorageHelper.GetBlobContainerSasUri( diff --git a/src/Azure/Azure.Quantum.Client/Storage/JobStorageHelperBase.cs b/src/Azure/Azure.Quantum.Client/Storage/JobStorageHelperBase.cs index 92ea7fdb47f..b0c0fcfd6e3 100644 --- a/src/Azure/Azure.Quantum.Client/Storage/JobStorageHelperBase.cs +++ b/src/Azure/Azure.Quantum.Client/Storage/JobStorageHelperBase.cs @@ -7,7 +7,9 @@ namespace Microsoft.Azure.Quantum.Storage using System.IO; using System.Threading; using System.Threading.Tasks; + using global::Azure.Storage.Blobs; + using Microsoft.Azure.Quantum.Utility; public abstract class JobStorageHelperBase : IJobStorageHelper @@ -54,17 +56,20 @@ await this.StorageHelper.DownloadBlobAsync( return; } - /// - /// Uploads the job input. - /// - /// The job id. - /// The input. - /// The cancellation token. - /// Container uri + Input uri. + /// public abstract Task<(string containerUri, string inputUri)> UploadJobInputAsync( - string jobId, - Stream input, - CancellationToken cancellationToken = default); + string jobId, + Stream input, + string contentType, + bool compress, + CancellationToken cancellationToken = default); + + /// + public Task<(string containerUri, string inputUri)> UploadJobInputAsync( + string jobId, + Stream input, + CancellationToken cancellationToken = default) => + this.UploadJobInputAsync(jobId, input, null, false, cancellationToken); /// /// Uploads the job program output mapping. diff --git a/src/Azure/Azure.Quantum.Client/Storage/LinkedStorageJobHelper.cs b/src/Azure/Azure.Quantum.Client/Storage/LinkedStorageJobHelper.cs index e3e59f5f0b1..b9b103a5ad8 100644 --- a/src/Azure/Azure.Quantum.Client/Storage/LinkedStorageJobHelper.cs +++ b/src/Azure/Azure.Quantum.Client/Storage/LinkedStorageJobHelper.cs @@ -23,28 +23,34 @@ public LinkedStorageJobHelper(IWorkspace workspace) this.workspace = workspace; } - /// - /// Uploads the job input. - /// - /// The job id. - /// The input. - /// The cancellation token. - /// - /// Container uri + Input uri without SAS. - /// + /// public override async Task<(string containerUri, string inputUri)> UploadJobInputAsync( string jobId, Stream input, + string contentType, + bool compress, CancellationToken cancellationToken = default) { string containerName = GetContainerName(jobId); + string encoding = null; + Stream data = input; BlobContainerClient containerClient = await this.GetContainerClient(containerName); + if (compress) + { + var compressedInput = new MemoryStream(); + await Compression.Compress(input, compressedInput); + data = compressedInput; + encoding = "gzip"; + } + await this.StorageHelper.UploadBlobAsync( - containerClient, - Constants.Storage.InputBlobName, - input, + containerClient: containerClient, + blobName: Constants.Storage.InputBlobName, + input: data, + contentType: contentType, + contentEncoding: encoding, cancellationToken); Uri inputUri = containerClient @@ -54,13 +60,7 @@ await this.StorageHelper.UploadBlobAsync( return (GetUriPath(containerClient.Uri), GetUriPath(inputUri)); } - /// - /// Uploads the job program output mapping. - /// - /// The job id. - /// The job program output mapping. - /// The cancellation token. - /// Container uri + Mapping uri without SAS. + /// public override async Task<(string containerUri, string mappingUri)> UploadJobMappingAsync( string jobId, Stream mapping, diff --git a/src/Azure/Azure.Quantum.Client/Storage/StorageHelper.cs b/src/Azure/Azure.Quantum.Client/Storage/StorageHelper.cs index b385af601e7..b896cddb582 100644 --- a/src/Azure/Azure.Quantum.Client/Storage/StorageHelper.cs +++ b/src/Azure/Azure.Quantum.Client/Storage/StorageHelper.cs @@ -5,6 +5,8 @@ namespace Microsoft.Azure.Quantum.Storage { using System; using System.IO; + using System.Net.Mime; + using System.Text; using System.Threading; using System.Threading.Tasks; using global::Azure.Storage.Blobs; @@ -42,18 +44,13 @@ public async Task DownloadBlobAsync( return; } - /// - /// Uploads the BLOB. - /// - /// Container client. - /// Name of the BLOB. - /// The input. - /// The cancellation token. - /// Async task. + /// public async Task UploadBlobAsync( BlobContainerClient containerClient, string blobName, Stream input, + string contentType, + string contentEncoding, CancellationToken cancellationToken = default) { try @@ -61,9 +58,20 @@ public async Task UploadBlobAsync( // Ensure container is created await containerClient.CreateIfNotExistsAsync(PublicAccessType.None, cancellationToken: cancellationToken); + var headers = new BlobHttpHeaders + { + ContentEncoding = contentEncoding, + ContentType = contentType, + }; + + var options = new BlobUploadOptions + { + HttpHeaders = headers, + }; + // Upload blob BlobClient blob = containerClient.GetBlobClient(blobName); - await blob.UploadAsync(input, overwrite: true, cancellationToken); + await blob.UploadAsync(input, options, cancellationToken); } catch (Exception ex) { diff --git a/src/Azure/Azure.Quantum.Client/Utility/Compression.cs b/src/Azure/Azure.Quantum.Client/Utility/Compression.cs new file mode 100644 index 00000000000..647b06d4bf3 --- /dev/null +++ b/src/Azure/Azure.Quantum.Client/Utility/Compression.cs @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Microsoft.Azure.Quantum.Utility +{ + using System.IO; + using System.IO.Compression; + using System.Threading.Tasks; + + internal class Compression + { + public static async Task Compress(Stream data, Stream compressedData) + { + using (var auxStream = new MemoryStream()) + using (var zipStream = new GZipStream(auxStream, CompressionMode.Compress)) + { + await data.CopyToAsync(zipStream); + await zipStream.FlushAsync(); + auxStream.Position = 0; + await auxStream.CopyToAsync(compressedData); + await compressedData.FlushAsync(); + } + + compressedData.Position = 0; + } + } +} diff --git a/src/Qir/Common/cmake/qir_cmake_include.cmake b/src/Qir/Common/cmake/qir_cmake_include.cmake index 25e66fbd104..9ad60d716ea 100644 --- a/src/Qir/Common/cmake/qir_cmake_include.cmake +++ b/src/Qir/Common/cmake/qir_cmake_include.cmake @@ -39,3 +39,172 @@ macro(target_source_from_qir target_name source_file) ${OBJFILE} ) endmacro() + + +#=============================================================================== +# Common flags + +# Always use available Spectre mitigations where available +if (NOT APPLE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mspeculative-load-hardening -mretpoline") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mspeculative-load-hardening -mretpoline") +endif() + +set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG") +set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DDEBUG") + +#=============================================================================== +# Warnings + +# Treat warnings as errors: +# https://clang.llvm.org/docs/UsersManual.html#options-to-control-error-and-warning-messages +set(WARNING_FLAGS "-Werror") + +# Enable all warnings: +# https://clang.llvm.org/docs/UsersManual.html#enabling-all-diagnostics +# https://clang.llvm.org/docs/DiagnosticsReference.html +set(WARNING_FLAGS "${WARNING_FLAGS} -Weverything") + +# Disable these warnings: + +# We don't care about keeping compatibility with C++98/03, C++11, C++14. Any new features unknown to our compiler version will be reported as errors. +# -Wc++98-compat-pedantic +# -Wc++98-compat, +# -Wc++98-compat-local-type-template-args, -Wc++98-compat-unnamed-type-template-args, -Wpre-c++14-compat, +# -Wpre-c++17-compat, -Wpre-c++20-compat, -Wpre-c++2b-compat. +# -Wc++98-compat-bind-to-temporary-copy, -Wc++98-compat-extra-semi, +# -Wpre-c++14-compat-pedantic, +# -Wc++98-c++11-compat-binary-literal, -Wpre-c++14-compat. +# -Wpre-c++17-compat-pedantic, +# -Wpre-c++17-compat. +# -Wpre-c++20-compat-pedantic, +# -Wpre-c++20-compat. +# -Wpre-c++2b-compat-pedantic (= -Wpre-c++2b-compat). + +# https://clang.llvm.org/docs/DiagnosticsReference.html#wc-98-compat-pedantic +set(WARNING_FLAGS "${WARNING_FLAGS} -Wno-c++98-compat-pedantic") + +# Old-style casts increase readability as opposed to `reinterpret_cast<..>()`. We want to be able to use the old-style casts. +set(WARNING_FLAGS "${WARNING_FLAGS} -Wno-old-style-cast") + +# Even if the `switch` covers all the enumerators, it is still good to have `default` label to cover the potential newly added (but not handled) enumerators. +set(WARNING_FLAGS "${WARNING_FLAGS} -Wno-covered-switch-default") + +# We are OK using C99 features. +# -Wc99-extension +# -Wc99-designator +# -Wc++20-designator +set(WARNING_FLAGS "${WARNING_FLAGS} -Wno-c99-extensions") + +# We are OK that the structs are padded to align the fields. +# https://clang.llvm.org/docs/DiagnosticsReference.html#wpadded +set(WARNING_FLAGS "${WARNING_FLAGS} -Wno-padded") + +# We are OK with abstract classes. +set(WARNING_FLAGS "${WARNING_FLAGS} -Wno-weak-vtables") + +# Temporarily disable the following warnings (until QIR RT is refactored to expose C interface). + +# Looks like the `-Wglobal-constructors` warns that the instance of the `__dllexport` class/struct (or a static member var of such class/struct) +# needs to be constructible by calling a global `__dllexport` function (to guarantee that a single instance is created and the same instance is used +# both inside and outside of the binary (dynamic library or executable)). +# Or it warns about the constructor that is invoked for a global (or static member) variable _before_ the `main()` is invoked, thus slowing down the start, +# see https://stackoverflow.com/a/15708829/6362941 + +# https://clang.llvm.org/docs/DiagnosticsReference.html#wglobal-constructors +set(WARNING_FLAGS "${WARNING_FLAGS} -Wno-global-constructors") + +# Looks like the `-Wexit-time-destructors` warns that the destructor of a global or static member variable will be invoked +# _after_ the `main()` returns (thus slowing down the termination/restart). +set(WARNING_FLAGS "${WARNING_FLAGS} -Wno-exit-time-destructors") + +# Temporarily disable "-Wextra-semi-stmt" that warns about redundant `;` in the end of `INFO(id);` of Catch tests framework (which looks fixed in the latest Catch version). +# Disable until the Catch header "src\Qir\Common\Externals\catch2\catch.hpp" is updated to a version newer than v2.12.1 (from https://github.com/catchorg/Catch2). + +# https://clang.llvm.org/docs/DiagnosticsReference.html#wextra-semi-stmt +set(WARNING_FLAGS "${WARNING_FLAGS} -Wno-extra-semi-stmt") + +# Save the assembled warnings +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNING_FLAGS}") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARNING_FLAGS}") + + +#=============================================================================== +# Sanitizers (https://clang.llvm.org/docs/UsersManual.html#controlling-code-generation): + +if (NOT WIN32) + set(SANITIZE_FLAGS "") + + # Undefined Behavior Sanitizer (https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html) + # Win: + # FAILED: lib/QIR/Microsoft.Quantum.Qir.Runtime.dll lib/QIR/Microsoft.Quantum.Qir.Runtime.lib + # lld-link: error: /failifmismatch: mismatch detected for 'RuntimeLibrary': + # >>> lib/QIR/CMakeFiles/qir-rt-support-obj.dir/QubitManager.cpp.obj has value MD_DynamicRelease + # >>> clang_rt.ubsan_standalone_cxx-x86_64.lib(ubsan_type_hash_win.cc.obj) has value MT_StaticRelease + # clang++: error: linker command failed with exit code 1 (use -v to see invocation) + set(SANITIZE_FLAGS "${SANITIZE_FLAGS} -fsanitize=undefined -fsanitize=float-divide-by-zero -fsanitize=unsigned-integer-overflow -fsanitize=implicit-conversion -fsanitize=local-bounds -fsanitize=nullability") + + # TODO: + # For Win consider extra build configuration linking all libs statically, enable `-fsanitize=undefined`, run the statically linked tests. + + #if (-not ($IsMacOS)) # Cannot be combined with `-fsanitize=address`. + #{ + # # Safe Stack instrumentation (https://clang.llvm.org/docs/SafeStack.html): + # # No support for Win, Mac. + # # clang: error: unsupported option '-fsanitize=safe-stack' for target 'x86_64-apple-darwin19.6.0' + # # Linking a DSO with SafeStack is not currently supported. But compilation, linking, and test runs all succeed. + # $sanitizeFlags += " -fsanitize=safe-stack" + #} + + ## Memory Sanitizer (https://clang.llvm.org/docs/MemorySanitizer.html) + ## Win: Not supported. + ## clang: error: unsupported option '-fsanitize=memory' for target 'x86_64-pc-windows-msvc' + ## WSL: Complains for use-of-uninitialized-value in `catch2/catch.hpp` during initialization of global vars + ## (if run both as `pwsh Runtime/test-qir-runtime.ps1` (or Tests/test-qir-tests.ps1) and as standalone). + ## An update of `catch2/catch.hpp` to 2.13.6 (search for "go to the v2.x branch" at https://github.com/catchorg/Catch2) didn't help. + ## Suppressing of the errors in the updated `catch2/catch.hpp` and standard library headers eventually bumps into errors reported in `memcmp`, + ## suppressing of which does not work (https://github.com/google/sanitizers/issues/1429#issuecomment-876799463). + ## Looks like MSan will not work until the libstdc++ is recompiled to be instrumented (https://clang.llvm.org/docs/MemorySanitizer.html#handling-external-code). + ## Instrumenting libstdc++ during CI builds seems impractical (https://stackoverflow.com/a/22301584/6362941). + #$sanitizeFlags += " -fsanitize=memory -fsanitize-memory-track-origins=2" + + # Address Sanitizer (https://clang.llvm.org/docs/AddressSanitizer.html) + # Win: (Conflict between the ASan library and MSVC library) + # [19/35] Linking CXX shared library lib\QIR\Microsoft.Quantum.Qir.Runtime.dll + # FAILED: lib/QIR/Microsoft.Quantum.Qir.Runtime.dll lib/QIR/Microsoft.Quantum.Qir.Runtime.lib + # cmd.exe /C "cd . && C:\PROGRA~1\LLVM12\bin\CLANG_~1.EXE -fuse-ld=lld-link -nostartfiles -nostdlib -Werror -Weverything .... \ + # -fsanitize=address -g -Xclang -gcodeview -O0 -DDEBUG -D_DEBUG -D_DLL -D_MT -Xclang --dependent-lib=msvcrtd \ + # -Xlinker /guard:cf -shared -o lib\QIR\Microsoft.Quantum.Qir.Runtime.dll -Xlinker /implib:lib\QIR\Microsoft.Quantum.Qir.Runtime.lib \ + # -Xlinker /pdb:lib\QIR\Microsoft.Quantum.Qir.Runtime.pdb -Xlinker /version:0.0 lib/QIR/bridge-rt.obj \ + # lib/QIR/CMakeFiles/qir-rt-support-obj.dir/QirRange.cpp.obj lib/QIR/CMakeFiles/qir-rt-support-obj.dir/OutputStream.cpp.obj ....\ + # -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 -loldnames && cd ." + # lld-link: error: duplicate symbol: malloc + # >>> defined at C:\src\llvm_package_6923b0a7\llvm-project\compiler-rt\lib\asan\asan_win_dll_thunk.cpp:34 + # >>> clang_rt.asan_dll_thunk-x86_64.lib(asan_win_dll_thunk.cpp.obj) + # >>> defined at ucrtbased.dll + # clang++: error: linker command failed with exit code 1 (use -v to see invocation) + + # https://clang.llvm.org/docs/AddressSanitizer.html + set(SANITIZE_FLAGS "${SANITIZE_FLAGS} -fsanitize=address") + + # TODO: + # * Some tests verify the failure behavior, i.e. they cause `Fail()` to be called and return to the caller with the exception. + # Any allocations made between the call and the exception throw (caught by `REQUIRE_THROWS()`) are leaking. + # Extract such tests to a separate .cpp file or executable and compile with leak check off (or suppress leaks in that .cpp or executable only). + + # Common for all sanitizers: + # https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html#suppressing-errors-in-recompiled-code-ignorelist + # https://releases.llvm.org/11.0.1/tools/clang/docs/SanitizerSpecialCaseList.html + set(SANITIZE_FLAGS "${SANITIZE_FLAGS} -fsanitize-blacklist=${CMAKE_CURRENT_LIST_DIR}/../../UBSan.ignore") + + # https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html + set(SANITIZE_FLAGS "${SANITIZE_FLAGS} -fno-omit-frame-pointer") + + # https://clang.llvm.org/docs/AddressSanitizer.html + set(SANITIZE_FLAGS "${SANITIZE_FLAGS} -fno-optimize-sibling-calls") + + # Save the flags + set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${SANITIZE_FLAGS}") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${SANITIZE_FLAGS}") +endif() + diff --git a/src/Qir/Common/cmake/unit_test_include.cmake b/src/Qir/Common/cmake/unit_test_include.cmake index 5c29fc114c7..93701f563b0 100644 --- a/src/Qir/Common/cmake/unit_test_include.cmake +++ b/src/Qir/Common/cmake/unit_test_include.cmake @@ -9,7 +9,7 @@ macro(add_unit_test target) if(DEFINED ENV{NATIVE_SIMULATOR}) set(TEST_DEPS1 $ENV{NATIVE_SIMULATOR}) else() - set(TEST_DEPS1 "${PROJECT_SOURCE_DIR}/../../Simulation/native/build/$ENV{BUILD_CONFIGURATION}") + set(TEST_DEPS1 "${PROJECT_SOURCE_DIR}/../../Simulation/native/build/drop") endif() set(TEST_DEPS2 "${CMAKE_BINARY_DIR}/bin") diff --git a/src/Qir/Runtime/CMakeLists.txt b/src/Qir/Runtime/CMakeLists.txt index 3c3c109b019..0f4bdf52d55 100644 --- a/src/Qir/Runtime/CMakeLists.txt +++ b/src/Qir/Runtime/CMakeLists.txt @@ -9,14 +9,48 @@ project(qirruntime) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED True) -set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG") +if (WIN32) + # Enforce use of static runtime (avoids target machine needing msvcrt installed). + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") -# Always use available Spectre mitigations where available -if (NOT APPLE) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mspeculative-load-hardening -mretpoline") -endif() + # Locate the vswhere application, which will provide paths to any installed Visual Studio instances. + # By invoking it with "-find **/lib/spectre/x64" we will find any Spectre mitigated libaries that + # have been installed. + find_program(_vswhere_tool + NAMES vswhere + PATHS "$ENV{ProgramFiles\(x86\)}/Microsoft Visual Studio/Installer") + if (NOT ${vswhere}) + message(FATAL_ERROR "Could not locate vswhere.exe - unable to source vc redistributable") + endif() + execute_process( + COMMAND "${_vswhere_tool}" -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -find **/14.29.*/**/lib/spectre/x64 -sort + OUTPUT_VARIABLE _vs_install_loc_out + RESULT_VARIABLE _vs_where_exitcode + OUTPUT_STRIP_TRAILING_WHITESPACE) + file(TO_CMAKE_PATH "${_vs_install_loc_out}" SPECTRE_LIB_PATH_OUT) + string(REGEX REPLACE "[\r\n]+" ";" SPECTRE_LIB_PATH ${SPECTRE_LIB_PATH_OUT}) + message(INFO "*** install loc: ${SPECTRE_LIB_PATH}") + + # Locate the spectre mitigated runtime libraries and fail if they can't be found. Targets in this + # cmake project can use the variables to explicitly link these libraries rather than using the + # non-mitigated libraries that are found by default. + find_library(LIBCMT_SPECTRE_REL libcmt PATHS ${SPECTRE_LIB_PATH} REQUIRED) + find_library(LIBCMT_SPECTRE_DEB libcmtd PATHS ${SPECTRE_LIB_PATH} REQUIRED) + set(LIBCMT_SPECTRE debug ${LIBCMT_SPECTRE_DEB} optimized ${LIBCMT_SPECTRE_REL}) + message(INFO "*** using spectre lib: ${LIBCMT_SPECTRE}") + find_library(LIBCPMT_SPECTRE_REL libcpmt PATHS ${SPECTRE_LIB_PATH} REQUIRED) + find_library(LIBCPMT_SPECTRE_DEB libcpmtd PATHS ${SPECTRE_LIB_PATH} REQUIRED) + set(LIBCPMT_SPECTRE debug ${LIBCPMT_SPECTRE_DEB} optimized ${LIBCPMT_SPECTRE_REL}) + message(INFO "*** using spectre lib: ${LIBCPMT_SPECTRE}") + find_library(LIBVCRUNTIME_SPECTRE_REL libvcruntime PATHS ${SPECTRE_LIB_PATH} REQUIRED) + find_library(LIBVCRUNTIME_SPECTRE_DEB libvcruntimed PATHS ${SPECTRE_LIB_PATH} REQUIRED) + set(LIBVCRUNTIME_SPECTRE debug ${LIBVCRUNTIME_SPECTRE_DEB} optimized ${LIBVCRUNTIME_SPECTRE_REL}) + message(INFO "*** using spectre lib: ${LIBVCRUNTIME_SPECTRE}") + set(SPECTRE_LIBS + ${LIBCMT_SPECTRE} + ${LIBCPMT_SPECTRE} + ${LIBVCRUNTIME_SPECTRE}) -if (WIN32) add_link_options("LINKER:/guard:cf") endif() diff --git a/src/Qir/Runtime/README.md b/src/Qir/Runtime/README.md index c12eacdd5eb..ca78e33afa0 100644 --- a/src/Qir/Runtime/README.md +++ b/src/Qir/Runtime/README.md @@ -2,7 +2,7 @@ This folder contains the Quantum Intermediate Representation (QIR) Runtime project. The QIR is a subset of the [LLVM](https://llvm.org/) Intermediate Representation. The QIR runtime includes an implementation of the - [QIR specification](https://github.com/microsoft/qsharp-language/tree/main/Specifications/QIR) and the bridge to + [QIR specification](https://github.com/qir-alliance/qir-spec) and the bridge to run QIR against the native full state simulator. - `public` folder contains the public headers @@ -98,7 +98,7 @@ For tests that depend on the native simulator and qdk shared libraries, you migh ## QIR Bridge and Runtime This project contains an implementation of the QIR runtime per the - [QIR specifications](https://github.com/microsoft/qsharp-language/tree/main/Specifications/QIR) and the translation + [QIR specifications](https://github.com/qir-alliance/qir-spec) and the translation layer between the QIR and the IR, generated by Clang from the native code. Translation layer is called the "QIR Bridge". ![QIR Bridge architecture diagram](qir.png?raw=true "QIR Bridge architecture diagram") diff --git a/src/Qir/Runtime/lib/QIR/BasicRuntimeDriver.cpp b/src/Qir/Runtime/lib/QIR/BasicRuntimeDriver.cpp new file mode 100644 index 00000000000..f84399ae30c --- /dev/null +++ b/src/Qir/Runtime/lib/QIR/BasicRuntimeDriver.cpp @@ -0,0 +1,75 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#include +#include + +#include "QirRuntimeApi_I.hpp" +#include "QubitManager.hpp" +#include "BasicRuntimeDriverFactory.h" + +namespace Microsoft +{ +namespace Quantum +{ + class CBasicRuntimeDriver : public IRuntimeDriver + { + std::unique_ptr qubitManager; + + public: + CBasicRuntimeDriver() + { + qubitManager = std::make_unique(); + } + + ~CBasicRuntimeDriver() override + { + } + + std::string QubitToString(QubitIdType q) override + { + return std::to_string(q); + } + + QubitIdType AllocateQubit() override + { + return qubitManager->Allocate(); + } + + void ReleaseQubit(QubitIdType q) override + { + qubitManager->Release(q); + } + + void ReleaseResult(Result /* result */) override + { + } + + bool AreEqualResults(Result r1, Result r2) override + { + return r1 == r2; + } + + ResultValue GetResultValue(Result r) override + { + return (r == UseZero()) ? Result_Zero : Result_One; + } + + Result UseZero() override + { + return reinterpret_cast(0); + } + + Result UseOne() override + { + return reinterpret_cast(1); + } + }; + + extern "C" void* CreateBasicRuntimeDriver() + { + return (IRuntimeDriver*)new CBasicRuntimeDriver(); + } + +} // namespace Quantum +} // namespace Microsoft diff --git a/src/Qir/Runtime/lib/QIR/CMakeLists.txt b/src/Qir/Runtime/lib/QIR/CMakeLists.txt index f7ef19d24ed..f100670f063 100644 --- a/src/Qir/Runtime/lib/QIR/CMakeLists.txt +++ b/src/Qir/Runtime/lib/QIR/CMakeLists.txt @@ -19,6 +19,7 @@ set(rt_sup_source_files strings.cpp utils.cpp QubitManager.cpp + BasicRuntimeDriver.cpp ) # Produce object lib we'll use to create a shared lib (so/dll) later on @@ -43,6 +44,7 @@ add_library(Microsoft.Quantum.Qir.Runtime SHARED) target_link_libraries(Microsoft.Quantum.Qir.Runtime ${CMAKE_DL_LIBS} qir-rt-support-obj + ${SPECTRE_LIBS} ) target_include_directories(Microsoft.Quantum.Qir.Runtime PUBLIC ${public_includes}) diff --git a/src/Qir/Runtime/lib/QSharpCore/CMakeLists.txt b/src/Qir/Runtime/lib/QSharpCore/CMakeLists.txt index d3fe9170f9f..7bd86a74662 100644 --- a/src/Qir/Runtime/lib/QSharpCore/CMakeLists.txt +++ b/src/Qir/Runtime/lib/QSharpCore/CMakeLists.txt @@ -27,6 +27,7 @@ target_link_libraries(Microsoft.Quantum.Qir.QSharp.Core simulators-obj "-L${CMAKE_BINARY_DIR}/lib/QIR" -lMicrosoft.Quantum.Qir.Runtime + ${SPECTRE_LIBS} ) add_dependencies(Microsoft.Quantum.Qir.QSharp.Core Microsoft.Quantum.Qir.Runtime) diff --git a/src/Qir/Runtime/lib/QSharpFoundation/CMakeLists.txt b/src/Qir/Runtime/lib/QSharpFoundation/CMakeLists.txt index 744d94c86a1..f8ca4ebe1c0 100644 --- a/src/Qir/Runtime/lib/QSharpFoundation/CMakeLists.txt +++ b/src/Qir/Runtime/lib/QSharpFoundation/CMakeLists.txt @@ -30,6 +30,7 @@ target_link_libraries(Microsoft.Quantum.Qir.QSharp.Foundation qsharp-foundation-qis-support-obj "-L${CMAKE_BINARY_DIR}/lib/QIR" -lMicrosoft.Quantum.Qir.Runtime + ${SPECTRE_LIBS} ) add_dependencies(Microsoft.Quantum.Qir.QSharp.Foundation Microsoft.Quantum.Qir.Runtime) @@ -46,4 +47,3 @@ install(TARGETS Microsoft.Quantum.Qir.QSharp.Foundation LIBRARY DESTINATION "${CMAKE_BINARY_DIR}/bin" ARCHIVE DESTINATION "${CMAKE_BINARY_DIR}/bin" ) - diff --git a/src/Qir/Runtime/lib/README.md b/src/Qir/Runtime/lib/README.md index dc13b07d59f..c29f64860de 100644 --- a/src/Qir/Runtime/lib/README.md +++ b/src/Qir/Runtime/lib/README.md @@ -16,7 +16,7 @@ Is a project defined [here](../../../Simulation/QSharpFoundation). Is a project defined [here](../../../Simulation/QSharpCore). ## QIR -Anything that is required by the [QIR specs](https://github.com/microsoft/qsharp-language/tree/main/Specifications/QIR), +Anything that is required by the [QIR specs](https://github.com/qir-alliance/qir-spec), which in particular includes the ["methods that delegate to the simulators"](QIR/bridge-rt.ll#46), should live in the QIR folder. They require support from the backend, but are not language-specific. Both the Q# Core and the Q# Foundation are Q#-specific in that these are the target instructions that the Q# libraries are built on. diff --git a/src/Qir/Runtime/lib/Simulators/FullstateSimulator.cpp b/src/Qir/Runtime/lib/Simulators/FullstateSimulator.cpp index c077f826643..93836936317 100644 --- a/src/Qir/Runtime/lib/Simulators/FullstateSimulator.cpp +++ b/src/Qir/Runtime/lib/Simulators/FullstateSimulator.cpp @@ -211,7 +211,7 @@ namespace Quantum { if (this->simulatorId != NULL_SIMULATORID) { - typedef unsigned (*TDestroy)(unsigned); + typedef void (*TDestroy)(unsigned); static TDestroy destroySimulatorInstance = reinterpret_cast(LoadProc(this->handle, "destroy")); assert(destroySimulatorInstance); @@ -226,7 +226,7 @@ namespace Quantum // Deprecated, use `DumpMachine()` and `DumpRegister()` instead. void GetState(TGetStateCallback callback) override { - typedef bool (*TDump)(unsigned, TGetStateCallback); + typedef void (*TDump)(unsigned, TGetStateCallback); static TDump dump = reinterpret_cast(this->GetProc("Dump")); dump(this->simulatorId, callback); } @@ -462,7 +462,7 @@ namespace Quantum void R(PauliId axis, QubitIdType target, double theta) override { - typedef unsigned (*TR)(unsigned, unsigned, double, unsigned); + typedef void (*TR)(unsigned, unsigned, double, unsigned); static TR r = reinterpret_cast(this->GetProc("R")); r(this->simulatorId, GetBasis(axis), theta, GetQubitId(target)); @@ -472,7 +472,7 @@ namespace Quantum void ControlledR(long numControls, QubitIdType controls[], PauliId axis, QubitIdType target, double theta) override { - typedef unsigned (*TMCR)(unsigned, unsigned, double, unsigned, unsigned*, unsigned); + typedef void (*TMCR)(unsigned, unsigned, double, unsigned, unsigned*, unsigned); static TMCR cr = reinterpret_cast(this->GetProc("MCR")); std::vector ids = GetQubitIds(numControls, controls); @@ -483,7 +483,7 @@ namespace Quantum void Exp(long numTargets, PauliId paulis[], QubitIdType targets[], double theta) override { - typedef unsigned (*TExp)(unsigned, unsigned, unsigned*, double, unsigned*); + typedef void (*TExp)(unsigned, unsigned, unsigned*, double, unsigned*); static TExp exp = reinterpret_cast(this->GetProc("Exp")); std::vector ids = GetQubitIds(numTargets, targets); std::vector convertedBases = GetBases(numTargets, paulis); @@ -494,7 +494,7 @@ namespace Quantum void ControlledExp(long numControls, QubitIdType controls[], long numTargets, PauliId paulis[], QubitIdType targets[], double theta) override { - typedef unsigned (*TMCExp)(unsigned, unsigned, unsigned*, double, unsigned, unsigned*, unsigned*); + typedef void (*TMCExp)(unsigned, unsigned, unsigned*, double, unsigned, unsigned*, unsigned*); static TMCExp cexp = reinterpret_cast(this->GetProc("MCExp")); std::vector idsTargets = GetQubitIds(numTargets, targets); std::vector idsControls = GetQubitIds(numControls, controls); diff --git a/src/Qir/Runtime/lib/Tracer/CMakeLists.txt b/src/Qir/Runtime/lib/Tracer/CMakeLists.txt index 8ef274e87ef..a28bd52a0d3 100644 --- a/src/Qir/Runtime/lib/Tracer/CMakeLists.txt +++ b/src/Qir/Runtime/lib/Tracer/CMakeLists.txt @@ -25,6 +25,7 @@ target_link_libraries(Microsoft.Quantum.Qir.Tracer tracer-obj "-L${CMAKE_BINARY_DIR}/lib/QIR" -lMicrosoft.Quantum.Qir.Runtime + ${SPECTRE_LIBS} ) add_dependencies(Microsoft.Quantum.Qir.QSharp.Foundation Microsoft.Quantum.Qir.Runtime) diff --git a/src/Qir/Runtime/lib/Tracer/README.md b/src/Qir/Runtime/lib/Tracer/README.md index 43993131345..ed0ec4e74dd 100644 --- a/src/Qir/Runtime/lib/Tracer/README.md +++ b/src/Qir/Runtime/lib/Tracer/README.md @@ -6,7 +6,7 @@ The purpose of the Resource Tracer is to provide efficient and flexible way to e for more background on resource estimation for quantum programs. To run against the tracer, the quantum program should comply with the - [QIR specifications](https://github.com/microsoft/qsharp-language/tree/main/Specifications/QIR) as well as: + [QIR specifications](https://github.com/qir-alliance/qir-spec) as well as: 1. convert _each_ used intrinsic operation into one of the Quantum Instruction Set (_qis_) operations supported by the tracer (see the last section of this readme); diff --git a/src/Qir/Runtime/public/BasicRuntimeDriverFactory.h b/src/Qir/Runtime/public/BasicRuntimeDriverFactory.h new file mode 100644 index 00000000000..ca33e2b609b --- /dev/null +++ b/src/Qir/Runtime/public/BasicRuntimeDriverFactory.h @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#ifndef BASICRUNTIMEDRIVERFACTORY_H +#define BASICRUNTIMEDRIVERFACTORY_H + +#include +#include "CoreDefines.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + QIR_SHARED_API void* CreateBasicRuntimeDriver(); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // #ifndef BASICRUNTIMEDRIVERFACTORY_H diff --git a/src/Qir/Runtime/public/QubitManager.hpp b/src/Qir/Runtime/public/QubitManager.hpp index 1d1bda589db..5f81de5a7bb 100644 --- a/src/Qir/Runtime/public/QubitManager.hpp +++ b/src/Qir/Runtime/public/QubitManager.hpp @@ -40,7 +40,9 @@ namespace Quantum // No complex scenarios for now. Don't need to support copying/moving. CQubitManager(const CQubitManager&) = delete; CQubitManager& operator=(const CQubitManager&) = delete; - virtual ~CQubitManager(); + ~CQubitManager(); // If this dtor is made _virtual_ then the QIR RT tests crash (at least in Debug config) + // if the native simulator is compiled with Clang (as opposed to GCC). Nothing wrong found in + // the code, probably is the compiler bug. // Restricted reuse area control void StartRestrictedReuseArea(); diff --git a/src/Qir/Runtime/test-qir-runtime.ps1 b/src/Qir/Runtime/test-qir-runtime.ps1 index 68a09d7b990..377ee141411 100644 --- a/src/Qir/Runtime/test-qir-runtime.ps1 +++ b/src/Qir/Runtime/test-qir-runtime.ps1 @@ -3,8 +3,10 @@ . (Join-Path $PSScriptRoot .. qir-utils.ps1) -# TODO: `ASAN_OPTIONS=check_initialization_order=1` (https://clang.llvm.org/docs/AddressSanitizer.html#initialization-order-checking). # TODO: macOS: `ASAN_OPTIONS=detect_leaks=1` (https://clang.llvm.org/docs/AddressSanitizer.html#memory-leak-detection). +$env:ASAN_OPTIONS = "check_initialization_order=true:detect_stack_use_after_return=true:" ` + + "alloc_dealloc_mismatch=true:new_delete_type_mismatch=true:strict_init_order=true:strict_string_checks=true:" ` + + "detect_invalid_pointer_pairs=2" if (-not (Test-CTest (Join-Path $PSScriptRoot bin $Env:BUILD_CONFIGURATION unittests) "QIR Runtime")) { throw "At least one project failed testing. Check the logs." diff --git a/src/Qir/Samples/StandaloneInputReference/CMakeLists.txt b/src/Qir/Samples/StandaloneInputReference/CMakeLists.txt index 5f994b1dc24..8006d3a5694 100644 --- a/src/Qir/Samples/StandaloneInputReference/CMakeLists.txt +++ b/src/Qir/Samples/StandaloneInputReference/CMakeLists.txt @@ -34,7 +34,7 @@ add_test( if(DEFINED ENV{NATIVE_SIMULATOR}) set(TEST_DEPS1 $ENV{NATIVE_SIMULATOR}) else() - set(TEST_DEPS1 "${PROJECT_SOURCE_DIR}/../../Simulation/native/build/$ENV{BUILD_CONFIGURATION}") + set(TEST_DEPS1 "${PROJECT_SOURCE_DIR}/../../Simulation/native/build/drop") endif() set(TEST_DEPS2 "${PROJECT_SOURCE_DIR}/../Runtime/bin/$ENV{BUILD_CONFIGURATION}/bin") diff --git a/src/Qir/Samples/test-qir-samples.ps1 b/src/Qir/Samples/test-qir-samples.ps1 index 1a1246cb732..a5bbef65a84 100644 --- a/src/Qir/Samples/test-qir-samples.ps1 +++ b/src/Qir/Samples/test-qir-samples.ps1 @@ -3,8 +3,10 @@ . (Join-Path $PSScriptRoot .. qir-utils.ps1) -# TODO: `ASAN_OPTIONS=check_initialization_order=1` (https://clang.llvm.org/docs/AddressSanitizer.html#initialization-order-checking). # TODO: macOS: `ASAN_OPTIONS=detect_leaks=1` (https://clang.llvm.org/docs/AddressSanitizer.html#memory-leak-detection). +$env:ASAN_OPTIONS = "check_initialization_order=true:detect_stack_use_after_return=true:" ` + + "alloc_dealloc_mismatch=true:new_delete_type_mismatch=true:strict_init_order=true:strict_string_checks=true:" ` + + "detect_invalid_pointer_pairs=2" if (-not (Test-CTest (Join-Path $PSScriptRoot bin $Env:BUILD_CONFIGURATION StandaloneInputReference) "QIR Samples (StandaloneInputReference)")) { throw "At least one project failed testing. Check the logs." diff --git a/src/Qir/Tests/QIR-static/qir-test-math.cpp b/src/Qir/Tests/QIR-static/qir-test-math.cpp index 91e0e09857c..87765cb22e4 100644 --- a/src/Qir/Tests/QIR-static/qir-test-math.cpp +++ b/src/Qir/Tests/QIR-static/qir-test-math.cpp @@ -23,6 +23,7 @@ extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Math__SinhTest__Interop(); extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Math__CoshTest__Interop(); // NOLINT extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Math__TanhTest__Interop(); // NOLINT extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Math__IeeeRemainderTest__Interop(); // NOLINT +extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Math__ExponentTest__Interop(); // NOLINT extern "C" int64_t Microsoft__Quantum__Testing__QIR__Math__TestDrawRandomInt__Interop( // NOLINT int64_t min, int64_t max); extern "C" double Microsoft__Quantum__Testing__QIR__Math__TestDrawRandomDouble__Interop( // NOLINT @@ -98,6 +99,11 @@ TEST_CASE("QIR: Math.IeeeRemainder", "[qir.math][qir.Math.IeeeRemainder]") REQUIRE(0 == Microsoft__Quantum__Testing__QIR__Math__IeeeRemainderTest__Interop()); } +TEST_CASE("QIR: Math.Exponent.builtin", "[qir.math][qir.Math.Exponent.builtin]") +{ + REQUIRE(0 == Microsoft__Quantum__Testing__QIR__Math__ExponentTest__Interop()); +} + TEST_CASE("QIR: Math.DrawRandomInt", "[qir.math][qir.Math.DrawRandomInt]") { // Test that the Q# random number generator is a wrapper around the C++ generator: diff --git a/src/Qir/Tests/QIR-static/qsharp/qir-test-math.qs b/src/Qir/Tests/QIR-static/qsharp/qir-test-math.qs index 000260ef140..052d0168a2b 100644 --- a/src/Qir/Tests/QIR-static/qsharp/qir-test-math.qs +++ b/src/Qir/Tests/QIR-static/qsharp/qir-test-math.qs @@ -346,4 +346,9 @@ namespace Microsoft.Quantum.Testing.QIR.Math { return 0; } + @EntryPoint() + function ExponentTest() : Int { + return (2 ^ 2) - 4; + } + } diff --git a/src/Qir/Tests/test-qir-tests.ps1 b/src/Qir/Tests/test-qir-tests.ps1 index f6ad54463b5..fef566d1b62 100644 --- a/src/Qir/Tests/test-qir-tests.ps1 +++ b/src/Qir/Tests/test-qir-tests.ps1 @@ -16,14 +16,10 @@ if ($Env:BUILD_CONFIGURATION -eq "Debug") if (-not ($IsWindows)) { $env:LSAN_OPTIONS += "suppressions=../../../../LSan.ignore" # https://clang.llvm.org/docs/AddressSanitizer.html#suppressing-memory-leaks - if (-not ($IsMacOS)) - { - $env:ASAN_OPTIONS += "check_initialization_order=1" # https://clang.llvm.org/docs/AddressSanitizer.html#initialization-order-checking - } - #else # AddressSanitizer: detect_leaks is not supported on this platform. Re-enable this once supported. - #{ - # $env:ASAN_OPTIONS += "detect_leaks=1" # https://clang.llvm.org/docs/AddressSanitizer.html#memory-leak-detection - #} + # TODO: macOS: `ASAN_OPTIONS=detect_leaks=1` (https://clang.llvm.org/docs/AddressSanitizer.html#memory-leak-detection). + $env:ASAN_OPTIONS = "check_initialization_order=true:detect_stack_use_after_return=true:" ` + + "alloc_dealloc_mismatch=true:new_delete_type_mismatch=true:strict_init_order=true:strict_string_checks=true" + # + ":detect_invalid_pointer_pairs=2" TODO(rokuzmin, #883): ==8218==ERROR: AddressSanitizer: invalid-pointer-pair: 0x602000000af4 0x602000000af0 } } diff --git a/src/Qir/microsoft-quantum-qir-runtime-sys/Cargo.toml b/src/Qir/microsoft-quantum-qir-runtime-sys/Cargo.toml new file mode 100644 index 00000000000..237bdcaa69a --- /dev/null +++ b/src/Qir/microsoft-quantum-qir-runtime-sys/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "microsoft-quantum-qir-runtime-sys" +version = "0.1.0" +edition = "2018" +build = "build.rs" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +cty = "0.2.1" +libloading = "0.7.0" +log = "0.4.14" +tempfile = "3.2.0" +llvm-sys = { version = "110", optional = true } +inkwell = { git = "https://github.com/TheDan64/inkwell", branch = "master", default-features = false, features = ["llvm11-0", "target-x86"], optional = true } +lazy_static = "1.4.0" + +[build-dependencies] +cmake = "0.1.46" +bindgen = "0.59.1" +cc = "1.0.71" +which = "4.2.2" + +[lib] + + +[features] +runtime = [] +foundation = [] +llvm-libloading = ["llvm-sys", "inkwell"] +default = ["runtime", "foundation"] diff --git a/src/Qir/microsoft-quantum-qir-runtime-sys/build.rs b/src/Qir/microsoft-quantum-qir-runtime-sys/build.rs new file mode 100644 index 00000000000..287da25af7c --- /dev/null +++ b/src/Qir/microsoft-quantum-qir-runtime-sys/build.rs @@ -0,0 +1,79 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +use cmake::Config; +use std::boxed::Box; +use std::env; +use std::error::Error; + +fn main() -> Result<(), Box> { + println!("cargo:rerun-if-env-changed=TARGET"); + println!("cargo:rerun-if-changed=build.rs"); + + for (key, value) in env::vars() { + println!("{}: {}", key, value); + } + if cfg!(target_os = "windows") { + let path_to_runtime_src = "..\\Runtime"; + compile_runtime_libraries(path_to_runtime_src)?; + } else { + let path_to_runtime_src = "../Runtime"; + compile_runtime_libraries(path_to_runtime_src)?; + } + + Ok(()) +} + +fn compile_runtime_libraries(path_to_runtime_src: &str) -> Result<(), Box> { + let mut config = Config::new(path_to_runtime_src); + + if cfg!(target_os = "windows") { + config.static_crt(true); + } + + set_compiler(&mut config)?; + set_profile(&mut config)?; + + config.generator("Ninja"); + + let _ = config.build(); + Ok(()) +} + +// https://gitlab.kitware.com/cmake/community/-/wikis/FAQ#how-do-i-use-a-different-compiler +// We set this here as setting it in the cmakefile is discouraged +fn set_compiler(config: &mut Config) -> Result<(), Box>{ + if cfg!(target_os = "linux") { + let mut c_cfg = cc::Build::new(); + let clang_11 = which::which("clang-11")?; + c_cfg.compiler(clang_11); + config.init_c_cfg(c_cfg); + + let mut cxx_cfg = cc::Build::new(); + let clangpp_11 = which::which("clang++-11")?; + cxx_cfg.compiler(clangpp_11); + config.init_cxx_cfg(cxx_cfg); + } else if cfg!(target_os = "windows") { + let mut c_cfg = cc::Build::new(); + let clang = which::which("clang.exe")?; + c_cfg.compiler(clang); + config.init_c_cfg(c_cfg); + + let mut cxx_cfg = cc::Build::new(); + let clangpp = which::which("clang++.exe")?; + cxx_cfg.compiler(clangpp); + config.init_cxx_cfg(cxx_cfg); + } else if cfg!(target_os = "macos") { + // Use macos default + } else { + panic!("Unsupported platform") + } + Ok(()) +} + +fn set_profile(config: &mut Config) -> Result<(), Box> { + config.define("CMAKE_BUILD_TYPE", "RelWithDebInfo"); + config.define("CMAKE_C_COMPILER_WORKS", "1"); + config.define("CMAKE_CXX_COMPILER_WORKS", "1"); + Ok(()) +} diff --git a/src/Qir/microsoft-quantum-qir-runtime-sys/src/foundation.rs b/src/Qir/microsoft-quantum-qir-runtime-sys/src/foundation.rs new file mode 100644 index 00000000000..f061706b3ea --- /dev/null +++ b/src/Qir/microsoft-quantum-qir-runtime-sys/src/foundation.rs @@ -0,0 +1,59 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +use lazy_static::lazy_static; + +use libloading::Library; + +#[cfg(target_os = "linux")] +const FOUNDATION_BYTES: &'static [u8] = include_bytes!(concat!( + env!("OUT_DIR"), + "/build/lib/QSharpFoundation/libMicrosoft.Quantum.Qir.QSharp.Foundation.so" +)); + +#[cfg(target_os = "macos")] +const FOUNDATION_BYTES: &'static [u8] = include_bytes!(concat!( + env!("OUT_DIR"), + "/build/lib/QSharpFoundation/libMicrosoft.Quantum.Qir.QSharp.Foundation.dylib" +)); + +#[cfg(target_os = "windows")] +const FOUNDATION_BYTES: &'static [u8] = include_bytes!(concat!( + env!("OUT_DIR"), + "/build/lib/QSharpFoundation/Microsoft.Quantum.Qir.QSharp.Foundation.dll" +)); + +lazy_static! { + pub(crate) static ref FOUNDATION_LIBRARY: Library = unsafe { + crate::qir_libloading::load_library_bytes( + "Microsoft.Quantum.Qir.QSharp.Foundation", + FOUNDATION_BYTES, + ) + .unwrap() + }; +} + +pub struct QSharpFoundation {} + +impl QSharpFoundation { + pub fn new() -> QSharpFoundation { + let _ = FOUNDATION_LIBRARY; + QSharpFoundation {} + } +} + +#[cfg(test)] +mod tests { + use crate::foundation::QSharpFoundation; + + #[test] + fn library_loads_on_new() { + let _ = QSharpFoundation::new(); + } + #[test] + fn library_can_be_initialized_multiple_times() { + let _ = QSharpFoundation::new(); + let _ = QSharpFoundation::new(); + let _ = QSharpFoundation::new(); + } +} diff --git a/src/Qir/microsoft-quantum-qir-runtime-sys/src/lib.rs b/src/Qir/microsoft-quantum-qir-runtime-sys/src/lib.rs new file mode 100644 index 00000000000..5e2313ba80a --- /dev/null +++ b/src/Qir/microsoft-quantum-qir-runtime-sys/src/lib.rs @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#[cfg(feature = "foundation")] +pub mod foundation; + +#[cfg(feature = "runtime")] +pub mod runtime; + +mod qir_libloading; diff --git a/src/Qir/microsoft-quantum-qir-runtime-sys/src/qir_libloading.rs b/src/Qir/microsoft-quantum-qir-runtime-sys/src/qir_libloading.rs new file mode 100644 index 00000000000..0fdfd627505 --- /dev/null +++ b/src/Qir/microsoft-quantum-qir-runtime-sys/src/qir_libloading.rs @@ -0,0 +1,55 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +use libloading::{library_filename, Library}; +use log; +use std::error::Error; +use std::path::Path; +use tempfile::tempdir; + +pub(crate) fn write_library>( + path: P, + lib: &'static [u8], +) -> Result<(), Box> { + log::debug!("Writing {}", path.as_ref().display()); + std::fs::write(path, lib)?; + Ok(()) +} + +pub(crate) unsafe fn load_library_bytes( + base_name: &str, + lib: &'static [u8], +) -> Result> { + let name = library_filename(base_name) + .into_string() + .expect("Could not get library name as string"); + let path = tempdir().expect(""); + let filepath = path.as_ref().join(name); + write_library(&filepath, lib)?; + let library = load_library(&filepath)?; + Ok(library) +} + +pub(crate) unsafe fn load_library>(path: P) -> Result> { + log::debug!("Loading {}", path.as_ref().display()); + let library = Library::new(path.as_ref().as_os_str())?; + + #[cfg(feature = "llvm-libloading")] + load_library_with_llvm(path); + + Ok(library) +} + +#[cfg(feature = "llvm-libloading")] +fn load_library_with_llvm>(path: P) { + let library_path = path + .as_ref() + .to_str() + .expect("Could not convert library path to &str"); + let was_loaded_by_llvm = inkwell::support::load_library_permanently(library_path); + if was_loaded_by_llvm { + log::error!("Failed to load {} into LLVM", library_path); + } else { + log::debug!("Loaded {} into LLVM", library_path); + } +} diff --git a/src/Qir/microsoft-quantum-qir-runtime-sys/src/runtime.rs b/src/Qir/microsoft-quantum-qir-runtime-sys/src/runtime.rs new file mode 100644 index 00000000000..948a0200235 --- /dev/null +++ b/src/Qir/microsoft-quantum-qir-runtime-sys/src/runtime.rs @@ -0,0 +1,118 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +use lazy_static::lazy_static; + +use std::ffi::CString; + +use cty; +use libloading::Library; + +#[cfg(target_os = "linux")] +const RUNTIME_BYTES: &'static [u8] = include_bytes!(concat!( + env!("OUT_DIR"), + "/build/lib/QIR/libMicrosoft.Quantum.Qir.Runtime.so" +)); + +#[cfg(target_os = "macos")] +const RUNTIME_BYTES: &'static [u8] = include_bytes!(concat!( + env!("OUT_DIR"), + "/build/lib/QIR/libMicrosoft.Quantum.Qir.Runtime.dylib" +)); + +#[cfg(target_os = "windows")] +const RUNTIME_BYTES: &'static [u8] = include_bytes!(concat!( + env!("OUT_DIR"), + "/build/lib/QIR/Microsoft.Quantum.Qir.Runtime.dll" +)); + +lazy_static! { + pub(crate) static ref RUNTIME_LIBRARY: Library = unsafe { + crate::qir_libloading::load_library_bytes("Microsoft.Quantum.Qir.Runtime", RUNTIME_BYTES) + .unwrap() + }; +} + +pub type QUBIT = u64; + +#[repr(C)] +pub struct QirArray { + private: [u8; 0], +} + +pub type IRuntimeDriver = cty::c_void; + +pub struct BasicRuntimeDriver {} + +impl BasicRuntimeDriver { + pub unsafe fn initialize_qir_context(track_allocated_objects: bool) { + // The libloading calls need to be used instead of the extern "C" calls + // to prevent linkage. Python can't init the lib if we take a hard + // dependency on the library + let driver = QirRuntime::create_basic_runtime_driver(); + QirRuntime::initialize_qir_context(driver, track_allocated_objects); + } +} + +pub struct QirRuntime {} + +impl QirRuntime { + pub fn new() -> QirRuntime { + let _ = RUNTIME_LIBRARY; + QirRuntime {} + } + + pub unsafe fn create_basic_runtime_driver() -> *mut cty::c_void { + let library = &RUNTIME_LIBRARY; + let create = library + .get:: *mut IRuntimeDriver>( + CString::new("CreateBasicRuntimeDriver") + .unwrap() + .as_bytes_with_nul(), + ) + .unwrap(); + create() + } + + pub unsafe fn initialize_qir_context(driver: *mut cty::c_void, track_allocated_objects: bool) { + let library = &RUNTIME_LIBRARY; + let init = library + .get::( + CString::new("InitializeQirContext") + .unwrap() + .as_bytes_with_nul(), + ) + .unwrap(); + init(driver, track_allocated_objects) + } + + pub unsafe fn quantum_rt_array_get_element_ptr_1d( + array: *mut QirArray, + index: i64, + ) -> *mut cty::c_char { + let library = &RUNTIME_LIBRARY; + let get_element_ptr = library + .get:: *mut cty::c_char>( + CString::new("__quantum__rt__array_get_element_ptr_1d") + .unwrap() + .as_bytes_with_nul(), + ) + .unwrap(); + get_element_ptr(array, index) + } +} + +#[cfg(test)] +mod tests { + use crate::runtime::QirRuntime; + #[test] + fn library_loads_on_new() { + let _ = QirRuntime::new(); + } + #[test] + fn library_can_be_initialized_multiple_times() { + let _ = QirRuntime::new(); + let _ = QirRuntime::new(); + let _ = QirRuntime::new(); + } +} diff --git a/src/Qir/qir-utils.ps1 b/src/Qir/qir-utils.ps1 index 11aac34ecfa..612c19b9246 100644 --- a/src/Qir/qir-utils.ps1 +++ b/src/Qir/qir-utils.ps1 @@ -34,163 +34,24 @@ function Build-CMakeProject { ) Write-Host "##[info]Build $Name" - $oldCC = $env:CC - $oldCXX = $env:CXX - $oldRC = $env:RC - $oldCFLAGS = $env:CFLAGS - $oldCXXFLAGS = $env:CXXFLAGS + $CMAKE_C_COMPILER = "" + $CMAKE_CXX_COMPILER = "" $clangTidy = "" - # Treat warnings as errors: - $warningFlags = "-Werror" # https://clang.llvm.org/docs/UsersManual.html#options-to-control-error-and-warning-messages - # Enable all warnings: - $warningFlags += " -Weverything" # https://clang.llvm.org/docs/UsersManual.html#enabling-all-diagnostics - # https://clang.llvm.org/docs/DiagnosticsReference.html - - # Disable these warnings: - - # We don't care about keeping compatibility with C++98/03, C++11, C++14. Any new features unknown to our compiler version will be reported as errors. - # -Wc++98-compat-pedantic - # -Wc++98-compat, - # -Wc++98-compat-local-type-template-args, -Wc++98-compat-unnamed-type-template-args, -Wpre-c++14-compat, - # -Wpre-c++17-compat, -Wpre-c++20-compat, -Wpre-c++2b-compat. - # -Wc++98-compat-bind-to-temporary-copy, -Wc++98-compat-extra-semi, - # -Wpre-c++14-compat-pedantic, - # -Wc++98-c++11-compat-binary-literal, -Wpre-c++14-compat. - # -Wpre-c++17-compat-pedantic, - # -Wpre-c++17-compat. - # -Wpre-c++20-compat-pedantic, - # -Wpre-c++20-compat. - # -Wpre-c++2b-compat-pedantic (= -Wpre-c++2b-compat). - $warningFlags += " -Wno-c++98-compat-pedantic" # https://clang.llvm.org/docs/DiagnosticsReference.html#wc-98-compat-pedantic - # Old-style casts increase readability as opposed to `reinterpret_cast<..>()`. We want to be able to use the old-style casts. - $warningFlags += " -Wno-old-style-cast" - # Even if the `switch` covers all the enumerators, it is still good to have `default` label to cover the potential newly added (but not handled) enumerators. - $warningFlags += " -Wno-covered-switch-default" - # We are OK using C99 features. - # -Wc99-extension - # -Wc99-designator - # -Wc++20-designator - $warningFlags += " -Wno-c99-extensions" - # We are OK that the structs are padded to align the fields. - $warningFlags += " -Wno-padded" # https://clang.llvm.org/docs/DiagnosticsReference.html#wpadded - # We are OK with abstract classes. - $warningFlags += " -Wno-weak-vtables" - - - # Temporarily disable the following warnings (until QIR RT is refactored to expose C interface). - - # Looks like the `-Wglobal-constructors` warns that the instance of the `__dllexport` class/struct (or a static member var of such class/struct) - # needs to be constructible by calling a global `__dllexport` function (to guarantee that a single instance is created and the same instance is used - # both inside and outside of the binary (dynamic library or executable)). - # Or it warns about the constructor that is invoked for a global (or static member) variable _before_ the `main()` is invoked, thus slowing down the start, - # see https://stackoverflow.com/a/15708829/6362941 - $warningFlags += " -Wno-global-constructors" # https://clang.llvm.org/docs/DiagnosticsReference.html#wglobal-constructors - # Looks like the `-Wexit-time-destructors` warns that the destructor of a global or static member variable will be invoked - # _after_ the `main()` returns (thus slowing down the termination/restart). - $warningFlags += " -Wno-exit-time-destructors" - - # Temporarily disable "-Wextra-semi-stmt" that warns about redundant `;` in the end of `INFO(id);` of Catch tests framework (which looks fixed in the latest Catch version). - # Disable until the Catch header "src\Qir\Common\Externals\catch2\catch.hpp" is updated to a version newer than v2.12.1 (from https://github.com/catchorg/Catch2). - $warningFlags += " -Wno-extra-semi-stmt" # https://clang.llvm.org/docs/DiagnosticsReference.html#wextra-semi-stmt - - $env:CFLAGS += $warningFlags - $env:CXXFLAGS += $warningFlags - - - if ($Env:BUILD_CONFIGURATION -eq "Debug") - { - # Sanitizers (https://clang.llvm.org/docs/UsersManual.html#controlling-code-generation): - - $sanitizeFlags = "" - if (-not ($IsWindows)) - { - # Undefined Behavior Sanitizer (https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html) - # Win: - # FAILED: lib/QIR/Microsoft.Quantum.Qir.Runtime.dll lib/QIR/Microsoft.Quantum.Qir.Runtime.lib - # lld-link: error: /failifmismatch: mismatch detected for 'RuntimeLibrary': - # >>> lib/QIR/CMakeFiles/qir-rt-support-obj.dir/QubitManager.cpp.obj has value MD_DynamicRelease - # >>> clang_rt.ubsan_standalone_cxx-x86_64.lib(ubsan_type_hash_win.cc.obj) has value MT_StaticRelease - # clang++: error: linker command failed with exit code 1 (use -v to see invocation) - $sanitizeFlags += " -fsanitize=undefined -fsanitize=float-divide-by-zero -fsanitize=unsigned-integer-overflow -fsanitize=implicit-conversion -fsanitize=local-bounds -fsanitize=nullability" - # TODO: - # For Win consider extra build configuration linking all libs statically, enable `-fsanitize=undefined`, run the statically linked tests. - - #if (-not ($IsMacOS)) # Cannot be combined with `-fsanitize=address`. - #{ - # # Safe Stack instrumentation (https://clang.llvm.org/docs/SafeStack.html): - # # No support for Win, Mac. - # # clang: error: unsupported option '-fsanitize=safe-stack' for target 'x86_64-apple-darwin19.6.0' - # # Linking a DSO with SafeStack is not currently supported. But compilation, linking, and test runs all succeed. - # $sanitizeFlags += " -fsanitize=safe-stack" - #} - - ## Memory Sanitizer (https://clang.llvm.org/docs/MemorySanitizer.html) - ## Win: Not supported. - ## clang: error: unsupported option '-fsanitize=memory' for target 'x86_64-pc-windows-msvc' - ## WSL: Complains for use-of-uninitialized-value in `catch2/catch.hpp` during initialization of global vars - ## (if run both as `pwsh Runtime/test-qir-runtime.ps1` (or Tests/test-qir-tests.ps1) and as standalone). - ## An update of `catch2/catch.hpp` to 2.13.6 (search for "go to the v2.x branch" at https://github.com/catchorg/Catch2) didn't help. - ## Suppressing of the errors in the updated `catch2/catch.hpp` and standard library headers eventually bumps into errors reported in `memcmp`, - ## suppressing of which does not work (https://github.com/google/sanitizers/issues/1429#issuecomment-876799463). - ## Looks like MSan will not work until the libstdc++ is recompiled to be instrumented (https://clang.llvm.org/docs/MemorySanitizer.html#handling-external-code). - ## Instrumenting libstdc++ during CI builds seems impractical (https://stackoverflow.com/a/22301584/6362941). - #$sanitizeFlags += " -fsanitize=memory -fsanitize-memory-track-origins=2" - - # Address Sanitizer (https://clang.llvm.org/docs/AddressSanitizer.html) - # Win: (Conflict between the ASan library and MSVC library) - # [19/35] Linking CXX shared library lib\QIR\Microsoft.Quantum.Qir.Runtime.dll - # FAILED: lib/QIR/Microsoft.Quantum.Qir.Runtime.dll lib/QIR/Microsoft.Quantum.Qir.Runtime.lib - # cmd.exe /C "cd . && C:\PROGRA~1\LLVM12\bin\CLANG_~1.EXE -fuse-ld=lld-link -nostartfiles -nostdlib -Werror -Weverything .... \ - # -fsanitize=address -g -Xclang -gcodeview -O0 -DDEBUG -D_DEBUG -D_DLL -D_MT -Xclang --dependent-lib=msvcrtd \ - # -Xlinker /guard:cf -shared -o lib\QIR\Microsoft.Quantum.Qir.Runtime.dll -Xlinker /implib:lib\QIR\Microsoft.Quantum.Qir.Runtime.lib \ - # -Xlinker /pdb:lib\QIR\Microsoft.Quantum.Qir.Runtime.pdb -Xlinker /version:0.0 lib/QIR/bridge-rt.obj \ - # lib/QIR/CMakeFiles/qir-rt-support-obj.dir/QirRange.cpp.obj lib/QIR/CMakeFiles/qir-rt-support-obj.dir/OutputStream.cpp.obj ....\ - # -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 -loldnames && cd ." - # lld-link: error: duplicate symbol: malloc - # >>> defined at C:\src\llvm_package_6923b0a7\llvm-project\compiler-rt\lib\asan\asan_win_dll_thunk.cpp:34 - # >>> clang_rt.asan_dll_thunk-x86_64.lib(asan_win_dll_thunk.cpp.obj) - # >>> defined at ucrtbased.dll - # clang++: error: linker command failed with exit code 1 (use -v to see invocation) - $sanitizeFlags += " -fsanitize=address" # https://clang.llvm.org/docs/AddressSanitizer.html - # TODO: - # * Some tests verify the failure behavior, i.e. they cause `Fail()` to be called and return to the caller with the exception. - # Any allocations made between the call and the exception throw (caught by `REQUIRE_THROWS()`) are leaking. - # Extract such tests to a separate .cpp file or executable and compile with leak check off (or suppress leaks in that .cpp or executable only). - - # Common for all sanitizers: - $sanitizeFlags += " -fsanitize-blacklist=" # https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html#suppressing-errors-in-recompiled-code-ignorelist - # https://releases.llvm.org/11.0.1/tools/clang/docs/SanitizerSpecialCaseList.html - $sanitizeFlags += (Join-Path $Path .. UBSan.ignore) - - $sanitizeFlags += " -fno-omit-frame-pointer" # https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html - $sanitizeFlags += " -fno-optimize-sibling-calls" # https://clang.llvm.org/docs/AddressSanitizer.html - } # if (-not ($IsWindows)) - - $env:CFLAGS += $sanitizeFlags - $env:CXXFLAGS += $sanitizeFlags - } # if ($Env:BUILD_CONFIGURATION -eq "Debug") - - - if (($IsMacOS) -or ((Test-Path Env:/AGENT_OS) -and ($Env:AGENT_OS.StartsWith("Darwin")))) - { + if (($IsMacOS) -or ((Test-Path Env:/AGENT_OS) -and ($Env:AGENT_OS.StartsWith("Darwin")))) { Write-Host "On MacOS build $Name using the default C/C++ compiler (should be AppleClang)" } - elseif (($IsLinux) -or ((Test-Path Env:AGENT_OS) -and ($Env:AGENT_OS.StartsWith("Lin")))) - { + elseif (($IsLinux) -or ((Test-Path Env:AGENT_OS) -and ($Env:AGENT_OS.StartsWith("Lin")))) { Write-Host "On Linux build $Name using Clang" - $env:CC = "clang-11" - $env:CXX = "clang++-11" - $env:RC = "clang++-11" + $CMAKE_C_COMPILER = "-DCMAKE_C_COMPILER=clang-11" + $CMAKE_CXX_COMPILER = "-DCMAKE_CXX_COMPILER=clang++-11" $clangTidy = "-DCMAKE_CXX_CLANG_TIDY=clang-tidy-11" } - elseif (($IsWindows) -or ((Test-Path Env:AGENT_OS) -and ($Env:AGENT_OS.StartsWith("Win")))) - { + elseif (($IsWindows) -or ((Test-Path Env:AGENT_OS) -and ($Env:AGENT_OS.StartsWith("Win")))) { Write-Host "On Windows build $Name using Clang" - $env:CC = "clang.exe" - $env:CXX = "clang++.exe" - $env:RC = "clang++.exe" + $CMAKE_C_COMPILER = "-DCMAKE_C_COMPILER=clang.exe" + $CMAKE_CXX_COMPILER = "-DCMAKE_CXX_COMPILER=clang++.exe" if ((!(Get-Command clang -ErrorAction SilentlyContinue) -and (choco find --idonly -l llvm) -contains "llvm") -or ` (Test-Path Env:/AGENT_OS)) { @@ -204,7 +65,8 @@ function Build-CMakeProject { # the Linux build catch tidy issues. $clangTidy = "-DCMAKE_CXX_CLANG_TIDY=clang-tidy" } - } else { + } + else { Write-Host "##vso[task.logissue type=warning;]Failed to identify the OS. Will use default CXX compiler" } @@ -218,15 +80,16 @@ function Build-CMakeProject { Push-Location $cmakeBuildFolder $buildType = $Env:BUILD_CONFIGURATION - if ($buildType -eq "Release"){ + if ($buildType -eq "Release") { $buildType = "RelWithDebInfo" } - cmake -G Ninja $clangTidy -D CMAKE_VERBOSE_MAKEFILE:BOOL=ON -D CMAKE_BUILD_TYPE="$buildType" ../.. | Write-Host + cmake -G Ninja $CMAKE_C_COMPILER $CMAKE_CXX_COMPILER $clangTidy -D CMAKE_BUILD_TYPE="$buildType" ../.. | Write-Host if ($LastExitCode -ne 0) { Write-Host "##vso[task.logissue type=error;]Failed to generate $Name." $all_ok = $false - } else { + } + else { cmake --build . --target install | Write-Host if ($LastExitCode -ne 0) { Write-Host "##vso[task.logissue type=error;]Failed to build $Name." @@ -236,13 +99,6 @@ function Build-CMakeProject { Pop-Location - $env:CXXFLAGS = $oldCXXFLAGS - $env:CFLAGS = $oldCFLAGS - - $env:CC = $oldCC - $env:CXX = $oldCXX - $env:RC = $oldRC - return $all_ok } diff --git a/src/Simulation/Common/IQuantumProcessor.cs b/src/Simulation/Common/IQuantumProcessor.cs index 8bd4dc6ec7f..cd6b3380e1a 100644 --- a/src/Simulation/Common/IQuantumProcessor.cs +++ b/src/Simulation/Common/IQuantumProcessor.cs @@ -563,7 +563,7 @@ public interface IQuantumProcessor void OnFail(System.Runtime.ExceptionServices.ExceptionDispatchInfo exceptionDispatchInfo); /// - /// Called when qubits are allocated by Q# using block. + /// Called when qubits are allocated by Q# use block. /// /// Qubits that are being allocated. /// @@ -573,7 +573,7 @@ public interface IQuantumProcessor void OnAllocateQubits(IQArray qubits); /// - /// Called when qubits are released in Q# in the end of using block. + /// Called when qubits are released in Q# in the end of use block. /// /// Qubits that are being released. /// @@ -583,7 +583,7 @@ public interface IQuantumProcessor void OnReleaseQubits(IQArray qubits); /// - /// Called when qubits are borrowed by Q# borrowing block. + /// Called when qubits are borrowed by Q# borrow block. /// /// Qubits that are being borrowed. /// Number of qubits that have been allocated for borrowing. This might happen if there have not been enough already allocated qubits available for borrowing.. @@ -594,7 +594,7 @@ public interface IQuantumProcessor void OnBorrowQubits(IQArray qubits, long allocatedForBorrowingCount); /// - /// Called when qubits are returned in the end of Q# borrowing block. + /// Called when qubits are returned in the end of Q# borrow block. /// /// Qubits that have been borrowed and are now being returned. /// Number of qubits that have been released once returned. This might happen if they have been allocated only for borrowing.. diff --git a/src/Simulation/Common/Simulators.Dev.props b/src/Simulation/Common/Simulators.Dev.props index 9abcca669a7..bf304660f95 100644 --- a/src/Simulation/Common/Simulators.Dev.props +++ b/src/Simulation/Common/Simulators.Dev.props @@ -16,6 +16,9 @@ $(QsimDllMac) $(QsimDllLinux) $(QsimDllWindows) + $([MSBuild]::NormalizePath($(NativeBuildPath)/../../osx)) + $([MSBuild]::NormalizePath($(NativeBuildPath)/../../linux)) + $([MSBuild]::NormalizePath($(NativeBuildPath)/../../win10)) @@ -29,6 +32,11 @@ PreserveNewest false + + %(Filename)%(Extension) + PreserveNewest + false + diff --git a/src/Simulation/EntryPointDriver.Tests/Tests.fs b/src/Simulation/EntryPointDriver.Tests/Tests.fs index 58037e52f0e..1e00e8bd15b 100644 --- a/src/Simulation/EntryPointDriver.Tests/Tests.fs +++ b/src/Simulation/EntryPointDriver.Tests/Tests.fs @@ -646,7 +646,7 @@ let ``Submit allows overriding default values`` () = https://www.example.com/00000000-0000-0000-0000-0000000000000" - + [] let ``Submit allows a long user-agent`` () = let given = test "Returns Unit" @@ -661,7 +661,7 @@ let ``Submit allows a long user-agent`` () = "--shots" "750" "--user-agent" - "a-very-long-user-agent-(it-will-be-truncated)" + "a-very-long-user-agent-(it-will-be-not-be-truncated-here)" "--credential" "cli" ]) @@ -674,18 +674,17 @@ let ``Submit allows a long user-agent`` () = Location: myLocation Credential: CLI AadToken: myTok - UserAgent: a-very-long-user-agent-( + UserAgent: a-very-long-user-agent-(it-will-be-not-be-truncated-here) Job Name: myJobName Job Parameters: Shots: 750 Output: FriendlyUri Dry Run: False Verbose: True - Submitting Q# entry point using a quantum machine. - https://www.example.com/00000000-0000-0000-0000-0000000000000" - + + [] let ``Submit extracts the location from a quantum endpoint`` () = let given = test "Returns Unit" diff --git a/src/Simulation/EntryPointDriver/Azure/AzureSettings.cs b/src/Simulation/EntryPointDriver/Azure/AzureSettings.cs index 87dedafc164..3577d5258f6 100644 --- a/src/Simulation/EntryPointDriver/Azure/AzureSettings.cs +++ b/src/Simulation/EntryPointDriver/Azure/AzureSettings.cs @@ -136,19 +136,20 @@ internal TokenCredential CreateCredentials() } } - internal string? TrimmedUserAgent() { - var userAgent = (UserAgent ?? System.Environment.GetEnvironmentVariable("USER_AGENT"))?.Trim(); - - return (userAgent == null || userAgent.Length < 25) - ? userAgent - : userAgent.Substring(0, 24); - } - - internal QuantumJobClientOptions CreateClientOptions() { var options = new QuantumJobClientOptions(); - options.Diagnostics.ApplicationId = TrimmedUserAgent(); + + // This value will be added as a prefix in the UserAgent when + // calling the Azure Quantum API + // It cannot be larger than 24 characters. + var applicationId = string.Join('@', "Q#Run", UserAgent?.Trim()).Trim(' ', '@'); + if (applicationId?.Length > 24) + { + applicationId = applicationId.Substring(0, 24); + } + + options.Diagnostics.ApplicationId = applicationId; return options; } @@ -187,7 +188,7 @@ public override string ToString() => string.Join( $"Location: {Location ?? ExtractLocation(BaseUri)}", $"Credential: {Credential}", $"AadToken: {AadToken?.Substring(0, 5)}", - $"UserAgent: {TrimmedUserAgent()}", + $"UserAgent: {UserAgent}", $"Job Name: {JobName}", $"Job Parameters: {string.Join(", ", JobParams.OrderBy(item => item.Key))}", $"Shots: {Shots}", diff --git a/src/Simulation/Native/.gitignore b/src/Simulation/Native/.gitignore index aa51796222b..8f1fc6e9a01 100644 --- a/src/Simulation/Native/.gitignore +++ b/src/Simulation/Native/.gitignore @@ -10,14 +10,3 @@ foo* CMakeFiles/ CMakeCache.txt *.so - -# Ignore build artifacts... -win10 -# ...except for vcomp140, which isn't actually a build -# artifact, but provides the Visual C/C++ OpenMP runtime -# needed by the full-state simulator. -# -# Making sure that this file is in the repo will make -# sure it ends up in our final NuGet packages, as needed -# for the full-state simulator to work correctly. -!win10/vcomp140.dll diff --git a/src/Simulation/Native/CMakeLists.txt b/src/Simulation/Native/CMakeLists.txt index 06b27fd43de..ced3222baeb 100644 --- a/src/Simulation/Native/CMakeLists.txt +++ b/src/Simulation/Native/CMakeLists.txt @@ -32,26 +32,81 @@ option(USE_SINGLE_PRECISION "Use single-precision floating point operations" OFF option(HAVE_INTRINSICS "Have AVX intrinsics" OFF) option(USE_GATE_FUSION "Use gate fusion" ON) -# windows specific flags -if (MSVC) - # always create debug info - add_definitions("/Zi") - add_definitions("/Z7") - - # build with no VC runtime depedencies: - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT /Qspectre /guard:cf /Zi /Z7") - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd /Qspectre /guard:cf") - set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG") -else (MSVC) - set(CMAKE_CXX_FLAGS "-static-libgcc") -endif (MSVC) - +# Always use Spectre mitigations where available +if (WIN32) + # Enforce use of static runtime (avoids target machine needing msvcrt installed). + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") + + # Locate the vswhere application, which will provide paths to any installed Visual Studio instances. + # By invoking it with "-find **/lib/spectre/x64" we will find any Spectre mitigated libaries that + # have been installed. + find_program(_vswhere_tool + NAMES vswhere + PATHS "$ENV{ProgramFiles\(x86\)}/Microsoft Visual Studio/Installer") + if (NOT ${vswhere}) + message(FATAL_ERROR "Could not locate vswhere.exe - unable to source vc redistributable") + endif() + execute_process( + COMMAND "${_vswhere_tool}" -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -find **/14.29.*/**/lib/spectre/x64 -sort + OUTPUT_VARIABLE _vs_install_loc_out + RESULT_VARIABLE _vs_where_exitcode + OUTPUT_STRIP_TRAILING_WHITESPACE) + file(TO_CMAKE_PATH "${_vs_install_loc_out}" SPECTRE_LIB_PATH_OUT) + string(REGEX REPLACE "[\r\n]+" ";" SPECTRE_LIB_PATH ${SPECTRE_LIB_PATH_OUT}) + message(INFO "*** install loc: ${SPECTRE_LIB_PATH}") + + # Locate the spectre mitigated runtime libraries and fail if they can't be found. Targets in this + # cmake project can use the variables to explicitly link these libraries rather than using the + # non-mitigated libraries that are found by default. + find_library(LIBCMT_SPECTRE_REL libcmt PATHS ${SPECTRE_LIB_PATH} REQUIRED) + find_library(LIBCMT_SPECTRE_DEB libcmtd PATHS ${SPECTRE_LIB_PATH} REQUIRED) + set(LIBCMT_SPECTRE debug ${LIBCMT_SPECTRE_DEB} optimized ${LIBCMT_SPECTRE_REL}) + message(INFO "*** using spectre lib: ${LIBCMT_SPECTRE}") + find_library(LIBCPMT_SPECTRE_REL libcpmt PATHS ${SPECTRE_LIB_PATH} REQUIRED) + find_library(LIBCPMT_SPECTRE_DEB libcpmtd PATHS ${SPECTRE_LIB_PATH} REQUIRED) + set(LIBCPMT_SPECTRE debug ${LIBCPMT_SPECTRE_DEB} optimized ${LIBCPMT_SPECTRE_REL}) + message(INFO "*** using spectre lib: ${LIBCPMT_SPECTRE}") + find_library(LIBVCRUNTIME_SPECTRE_REL libvcruntime PATHS ${SPECTRE_LIB_PATH} REQUIRED) + find_library(LIBVCRUNTIME_SPECTRE_DEB libvcruntimed PATHS ${SPECTRE_LIB_PATH} REQUIRED) + set(LIBVCRUNTIME_SPECTRE debug ${LIBVCRUNTIME_SPECTRE_DEB} optimized ${LIBVCRUNTIME_SPECTRE_REL}) + message(INFO "*** using spectre lib: ${LIBVCRUNTIME_SPECTRE}") + set(SPECTRE_LIBS + ${LIBCMT_SPECTRE} + ${LIBCPMT_SPECTRE} + ${LIBVCRUNTIME_SPECTRE}) + + add_link_options("LINKER:/guard:cf") +endif() + +if (NOT APPLE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mspeculative-load-hardening -mretpoline") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mspeculative-load-hardening -mretpoline") +endif() include_directories(${PROJECT_BINARY_DIR}/src) include_directories(${PROJECT_SOURCE_DIR}/src) # OpenMP if(ENABLE_OPENMP) + +if (APPLE) + set(OPENMP_LOCAL_PATH "${PROJECT_SOURCE_DIR}/osx") + # Note we use `-rpath @loader_path` to ensure the produced binary includes the folder of the binary + # itself in the runtime search path for dynamic library load, regardless of environment settings. + # We don't use `@executable_path` because that takes into account recursive dependencies and will be + # the folder of the originally launched binary (root of the dependency tree) instead of loading binary + # (the immediate parent in the dependency tree), which will be the simulatory library itself. + # See https://www.man7.org/linux/man-pages/man1/ld.1.html and https://stackoverflow.com/questions/52981210/linking-with-dylib-library-from-the-command-line-using-clang + set(OPENMP_COMPILER_FLAGS "-Xpreprocessor -fopenmp -I${OPENMP_LOCAL_PATH}/include -L${OPENMP_LOCAL_PATH} -lomp -rpath @loader_path") + set(OPENMP_LIB_NAME "omp") + + set(OpenMP_CXX_FLAGS "${OPENMP_COMPILER_FLAGS}") + set(OpenMP_C_FLAGS "${OPENMP_COMPILER_FLAGS}") + set(OpenMP_CXX_LIB_NAMES "${OPENMP_LIB_NAME}") + set(OpenMP_C_LIB_NAMES "${OPENMP_LIB_NAME}") + set(OpenMP_omp_LIBRARY "${OPENMP_LOCAL_PATH}/libomp.dylib") +endif() + find_package(OpenMP) if(OPENMP_FOUND) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") diff --git a/src/Simulation/Native/build-native-simulator.ps1 b/src/Simulation/Native/build-native-simulator.ps1 index 3908c7df01c..75f7043fc68 100644 --- a/src/Simulation/Native/build-native-simulator.ps1 +++ b/src/Simulation/Native/build-native-simulator.ps1 @@ -3,6 +3,15 @@ Write-Host "##[info]Build Native simulator for $Env:BUILD_CONFIGURATION" +if ($IsMacOS) { + # To ensure loading succeeds on Mac the install id of the library needs to be updated to use + # paths relative to target dynamic load path. Otherwise it will keep the full path encoding in the + # library from when it was built by homebrew. + # See https://stackoverflow.com/questions/52981210/linking-with-dylib-library-from-the-command-line-using-clang + Write-Host "##[info]Fixing binary dependencies with install_name_tool..." + install_name_tool -id "@rpath/libomp.dylib" (Join-Path $PSScriptRoot osx libomp.dylib) +} + $nativeBuild = (Join-Path $PSScriptRoot "build") if (-not (Test-Path $nativeBuild)) { @@ -10,31 +19,74 @@ if (-not (Test-Path $nativeBuild)) { } Push-Location $nativeBuild +# Search for "sanitize" in +# https://clang.llvm.org/docs/ClangCommandLineReference.html +# https://man7.org/linux/man-pages/man1/gcc.1.html +$SANITIZE_FLAGS=` + "-fsanitize=undefined " ` + + "-fsanitize=shift -fsanitize=shift-base " ` + + "-fsanitize=integer-divide-by-zero -fsanitize=float-divide-by-zero " ` + + "-fsanitize=unreachable " ` + + "-fsanitize=vla-bound -fsanitize=null -fsanitize=return " ` + + "-fsanitize=signed-integer-overflow -fsanitize=bounds -fsanitize=alignment -fsanitize=object-size " ` + + "-fsanitize=float-cast-overflow -fsanitize=nonnull-attribute -fsanitize=returns-nonnull-attribute -fsanitize=bool -fsanitize=enum " ` + + "-fsanitize=vptr -fsanitize=pointer-overflow -fsanitize=builtin " ` + + "-fsanitize=implicit-conversion -fsanitize=local-bounds -fsanitize=nullability " ` + ` + + "-fsanitize=address " ` + + "-fsanitize=pointer-compare -fsanitize=pointer-subtract " ` + + "-fsanitize-address-use-after-scope " ` + + "-fno-omit-frame-pointer -fno-optimize-sibling-calls" + + #+ "-fsanitize=unsigned-integer-overflow " # TODO(rokuzmin, #884): Disable this option for _specific_ lines + # of code, but not for the whole binary. + # There should be no space after -D CMAKE_BUILD_TYPE= but if we provide the environment variable inline, without # the space it doesn't seem to get substituted... With invalid -D CMAKE_BUILD_TYPE argument cmake silently produces # a DEBUG build. if (($IsWindows) -or ((Test-Path Env:AGENT_OS) -and ($Env:AGENT_OS.StartsWith("Win")))) { - Write-Host "On Windows build native simulator using the default C/C++ compiler (should be MSVC)" - cmake -D BUILD_SHARED_LIBS:BOOL="1" -D CMAKE_BUILD_TYPE="$Env:BUILD_CONFIGURATION" .. + $CMAKE_C_COMPILER = "-DCMAKE_C_COMPILER=clang.exe" + $CMAKE_CXX_COMPILER = "-DCMAKE_CXX_COMPILER=clang++.exe" + + if ((!(Get-Command clang -ErrorAction SilentlyContinue) -and (choco find --idonly -l llvm) -contains "llvm") -or ` + (Test-Path Env:/AGENT_OS)) { + # LLVM was installed by Chocolatey, so add the install location to the path. + $env:PATH = "$($env:SystemDrive)\Program Files\LLVM\bin;$env:Path" + } + + cmake -G Ninja -D BUILD_SHARED_LIBS:BOOL="1" $CMAKE_C_COMPILER $CMAKE_CXX_COMPILER ` + -D CMAKE_BUILD_TYPE="$Env:BUILD_CONFIGURATION" .. + # Without `-G Ninja` we fail to switch from MSVC to Clang. + # Sanitizers are not supported on Windows at the moment. Check again after migrating from Clang-11. } elseif (($IsLinux) -or ((Test-Path Env:AGENT_OS) -and ($Env:AGENT_OS.StartsWith("Lin")))) { - Write-Host "On Linux build native simulator using gcc (needed for OpenMP)" - cmake -D BUILD_SHARED_LIBS:BOOL="1" -D CMAKE_C_COMPILER=gcc -D CMAKE_CXX_COMPILER=g++ -D CMAKE_BUILD_TYPE="$Env:BUILD_CONFIGURATION" .. + cmake -D BUILD_SHARED_LIBS:BOOL="1" -D CMAKE_C_COMPILER=clang-11 -D CMAKE_CXX_COMPILER=clang++-11 ` + -D CMAKE_C_FLAGS_DEBUG="$SANITIZE_FLAGS" ` + -D CMAKE_CXX_FLAGS_DEBUG="$SANITIZE_FLAGS" ` + -D CMAKE_BUILD_TYPE="$Env:BUILD_CONFIGURATION" .. } elseif (($IsMacOS) -or ((Test-Path Env:AGENT_OS) -and ($Env:AGENT_OS.StartsWith("Darwin")))) { - Write-Host "On MacOS build native simulator using gcc (needed for OpenMP)" - # `gcc`on Darwin seems to be a shim that redirects to AppleClang, to get real gcc, must point to the specific - # version of gcc we've installed. - cmake -D BUILD_SHARED_LIBS:BOOL="1" -D CMAKE_C_COMPILER=gcc-7 -D CMAKE_CXX_COMPILER=g++-7 -D CMAKE_BUILD_TYPE="$Env:BUILD_CONFIGURATION" .. + Write-Host "On MacOS build using the default C/C++ compiler (should be AppleClang)" + + cmake -D BUILD_SHARED_LIBS:BOOL="1" ` + -D CMAKE_C_FLAGS_DEBUG="$SANITIZE_FLAGS" ` + -D CMAKE_CXX_FLAGS_DEBUG="$SANITIZE_FLAGS" ` + -D CMAKE_BUILD_TYPE="$Env:BUILD_CONFIGURATION" .. } else { cmake -D BUILD_SHARED_LIBS:BOOL="1" -D CMAKE_BUILD_TYPE="$Env:BUILD_CONFIGURATION" .. } cmake --build . --config "$Env:BUILD_CONFIGURATION" --target install +if ($IsMacOS) { + Write-Host "##[info]Copying libomp..." + Copy-Item -Verbose (Join-Path $PSScriptRoot osx libomp.dylib) (Join-Path $PSScriptRoot build) + Copy-Item -Verbose (Join-Path $PSScriptRoot osx libomp.dylib) (Join-Path $PSScriptRoot build drop) +} + Pop-Location diff --git a/src/Simulation/Native/linux/libomp.so b/src/Simulation/Native/linux/libomp.so new file mode 100644 index 00000000000..de31ecb353a Binary files /dev/null and b/src/Simulation/Native/linux/libomp.so differ diff --git a/src/Simulation/Native/osx/include/omp-tools.h b/src/Simulation/Native/osx/include/omp-tools.h new file mode 100644 index 00000000000..5092174d66e --- /dev/null +++ b/src/Simulation/Native/osx/include/omp-tools.h @@ -0,0 +1,1376 @@ +/* + * include/omp-tools.h.var + */ + +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef __OMPT__ +#define __OMPT__ + +/***************************************************************************** + * system include files + *****************************************************************************/ + +#include +#include + +#ifdef DEPRECATION_WARNINGS +# ifdef __cplusplus +# define DEPRECATED_51 [[deprecated("as of 5.1")]] +# else +# define DEPRECATED_51 __attribute__((deprecated("as of 5.1"))) +#endif +#else +#define DEPRECATED_51 +#endif + +/***************************************************************************** + * iteration macros + *****************************************************************************/ + +#define FOREACH_OMPT_INQUIRY_FN(macro) \ + macro (ompt_enumerate_states) \ + macro (ompt_enumerate_mutex_impls) \ + \ + macro (ompt_set_callback) \ + macro (ompt_get_callback) \ + \ + macro (ompt_get_state) \ + \ + macro (ompt_get_parallel_info) \ + macro (ompt_get_task_info) \ + macro (ompt_get_task_memory) \ + macro (ompt_get_thread_data) \ + macro (ompt_get_unique_id) \ + macro (ompt_finalize_tool) \ + \ + macro(ompt_get_num_procs) \ + macro(ompt_get_num_places) \ + macro(ompt_get_place_proc_ids) \ + macro(ompt_get_place_num) \ + macro(ompt_get_partition_place_nums) \ + macro(ompt_get_proc_id) \ + \ + macro(ompt_get_target_info) \ + macro(ompt_get_num_devices) + +#define FOREACH_OMPT_STATE(macro) \ + \ + /* first available state */ \ + macro (ompt_state_undefined, 0x102) /* undefined thread state */ \ + \ + /* work states (0..15) */ \ + macro (ompt_state_work_serial, 0x000) /* working outside parallel */ \ + macro (ompt_state_work_parallel, 0x001) /* working within parallel */ \ + macro (ompt_state_work_reduction, 0x002) /* performing a reduction */ \ + \ + /* barrier wait states (16..31) */ \ + macro (ompt_state_wait_barrier, 0x010) /* waiting at a barrier */ \ + macro (ompt_state_wait_barrier_implicit_parallel, 0x011) \ + /* implicit barrier at the end of parallel region */\ + macro (ompt_state_wait_barrier_implicit_workshare, 0x012) \ + /* implicit barrier at the end of worksharing */ \ + macro (ompt_state_wait_barrier_implicit, 0x013) /* implicit barrier */ \ + macro (ompt_state_wait_barrier_explicit, 0x014) /* explicit barrier */ \ + \ + /* task wait states (32..63) */ \ + macro (ompt_state_wait_taskwait, 0x020) /* waiting at a taskwait */ \ + macro (ompt_state_wait_taskgroup, 0x021) /* waiting at a taskgroup */ \ + \ + /* mutex wait states (64..127) */ \ + macro (ompt_state_wait_mutex, 0x040) \ + macro (ompt_state_wait_lock, 0x041) /* waiting for lock */ \ + macro (ompt_state_wait_critical, 0x042) /* waiting for critical */ \ + macro (ompt_state_wait_atomic, 0x043) /* waiting for atomic */ \ + macro (ompt_state_wait_ordered, 0x044) /* waiting for ordered */ \ + \ + /* target wait states (128..255) */ \ + macro (ompt_state_wait_target, 0x080) /* waiting for target region */ \ + macro (ompt_state_wait_target_map, 0x081) /* waiting for target data mapping operation */ \ + macro (ompt_state_wait_target_update, 0x082) /* waiting for target update operation */ \ + \ + /* misc (256..511) */ \ + macro (ompt_state_idle, 0x100) /* waiting for work */ \ + macro (ompt_state_overhead, 0x101) /* overhead excluding wait states */ \ + \ + /* implementation-specific states (512..) */ + + +#define FOREACH_KMP_MUTEX_IMPL(macro) \ + macro (kmp_mutex_impl_none, 0) /* unknown implementation */ \ + macro (kmp_mutex_impl_spin, 1) /* based on spin */ \ + macro (kmp_mutex_impl_queuing, 2) /* based on some fair policy */ \ + macro (kmp_mutex_impl_speculative, 3) /* based on HW-supported speculation */ + +#define FOREACH_OMPT_EVENT(macro) \ + \ + /*--- Mandatory Events ---*/ \ + macro (ompt_callback_thread_begin, ompt_callback_thread_begin_t, 1) /* thread begin */ \ + macro (ompt_callback_thread_end, ompt_callback_thread_end_t, 2) /* thread end */ \ + \ + macro (ompt_callback_parallel_begin, ompt_callback_parallel_begin_t, 3) /* parallel begin */ \ + macro (ompt_callback_parallel_end, ompt_callback_parallel_end_t, 4) /* parallel end */ \ + \ + macro (ompt_callback_task_create, ompt_callback_task_create_t, 5) /* task begin */ \ + macro (ompt_callback_task_schedule, ompt_callback_task_schedule_t, 6) /* task schedule */ \ + macro (ompt_callback_implicit_task, ompt_callback_implicit_task_t, 7) /* implicit task */ \ + \ + macro (ompt_callback_target, ompt_callback_target_t, 8) /* target */ \ + macro (ompt_callback_target_data_op, ompt_callback_target_data_op_t, 9) /* target data op */ \ + macro (ompt_callback_target_submit, ompt_callback_target_submit_t, 10) /* target submit */ \ + \ + macro (ompt_callback_control_tool, ompt_callback_control_tool_t, 11) /* control tool */ \ + \ + macro (ompt_callback_device_initialize, ompt_callback_device_initialize_t, 12) /* device initialize */ \ + macro (ompt_callback_device_finalize, ompt_callback_device_finalize_t, 13) /* device finalize */ \ + \ + macro (ompt_callback_device_load, ompt_callback_device_load_t, 14) /* device load */ \ + macro (ompt_callback_device_unload, ompt_callback_device_unload_t, 15) /* device unload */ \ + \ + /* Optional Events */ \ + macro (ompt_callback_sync_region_wait, ompt_callback_sync_region_t, 16) /* sync region wait begin or end */ \ + \ + macro (ompt_callback_mutex_released, ompt_callback_mutex_t, 17) /* mutex released */ \ + \ + macro (ompt_callback_dependences, ompt_callback_dependences_t, 18) /* report task dependences */ \ + macro (ompt_callback_task_dependence, ompt_callback_task_dependence_t, 19) /* report task dependence */ \ + \ + macro (ompt_callback_work, ompt_callback_work_t, 20) /* task at work begin or end */ \ + \ + macro (ompt_callback_masked, ompt_callback_masked_t, 21) /* task at masked begin or end */ \ + \ + macro (ompt_callback_target_map, ompt_callback_target_map_t, 22) /* target map */ \ + \ + macro (ompt_callback_sync_region, ompt_callback_sync_region_t, 23) /* sync region begin or end */ \ + \ + macro (ompt_callback_lock_init, ompt_callback_mutex_acquire_t, 24) /* lock init */ \ + macro (ompt_callback_lock_destroy, ompt_callback_mutex_t, 25) /* lock destroy */ \ + \ + macro (ompt_callback_mutex_acquire, ompt_callback_mutex_acquire_t, 26) /* mutex acquire */ \ + macro (ompt_callback_mutex_acquired, ompt_callback_mutex_t, 27) /* mutex acquired */ \ + \ + macro (ompt_callback_nest_lock, ompt_callback_nest_lock_t, 28) /* nest lock */ \ + \ + macro (ompt_callback_flush, ompt_callback_flush_t, 29) /* after executing flush */ \ + \ + macro (ompt_callback_cancel, ompt_callback_cancel_t, 30) /* cancel innermost binding region */ \ + \ + macro (ompt_callback_reduction, ompt_callback_sync_region_t, 31) /* reduction */ \ + \ + macro (ompt_callback_dispatch, ompt_callback_dispatch_t, 32) /* dispatch of work */ \ + macro (ompt_callback_target_emi, ompt_callback_target_emi_t, 33) /* target */ \ + macro (ompt_callback_target_data_op_emi,ompt_callback_target_data_op_emi_t,34) /* target data op */ \ + macro (ompt_callback_target_submit_emi, ompt_callback_target_submit_emi_t, 35) /* target submit */ \ + macro (ompt_callback_target_map_emi, ompt_callback_target_map_emi_t, 36) /* target map */ \ + macro (ompt_callback_error, ompt_callback_error_t, 37) /* error */ + +/***************************************************************************** + * implementation specific types + *****************************************************************************/ + +typedef enum kmp_mutex_impl_t { +#define kmp_mutex_impl_macro(impl, code) impl = code, + FOREACH_KMP_MUTEX_IMPL(kmp_mutex_impl_macro) +#undef kmp_mutex_impl_macro +} kmp_mutex_impl_t; + +/***************************************************************************** + * definitions generated from spec + *****************************************************************************/ + +typedef enum ompt_callbacks_t { + ompt_callback_thread_begin = 1, + ompt_callback_thread_end = 2, + ompt_callback_parallel_begin = 3, + ompt_callback_parallel_end = 4, + ompt_callback_task_create = 5, + ompt_callback_task_schedule = 6, + ompt_callback_implicit_task = 7, + ompt_callback_target = 8, + ompt_callback_target_data_op = 9, + ompt_callback_target_submit = 10, + ompt_callback_control_tool = 11, + ompt_callback_device_initialize = 12, + ompt_callback_device_finalize = 13, + ompt_callback_device_load = 14, + ompt_callback_device_unload = 15, + ompt_callback_sync_region_wait = 16, + ompt_callback_mutex_released = 17, + ompt_callback_dependences = 18, + ompt_callback_task_dependence = 19, + ompt_callback_work = 20, + ompt_callback_master DEPRECATED_51 = 21, + ompt_callback_masked = 21, + ompt_callback_target_map = 22, + ompt_callback_sync_region = 23, + ompt_callback_lock_init = 24, + ompt_callback_lock_destroy = 25, + ompt_callback_mutex_acquire = 26, + ompt_callback_mutex_acquired = 27, + ompt_callback_nest_lock = 28, + ompt_callback_flush = 29, + ompt_callback_cancel = 30, + ompt_callback_reduction = 31, + ompt_callback_dispatch = 32, + ompt_callback_target_emi = 33, + ompt_callback_target_data_op_emi = 34, + ompt_callback_target_submit_emi = 35, + ompt_callback_target_map_emi = 36, + ompt_callback_error = 37 +} ompt_callbacks_t; + +typedef enum ompt_record_t { + ompt_record_ompt = 1, + ompt_record_native = 2, + ompt_record_invalid = 3 +} ompt_record_t; + +typedef enum ompt_record_native_t { + ompt_record_native_info = 1, + ompt_record_native_event = 2 +} ompt_record_native_t; + +typedef enum ompt_set_result_t { + ompt_set_error = 0, + ompt_set_never = 1, + ompt_set_impossible = 2, + ompt_set_sometimes = 3, + ompt_set_sometimes_paired = 4, + ompt_set_always = 5 +} ompt_set_result_t; + +typedef uint64_t ompt_id_t; + +typedef uint64_t ompt_device_time_t; + +typedef uint64_t ompt_buffer_cursor_t; + +typedef enum ompt_thread_t { + ompt_thread_initial = 1, + ompt_thread_worker = 2, + ompt_thread_other = 3, + ompt_thread_unknown = 4 +} ompt_thread_t; + +typedef enum ompt_scope_endpoint_t { + ompt_scope_begin = 1, + ompt_scope_end = 2, + ompt_scope_beginend = 3 +} ompt_scope_endpoint_t; + +typedef enum ompt_dispatch_t { + ompt_dispatch_iteration = 1, + ompt_dispatch_section = 2 +} ompt_dispatch_t; + +typedef enum ompt_sync_region_t { + ompt_sync_region_barrier DEPRECATED_51 = 1, + ompt_sync_region_barrier_implicit DEPRECATED_51 = 2, + ompt_sync_region_barrier_explicit = 3, + ompt_sync_region_barrier_implementation = 4, + ompt_sync_region_taskwait = 5, + ompt_sync_region_taskgroup = 6, + ompt_sync_region_reduction = 7, + ompt_sync_region_barrier_implicit_workshare = 8, + ompt_sync_region_barrier_implicit_parallel = 9, + ompt_sync_region_barrier_teams = 10 +} ompt_sync_region_t; + +typedef enum ompt_target_data_op_t { + ompt_target_data_alloc = 1, + ompt_target_data_transfer_to_device = 2, + ompt_target_data_transfer_from_device = 3, + ompt_target_data_delete = 4, + ompt_target_data_associate = 5, + ompt_target_data_disassociate = 6, + ompt_target_data_alloc_async = 17, + ompt_target_data_transfer_to_device_async = 18, + ompt_target_data_transfer_from_device_async = 19, + ompt_target_data_delete_async = 20 +} ompt_target_data_op_t; + +typedef enum ompt_work_t { + ompt_work_loop = 1, + ompt_work_sections = 2, + ompt_work_single_executor = 3, + ompt_work_single_other = 4, + ompt_work_workshare = 5, + ompt_work_distribute = 6, + ompt_work_taskloop = 7, + ompt_work_scope = 8 +} ompt_work_t; + +typedef enum ompt_mutex_t { + ompt_mutex_lock = 1, + ompt_mutex_test_lock = 2, + ompt_mutex_nest_lock = 3, + ompt_mutex_test_nest_lock = 4, + ompt_mutex_critical = 5, + ompt_mutex_atomic = 6, + ompt_mutex_ordered = 7 +} ompt_mutex_t; + +typedef enum ompt_native_mon_flag_t { + ompt_native_data_motion_explicit = 0x01, + ompt_native_data_motion_implicit = 0x02, + ompt_native_kernel_invocation = 0x04, + ompt_native_kernel_execution = 0x08, + ompt_native_driver = 0x10, + ompt_native_runtime = 0x20, + ompt_native_overhead = 0x40, + ompt_native_idleness = 0x80 +} ompt_native_mon_flag_t; + +typedef enum ompt_task_flag_t { + ompt_task_initial = 0x00000001, + ompt_task_implicit = 0x00000002, + ompt_task_explicit = 0x00000004, + ompt_task_target = 0x00000008, + ompt_task_taskwait = 0x00000010, + ompt_task_undeferred = 0x08000000, + ompt_task_untied = 0x10000000, + ompt_task_final = 0x20000000, + ompt_task_mergeable = 0x40000000, + ompt_task_merged = 0x80000000 +} ompt_task_flag_t; + +typedef enum ompt_task_status_t { + ompt_task_complete = 1, + ompt_task_yield = 2, + ompt_task_cancel = 3, + ompt_task_detach = 4, + ompt_task_early_fulfill = 5, + ompt_task_late_fulfill = 6, + ompt_task_switch = 7, + ompt_taskwait_complete = 8 +} ompt_task_status_t; + +typedef enum ompt_target_t { + ompt_target = 1, + ompt_target_enter_data = 2, + ompt_target_exit_data = 3, + ompt_target_update = 4, + ompt_target_nowait = 9, + ompt_target_enter_data_nowait = 10, + ompt_target_exit_data_nowait = 11, + ompt_target_update_nowait = 12 +} ompt_target_t; + +typedef enum ompt_parallel_flag_t { + ompt_parallel_invoker_program = 0x00000001, + ompt_parallel_invoker_runtime = 0x00000002, + ompt_parallel_league = 0x40000000, + ompt_parallel_team = 0x80000000 +} ompt_parallel_flag_t; + +typedef enum ompt_target_map_flag_t { + ompt_target_map_flag_to = 0x01, + ompt_target_map_flag_from = 0x02, + ompt_target_map_flag_alloc = 0x04, + ompt_target_map_flag_release = 0x08, + ompt_target_map_flag_delete = 0x10, + ompt_target_map_flag_implicit = 0x20 +} ompt_target_map_flag_t; + +typedef enum ompt_dependence_type_t { + ompt_dependence_type_in = 1, + ompt_dependence_type_out = 2, + ompt_dependence_type_inout = 3, + ompt_dependence_type_mutexinoutset = 4, + ompt_dependence_type_source = 5, + ompt_dependence_type_sink = 6, + ompt_dependence_type_inoutset = 7 +} ompt_dependence_type_t; + +typedef enum ompt_severity_t { + ompt_warning = 1, + ompt_fatal = 2 +} ompt_severity_t; + +typedef enum ompt_cancel_flag_t { + ompt_cancel_parallel = 0x01, + ompt_cancel_sections = 0x02, + ompt_cancel_loop = 0x04, + ompt_cancel_taskgroup = 0x08, + ompt_cancel_activated = 0x10, + ompt_cancel_detected = 0x20, + ompt_cancel_discarded_task = 0x40 +} ompt_cancel_flag_t; + +typedef uint64_t ompt_hwid_t; + +typedef uint64_t ompt_wait_id_t; + +typedef enum ompt_frame_flag_t { + ompt_frame_runtime = 0x00, + ompt_frame_application = 0x01, + ompt_frame_cfa = 0x10, + ompt_frame_framepointer = 0x20, + ompt_frame_stackaddress = 0x30 +} ompt_frame_flag_t; + +typedef enum ompt_state_t { + ompt_state_work_serial = 0x000, + ompt_state_work_parallel = 0x001, + ompt_state_work_reduction = 0x002, + + ompt_state_wait_barrier DEPRECATED_51 = 0x010, + ompt_state_wait_barrier_implicit_parallel = 0x011, + ompt_state_wait_barrier_implicit_workshare = 0x012, + ompt_state_wait_barrier_implicit DEPRECATED_51 = 0x013, + ompt_state_wait_barrier_explicit = 0x014, + ompt_state_wait_barrier_implementation = 0x015, + ompt_state_wait_barrier_teams = 0x016, + + ompt_state_wait_taskwait = 0x020, + ompt_state_wait_taskgroup = 0x021, + + ompt_state_wait_mutex = 0x040, + ompt_state_wait_lock = 0x041, + ompt_state_wait_critical = 0x042, + ompt_state_wait_atomic = 0x043, + ompt_state_wait_ordered = 0x044, + + ompt_state_wait_target = 0x080, + ompt_state_wait_target_map = 0x081, + ompt_state_wait_target_update = 0x082, + + ompt_state_idle = 0x100, + ompt_state_overhead = 0x101, + ompt_state_undefined = 0x102 +} ompt_state_t; + +typedef uint64_t (*ompt_get_unique_id_t) (void); + +typedef uint64_t ompd_size_t; + +typedef uint64_t ompd_wait_id_t; + +typedef uint64_t ompd_addr_t; +typedef int64_t ompd_word_t; +typedef uint64_t ompd_seg_t; + +typedef uint64_t ompd_device_t; + +typedef uint64_t ompd_thread_id_t; + +typedef enum ompd_scope_t { + ompd_scope_global = 1, + ompd_scope_address_space = 2, + ompd_scope_thread = 3, + ompd_scope_parallel = 4, + ompd_scope_implicit_task = 5, + ompd_scope_task = 6 +} ompd_scope_t; + +typedef uint64_t ompd_icv_id_t; + +typedef enum ompd_rc_t { + ompd_rc_ok = 0, + ompd_rc_unavailable = 1, + ompd_rc_stale_handle = 2, + ompd_rc_bad_input = 3, + ompd_rc_error = 4, + ompd_rc_unsupported = 5, + ompd_rc_needs_state_tracking = 6, + ompd_rc_incompatible = 7, + ompd_rc_device_read_error = 8, + ompd_rc_device_write_error = 9, + ompd_rc_nomem = 10, + ompd_rc_incomplete = 11, + ompd_rc_callback_error = 12 +} ompd_rc_t; + +typedef void (*ompt_interface_fn_t) (void); + +typedef ompt_interface_fn_t (*ompt_function_lookup_t) ( + const char *interface_function_name +); + +typedef union ompt_data_t { + uint64_t value; + void *ptr; +} ompt_data_t; + +typedef struct ompt_frame_t { + ompt_data_t exit_frame; + ompt_data_t enter_frame; + int exit_frame_flags; + int enter_frame_flags; +} ompt_frame_t; + +typedef void (*ompt_callback_t) (void); + +typedef void ompt_device_t; + +typedef void ompt_buffer_t; + +typedef void (*ompt_callback_buffer_request_t) ( + int device_num, + ompt_buffer_t **buffer, + size_t *bytes +); + +typedef void (*ompt_callback_buffer_complete_t) ( + int device_num, + ompt_buffer_t *buffer, + size_t bytes, + ompt_buffer_cursor_t begin, + int buffer_owned +); + +typedef void (*ompt_finalize_t) ( + ompt_data_t *tool_data +); + +typedef int (*ompt_initialize_t) ( + ompt_function_lookup_t lookup, + int initial_device_num, + ompt_data_t *tool_data +); + +typedef struct ompt_start_tool_result_t { + ompt_initialize_t initialize; + ompt_finalize_t finalize; + ompt_data_t tool_data; +} ompt_start_tool_result_t; + +typedef struct ompt_record_abstract_t { + ompt_record_native_t rclass; + const char *type; + ompt_device_time_t start_time; + ompt_device_time_t end_time; + ompt_hwid_t hwid; +} ompt_record_abstract_t; + +typedef struct ompt_dependence_t { + ompt_data_t variable; + ompt_dependence_type_t dependence_type; +} ompt_dependence_t; + +typedef int (*ompt_enumerate_states_t) ( + int current_state, + int *next_state, + const char **next_state_name +); + +typedef int (*ompt_enumerate_mutex_impls_t) ( + int current_impl, + int *next_impl, + const char **next_impl_name +); + +typedef ompt_set_result_t (*ompt_set_callback_t) ( + ompt_callbacks_t event, + ompt_callback_t callback +); + +typedef int (*ompt_get_callback_t) ( + ompt_callbacks_t event, + ompt_callback_t *callback +); + +typedef ompt_data_t *(*ompt_get_thread_data_t) (void); + +typedef int (*ompt_get_num_procs_t) (void); + +typedef int (*ompt_get_num_places_t) (void); + +typedef int (*ompt_get_place_proc_ids_t) ( + int place_num, + int ids_size, + int *ids +); + +typedef int (*ompt_get_place_num_t) (void); + +typedef int (*ompt_get_partition_place_nums_t) ( + int place_nums_size, + int *place_nums +); + +typedef int (*ompt_get_proc_id_t) (void); + +typedef int (*ompt_get_state_t) ( + ompt_wait_id_t *wait_id +); + +typedef int (*ompt_get_parallel_info_t) ( + int ancestor_level, + ompt_data_t **parallel_data, + int *team_size +); + +typedef int (*ompt_get_task_info_t) ( + int ancestor_level, + int *flags, + ompt_data_t **task_data, + ompt_frame_t **task_frame, + ompt_data_t **parallel_data, + int *thread_num +); + +typedef int (*ompt_get_task_memory_t)( + void **addr, + size_t *size, + int block +); + +typedef int (*ompt_get_target_info_t) ( + uint64_t *device_num, + ompt_id_t *target_id, + ompt_id_t *host_op_id +); + +typedef int (*ompt_get_num_devices_t) (void); + +typedef void (*ompt_finalize_tool_t) (void); + +typedef int (*ompt_get_device_num_procs_t) ( + ompt_device_t *device +); + +typedef ompt_device_time_t (*ompt_get_device_time_t) ( + ompt_device_t *device +); + +typedef double (*ompt_translate_time_t) ( + ompt_device_t *device, + ompt_device_time_t time +); + +typedef ompt_set_result_t (*ompt_set_trace_ompt_t) ( + ompt_device_t *device, + unsigned int enable, + unsigned int etype +); + +typedef ompt_set_result_t (*ompt_set_trace_native_t) ( + ompt_device_t *device, + int enable, + int flags +); + +typedef int (*ompt_start_trace_t) ( + ompt_device_t *device, + ompt_callback_buffer_request_t request, + ompt_callback_buffer_complete_t complete +); + +typedef int (*ompt_pause_trace_t) ( + ompt_device_t *device, + int begin_pause +); + +typedef int (*ompt_flush_trace_t) ( + ompt_device_t *device +); + +typedef int (*ompt_stop_trace_t) ( + ompt_device_t *device +); + +typedef int (*ompt_advance_buffer_cursor_t) ( + ompt_device_t *device, + ompt_buffer_t *buffer, + size_t size, + ompt_buffer_cursor_t current, + ompt_buffer_cursor_t *next +); + +typedef ompt_record_t (*ompt_get_record_type_t) ( + ompt_buffer_t *buffer, + ompt_buffer_cursor_t current +); + +typedef void *(*ompt_get_record_native_t) ( + ompt_buffer_t *buffer, + ompt_buffer_cursor_t current, + ompt_id_t *host_op_id +); + +typedef ompt_record_abstract_t * +(*ompt_get_record_abstract_t) ( + void *native_record +); + +typedef void (*ompt_callback_thread_begin_t) ( + ompt_thread_t thread_type, + ompt_data_t *thread_data +); + +typedef struct ompt_record_thread_begin_t { + ompt_thread_t thread_type; +} ompt_record_thread_begin_t; + +typedef void (*ompt_callback_thread_end_t) ( + ompt_data_t *thread_data +); + +typedef void (*ompt_callback_parallel_begin_t) ( + ompt_data_t *encountering_task_data, + const ompt_frame_t *encountering_task_frame, + ompt_data_t *parallel_data, + unsigned int requested_parallelism, + int flags, + const void *codeptr_ra +); + +typedef struct ompt_record_parallel_begin_t { + ompt_id_t encountering_task_id; + ompt_id_t parallel_id; + unsigned int requested_parallelism; + int flags; + const void *codeptr_ra; +} ompt_record_parallel_begin_t; + +typedef void (*ompt_callback_parallel_end_t) ( + ompt_data_t *parallel_data, + ompt_data_t *encountering_task_data, + int flags, + const void *codeptr_ra +); + +typedef struct ompt_record_parallel_end_t { + ompt_id_t parallel_id; + ompt_id_t encountering_task_id; + int flags; + const void *codeptr_ra; +} ompt_record_parallel_end_t; + +typedef void (*ompt_callback_work_t) ( + ompt_work_t wstype, + ompt_scope_endpoint_t endpoint, + ompt_data_t *parallel_data, + ompt_data_t *task_data, + uint64_t count, + const void *codeptr_ra +); + +typedef struct ompt_record_work_t { + ompt_work_t wstype; + ompt_scope_endpoint_t endpoint; + ompt_id_t parallel_id; + ompt_id_t task_id; + uint64_t count; + const void *codeptr_ra; +} ompt_record_work_t; + +typedef void (*ompt_callback_dispatch_t) ( + ompt_data_t *parallel_data, + ompt_data_t *task_data, + ompt_dispatch_t kind, + ompt_data_t instance +); + +typedef struct ompt_record_dispatch_t { + ompt_id_t parallel_id; + ompt_id_t task_id; + ompt_dispatch_t kind; + ompt_data_t instance; +} ompt_record_dispatch_t; + +typedef void (*ompt_callback_task_create_t) ( + ompt_data_t *encountering_task_data, + const ompt_frame_t *encountering_task_frame, + ompt_data_t *new_task_data, + int flags, + int has_dependences, + const void *codeptr_ra +); + +typedef struct ompt_record_task_create_t { + ompt_id_t encountering_task_id; + ompt_id_t new_task_id; + int flags; + int has_dependences; + const void *codeptr_ra; +} ompt_record_task_create_t; + +typedef void (*ompt_callback_dependences_t) ( + ompt_data_t *task_data, + const ompt_dependence_t *deps, + int ndeps +); + +typedef struct ompt_record_dependences_t { + ompt_id_t task_id; + ompt_dependence_t dep; + int ndeps; +} ompt_record_dependences_t; + +typedef void (*ompt_callback_task_dependence_t) ( + ompt_data_t *src_task_data, + ompt_data_t *sink_task_data +); + +typedef struct ompt_record_task_dependence_t { + ompt_id_t src_task_id; + ompt_id_t sink_task_id; +} ompt_record_task_dependence_t; + +typedef void (*ompt_callback_task_schedule_t) ( + ompt_data_t *prior_task_data, + ompt_task_status_t prior_task_status, + ompt_data_t *next_task_data +); + +typedef struct ompt_record_task_schedule_t { + ompt_id_t prior_task_id; + ompt_task_status_t prior_task_status; + ompt_id_t next_task_id; +} ompt_record_task_schedule_t; + +typedef void (*ompt_callback_implicit_task_t) ( + ompt_scope_endpoint_t endpoint, + ompt_data_t *parallel_data, + ompt_data_t *task_data, + unsigned int actual_parallelism, + unsigned int index, + int flags +); + +typedef struct ompt_record_implicit_task_t { + ompt_scope_endpoint_t endpoint; + ompt_id_t parallel_id; + ompt_id_t task_id; + unsigned int actual_parallelism; + unsigned int index; + int flags; +} ompt_record_implicit_task_t; + +typedef void (*ompt_callback_masked_t) ( + ompt_scope_endpoint_t endpoint, + ompt_data_t *parallel_data, + ompt_data_t *task_data, + const void *codeptr_ra +); + +typedef ompt_callback_masked_t ompt_callback_master_t DEPRECATED_51; + +typedef struct ompt_record_masked_t { + ompt_scope_endpoint_t endpoint; + ompt_id_t parallel_id; + ompt_id_t task_id; + const void *codeptr_ra; +} ompt_record_masked_t; + +typedef void (*ompt_callback_sync_region_t) ( + ompt_sync_region_t kind, + ompt_scope_endpoint_t endpoint, + ompt_data_t *parallel_data, + ompt_data_t *task_data, + const void *codeptr_ra +); + +typedef struct ompt_record_sync_region_t { + ompt_sync_region_t kind; + ompt_scope_endpoint_t endpoint; + ompt_id_t parallel_id; + ompt_id_t task_id; + const void *codeptr_ra; +} ompt_record_sync_region_t; + +typedef void (*ompt_callback_mutex_acquire_t) ( + ompt_mutex_t kind, + unsigned int hint, + unsigned int impl, + ompt_wait_id_t wait_id, + const void *codeptr_ra +); + +typedef struct ompt_record_mutex_acquire_t { + ompt_mutex_t kind; + unsigned int hint; + unsigned int impl; + ompt_wait_id_t wait_id; + const void *codeptr_ra; +} ompt_record_mutex_acquire_t; + +typedef void (*ompt_callback_mutex_t) ( + ompt_mutex_t kind, + ompt_wait_id_t wait_id, + const void *codeptr_ra +); + +typedef struct ompt_record_mutex_t { + ompt_mutex_t kind; + ompt_wait_id_t wait_id; + const void *codeptr_ra; +} ompt_record_mutex_t; + +typedef void (*ompt_callback_nest_lock_t) ( + ompt_scope_endpoint_t endpoint, + ompt_wait_id_t wait_id, + const void *codeptr_ra +); + +typedef struct ompt_record_nest_lock_t { + ompt_scope_endpoint_t endpoint; + ompt_wait_id_t wait_id; + const void *codeptr_ra; +} ompt_record_nest_lock_t; + +typedef void (*ompt_callback_flush_t) ( + ompt_data_t *thread_data, + const void *codeptr_ra +); + +typedef struct ompt_record_flush_t { + const void *codeptr_ra; +} ompt_record_flush_t; + +typedef void (*ompt_callback_cancel_t) ( + ompt_data_t *task_data, + int flags, + const void *codeptr_ra +); + +typedef struct ompt_record_cancel_t { + ompt_id_t task_id; + int flags; + const void *codeptr_ra; +} ompt_record_cancel_t; + +typedef void (*ompt_callback_device_initialize_t) ( + int device_num, + const char *type, + ompt_device_t *device, + ompt_function_lookup_t lookup, + const char *documentation +); + +typedef void (*ompt_callback_device_finalize_t) ( + int device_num +); + +typedef void (*ompt_callback_device_load_t) ( + int device_num, + const char *filename, + int64_t offset_in_file, + void *vma_in_file, + size_t bytes, + void *host_addr, + void *device_addr, + uint64_t module_id +); + +typedef void (*ompt_callback_device_unload_t) ( + int device_num, + uint64_t module_id +); + +typedef void (*ompt_callback_target_data_op_emi_t) ( + ompt_scope_endpoint_t endpoint, + ompt_data_t *target_task_data, + ompt_data_t *target_data, + ompt_id_t *host_op_id, + ompt_target_data_op_t optype, + void *src_addr, + int src_device_num, + void *dest_addr, + int dest_device_num, + size_t bytes, + const void *codeptr_ra +); + +typedef void (*ompt_callback_target_data_op_t) ( + ompt_id_t target_id, + ompt_id_t host_op_id, + ompt_target_data_op_t optype, + void *src_addr, + int src_device_num, + void *dest_addr, + int dest_device_num, + size_t bytes, + const void *codeptr_ra +); + +typedef struct ompt_record_target_data_op_t { + ompt_id_t host_op_id; + ompt_target_data_op_t optype; + void *src_addr; + int src_device_num; + void *dest_addr; + int dest_device_num; + size_t bytes; + ompt_device_time_t end_time; + const void *codeptr_ra; +} ompt_record_target_data_op_t; + +typedef void (*ompt_callback_target_emi_t) ( + ompt_target_t kind, + ompt_scope_endpoint_t endpoint, + int device_num, + ompt_data_t *task_data, + ompt_data_t *target_task_data, + ompt_data_t *target_data, + const void *codeptr_ra +); + +typedef void (*ompt_callback_target_t) ( + ompt_target_t kind, + ompt_scope_endpoint_t endpoint, + int device_num, + ompt_data_t *task_data, + ompt_id_t target_id, + const void *codeptr_ra +); + +typedef struct ompt_record_target_t { + ompt_target_t kind; + ompt_scope_endpoint_t endpoint; + int device_num; + ompt_id_t task_id; + ompt_id_t target_id; + const void *codeptr_ra; +} ompt_record_target_t; + +typedef void (*ompt_callback_target_map_emi_t) ( + ompt_data_t *target_data, + unsigned int nitems, + void **host_addr, + void **device_addr, + size_t *bytes, + unsigned int *mapping_flags, + const void *codeptr_ra +); + +typedef void (*ompt_callback_target_map_t) ( + ompt_id_t target_id, + unsigned int nitems, + void **host_addr, + void **device_addr, + size_t *bytes, + unsigned int *mapping_flags, + const void *codeptr_ra +); + +typedef struct ompt_record_target_map_t { + ompt_id_t target_id; + unsigned int nitems; + void **host_addr; + void **device_addr; + size_t *bytes; + unsigned int *mapping_flags; + const void *codeptr_ra; +} ompt_record_target_map_t; + +typedef void (*ompt_callback_target_submit_emi_t) ( + ompt_scope_endpoint_t endpoint, + ompt_data_t *target_data, + ompt_id_t *host_op_id, + unsigned int requested_num_teams +); + +typedef void (*ompt_callback_target_submit_t) ( + ompt_id_t target_id, + ompt_id_t host_op_id, + unsigned int requested_num_teams +); + +typedef struct ompt_record_target_kernel_t { + ompt_id_t host_op_id; + unsigned int requested_num_teams; + unsigned int granted_num_teams; + ompt_device_time_t end_time; +} ompt_record_target_kernel_t; + +typedef int (*ompt_callback_control_tool_t) ( + uint64_t command, + uint64_t modifier, + void *arg, + const void *codeptr_ra +); + +typedef struct ompt_record_control_tool_t { + uint64_t command; + uint64_t modifier; + const void *codeptr_ra; +} ompt_record_control_tool_t; + +typedef void (*ompt_callback_error_t) ( + ompt_severity_t severity, + const char *message, size_t length, + const void *codeptr_ra +); + +typedef struct ompt_record_error_t { + ompt_severity_t severity; + const char *message; + size_t length; + const void *codeptr_ra; +} ompt_record_error_t; + +typedef struct ompd_address_t { + ompd_seg_t segment; + ompd_addr_t address; +} ompd_address_t; + +typedef struct ompd_frame_info_t { + ompd_address_t frame_address; + ompd_word_t frame_flag; +} ompd_frame_info_t; + +typedef struct _ompd_aspace_handle ompd_address_space_handle_t; +typedef struct _ompd_thread_handle ompd_thread_handle_t; +typedef struct _ompd_parallel_handle ompd_parallel_handle_t; +typedef struct _ompd_task_handle ompd_task_handle_t; + +typedef struct _ompd_aspace_cont ompd_address_space_context_t; +typedef struct _ompd_thread_cont ompd_thread_context_t; + +typedef struct ompd_device_type_sizes_t { + uint8_t sizeof_char; + uint8_t sizeof_short; + uint8_t sizeof_int; + uint8_t sizeof_long; + uint8_t sizeof_long_long; + uint8_t sizeof_pointer; +} ompd_device_type_sizes_t; + +void ompd_dll_locations_valid(void); + +typedef ompd_rc_t (*ompd_callback_memory_alloc_fn_t)(ompd_size_t nbytes, + void **ptr); + +typedef ompd_rc_t (*ompd_callback_memory_free_fn_t)(void *ptr); + +typedef ompd_rc_t (*ompd_callback_get_thread_context_for_thread_id_fn_t)( + ompd_address_space_context_t *address_space_context, ompd_thread_id_t kind, + ompd_size_t sizeof_thread_id, const void *thread_id, + ompd_thread_context_t **thread_context); + +typedef ompd_rc_t (*ompd_callback_sizeof_fn_t)( + ompd_address_space_context_t *address_space_context, + ompd_device_type_sizes_t *sizes); + +typedef ompd_rc_t (*ompd_callback_symbol_addr_fn_t)( + ompd_address_space_context_t *address_space_context, + ompd_thread_context_t *thread_context, const char *symbol_name, + ompd_address_t *symbol_addr, const char *file_name); + +typedef ompd_rc_t (*ompd_callback_memory_read_fn_t)( + ompd_address_space_context_t *address_space_context, + ompd_thread_context_t *thread_context, const ompd_address_t *addr, + ompd_size_t nbytes, void *buffer); + +typedef ompd_rc_t (*ompd_callback_memory_write_fn_t)( + ompd_address_space_context_t *address_space_context, + ompd_thread_context_t *thread_context, const ompd_address_t *addr, + ompd_size_t nbytes, const void *buffer); + +typedef ompd_rc_t (*ompd_callback_device_host_fn_t)( + ompd_address_space_context_t *address_space_context, const void *input, + ompd_size_t unit_size, ompd_size_t count, void *output); + +typedef ompd_rc_t (*ompd_callback_print_string_fn_t)(const char *string, + int category); + +typedef struct ompd_callbacks_t { + ompd_callback_memory_alloc_fn_t alloc_memory; + ompd_callback_memory_free_fn_t free_memory; + ompd_callback_print_string_fn_t print_string; + ompd_callback_sizeof_fn_t sizeof_type; + ompd_callback_symbol_addr_fn_t symbol_addr_lookup; + ompd_callback_memory_read_fn_t read_memory; + ompd_callback_memory_write_fn_t write_memory; + ompd_callback_memory_read_fn_t read_string; + ompd_callback_device_host_fn_t device_to_host; + ompd_callback_device_host_fn_t host_to_device; + ompd_callback_get_thread_context_for_thread_id_fn_t + get_thread_context_for_thread_id; +} ompd_callbacks_t; + +void ompd_bp_parallel_begin(void); + +void ompd_bp_parallel_end(void); + +void ompd_bp_task_begin(void); + +void ompd_bp_task_end(void); + +void ompd_bp_thread_begin(void); + +void ompd_bp_thread_end(void); + +void ompd_bp_device_begin(void); + +void ompd_bp_device_end(void); + +ompd_rc_t ompd_initialize(ompd_word_t api_version, + const ompd_callbacks_t *callbacks); + +ompd_rc_t ompd_get_api_version(ompd_word_t *version); + +ompd_rc_t ompd_get_version_string(const char **string); + +ompd_rc_t ompd_finalize(void); + +ompd_rc_t ompd_process_initialize(ompd_address_space_context_t *context, + ompd_address_space_handle_t **handle); + +ompd_rc_t ompd_device_initialize(ompd_address_space_handle_t *process_handle, + ompd_address_space_context_t *device_context, + ompd_device_t kind, ompd_size_t sizeof_id, + void *id, + ompd_address_space_handle_t **device_handle); + +ompd_rc_t ompd_rel_address_space_handle(ompd_address_space_handle_t *handle); + +ompd_rc_t ompd_get_omp_version(ompd_address_space_handle_t *address_space, + ompd_word_t *omp_version); + +ompd_rc_t +ompd_get_omp_version_string(ompd_address_space_handle_t *address_space, + const char **string); + +ompd_rc_t ompd_get_thread_in_parallel(ompd_parallel_handle_t *parallel_handle, + int thread_num, + ompd_thread_handle_t **thread_handle); + +ompd_rc_t ompd_get_thread_handle(ompd_address_space_handle_t *handle, + ompd_thread_id_t kind, + ompd_size_t sizeof_thread_id, + const void *thread_id, + ompd_thread_handle_t **thread_handle); + +ompd_rc_t ompd_rel_thread_handle(ompd_thread_handle_t *thread_handle); + +ompd_rc_t ompd_thread_handle_compare(ompd_thread_handle_t *thread_handle_1, + ompd_thread_handle_t *thread_handle_2, + int *cmp_value); + +ompd_rc_t ompd_get_thread_id(ompd_thread_handle_t *thread_handle, + ompd_thread_id_t kind, + ompd_size_t sizeof_thread_id, void *thread_id); + +ompd_rc_t +ompd_get_curr_parallel_handle(ompd_thread_handle_t *thread_handle, + ompd_parallel_handle_t **parallel_handle); + +ompd_rc_t ompd_get_enclosing_parallel_handle( + ompd_parallel_handle_t *parallel_handle, + ompd_parallel_handle_t **enclosing_parallel_handle); + +ompd_rc_t +ompd_get_task_parallel_handle(ompd_task_handle_t *task_handle, + ompd_parallel_handle_t **task_parallel_handle); + +ompd_rc_t ompd_rel_parallel_handle(ompd_parallel_handle_t *parallel_handle); + +ompd_rc_t +ompd_parallel_handle_compare(ompd_parallel_handle_t *parallel_handle_1, + ompd_parallel_handle_t *parallel_handle_2, + int *cmp_value); + +ompd_rc_t ompd_get_curr_task_handle(ompd_thread_handle_t *thread_handle, + ompd_task_handle_t **task_handle); + +ompd_rc_t +ompd_get_generating_task_handle(ompd_task_handle_t *task_handle, + ompd_task_handle_t **generating_task_handle); + +ompd_rc_t +ompd_get_scheduling_task_handle(ompd_task_handle_t *task_handle, + ompd_task_handle_t **scheduling_task_handle); + +ompd_rc_t ompd_get_task_in_parallel(ompd_parallel_handle_t *parallel_handle, + int thread_num, + ompd_task_handle_t **task_handle); + +ompd_rc_t ompd_rel_task_handle(ompd_task_handle_t *task_handle); + +ompd_rc_t ompd_task_handle_compare(ompd_task_handle_t *task_handle_1, + ompd_task_handle_t *task_handle_2, + int *cmp_value); + +ompd_rc_t ompd_get_task_function(ompd_task_handle_t *task_handle, + ompd_address_t *entry_point); + +ompd_rc_t ompd_get_task_frame(ompd_task_handle_t *task_handle, + ompd_frame_info_t *exit_frame, + ompd_frame_info_t *enter_frame); + +ompd_rc_t +ompd_enumerate_states(ompd_address_space_handle_t *address_space_handle, + ompd_word_t current_state, ompd_word_t *next_state, + const char **next_state_name, ompd_word_t *more_enums); + +ompd_rc_t ompd_get_state(ompd_thread_handle_t *thread_handle, + ompd_word_t *state, ompd_wait_id_t *wait_id); + +ompd_rc_t +ompd_get_display_control_vars(ompd_address_space_handle_t *address_space_handle, + const char *const **control_vars); + +ompd_rc_t ompd_rel_display_control_vars(const char *const **control_vars); + +ompd_rc_t ompd_enumerate_icvs(ompd_address_space_handle_t *handle, + ompd_icv_id_t current, ompd_icv_id_t *next_id, + const char **next_icv_name, + ompd_scope_t *next_scope, int *more); + +ompd_rc_t ompd_get_icv_from_scope(void *handle, ompd_scope_t scope, + ompd_icv_id_t icv_id, ompd_word_t *icv_value); + +ompd_rc_t ompd_get_icv_string_from_scope(void *handle, ompd_scope_t scope, + ompd_icv_id_t icv_id, + const char **icv_string); + +ompd_rc_t ompd_get_tool_data(void *handle, ompd_scope_t scope, + ompd_word_t *value, ompd_address_t *ptr); + +typedef struct ompt_record_ompt_t { + ompt_callbacks_t type; + ompt_device_time_t time; + ompt_id_t thread_id; + ompt_id_t target_id; + union { + ompt_record_thread_begin_t thread_begin; + ompt_record_parallel_begin_t parallel_begin; + ompt_record_parallel_end_t parallel_end; + ompt_record_work_t work; + ompt_record_dispatch_t dispatch; + ompt_record_task_create_t task_create; + ompt_record_dependences_t dependences; + ompt_record_task_dependence_t task_dependence; + ompt_record_task_schedule_t task_schedule; + ompt_record_implicit_task_t implicit_task; + ompt_record_masked_t masked; + ompt_record_sync_region_t sync_region; + ompt_record_mutex_acquire_t mutex_acquire; + ompt_record_mutex_t mutex; + ompt_record_nest_lock_t nest_lock; + ompt_record_flush_t flush; + ompt_record_cancel_t cancel; + ompt_record_target_t target; + ompt_record_target_data_op_t target_data_op; + ompt_record_target_map_t target_map; + ompt_record_target_kernel_t target_kernel; + ompt_record_control_tool_t control_tool; + } record; +} ompt_record_ompt_t; + +typedef ompt_record_ompt_t *(*ompt_get_record_ompt_t) ( + ompt_buffer_t *buffer, + ompt_buffer_cursor_t current +); + +#define ompt_id_none 0 +#define ompt_data_none {0} +#define ompt_time_none 0 +#define ompt_hwid_none 0 +#define ompt_addr_none ~0 +#define ompt_mutex_impl_none 0 +#define ompt_wait_id_none 0 + +#define ompd_segment_none 0 + +#endif /* __OMPT__ */ diff --git a/src/Simulation/Native/osx/include/omp.h b/src/Simulation/Native/osx/include/omp.h new file mode 100644 index 00000000000..f2e6345d4ca --- /dev/null +++ b/src/Simulation/Native/osx/include/omp.h @@ -0,0 +1,504 @@ +/* + * include/omp.h.var + */ + + +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + + +#ifndef __OMP_H +# define __OMP_H + +# include +# include + +# define KMP_VERSION_MAJOR 5 +# define KMP_VERSION_MINOR 0 +# define KMP_VERSION_BUILD 20140926 +# define KMP_BUILD_DATE "No_Timestamp" + +# ifdef __cplusplus + extern "C" { +# endif + +# define omp_set_affinity_format ompc_set_affinity_format +# define omp_get_affinity_format ompc_get_affinity_format +# define omp_display_affinity ompc_display_affinity +# define omp_capture_affinity ompc_capture_affinity + +# if defined(_WIN32) +# define __KAI_KMPC_CONVENTION __cdecl +# ifndef __KMP_IMP +# define __KMP_IMP __declspec(dllimport) +# endif +# else +# define __KAI_KMPC_CONVENTION +# ifndef __KMP_IMP +# define __KMP_IMP +# endif +# endif + + /* schedule kind constants */ + typedef enum omp_sched_t { + omp_sched_static = 1, + omp_sched_dynamic = 2, + omp_sched_guided = 3, + omp_sched_auto = 4, + omp_sched_monotonic = 0x80000000 + } omp_sched_t; + + /* set API functions */ + extern void __KAI_KMPC_CONVENTION omp_set_num_threads (int); + extern void __KAI_KMPC_CONVENTION omp_set_dynamic (int); + extern void __KAI_KMPC_CONVENTION omp_set_nested (int); + extern void __KAI_KMPC_CONVENTION omp_set_max_active_levels (int); + extern void __KAI_KMPC_CONVENTION omp_set_schedule (omp_sched_t, int); + + /* query API functions */ + extern int __KAI_KMPC_CONVENTION omp_get_num_threads (void); + extern int __KAI_KMPC_CONVENTION omp_get_dynamic (void); + extern int __KAI_KMPC_CONVENTION omp_get_nested (void); + extern int __KAI_KMPC_CONVENTION omp_get_max_threads (void); + extern int __KAI_KMPC_CONVENTION omp_get_thread_num (void); + extern int __KAI_KMPC_CONVENTION omp_get_num_procs (void); + extern int __KAI_KMPC_CONVENTION omp_in_parallel (void); + extern int __KAI_KMPC_CONVENTION omp_in_final (void); + extern int __KAI_KMPC_CONVENTION omp_get_active_level (void); + extern int __KAI_KMPC_CONVENTION omp_get_level (void); + extern int __KAI_KMPC_CONVENTION omp_get_ancestor_thread_num (int); + extern int __KAI_KMPC_CONVENTION omp_get_team_size (int); + extern int __KAI_KMPC_CONVENTION omp_get_thread_limit (void); + extern int __KAI_KMPC_CONVENTION omp_get_max_active_levels (void); + extern void __KAI_KMPC_CONVENTION omp_get_schedule (omp_sched_t *, int *); + extern int __KAI_KMPC_CONVENTION omp_get_max_task_priority (void); + + /* lock API functions */ + typedef struct omp_lock_t { + void * _lk; + } omp_lock_t; + + extern void __KAI_KMPC_CONVENTION omp_init_lock (omp_lock_t *); + extern void __KAI_KMPC_CONVENTION omp_set_lock (omp_lock_t *); + extern void __KAI_KMPC_CONVENTION omp_unset_lock (omp_lock_t *); + extern void __KAI_KMPC_CONVENTION omp_destroy_lock (omp_lock_t *); + extern int __KAI_KMPC_CONVENTION omp_test_lock (omp_lock_t *); + + /* nested lock API functions */ + typedef struct omp_nest_lock_t { + void * _lk; + } omp_nest_lock_t; + + extern void __KAI_KMPC_CONVENTION omp_init_nest_lock (omp_nest_lock_t *); + extern void __KAI_KMPC_CONVENTION omp_set_nest_lock (omp_nest_lock_t *); + extern void __KAI_KMPC_CONVENTION omp_unset_nest_lock (omp_nest_lock_t *); + extern void __KAI_KMPC_CONVENTION omp_destroy_nest_lock (omp_nest_lock_t *); + extern int __KAI_KMPC_CONVENTION omp_test_nest_lock (omp_nest_lock_t *); + + /* OpenMP 5.0 Synchronization hints*/ + typedef enum omp_sync_hint_t { + omp_sync_hint_none = 0, + omp_lock_hint_none = omp_sync_hint_none, + omp_sync_hint_uncontended = 1, + omp_lock_hint_uncontended = omp_sync_hint_uncontended, + omp_sync_hint_contended = (1<<1), + omp_lock_hint_contended = omp_sync_hint_contended, + omp_sync_hint_nonspeculative = (1<<2), + omp_lock_hint_nonspeculative = omp_sync_hint_nonspeculative, + omp_sync_hint_speculative = (1<<3), + omp_lock_hint_speculative = omp_sync_hint_speculative, + kmp_lock_hint_hle = (1<<16), + kmp_lock_hint_rtm = (1<<17), + kmp_lock_hint_adaptive = (1<<18) + } omp_sync_hint_t; + + /* lock hint type for dynamic user lock */ + typedef omp_sync_hint_t omp_lock_hint_t; + + /* hinted lock initializers */ + extern void __KAI_KMPC_CONVENTION omp_init_lock_with_hint(omp_lock_t *, omp_lock_hint_t); + extern void __KAI_KMPC_CONVENTION omp_init_nest_lock_with_hint(omp_nest_lock_t *, omp_lock_hint_t); + + /* time API functions */ + extern double __KAI_KMPC_CONVENTION omp_get_wtime (void); + extern double __KAI_KMPC_CONVENTION omp_get_wtick (void); + + /* OpenMP 4.0 */ + extern int __KAI_KMPC_CONVENTION omp_get_default_device (void); + extern void __KAI_KMPC_CONVENTION omp_set_default_device (int); + extern int __KAI_KMPC_CONVENTION omp_is_initial_device (void); + extern int __KAI_KMPC_CONVENTION omp_get_num_devices (void); + extern int __KAI_KMPC_CONVENTION omp_get_num_teams (void); + extern int __KAI_KMPC_CONVENTION omp_get_team_num (void); + extern int __KAI_KMPC_CONVENTION omp_get_cancellation (void); + + /* OpenMP 4.5 */ + extern int __KAI_KMPC_CONVENTION omp_get_initial_device (void); + extern void* __KAI_KMPC_CONVENTION omp_target_alloc(size_t, int); + extern void __KAI_KMPC_CONVENTION omp_target_free(void *, int); + extern int __KAI_KMPC_CONVENTION omp_target_is_present(const void *, int); + extern int __KAI_KMPC_CONVENTION omp_target_memcpy(void *, const void *, size_t, size_t, size_t, int, int); + extern int __KAI_KMPC_CONVENTION omp_target_memcpy_rect(void *, const void *, size_t, int, const size_t *, + const size_t *, const size_t *, const size_t *, const size_t *, int, int); + extern int __KAI_KMPC_CONVENTION omp_target_associate_ptr(const void *, const void *, size_t, size_t, int); + extern int __KAI_KMPC_CONVENTION omp_target_disassociate_ptr(const void *, int); + + /* OpenMP 5.0 */ + extern int __KAI_KMPC_CONVENTION omp_get_device_num (void); + typedef void * omp_depend_t; + + /* OpenMP 5.1 interop */ + typedef intptr_t omp_intptr_t; + + /* 0..omp_get_num_interop_properties()-1 are reserved for implementation-defined properties */ + typedef enum omp_interop_property { + omp_ipr_fr_id = -1, + omp_ipr_fr_name = -2, + omp_ipr_vendor = -3, + omp_ipr_vendor_name = -4, + omp_ipr_device_num = -5, + omp_ipr_platform = -6, + omp_ipr_device = -7, + omp_ipr_device_context = -8, + omp_ipr_targetsync = -9, + omp_ipr_first = -9 + } omp_interop_property_t; + + #define omp_interop_none 0 + + typedef enum omp_interop_rc { + omp_irc_no_value = 1, + omp_irc_success = 0, + omp_irc_empty = -1, + omp_irc_out_of_range = -2, + omp_irc_type_int = -3, + omp_irc_type_ptr = -4, + omp_irc_type_str = -5, + omp_irc_other = -6 + } omp_interop_rc_t; + + typedef enum omp_interop_fr { + omp_ifr_cuda = 1, + omp_ifr_cuda_driver = 2, + omp_ifr_opencl = 3, + omp_ifr_sycl = 4, + omp_ifr_hip = 5, + omp_ifr_level_zero = 6, + omp_ifr_last = 7 + } omp_interop_fr_t; + + typedef void * omp_interop_t; + + /*! + * The `omp_get_num_interop_properties` routine retrieves the number of implementation-defined properties available for an `omp_interop_t` object. + */ + extern int __KAI_KMPC_CONVENTION omp_get_num_interop_properties(const omp_interop_t); + /*! + * The `omp_get_interop_int` routine retrieves an integer property from an `omp_interop_t` object. + */ + extern omp_intptr_t __KAI_KMPC_CONVENTION omp_get_interop_int(const omp_interop_t, omp_interop_property_t, int *); + /*! + * The `omp_get_interop_ptr` routine retrieves a pointer property from an `omp_interop_t` object. + */ + extern void * __KAI_KMPC_CONVENTION omp_get_interop_ptr(const omp_interop_t, omp_interop_property_t, int *); + /*! + * The `omp_get_interop_str` routine retrieves a string property from an `omp_interop_t` object. + */ + extern const char * __KAI_KMPC_CONVENTION omp_get_interop_str(const omp_interop_t, omp_interop_property_t, int *); + /*! + * The `omp_get_interop_name` routine retrieves a property name from an `omp_interop_t` object. + */ + extern const char * __KAI_KMPC_CONVENTION omp_get_interop_name(const omp_interop_t, omp_interop_property_t); + /*! + * The `omp_get_interop_type_desc` routine retrieves a description of the type of a property associated with an `omp_interop_t` object. + */ + extern const char * __KAI_KMPC_CONVENTION omp_get_interop_type_desc(const omp_interop_t, omp_interop_property_t); + /*! + * The `omp_get_interop_rc_desc` routine retrieves a description of the return code associated with an `omp_interop_t` object. + */ + extern const char * __KAI_KMPC_CONVENTION omp_get_interop_rc_desc(const omp_interop_t, omp_interop_rc_t); + + /* OpenMP 5.1 device memory routines */ + + /*! + * The `omp_target_memcpy_async` routine asynchronously performs a copy between any combination of host and device pointers. + */ + extern int __KAI_KMPC_CONVENTION omp_target_memcpy_async(void *, const void *, size_t, size_t, size_t, int, + int, int, omp_depend_t *); + /*! + * The `omp_target_memcpy_rect_async` routine asynchronously performs a copy between any combination of host and device pointers. + */ + extern int __KAI_KMPC_CONVENTION omp_target_memcpy_rect_async(void *, const void *, size_t, int, const size_t *, + const size_t *, const size_t *, const size_t *, const size_t *, int, int, + int, omp_depend_t *); + /*! + * The `omp_get_mapped_ptr` routine returns the device pointer that is associated with a host pointer for a given device. + */ + extern void * __KAI_KMPC_CONVENTION omp_get_mapped_ptr(const void *, int); + extern int __KAI_KMPC_CONVENTION omp_target_is_accessible(const void *, size_t, int); + + /* kmp API functions */ + extern int __KAI_KMPC_CONVENTION kmp_get_stacksize (void); + extern void __KAI_KMPC_CONVENTION kmp_set_stacksize (int); + extern size_t __KAI_KMPC_CONVENTION kmp_get_stacksize_s (void); + extern void __KAI_KMPC_CONVENTION kmp_set_stacksize_s (size_t); + extern int __KAI_KMPC_CONVENTION kmp_get_blocktime (void); + extern int __KAI_KMPC_CONVENTION kmp_get_library (void); + extern void __KAI_KMPC_CONVENTION kmp_set_blocktime (int); + extern void __KAI_KMPC_CONVENTION kmp_set_library (int); + extern void __KAI_KMPC_CONVENTION kmp_set_library_serial (void); + extern void __KAI_KMPC_CONVENTION kmp_set_library_turnaround (void); + extern void __KAI_KMPC_CONVENTION kmp_set_library_throughput (void); + extern void __KAI_KMPC_CONVENTION kmp_set_defaults (char const *); + extern void __KAI_KMPC_CONVENTION kmp_set_disp_num_buffers (int); + + /* Intel affinity API */ + typedef void * kmp_affinity_mask_t; + + extern int __KAI_KMPC_CONVENTION kmp_set_affinity (kmp_affinity_mask_t *); + extern int __KAI_KMPC_CONVENTION kmp_get_affinity (kmp_affinity_mask_t *); + extern int __KAI_KMPC_CONVENTION kmp_get_affinity_max_proc (void); + extern void __KAI_KMPC_CONVENTION kmp_create_affinity_mask (kmp_affinity_mask_t *); + extern void __KAI_KMPC_CONVENTION kmp_destroy_affinity_mask (kmp_affinity_mask_t *); + extern int __KAI_KMPC_CONVENTION kmp_set_affinity_mask_proc (int, kmp_affinity_mask_t *); + extern int __KAI_KMPC_CONVENTION kmp_unset_affinity_mask_proc (int, kmp_affinity_mask_t *); + extern int __KAI_KMPC_CONVENTION kmp_get_affinity_mask_proc (int, kmp_affinity_mask_t *); + + /* OpenMP 4.0 affinity API */ + typedef enum omp_proc_bind_t { + omp_proc_bind_false = 0, + omp_proc_bind_true = 1, + omp_proc_bind_master = 2, + omp_proc_bind_close = 3, + omp_proc_bind_spread = 4 + } omp_proc_bind_t; + + extern omp_proc_bind_t __KAI_KMPC_CONVENTION omp_get_proc_bind (void); + + /* OpenMP 4.5 affinity API */ + extern int __KAI_KMPC_CONVENTION omp_get_num_places (void); + extern int __KAI_KMPC_CONVENTION omp_get_place_num_procs (int); + extern void __KAI_KMPC_CONVENTION omp_get_place_proc_ids (int, int *); + extern int __KAI_KMPC_CONVENTION omp_get_place_num (void); + extern int __KAI_KMPC_CONVENTION omp_get_partition_num_places (void); + extern void __KAI_KMPC_CONVENTION omp_get_partition_place_nums (int *); + + extern void * __KAI_KMPC_CONVENTION kmp_malloc (size_t); + extern void * __KAI_KMPC_CONVENTION kmp_aligned_malloc (size_t, size_t); + extern void * __KAI_KMPC_CONVENTION kmp_calloc (size_t, size_t); + extern void * __KAI_KMPC_CONVENTION kmp_realloc (void *, size_t); + extern void __KAI_KMPC_CONVENTION kmp_free (void *); + + extern void __KAI_KMPC_CONVENTION kmp_set_warnings_on(void); + extern void __KAI_KMPC_CONVENTION kmp_set_warnings_off(void); + + /* OpenMP 5.0 Tool Control */ + typedef enum omp_control_tool_result_t { + omp_control_tool_notool = -2, + omp_control_tool_nocallback = -1, + omp_control_tool_success = 0, + omp_control_tool_ignored = 1 + } omp_control_tool_result_t; + + typedef enum omp_control_tool_t { + omp_control_tool_start = 1, + omp_control_tool_pause = 2, + omp_control_tool_flush = 3, + omp_control_tool_end = 4 + } omp_control_tool_t; + + extern int __KAI_KMPC_CONVENTION omp_control_tool(int, int, void*); + + /* OpenMP 5.0 Memory Management */ + typedef uintptr_t omp_uintptr_t; + + typedef enum { + omp_atk_sync_hint = 1, + omp_atk_alignment = 2, + omp_atk_access = 3, + omp_atk_pool_size = 4, + omp_atk_fallback = 5, + omp_atk_fb_data = 6, + omp_atk_pinned = 7, + omp_atk_partition = 8 + } omp_alloctrait_key_t; + + typedef enum { + omp_atv_false = 0, + omp_atv_true = 1, + omp_atv_contended = 3, + omp_atv_uncontended = 4, + omp_atv_serialized = 5, + omp_atv_sequential = omp_atv_serialized, // (deprecated) + omp_atv_private = 6, + omp_atv_all = 7, + omp_atv_thread = 8, + omp_atv_pteam = 9, + omp_atv_cgroup = 10, + omp_atv_default_mem_fb = 11, + omp_atv_null_fb = 12, + omp_atv_abort_fb = 13, + omp_atv_allocator_fb = 14, + omp_atv_environment = 15, + omp_atv_nearest = 16, + omp_atv_blocked = 17, + omp_atv_interleaved = 18 + } omp_alloctrait_value_t; + #define omp_atv_default ((omp_uintptr_t)-1) + + typedef struct { + omp_alloctrait_key_t key; + omp_uintptr_t value; + } omp_alloctrait_t; + +# if defined(_WIN32) + // On Windows cl and icl do not support 64-bit enum, let's use integer then. + typedef omp_uintptr_t omp_allocator_handle_t; + extern __KMP_IMP omp_allocator_handle_t const omp_null_allocator; + extern __KMP_IMP omp_allocator_handle_t const omp_default_mem_alloc; + extern __KMP_IMP omp_allocator_handle_t const omp_large_cap_mem_alloc; + extern __KMP_IMP omp_allocator_handle_t const omp_const_mem_alloc; + extern __KMP_IMP omp_allocator_handle_t const omp_high_bw_mem_alloc; + extern __KMP_IMP omp_allocator_handle_t const omp_low_lat_mem_alloc; + extern __KMP_IMP omp_allocator_handle_t const omp_cgroup_mem_alloc; + extern __KMP_IMP omp_allocator_handle_t const omp_pteam_mem_alloc; + extern __KMP_IMP omp_allocator_handle_t const omp_thread_mem_alloc; + /* Preview of target memory support */ + extern __KMP_IMP omp_allocator_handle_t const llvm_omp_target_host_mem_alloc; + extern __KMP_IMP omp_allocator_handle_t const llvm_omp_target_shared_mem_alloc; + extern __KMP_IMP omp_allocator_handle_t const llvm_omp_target_device_mem_alloc; + + typedef omp_uintptr_t omp_memspace_handle_t; + extern __KMP_IMP omp_memspace_handle_t const omp_default_mem_space; + extern __KMP_IMP omp_memspace_handle_t const omp_large_cap_mem_space; + extern __KMP_IMP omp_memspace_handle_t const omp_const_mem_space; + extern __KMP_IMP omp_memspace_handle_t const omp_high_bw_mem_space; + extern __KMP_IMP omp_memspace_handle_t const omp_low_lat_mem_space; + /* Preview of target memory support */ + extern __KMP_IMP omp_memspace_handle_t const llvm_omp_target_host_mem_space; + extern __KMP_IMP omp_memspace_handle_t const llvm_omp_target_shared_mem_space; + extern __KMP_IMP omp_memspace_handle_t const llvm_omp_target_device_mem_space; +# else +# if __cplusplus >= 201103 + typedef enum omp_allocator_handle_t : omp_uintptr_t +# else + typedef enum omp_allocator_handle_t +# endif + { + omp_null_allocator = 0, + omp_default_mem_alloc = 1, + omp_large_cap_mem_alloc = 2, + omp_const_mem_alloc = 3, + omp_high_bw_mem_alloc = 4, + omp_low_lat_mem_alloc = 5, + omp_cgroup_mem_alloc = 6, + omp_pteam_mem_alloc = 7, + omp_thread_mem_alloc = 8, + /* Preview of target memory support */ + llvm_omp_target_host_mem_alloc = 100, + llvm_omp_target_shared_mem_alloc = 101, + llvm_omp_target_device_mem_alloc = 102, + KMP_ALLOCATOR_MAX_HANDLE = UINTPTR_MAX + } omp_allocator_handle_t; +# if __cplusplus >= 201103 + typedef enum omp_memspace_handle_t : omp_uintptr_t +# else + typedef enum omp_memspace_handle_t +# endif + { + omp_default_mem_space = 0, + omp_large_cap_mem_space = 1, + omp_const_mem_space = 2, + omp_high_bw_mem_space = 3, + omp_low_lat_mem_space = 4, + /* Preview of target memory support */ + llvm_omp_target_host_mem_space = 100, + llvm_omp_target_shared_mem_space = 101, + llvm_omp_target_device_mem_space = 102, + KMP_MEMSPACE_MAX_HANDLE = UINTPTR_MAX + } omp_memspace_handle_t; +# endif + extern omp_allocator_handle_t __KAI_KMPC_CONVENTION omp_init_allocator(omp_memspace_handle_t m, + int ntraits, omp_alloctrait_t traits[]); + extern void __KAI_KMPC_CONVENTION omp_destroy_allocator(omp_allocator_handle_t allocator); + + extern void __KAI_KMPC_CONVENTION omp_set_default_allocator(omp_allocator_handle_t a); + extern omp_allocator_handle_t __KAI_KMPC_CONVENTION omp_get_default_allocator(void); +# ifdef __cplusplus + extern void *__KAI_KMPC_CONVENTION omp_alloc(size_t size, omp_allocator_handle_t a = omp_null_allocator); + extern void *__KAI_KMPC_CONVENTION omp_calloc(size_t nmemb, size_t size, omp_allocator_handle_t a = omp_null_allocator); + extern void *__KAI_KMPC_CONVENTION omp_realloc(void *ptr, size_t size, + omp_allocator_handle_t allocator = omp_null_allocator, + omp_allocator_handle_t free_allocator = omp_null_allocator); + extern void __KAI_KMPC_CONVENTION omp_free(void * ptr, omp_allocator_handle_t a = omp_null_allocator); +# else + extern void *__KAI_KMPC_CONVENTION omp_alloc(size_t size, omp_allocator_handle_t a); + extern void *__KAI_KMPC_CONVENTION omp_calloc(size_t nmemb, size_t size, omp_allocator_handle_t a); + extern void *__KAI_KMPC_CONVENTION omp_realloc(void *ptr, size_t size, omp_allocator_handle_t allocator, + omp_allocator_handle_t free_allocator); + extern void __KAI_KMPC_CONVENTION omp_free(void *ptr, omp_allocator_handle_t a); +# endif + + /* OpenMP 5.0 Affinity Format */ + extern void __KAI_KMPC_CONVENTION omp_set_affinity_format(char const *); + extern size_t __KAI_KMPC_CONVENTION omp_get_affinity_format(char *, size_t); + extern void __KAI_KMPC_CONVENTION omp_display_affinity(char const *); + extern size_t __KAI_KMPC_CONVENTION omp_capture_affinity(char *, size_t, char const *); + + /* OpenMP 5.0 events */ +# if defined(_WIN32) + // On Windows cl and icl do not support 64-bit enum, let's use integer then. + typedef omp_uintptr_t omp_event_handle_t; +# else + typedef enum omp_event_handle_t { KMP_EVENT_MAX_HANDLE = UINTPTR_MAX } omp_event_handle_t; +# endif + extern void __KAI_KMPC_CONVENTION omp_fulfill_event ( omp_event_handle_t event ); + + /* OpenMP 5.0 Pause Resources */ + typedef enum omp_pause_resource_t { + omp_pause_resume = 0, + omp_pause_soft = 1, + omp_pause_hard = 2 + } omp_pause_resource_t; + extern int __KAI_KMPC_CONVENTION omp_pause_resource(omp_pause_resource_t, int); + extern int __KAI_KMPC_CONVENTION omp_pause_resource_all(omp_pause_resource_t); + + extern int __KAI_KMPC_CONVENTION omp_get_supported_active_levels(void); + + /* OpenMP 5.1 */ + extern void __KAI_KMPC_CONVENTION omp_set_num_teams(int num_teams); + extern int __KAI_KMPC_CONVENTION omp_get_max_teams(void); + extern void __KAI_KMPC_CONVENTION omp_set_teams_thread_limit(int limit); + extern int __KAI_KMPC_CONVENTION omp_get_teams_thread_limit(void); + + /* OpenMP 5.1 Display Environment */ + extern void omp_display_env(int verbose); + +# if defined(_OPENMP) && _OPENMP >= 201811 + #pragma omp begin declare variant match(device={kind(host)}) + static inline int omp_is_initial_device(void) { return 1; } + #pragma omp end declare variant + #pragma omp begin declare variant match(device={kind(nohost)}) + static inline int omp_is_initial_device(void) { return 0; } + #pragma omp end declare variant +# endif + +# undef __KAI_KMPC_CONVENTION +# undef __KMP_IMP + + /* Warning: + The following typedefs are not standard, deprecated and will be removed in a future release. + */ + typedef int omp_int_t; + typedef double omp_wtime_t; + +# ifdef __cplusplus + } +# endif + +#endif /* __OMP_H */ diff --git a/src/Simulation/Native/osx/include/ompt.h b/src/Simulation/Native/osx/include/ompt.h new file mode 100644 index 00000000000..5092174d66e --- /dev/null +++ b/src/Simulation/Native/osx/include/ompt.h @@ -0,0 +1,1376 @@ +/* + * include/omp-tools.h.var + */ + +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef __OMPT__ +#define __OMPT__ + +/***************************************************************************** + * system include files + *****************************************************************************/ + +#include +#include + +#ifdef DEPRECATION_WARNINGS +# ifdef __cplusplus +# define DEPRECATED_51 [[deprecated("as of 5.1")]] +# else +# define DEPRECATED_51 __attribute__((deprecated("as of 5.1"))) +#endif +#else +#define DEPRECATED_51 +#endif + +/***************************************************************************** + * iteration macros + *****************************************************************************/ + +#define FOREACH_OMPT_INQUIRY_FN(macro) \ + macro (ompt_enumerate_states) \ + macro (ompt_enumerate_mutex_impls) \ + \ + macro (ompt_set_callback) \ + macro (ompt_get_callback) \ + \ + macro (ompt_get_state) \ + \ + macro (ompt_get_parallel_info) \ + macro (ompt_get_task_info) \ + macro (ompt_get_task_memory) \ + macro (ompt_get_thread_data) \ + macro (ompt_get_unique_id) \ + macro (ompt_finalize_tool) \ + \ + macro(ompt_get_num_procs) \ + macro(ompt_get_num_places) \ + macro(ompt_get_place_proc_ids) \ + macro(ompt_get_place_num) \ + macro(ompt_get_partition_place_nums) \ + macro(ompt_get_proc_id) \ + \ + macro(ompt_get_target_info) \ + macro(ompt_get_num_devices) + +#define FOREACH_OMPT_STATE(macro) \ + \ + /* first available state */ \ + macro (ompt_state_undefined, 0x102) /* undefined thread state */ \ + \ + /* work states (0..15) */ \ + macro (ompt_state_work_serial, 0x000) /* working outside parallel */ \ + macro (ompt_state_work_parallel, 0x001) /* working within parallel */ \ + macro (ompt_state_work_reduction, 0x002) /* performing a reduction */ \ + \ + /* barrier wait states (16..31) */ \ + macro (ompt_state_wait_barrier, 0x010) /* waiting at a barrier */ \ + macro (ompt_state_wait_barrier_implicit_parallel, 0x011) \ + /* implicit barrier at the end of parallel region */\ + macro (ompt_state_wait_barrier_implicit_workshare, 0x012) \ + /* implicit barrier at the end of worksharing */ \ + macro (ompt_state_wait_barrier_implicit, 0x013) /* implicit barrier */ \ + macro (ompt_state_wait_barrier_explicit, 0x014) /* explicit barrier */ \ + \ + /* task wait states (32..63) */ \ + macro (ompt_state_wait_taskwait, 0x020) /* waiting at a taskwait */ \ + macro (ompt_state_wait_taskgroup, 0x021) /* waiting at a taskgroup */ \ + \ + /* mutex wait states (64..127) */ \ + macro (ompt_state_wait_mutex, 0x040) \ + macro (ompt_state_wait_lock, 0x041) /* waiting for lock */ \ + macro (ompt_state_wait_critical, 0x042) /* waiting for critical */ \ + macro (ompt_state_wait_atomic, 0x043) /* waiting for atomic */ \ + macro (ompt_state_wait_ordered, 0x044) /* waiting for ordered */ \ + \ + /* target wait states (128..255) */ \ + macro (ompt_state_wait_target, 0x080) /* waiting for target region */ \ + macro (ompt_state_wait_target_map, 0x081) /* waiting for target data mapping operation */ \ + macro (ompt_state_wait_target_update, 0x082) /* waiting for target update operation */ \ + \ + /* misc (256..511) */ \ + macro (ompt_state_idle, 0x100) /* waiting for work */ \ + macro (ompt_state_overhead, 0x101) /* overhead excluding wait states */ \ + \ + /* implementation-specific states (512..) */ + + +#define FOREACH_KMP_MUTEX_IMPL(macro) \ + macro (kmp_mutex_impl_none, 0) /* unknown implementation */ \ + macro (kmp_mutex_impl_spin, 1) /* based on spin */ \ + macro (kmp_mutex_impl_queuing, 2) /* based on some fair policy */ \ + macro (kmp_mutex_impl_speculative, 3) /* based on HW-supported speculation */ + +#define FOREACH_OMPT_EVENT(macro) \ + \ + /*--- Mandatory Events ---*/ \ + macro (ompt_callback_thread_begin, ompt_callback_thread_begin_t, 1) /* thread begin */ \ + macro (ompt_callback_thread_end, ompt_callback_thread_end_t, 2) /* thread end */ \ + \ + macro (ompt_callback_parallel_begin, ompt_callback_parallel_begin_t, 3) /* parallel begin */ \ + macro (ompt_callback_parallel_end, ompt_callback_parallel_end_t, 4) /* parallel end */ \ + \ + macro (ompt_callback_task_create, ompt_callback_task_create_t, 5) /* task begin */ \ + macro (ompt_callback_task_schedule, ompt_callback_task_schedule_t, 6) /* task schedule */ \ + macro (ompt_callback_implicit_task, ompt_callback_implicit_task_t, 7) /* implicit task */ \ + \ + macro (ompt_callback_target, ompt_callback_target_t, 8) /* target */ \ + macro (ompt_callback_target_data_op, ompt_callback_target_data_op_t, 9) /* target data op */ \ + macro (ompt_callback_target_submit, ompt_callback_target_submit_t, 10) /* target submit */ \ + \ + macro (ompt_callback_control_tool, ompt_callback_control_tool_t, 11) /* control tool */ \ + \ + macro (ompt_callback_device_initialize, ompt_callback_device_initialize_t, 12) /* device initialize */ \ + macro (ompt_callback_device_finalize, ompt_callback_device_finalize_t, 13) /* device finalize */ \ + \ + macro (ompt_callback_device_load, ompt_callback_device_load_t, 14) /* device load */ \ + macro (ompt_callback_device_unload, ompt_callback_device_unload_t, 15) /* device unload */ \ + \ + /* Optional Events */ \ + macro (ompt_callback_sync_region_wait, ompt_callback_sync_region_t, 16) /* sync region wait begin or end */ \ + \ + macro (ompt_callback_mutex_released, ompt_callback_mutex_t, 17) /* mutex released */ \ + \ + macro (ompt_callback_dependences, ompt_callback_dependences_t, 18) /* report task dependences */ \ + macro (ompt_callback_task_dependence, ompt_callback_task_dependence_t, 19) /* report task dependence */ \ + \ + macro (ompt_callback_work, ompt_callback_work_t, 20) /* task at work begin or end */ \ + \ + macro (ompt_callback_masked, ompt_callback_masked_t, 21) /* task at masked begin or end */ \ + \ + macro (ompt_callback_target_map, ompt_callback_target_map_t, 22) /* target map */ \ + \ + macro (ompt_callback_sync_region, ompt_callback_sync_region_t, 23) /* sync region begin or end */ \ + \ + macro (ompt_callback_lock_init, ompt_callback_mutex_acquire_t, 24) /* lock init */ \ + macro (ompt_callback_lock_destroy, ompt_callback_mutex_t, 25) /* lock destroy */ \ + \ + macro (ompt_callback_mutex_acquire, ompt_callback_mutex_acquire_t, 26) /* mutex acquire */ \ + macro (ompt_callback_mutex_acquired, ompt_callback_mutex_t, 27) /* mutex acquired */ \ + \ + macro (ompt_callback_nest_lock, ompt_callback_nest_lock_t, 28) /* nest lock */ \ + \ + macro (ompt_callback_flush, ompt_callback_flush_t, 29) /* after executing flush */ \ + \ + macro (ompt_callback_cancel, ompt_callback_cancel_t, 30) /* cancel innermost binding region */ \ + \ + macro (ompt_callback_reduction, ompt_callback_sync_region_t, 31) /* reduction */ \ + \ + macro (ompt_callback_dispatch, ompt_callback_dispatch_t, 32) /* dispatch of work */ \ + macro (ompt_callback_target_emi, ompt_callback_target_emi_t, 33) /* target */ \ + macro (ompt_callback_target_data_op_emi,ompt_callback_target_data_op_emi_t,34) /* target data op */ \ + macro (ompt_callback_target_submit_emi, ompt_callback_target_submit_emi_t, 35) /* target submit */ \ + macro (ompt_callback_target_map_emi, ompt_callback_target_map_emi_t, 36) /* target map */ \ + macro (ompt_callback_error, ompt_callback_error_t, 37) /* error */ + +/***************************************************************************** + * implementation specific types + *****************************************************************************/ + +typedef enum kmp_mutex_impl_t { +#define kmp_mutex_impl_macro(impl, code) impl = code, + FOREACH_KMP_MUTEX_IMPL(kmp_mutex_impl_macro) +#undef kmp_mutex_impl_macro +} kmp_mutex_impl_t; + +/***************************************************************************** + * definitions generated from spec + *****************************************************************************/ + +typedef enum ompt_callbacks_t { + ompt_callback_thread_begin = 1, + ompt_callback_thread_end = 2, + ompt_callback_parallel_begin = 3, + ompt_callback_parallel_end = 4, + ompt_callback_task_create = 5, + ompt_callback_task_schedule = 6, + ompt_callback_implicit_task = 7, + ompt_callback_target = 8, + ompt_callback_target_data_op = 9, + ompt_callback_target_submit = 10, + ompt_callback_control_tool = 11, + ompt_callback_device_initialize = 12, + ompt_callback_device_finalize = 13, + ompt_callback_device_load = 14, + ompt_callback_device_unload = 15, + ompt_callback_sync_region_wait = 16, + ompt_callback_mutex_released = 17, + ompt_callback_dependences = 18, + ompt_callback_task_dependence = 19, + ompt_callback_work = 20, + ompt_callback_master DEPRECATED_51 = 21, + ompt_callback_masked = 21, + ompt_callback_target_map = 22, + ompt_callback_sync_region = 23, + ompt_callback_lock_init = 24, + ompt_callback_lock_destroy = 25, + ompt_callback_mutex_acquire = 26, + ompt_callback_mutex_acquired = 27, + ompt_callback_nest_lock = 28, + ompt_callback_flush = 29, + ompt_callback_cancel = 30, + ompt_callback_reduction = 31, + ompt_callback_dispatch = 32, + ompt_callback_target_emi = 33, + ompt_callback_target_data_op_emi = 34, + ompt_callback_target_submit_emi = 35, + ompt_callback_target_map_emi = 36, + ompt_callback_error = 37 +} ompt_callbacks_t; + +typedef enum ompt_record_t { + ompt_record_ompt = 1, + ompt_record_native = 2, + ompt_record_invalid = 3 +} ompt_record_t; + +typedef enum ompt_record_native_t { + ompt_record_native_info = 1, + ompt_record_native_event = 2 +} ompt_record_native_t; + +typedef enum ompt_set_result_t { + ompt_set_error = 0, + ompt_set_never = 1, + ompt_set_impossible = 2, + ompt_set_sometimes = 3, + ompt_set_sometimes_paired = 4, + ompt_set_always = 5 +} ompt_set_result_t; + +typedef uint64_t ompt_id_t; + +typedef uint64_t ompt_device_time_t; + +typedef uint64_t ompt_buffer_cursor_t; + +typedef enum ompt_thread_t { + ompt_thread_initial = 1, + ompt_thread_worker = 2, + ompt_thread_other = 3, + ompt_thread_unknown = 4 +} ompt_thread_t; + +typedef enum ompt_scope_endpoint_t { + ompt_scope_begin = 1, + ompt_scope_end = 2, + ompt_scope_beginend = 3 +} ompt_scope_endpoint_t; + +typedef enum ompt_dispatch_t { + ompt_dispatch_iteration = 1, + ompt_dispatch_section = 2 +} ompt_dispatch_t; + +typedef enum ompt_sync_region_t { + ompt_sync_region_barrier DEPRECATED_51 = 1, + ompt_sync_region_barrier_implicit DEPRECATED_51 = 2, + ompt_sync_region_barrier_explicit = 3, + ompt_sync_region_barrier_implementation = 4, + ompt_sync_region_taskwait = 5, + ompt_sync_region_taskgroup = 6, + ompt_sync_region_reduction = 7, + ompt_sync_region_barrier_implicit_workshare = 8, + ompt_sync_region_barrier_implicit_parallel = 9, + ompt_sync_region_barrier_teams = 10 +} ompt_sync_region_t; + +typedef enum ompt_target_data_op_t { + ompt_target_data_alloc = 1, + ompt_target_data_transfer_to_device = 2, + ompt_target_data_transfer_from_device = 3, + ompt_target_data_delete = 4, + ompt_target_data_associate = 5, + ompt_target_data_disassociate = 6, + ompt_target_data_alloc_async = 17, + ompt_target_data_transfer_to_device_async = 18, + ompt_target_data_transfer_from_device_async = 19, + ompt_target_data_delete_async = 20 +} ompt_target_data_op_t; + +typedef enum ompt_work_t { + ompt_work_loop = 1, + ompt_work_sections = 2, + ompt_work_single_executor = 3, + ompt_work_single_other = 4, + ompt_work_workshare = 5, + ompt_work_distribute = 6, + ompt_work_taskloop = 7, + ompt_work_scope = 8 +} ompt_work_t; + +typedef enum ompt_mutex_t { + ompt_mutex_lock = 1, + ompt_mutex_test_lock = 2, + ompt_mutex_nest_lock = 3, + ompt_mutex_test_nest_lock = 4, + ompt_mutex_critical = 5, + ompt_mutex_atomic = 6, + ompt_mutex_ordered = 7 +} ompt_mutex_t; + +typedef enum ompt_native_mon_flag_t { + ompt_native_data_motion_explicit = 0x01, + ompt_native_data_motion_implicit = 0x02, + ompt_native_kernel_invocation = 0x04, + ompt_native_kernel_execution = 0x08, + ompt_native_driver = 0x10, + ompt_native_runtime = 0x20, + ompt_native_overhead = 0x40, + ompt_native_idleness = 0x80 +} ompt_native_mon_flag_t; + +typedef enum ompt_task_flag_t { + ompt_task_initial = 0x00000001, + ompt_task_implicit = 0x00000002, + ompt_task_explicit = 0x00000004, + ompt_task_target = 0x00000008, + ompt_task_taskwait = 0x00000010, + ompt_task_undeferred = 0x08000000, + ompt_task_untied = 0x10000000, + ompt_task_final = 0x20000000, + ompt_task_mergeable = 0x40000000, + ompt_task_merged = 0x80000000 +} ompt_task_flag_t; + +typedef enum ompt_task_status_t { + ompt_task_complete = 1, + ompt_task_yield = 2, + ompt_task_cancel = 3, + ompt_task_detach = 4, + ompt_task_early_fulfill = 5, + ompt_task_late_fulfill = 6, + ompt_task_switch = 7, + ompt_taskwait_complete = 8 +} ompt_task_status_t; + +typedef enum ompt_target_t { + ompt_target = 1, + ompt_target_enter_data = 2, + ompt_target_exit_data = 3, + ompt_target_update = 4, + ompt_target_nowait = 9, + ompt_target_enter_data_nowait = 10, + ompt_target_exit_data_nowait = 11, + ompt_target_update_nowait = 12 +} ompt_target_t; + +typedef enum ompt_parallel_flag_t { + ompt_parallel_invoker_program = 0x00000001, + ompt_parallel_invoker_runtime = 0x00000002, + ompt_parallel_league = 0x40000000, + ompt_parallel_team = 0x80000000 +} ompt_parallel_flag_t; + +typedef enum ompt_target_map_flag_t { + ompt_target_map_flag_to = 0x01, + ompt_target_map_flag_from = 0x02, + ompt_target_map_flag_alloc = 0x04, + ompt_target_map_flag_release = 0x08, + ompt_target_map_flag_delete = 0x10, + ompt_target_map_flag_implicit = 0x20 +} ompt_target_map_flag_t; + +typedef enum ompt_dependence_type_t { + ompt_dependence_type_in = 1, + ompt_dependence_type_out = 2, + ompt_dependence_type_inout = 3, + ompt_dependence_type_mutexinoutset = 4, + ompt_dependence_type_source = 5, + ompt_dependence_type_sink = 6, + ompt_dependence_type_inoutset = 7 +} ompt_dependence_type_t; + +typedef enum ompt_severity_t { + ompt_warning = 1, + ompt_fatal = 2 +} ompt_severity_t; + +typedef enum ompt_cancel_flag_t { + ompt_cancel_parallel = 0x01, + ompt_cancel_sections = 0x02, + ompt_cancel_loop = 0x04, + ompt_cancel_taskgroup = 0x08, + ompt_cancel_activated = 0x10, + ompt_cancel_detected = 0x20, + ompt_cancel_discarded_task = 0x40 +} ompt_cancel_flag_t; + +typedef uint64_t ompt_hwid_t; + +typedef uint64_t ompt_wait_id_t; + +typedef enum ompt_frame_flag_t { + ompt_frame_runtime = 0x00, + ompt_frame_application = 0x01, + ompt_frame_cfa = 0x10, + ompt_frame_framepointer = 0x20, + ompt_frame_stackaddress = 0x30 +} ompt_frame_flag_t; + +typedef enum ompt_state_t { + ompt_state_work_serial = 0x000, + ompt_state_work_parallel = 0x001, + ompt_state_work_reduction = 0x002, + + ompt_state_wait_barrier DEPRECATED_51 = 0x010, + ompt_state_wait_barrier_implicit_parallel = 0x011, + ompt_state_wait_barrier_implicit_workshare = 0x012, + ompt_state_wait_barrier_implicit DEPRECATED_51 = 0x013, + ompt_state_wait_barrier_explicit = 0x014, + ompt_state_wait_barrier_implementation = 0x015, + ompt_state_wait_barrier_teams = 0x016, + + ompt_state_wait_taskwait = 0x020, + ompt_state_wait_taskgroup = 0x021, + + ompt_state_wait_mutex = 0x040, + ompt_state_wait_lock = 0x041, + ompt_state_wait_critical = 0x042, + ompt_state_wait_atomic = 0x043, + ompt_state_wait_ordered = 0x044, + + ompt_state_wait_target = 0x080, + ompt_state_wait_target_map = 0x081, + ompt_state_wait_target_update = 0x082, + + ompt_state_idle = 0x100, + ompt_state_overhead = 0x101, + ompt_state_undefined = 0x102 +} ompt_state_t; + +typedef uint64_t (*ompt_get_unique_id_t) (void); + +typedef uint64_t ompd_size_t; + +typedef uint64_t ompd_wait_id_t; + +typedef uint64_t ompd_addr_t; +typedef int64_t ompd_word_t; +typedef uint64_t ompd_seg_t; + +typedef uint64_t ompd_device_t; + +typedef uint64_t ompd_thread_id_t; + +typedef enum ompd_scope_t { + ompd_scope_global = 1, + ompd_scope_address_space = 2, + ompd_scope_thread = 3, + ompd_scope_parallel = 4, + ompd_scope_implicit_task = 5, + ompd_scope_task = 6 +} ompd_scope_t; + +typedef uint64_t ompd_icv_id_t; + +typedef enum ompd_rc_t { + ompd_rc_ok = 0, + ompd_rc_unavailable = 1, + ompd_rc_stale_handle = 2, + ompd_rc_bad_input = 3, + ompd_rc_error = 4, + ompd_rc_unsupported = 5, + ompd_rc_needs_state_tracking = 6, + ompd_rc_incompatible = 7, + ompd_rc_device_read_error = 8, + ompd_rc_device_write_error = 9, + ompd_rc_nomem = 10, + ompd_rc_incomplete = 11, + ompd_rc_callback_error = 12 +} ompd_rc_t; + +typedef void (*ompt_interface_fn_t) (void); + +typedef ompt_interface_fn_t (*ompt_function_lookup_t) ( + const char *interface_function_name +); + +typedef union ompt_data_t { + uint64_t value; + void *ptr; +} ompt_data_t; + +typedef struct ompt_frame_t { + ompt_data_t exit_frame; + ompt_data_t enter_frame; + int exit_frame_flags; + int enter_frame_flags; +} ompt_frame_t; + +typedef void (*ompt_callback_t) (void); + +typedef void ompt_device_t; + +typedef void ompt_buffer_t; + +typedef void (*ompt_callback_buffer_request_t) ( + int device_num, + ompt_buffer_t **buffer, + size_t *bytes +); + +typedef void (*ompt_callback_buffer_complete_t) ( + int device_num, + ompt_buffer_t *buffer, + size_t bytes, + ompt_buffer_cursor_t begin, + int buffer_owned +); + +typedef void (*ompt_finalize_t) ( + ompt_data_t *tool_data +); + +typedef int (*ompt_initialize_t) ( + ompt_function_lookup_t lookup, + int initial_device_num, + ompt_data_t *tool_data +); + +typedef struct ompt_start_tool_result_t { + ompt_initialize_t initialize; + ompt_finalize_t finalize; + ompt_data_t tool_data; +} ompt_start_tool_result_t; + +typedef struct ompt_record_abstract_t { + ompt_record_native_t rclass; + const char *type; + ompt_device_time_t start_time; + ompt_device_time_t end_time; + ompt_hwid_t hwid; +} ompt_record_abstract_t; + +typedef struct ompt_dependence_t { + ompt_data_t variable; + ompt_dependence_type_t dependence_type; +} ompt_dependence_t; + +typedef int (*ompt_enumerate_states_t) ( + int current_state, + int *next_state, + const char **next_state_name +); + +typedef int (*ompt_enumerate_mutex_impls_t) ( + int current_impl, + int *next_impl, + const char **next_impl_name +); + +typedef ompt_set_result_t (*ompt_set_callback_t) ( + ompt_callbacks_t event, + ompt_callback_t callback +); + +typedef int (*ompt_get_callback_t) ( + ompt_callbacks_t event, + ompt_callback_t *callback +); + +typedef ompt_data_t *(*ompt_get_thread_data_t) (void); + +typedef int (*ompt_get_num_procs_t) (void); + +typedef int (*ompt_get_num_places_t) (void); + +typedef int (*ompt_get_place_proc_ids_t) ( + int place_num, + int ids_size, + int *ids +); + +typedef int (*ompt_get_place_num_t) (void); + +typedef int (*ompt_get_partition_place_nums_t) ( + int place_nums_size, + int *place_nums +); + +typedef int (*ompt_get_proc_id_t) (void); + +typedef int (*ompt_get_state_t) ( + ompt_wait_id_t *wait_id +); + +typedef int (*ompt_get_parallel_info_t) ( + int ancestor_level, + ompt_data_t **parallel_data, + int *team_size +); + +typedef int (*ompt_get_task_info_t) ( + int ancestor_level, + int *flags, + ompt_data_t **task_data, + ompt_frame_t **task_frame, + ompt_data_t **parallel_data, + int *thread_num +); + +typedef int (*ompt_get_task_memory_t)( + void **addr, + size_t *size, + int block +); + +typedef int (*ompt_get_target_info_t) ( + uint64_t *device_num, + ompt_id_t *target_id, + ompt_id_t *host_op_id +); + +typedef int (*ompt_get_num_devices_t) (void); + +typedef void (*ompt_finalize_tool_t) (void); + +typedef int (*ompt_get_device_num_procs_t) ( + ompt_device_t *device +); + +typedef ompt_device_time_t (*ompt_get_device_time_t) ( + ompt_device_t *device +); + +typedef double (*ompt_translate_time_t) ( + ompt_device_t *device, + ompt_device_time_t time +); + +typedef ompt_set_result_t (*ompt_set_trace_ompt_t) ( + ompt_device_t *device, + unsigned int enable, + unsigned int etype +); + +typedef ompt_set_result_t (*ompt_set_trace_native_t) ( + ompt_device_t *device, + int enable, + int flags +); + +typedef int (*ompt_start_trace_t) ( + ompt_device_t *device, + ompt_callback_buffer_request_t request, + ompt_callback_buffer_complete_t complete +); + +typedef int (*ompt_pause_trace_t) ( + ompt_device_t *device, + int begin_pause +); + +typedef int (*ompt_flush_trace_t) ( + ompt_device_t *device +); + +typedef int (*ompt_stop_trace_t) ( + ompt_device_t *device +); + +typedef int (*ompt_advance_buffer_cursor_t) ( + ompt_device_t *device, + ompt_buffer_t *buffer, + size_t size, + ompt_buffer_cursor_t current, + ompt_buffer_cursor_t *next +); + +typedef ompt_record_t (*ompt_get_record_type_t) ( + ompt_buffer_t *buffer, + ompt_buffer_cursor_t current +); + +typedef void *(*ompt_get_record_native_t) ( + ompt_buffer_t *buffer, + ompt_buffer_cursor_t current, + ompt_id_t *host_op_id +); + +typedef ompt_record_abstract_t * +(*ompt_get_record_abstract_t) ( + void *native_record +); + +typedef void (*ompt_callback_thread_begin_t) ( + ompt_thread_t thread_type, + ompt_data_t *thread_data +); + +typedef struct ompt_record_thread_begin_t { + ompt_thread_t thread_type; +} ompt_record_thread_begin_t; + +typedef void (*ompt_callback_thread_end_t) ( + ompt_data_t *thread_data +); + +typedef void (*ompt_callback_parallel_begin_t) ( + ompt_data_t *encountering_task_data, + const ompt_frame_t *encountering_task_frame, + ompt_data_t *parallel_data, + unsigned int requested_parallelism, + int flags, + const void *codeptr_ra +); + +typedef struct ompt_record_parallel_begin_t { + ompt_id_t encountering_task_id; + ompt_id_t parallel_id; + unsigned int requested_parallelism; + int flags; + const void *codeptr_ra; +} ompt_record_parallel_begin_t; + +typedef void (*ompt_callback_parallel_end_t) ( + ompt_data_t *parallel_data, + ompt_data_t *encountering_task_data, + int flags, + const void *codeptr_ra +); + +typedef struct ompt_record_parallel_end_t { + ompt_id_t parallel_id; + ompt_id_t encountering_task_id; + int flags; + const void *codeptr_ra; +} ompt_record_parallel_end_t; + +typedef void (*ompt_callback_work_t) ( + ompt_work_t wstype, + ompt_scope_endpoint_t endpoint, + ompt_data_t *parallel_data, + ompt_data_t *task_data, + uint64_t count, + const void *codeptr_ra +); + +typedef struct ompt_record_work_t { + ompt_work_t wstype; + ompt_scope_endpoint_t endpoint; + ompt_id_t parallel_id; + ompt_id_t task_id; + uint64_t count; + const void *codeptr_ra; +} ompt_record_work_t; + +typedef void (*ompt_callback_dispatch_t) ( + ompt_data_t *parallel_data, + ompt_data_t *task_data, + ompt_dispatch_t kind, + ompt_data_t instance +); + +typedef struct ompt_record_dispatch_t { + ompt_id_t parallel_id; + ompt_id_t task_id; + ompt_dispatch_t kind; + ompt_data_t instance; +} ompt_record_dispatch_t; + +typedef void (*ompt_callback_task_create_t) ( + ompt_data_t *encountering_task_data, + const ompt_frame_t *encountering_task_frame, + ompt_data_t *new_task_data, + int flags, + int has_dependences, + const void *codeptr_ra +); + +typedef struct ompt_record_task_create_t { + ompt_id_t encountering_task_id; + ompt_id_t new_task_id; + int flags; + int has_dependences; + const void *codeptr_ra; +} ompt_record_task_create_t; + +typedef void (*ompt_callback_dependences_t) ( + ompt_data_t *task_data, + const ompt_dependence_t *deps, + int ndeps +); + +typedef struct ompt_record_dependences_t { + ompt_id_t task_id; + ompt_dependence_t dep; + int ndeps; +} ompt_record_dependences_t; + +typedef void (*ompt_callback_task_dependence_t) ( + ompt_data_t *src_task_data, + ompt_data_t *sink_task_data +); + +typedef struct ompt_record_task_dependence_t { + ompt_id_t src_task_id; + ompt_id_t sink_task_id; +} ompt_record_task_dependence_t; + +typedef void (*ompt_callback_task_schedule_t) ( + ompt_data_t *prior_task_data, + ompt_task_status_t prior_task_status, + ompt_data_t *next_task_data +); + +typedef struct ompt_record_task_schedule_t { + ompt_id_t prior_task_id; + ompt_task_status_t prior_task_status; + ompt_id_t next_task_id; +} ompt_record_task_schedule_t; + +typedef void (*ompt_callback_implicit_task_t) ( + ompt_scope_endpoint_t endpoint, + ompt_data_t *parallel_data, + ompt_data_t *task_data, + unsigned int actual_parallelism, + unsigned int index, + int flags +); + +typedef struct ompt_record_implicit_task_t { + ompt_scope_endpoint_t endpoint; + ompt_id_t parallel_id; + ompt_id_t task_id; + unsigned int actual_parallelism; + unsigned int index; + int flags; +} ompt_record_implicit_task_t; + +typedef void (*ompt_callback_masked_t) ( + ompt_scope_endpoint_t endpoint, + ompt_data_t *parallel_data, + ompt_data_t *task_data, + const void *codeptr_ra +); + +typedef ompt_callback_masked_t ompt_callback_master_t DEPRECATED_51; + +typedef struct ompt_record_masked_t { + ompt_scope_endpoint_t endpoint; + ompt_id_t parallel_id; + ompt_id_t task_id; + const void *codeptr_ra; +} ompt_record_masked_t; + +typedef void (*ompt_callback_sync_region_t) ( + ompt_sync_region_t kind, + ompt_scope_endpoint_t endpoint, + ompt_data_t *parallel_data, + ompt_data_t *task_data, + const void *codeptr_ra +); + +typedef struct ompt_record_sync_region_t { + ompt_sync_region_t kind; + ompt_scope_endpoint_t endpoint; + ompt_id_t parallel_id; + ompt_id_t task_id; + const void *codeptr_ra; +} ompt_record_sync_region_t; + +typedef void (*ompt_callback_mutex_acquire_t) ( + ompt_mutex_t kind, + unsigned int hint, + unsigned int impl, + ompt_wait_id_t wait_id, + const void *codeptr_ra +); + +typedef struct ompt_record_mutex_acquire_t { + ompt_mutex_t kind; + unsigned int hint; + unsigned int impl; + ompt_wait_id_t wait_id; + const void *codeptr_ra; +} ompt_record_mutex_acquire_t; + +typedef void (*ompt_callback_mutex_t) ( + ompt_mutex_t kind, + ompt_wait_id_t wait_id, + const void *codeptr_ra +); + +typedef struct ompt_record_mutex_t { + ompt_mutex_t kind; + ompt_wait_id_t wait_id; + const void *codeptr_ra; +} ompt_record_mutex_t; + +typedef void (*ompt_callback_nest_lock_t) ( + ompt_scope_endpoint_t endpoint, + ompt_wait_id_t wait_id, + const void *codeptr_ra +); + +typedef struct ompt_record_nest_lock_t { + ompt_scope_endpoint_t endpoint; + ompt_wait_id_t wait_id; + const void *codeptr_ra; +} ompt_record_nest_lock_t; + +typedef void (*ompt_callback_flush_t) ( + ompt_data_t *thread_data, + const void *codeptr_ra +); + +typedef struct ompt_record_flush_t { + const void *codeptr_ra; +} ompt_record_flush_t; + +typedef void (*ompt_callback_cancel_t) ( + ompt_data_t *task_data, + int flags, + const void *codeptr_ra +); + +typedef struct ompt_record_cancel_t { + ompt_id_t task_id; + int flags; + const void *codeptr_ra; +} ompt_record_cancel_t; + +typedef void (*ompt_callback_device_initialize_t) ( + int device_num, + const char *type, + ompt_device_t *device, + ompt_function_lookup_t lookup, + const char *documentation +); + +typedef void (*ompt_callback_device_finalize_t) ( + int device_num +); + +typedef void (*ompt_callback_device_load_t) ( + int device_num, + const char *filename, + int64_t offset_in_file, + void *vma_in_file, + size_t bytes, + void *host_addr, + void *device_addr, + uint64_t module_id +); + +typedef void (*ompt_callback_device_unload_t) ( + int device_num, + uint64_t module_id +); + +typedef void (*ompt_callback_target_data_op_emi_t) ( + ompt_scope_endpoint_t endpoint, + ompt_data_t *target_task_data, + ompt_data_t *target_data, + ompt_id_t *host_op_id, + ompt_target_data_op_t optype, + void *src_addr, + int src_device_num, + void *dest_addr, + int dest_device_num, + size_t bytes, + const void *codeptr_ra +); + +typedef void (*ompt_callback_target_data_op_t) ( + ompt_id_t target_id, + ompt_id_t host_op_id, + ompt_target_data_op_t optype, + void *src_addr, + int src_device_num, + void *dest_addr, + int dest_device_num, + size_t bytes, + const void *codeptr_ra +); + +typedef struct ompt_record_target_data_op_t { + ompt_id_t host_op_id; + ompt_target_data_op_t optype; + void *src_addr; + int src_device_num; + void *dest_addr; + int dest_device_num; + size_t bytes; + ompt_device_time_t end_time; + const void *codeptr_ra; +} ompt_record_target_data_op_t; + +typedef void (*ompt_callback_target_emi_t) ( + ompt_target_t kind, + ompt_scope_endpoint_t endpoint, + int device_num, + ompt_data_t *task_data, + ompt_data_t *target_task_data, + ompt_data_t *target_data, + const void *codeptr_ra +); + +typedef void (*ompt_callback_target_t) ( + ompt_target_t kind, + ompt_scope_endpoint_t endpoint, + int device_num, + ompt_data_t *task_data, + ompt_id_t target_id, + const void *codeptr_ra +); + +typedef struct ompt_record_target_t { + ompt_target_t kind; + ompt_scope_endpoint_t endpoint; + int device_num; + ompt_id_t task_id; + ompt_id_t target_id; + const void *codeptr_ra; +} ompt_record_target_t; + +typedef void (*ompt_callback_target_map_emi_t) ( + ompt_data_t *target_data, + unsigned int nitems, + void **host_addr, + void **device_addr, + size_t *bytes, + unsigned int *mapping_flags, + const void *codeptr_ra +); + +typedef void (*ompt_callback_target_map_t) ( + ompt_id_t target_id, + unsigned int nitems, + void **host_addr, + void **device_addr, + size_t *bytes, + unsigned int *mapping_flags, + const void *codeptr_ra +); + +typedef struct ompt_record_target_map_t { + ompt_id_t target_id; + unsigned int nitems; + void **host_addr; + void **device_addr; + size_t *bytes; + unsigned int *mapping_flags; + const void *codeptr_ra; +} ompt_record_target_map_t; + +typedef void (*ompt_callback_target_submit_emi_t) ( + ompt_scope_endpoint_t endpoint, + ompt_data_t *target_data, + ompt_id_t *host_op_id, + unsigned int requested_num_teams +); + +typedef void (*ompt_callback_target_submit_t) ( + ompt_id_t target_id, + ompt_id_t host_op_id, + unsigned int requested_num_teams +); + +typedef struct ompt_record_target_kernel_t { + ompt_id_t host_op_id; + unsigned int requested_num_teams; + unsigned int granted_num_teams; + ompt_device_time_t end_time; +} ompt_record_target_kernel_t; + +typedef int (*ompt_callback_control_tool_t) ( + uint64_t command, + uint64_t modifier, + void *arg, + const void *codeptr_ra +); + +typedef struct ompt_record_control_tool_t { + uint64_t command; + uint64_t modifier; + const void *codeptr_ra; +} ompt_record_control_tool_t; + +typedef void (*ompt_callback_error_t) ( + ompt_severity_t severity, + const char *message, size_t length, + const void *codeptr_ra +); + +typedef struct ompt_record_error_t { + ompt_severity_t severity; + const char *message; + size_t length; + const void *codeptr_ra; +} ompt_record_error_t; + +typedef struct ompd_address_t { + ompd_seg_t segment; + ompd_addr_t address; +} ompd_address_t; + +typedef struct ompd_frame_info_t { + ompd_address_t frame_address; + ompd_word_t frame_flag; +} ompd_frame_info_t; + +typedef struct _ompd_aspace_handle ompd_address_space_handle_t; +typedef struct _ompd_thread_handle ompd_thread_handle_t; +typedef struct _ompd_parallel_handle ompd_parallel_handle_t; +typedef struct _ompd_task_handle ompd_task_handle_t; + +typedef struct _ompd_aspace_cont ompd_address_space_context_t; +typedef struct _ompd_thread_cont ompd_thread_context_t; + +typedef struct ompd_device_type_sizes_t { + uint8_t sizeof_char; + uint8_t sizeof_short; + uint8_t sizeof_int; + uint8_t sizeof_long; + uint8_t sizeof_long_long; + uint8_t sizeof_pointer; +} ompd_device_type_sizes_t; + +void ompd_dll_locations_valid(void); + +typedef ompd_rc_t (*ompd_callback_memory_alloc_fn_t)(ompd_size_t nbytes, + void **ptr); + +typedef ompd_rc_t (*ompd_callback_memory_free_fn_t)(void *ptr); + +typedef ompd_rc_t (*ompd_callback_get_thread_context_for_thread_id_fn_t)( + ompd_address_space_context_t *address_space_context, ompd_thread_id_t kind, + ompd_size_t sizeof_thread_id, const void *thread_id, + ompd_thread_context_t **thread_context); + +typedef ompd_rc_t (*ompd_callback_sizeof_fn_t)( + ompd_address_space_context_t *address_space_context, + ompd_device_type_sizes_t *sizes); + +typedef ompd_rc_t (*ompd_callback_symbol_addr_fn_t)( + ompd_address_space_context_t *address_space_context, + ompd_thread_context_t *thread_context, const char *symbol_name, + ompd_address_t *symbol_addr, const char *file_name); + +typedef ompd_rc_t (*ompd_callback_memory_read_fn_t)( + ompd_address_space_context_t *address_space_context, + ompd_thread_context_t *thread_context, const ompd_address_t *addr, + ompd_size_t nbytes, void *buffer); + +typedef ompd_rc_t (*ompd_callback_memory_write_fn_t)( + ompd_address_space_context_t *address_space_context, + ompd_thread_context_t *thread_context, const ompd_address_t *addr, + ompd_size_t nbytes, const void *buffer); + +typedef ompd_rc_t (*ompd_callback_device_host_fn_t)( + ompd_address_space_context_t *address_space_context, const void *input, + ompd_size_t unit_size, ompd_size_t count, void *output); + +typedef ompd_rc_t (*ompd_callback_print_string_fn_t)(const char *string, + int category); + +typedef struct ompd_callbacks_t { + ompd_callback_memory_alloc_fn_t alloc_memory; + ompd_callback_memory_free_fn_t free_memory; + ompd_callback_print_string_fn_t print_string; + ompd_callback_sizeof_fn_t sizeof_type; + ompd_callback_symbol_addr_fn_t symbol_addr_lookup; + ompd_callback_memory_read_fn_t read_memory; + ompd_callback_memory_write_fn_t write_memory; + ompd_callback_memory_read_fn_t read_string; + ompd_callback_device_host_fn_t device_to_host; + ompd_callback_device_host_fn_t host_to_device; + ompd_callback_get_thread_context_for_thread_id_fn_t + get_thread_context_for_thread_id; +} ompd_callbacks_t; + +void ompd_bp_parallel_begin(void); + +void ompd_bp_parallel_end(void); + +void ompd_bp_task_begin(void); + +void ompd_bp_task_end(void); + +void ompd_bp_thread_begin(void); + +void ompd_bp_thread_end(void); + +void ompd_bp_device_begin(void); + +void ompd_bp_device_end(void); + +ompd_rc_t ompd_initialize(ompd_word_t api_version, + const ompd_callbacks_t *callbacks); + +ompd_rc_t ompd_get_api_version(ompd_word_t *version); + +ompd_rc_t ompd_get_version_string(const char **string); + +ompd_rc_t ompd_finalize(void); + +ompd_rc_t ompd_process_initialize(ompd_address_space_context_t *context, + ompd_address_space_handle_t **handle); + +ompd_rc_t ompd_device_initialize(ompd_address_space_handle_t *process_handle, + ompd_address_space_context_t *device_context, + ompd_device_t kind, ompd_size_t sizeof_id, + void *id, + ompd_address_space_handle_t **device_handle); + +ompd_rc_t ompd_rel_address_space_handle(ompd_address_space_handle_t *handle); + +ompd_rc_t ompd_get_omp_version(ompd_address_space_handle_t *address_space, + ompd_word_t *omp_version); + +ompd_rc_t +ompd_get_omp_version_string(ompd_address_space_handle_t *address_space, + const char **string); + +ompd_rc_t ompd_get_thread_in_parallel(ompd_parallel_handle_t *parallel_handle, + int thread_num, + ompd_thread_handle_t **thread_handle); + +ompd_rc_t ompd_get_thread_handle(ompd_address_space_handle_t *handle, + ompd_thread_id_t kind, + ompd_size_t sizeof_thread_id, + const void *thread_id, + ompd_thread_handle_t **thread_handle); + +ompd_rc_t ompd_rel_thread_handle(ompd_thread_handle_t *thread_handle); + +ompd_rc_t ompd_thread_handle_compare(ompd_thread_handle_t *thread_handle_1, + ompd_thread_handle_t *thread_handle_2, + int *cmp_value); + +ompd_rc_t ompd_get_thread_id(ompd_thread_handle_t *thread_handle, + ompd_thread_id_t kind, + ompd_size_t sizeof_thread_id, void *thread_id); + +ompd_rc_t +ompd_get_curr_parallel_handle(ompd_thread_handle_t *thread_handle, + ompd_parallel_handle_t **parallel_handle); + +ompd_rc_t ompd_get_enclosing_parallel_handle( + ompd_parallel_handle_t *parallel_handle, + ompd_parallel_handle_t **enclosing_parallel_handle); + +ompd_rc_t +ompd_get_task_parallel_handle(ompd_task_handle_t *task_handle, + ompd_parallel_handle_t **task_parallel_handle); + +ompd_rc_t ompd_rel_parallel_handle(ompd_parallel_handle_t *parallel_handle); + +ompd_rc_t +ompd_parallel_handle_compare(ompd_parallel_handle_t *parallel_handle_1, + ompd_parallel_handle_t *parallel_handle_2, + int *cmp_value); + +ompd_rc_t ompd_get_curr_task_handle(ompd_thread_handle_t *thread_handle, + ompd_task_handle_t **task_handle); + +ompd_rc_t +ompd_get_generating_task_handle(ompd_task_handle_t *task_handle, + ompd_task_handle_t **generating_task_handle); + +ompd_rc_t +ompd_get_scheduling_task_handle(ompd_task_handle_t *task_handle, + ompd_task_handle_t **scheduling_task_handle); + +ompd_rc_t ompd_get_task_in_parallel(ompd_parallel_handle_t *parallel_handle, + int thread_num, + ompd_task_handle_t **task_handle); + +ompd_rc_t ompd_rel_task_handle(ompd_task_handle_t *task_handle); + +ompd_rc_t ompd_task_handle_compare(ompd_task_handle_t *task_handle_1, + ompd_task_handle_t *task_handle_2, + int *cmp_value); + +ompd_rc_t ompd_get_task_function(ompd_task_handle_t *task_handle, + ompd_address_t *entry_point); + +ompd_rc_t ompd_get_task_frame(ompd_task_handle_t *task_handle, + ompd_frame_info_t *exit_frame, + ompd_frame_info_t *enter_frame); + +ompd_rc_t +ompd_enumerate_states(ompd_address_space_handle_t *address_space_handle, + ompd_word_t current_state, ompd_word_t *next_state, + const char **next_state_name, ompd_word_t *more_enums); + +ompd_rc_t ompd_get_state(ompd_thread_handle_t *thread_handle, + ompd_word_t *state, ompd_wait_id_t *wait_id); + +ompd_rc_t +ompd_get_display_control_vars(ompd_address_space_handle_t *address_space_handle, + const char *const **control_vars); + +ompd_rc_t ompd_rel_display_control_vars(const char *const **control_vars); + +ompd_rc_t ompd_enumerate_icvs(ompd_address_space_handle_t *handle, + ompd_icv_id_t current, ompd_icv_id_t *next_id, + const char **next_icv_name, + ompd_scope_t *next_scope, int *more); + +ompd_rc_t ompd_get_icv_from_scope(void *handle, ompd_scope_t scope, + ompd_icv_id_t icv_id, ompd_word_t *icv_value); + +ompd_rc_t ompd_get_icv_string_from_scope(void *handle, ompd_scope_t scope, + ompd_icv_id_t icv_id, + const char **icv_string); + +ompd_rc_t ompd_get_tool_data(void *handle, ompd_scope_t scope, + ompd_word_t *value, ompd_address_t *ptr); + +typedef struct ompt_record_ompt_t { + ompt_callbacks_t type; + ompt_device_time_t time; + ompt_id_t thread_id; + ompt_id_t target_id; + union { + ompt_record_thread_begin_t thread_begin; + ompt_record_parallel_begin_t parallel_begin; + ompt_record_parallel_end_t parallel_end; + ompt_record_work_t work; + ompt_record_dispatch_t dispatch; + ompt_record_task_create_t task_create; + ompt_record_dependences_t dependences; + ompt_record_task_dependence_t task_dependence; + ompt_record_task_schedule_t task_schedule; + ompt_record_implicit_task_t implicit_task; + ompt_record_masked_t masked; + ompt_record_sync_region_t sync_region; + ompt_record_mutex_acquire_t mutex_acquire; + ompt_record_mutex_t mutex; + ompt_record_nest_lock_t nest_lock; + ompt_record_flush_t flush; + ompt_record_cancel_t cancel; + ompt_record_target_t target; + ompt_record_target_data_op_t target_data_op; + ompt_record_target_map_t target_map; + ompt_record_target_kernel_t target_kernel; + ompt_record_control_tool_t control_tool; + } record; +} ompt_record_ompt_t; + +typedef ompt_record_ompt_t *(*ompt_get_record_ompt_t) ( + ompt_buffer_t *buffer, + ompt_buffer_cursor_t current +); + +#define ompt_id_none 0 +#define ompt_data_none {0} +#define ompt_time_none 0 +#define ompt_hwid_none 0 +#define ompt_addr_none ~0 +#define ompt_mutex_impl_none 0 +#define ompt_wait_id_none 0 + +#define ompd_segment_none 0 + +#endif /* __OMPT__ */ diff --git a/src/Simulation/Native/osx/libomp.dylib b/src/Simulation/Native/osx/libomp.dylib new file mode 100644 index 00000000000..3aa24cd1ddc Binary files /dev/null and b/src/Simulation/Native/osx/libomp.dylib differ diff --git a/src/Simulation/Native/prerequisites.ps1 b/src/Simulation/Native/prerequisites.ps1 index 3f1272ffa84..935e7d4caaf 100644 --- a/src/Simulation/Native/prerequisites.ps1 +++ b/src/Simulation/Native/prerequisites.ps1 @@ -2,15 +2,30 @@ # Licensed under the MIT License. if (($IsMacOS) -or ((Test-Path Env:AGENT_OS) -and ($Env:AGENT_OS.StartsWith("Darwin")))) { - # building with gcc-9 succeeds but some of the unit tests fail - Write-Host "Install gcc-7 as pre-req for building native simulator on MacOS" - # temporary workaround for Bintray sunset - # remove this after Homebrew is updated to 3.1.1 on MacOS image, see: - # https://github.com/actions/virtual-environments/blob/main/images/macos/macos-10.15-Readme.md - brew update - brew install gcc@7 -} else { - Write-Host "No pre-reqs for building native simulator on platforms other than MacOS" + # Skip explicit install for testing purposes + # brew install libomp +} elseif (($IsWindows) -or ((Test-Path Env:/AGENT_OS) -and ($Env:AGENT_OS.StartsWith("Win")))) { + if (!(Get-Command clang -ErrorAction SilentlyContinue) -or ` + (Test-Path Env:/AGENT_OS)) { + choco install llvm --version=11.1.0 --allow-downgrade + Write-Host "##vso[task.setvariable variable=PATH;]$($env:SystemDrive)\Program Files\LLVM\bin;$Env:PATH" + } + if (!(Get-Command ninja -ErrorAction SilentlyContinue)) { + choco install ninja + } + if (!(Get-Command cmake -ErrorAction SilentlyContinue)) { + choco install cmake + } + refreshenv +} +else { + if (Get-Command sudo -ErrorAction SilentlyContinue) { + sudo apt update + sudo apt-get install -y clang-11 + } else { + apt update + apt-get install -y clang-11 + } } diff --git a/src/Simulation/Native/src/CMakeLists.txt b/src/Simulation/Native/src/CMakeLists.txt index dbbda28611f..81a510f7e9e 100644 --- a/src/Simulation/Native/src/CMakeLists.txt +++ b/src/Simulation/Native/src/CMakeLists.txt @@ -2,17 +2,10 @@ # Licensed under the MIT License. # AVX -if (MSVC) -set(AVXFLAGS "/arch:AVX" ) -set(AVX2FLAGS "/arch:AVX2" ) -set(AVX512FLAGS "/arch:AVX512" ) -set(FMAFLAGS "") -else(MSVC) -SET(AVXFLAGS "-mavx") +set(AVXFLAGS "-mavx") set(AVX2FLAGS "-mfma -mavx2") set(AVX512FLAGS "-mfma -mavx512f -mavx512cd") set(FMAFLAGS ) -endif(MSVC) configure_file(config.hpp.in ${PROJECT_BINARY_DIR}/src/config.hpp) configure_file(version.hpp.in ${PROJECT_BINARY_DIR}/src/version.hpp) @@ -23,20 +16,19 @@ add_subdirectory(simulator) set(SOURCES simulator/factory.cpp simulator/capi.cpp simulator/simulator.cpp util/openmp.cpp simulator/simulatoravx.cpp simulator/simulatoravx2.cpp simulator/simulatoravx512.cpp ) if(BUILD_SHARED_LIBS) add_library(Microsoft.Quantum.Simulator.Runtime SHARED ${SOURCES}) + set_source_files_properties(simulator/capi.cpp PROPERTIES COMPILE_FLAGS ${AVXFLAGS}) + set_source_files_properties(simulator/simulator.cpp PROPERTIES COMPILE_FLAGS ${AVXFLAGS}) set_source_files_properties(simulator/simulatoravx.cpp PROPERTIES COMPILE_FLAGS ${AVXFLAGS}) -if (MSVC) -set_source_files_properties(simulator/simulatoravx2.cpp PROPERTIES COMPILE_FLAGS -mfma COMPILE_FLAGS ${AVX2FLAGS}) -set_source_files_properties(simulator/simulatoravx512.cpp PROPERTIES COMPILE_FLAGS -mfma COMPILE_FLAGS ${AVX512FLAGS}) -else(MSVC) -set_source_files_properties(simulator/simulatoravx2.cpp PROPERTIES COMPILE_FLAGS -mfma COMPILE_FLAGS ${AVX2FLAGS}) -set_source_files_properties(simulator/simulatoravx512.cpp PROPERTIES COMPILE_FLAGS -mfma COMPILE_FLAGS ${AVX512FLAGS}) -endif(MSVC) + set_source_files_properties(simulator/simulatoravx2.cpp PROPERTIES COMPILE_FLAGS -mfma COMPILE_FLAGS ${AVX2FLAGS}) + set_source_files_properties(simulator/simulatoravx512.cpp PROPERTIES COMPILE_FLAGS -mfma COMPILE_FLAGS ${AVX512FLAGS}) message (STATUS "Building shared library") target_compile_definitions(Microsoft.Quantum.Simulator.Runtime PRIVATE BUILD_DLL=1) set_target_properties(Microsoft.Quantum.Simulator.Runtime PROPERTIES POSITION_INDEPENDENT_CODE TRUE) else(BUILD_SHARED_LIBS) message (STATUS "Building static library") add_library(Microsoft.Quantum.Simulator.Runtime STATIC ${SOURCES}) + set_source_files_properties(simulator/capi.cpp PROPERTIES COMPILE_FLAGS ${AVXFLAGS}) + set_source_files_properties(simulator/simulator.cpp PROPERTIES COMPILE_FLAGS ${AVXFLAGS}) set_source_files_properties(simulator/simulatoravx.cpp PROPERTIES COMPILE_FLAGS ${AVXFLAGS}) set_source_files_properties(simulator/simulatoravx2.cpp PROPERTIES COMPILE_FLAGS ${AVX2FLAGS}) set_source_files_properties(simulator/simulatoravx512.cpp PROPERTIES COMPILE_FLAGS ${AVX512FLAGS}) diff --git a/src/Simulation/Native/src/simulator/CMakeLists.txt b/src/Simulation/Native/src/simulator/CMakeLists.txt index d8b7a391013..d838c545bea 100644 --- a/src/Simulation/Native/src/simulator/CMakeLists.txt +++ b/src/Simulation/Native/src/simulator/CMakeLists.txt @@ -1,6 +1,8 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. +set(AVXFLAGS "-mavx") + add_executable(factory_test factory_test.cpp) target_link_libraries(factory_test Microsoft.Quantum.Simulator.Runtime) add_test(NAME factory_test COMMAND ./factory_test WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) @@ -19,6 +21,7 @@ add_executable(quantum_simulator_unittests "${PROJECT_SOURCE_DIR}/src/catch2/catch_driver.cpp" local_test.cpp ) +set_source_files_properties(local_test.cpp PROPERTIES COMPILE_FLAGS ${AVXFLAGS}) target_link_libraries(quantum_simulator_unittests PUBLIC Microsoft.Quantum.Simulator.Runtime diff --git a/src/Simulation/Native/src/simulator/kernels.hpp b/src/Simulation/Native/src/simulator/kernels.hpp index 3311bb27f8c..dbf406dd862 100644 --- a/src/Simulation/Native/src/simulator/kernels.hpp +++ b/src/Simulation/Native/src/simulator/kernels.hpp @@ -75,6 +75,8 @@ unsigned getvalue( std::vector, A> const& wfn, unsigned q, double eps = 100. * std::numeric_limits::epsilon()) + __attribute__((noinline)) // TODO(rokuzmin, #885): Try to remove `__attribute__((noinline))` after migrating + // to clang-13 on Win and Linux. { std::size_t mask = 1ull << q; for (std::size_t i = 0; i < wfn.size(); ++i) diff --git a/src/Simulation/Native/win10/libomp140.x86_64.dll b/src/Simulation/Native/win10/libomp140.x86_64.dll new file mode 100644 index 00000000000..9d805929c26 Binary files /dev/null and b/src/Simulation/Native/win10/libomp140.x86_64.dll differ diff --git a/src/Simulation/Native/win10/vcomp140.dll b/src/Simulation/Native/win10/vcomp140.dll deleted file mode 100644 index 872663e58d4..00000000000 Binary files a/src/Simulation/Native/win10/vcomp140.dll and /dev/null differ diff --git a/src/Simulation/QSharpFoundation/Diagnostics/AssertQubit.qs b/src/Simulation/QSharpFoundation/Diagnostics/AssertQubit.qs index e1a9e993012..e44142a93e1 100644 --- a/src/Simulation/QSharpFoundation/Diagnostics/AssertQubit.qs +++ b/src/Simulation/QSharpFoundation/Diagnostics/AssertQubit.qs @@ -19,7 +19,7 @@ namespace Microsoft.Quantum.Diagnostics { /// - AssertQubitIsInStateWithinTolerance /// /// # Remarks - /// allows for asserting + /// allows for asserting /// arbitrary qubit states rather than only $Z$ eigenstates. /// /// Note that the Adjoint and Controlled versions of this operation will not @@ -47,7 +47,7 @@ namespace Microsoft.Quantum.Diagnostics { /// - AssertQubitIsInStateWithinTolerance /// /// # Remarks - /// allows for asserting + /// allows for asserting /// arbitrary qubit states rather than only $Z$ eigenstates. /// /// Note that the Adjoint and Controlled versions of this operation will not diff --git a/src/Simulation/Simulators/CommonNativeSimulator/CommonNativeSimulator.cs b/src/Simulation/Simulators/CommonNativeSimulator/CommonNativeSimulator.cs index dda46fc992a..e444e7bc203 100644 --- a/src/Simulation/Simulators/CommonNativeSimulator/CommonNativeSimulator.cs +++ b/src/Simulation/Simulators/CommonNativeSimulator/CommonNativeSimulator.cs @@ -35,6 +35,8 @@ private protected CommonNativeSimulator( public uint Id { get; protected set; } + public abstract uint[] QubitIds { get; } + public override string Name { get diff --git a/src/Simulation/Simulators/CommonNativeSimulator/DisplayableState.cs b/src/Simulation/Simulators/CommonNativeSimulator/DisplayableState.cs new file mode 100644 index 00000000000..0cdf4fd272c --- /dev/null +++ b/src/Simulation/Simulators/CommonNativeSimulator/DisplayableState.cs @@ -0,0 +1,242 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Numerics; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; + +namespace Microsoft.Quantum.Simulation.Simulators +{ + public partial class CommonNativeSimulator + { + /// + /// The convention to be used in labeling computational basis states + /// given their representations as strings of classical bits. + /// + [JsonConverter(typeof(StringEnumConverter))] + public enum BasisStateLabelingConvention + { + /// + /// Label computational states directly by their bit strings. + /// + /// + /// Following this convention, the state |0⟩ ⊗ |1⟩ ⊗ |1⟩ is labeled + /// by |011⟩. + /// + Bitstring, + + /// + /// Label computational states directly by interpreting their bit + /// strings as little-endian encoded integers. + /// + /// + /// Following this convention, the state |0⟩ ⊗ |1⟩ ⊗ |1⟩ is labeled + /// by |6⟩. + /// + LittleEndian, + + /// + /// Label computational states directly by interpreting their bit + /// strings as big-endian encoded integers. + /// + /// + /// Following this convention, the state |0⟩ ⊗ |1⟩ ⊗ |1⟩ is labeled + /// by |3⟩. + /// + BigEndian + } + + /// + /// Represents a quantum state vector and all metadata needed to display + /// that state vector. + /// + public class DisplayableState + { + private static readonly IComparer ToIntComparer = + Comparer.Create((label1, label2) => + Comparer.Default.Compare( + Int32.Parse(label1), Int32.Parse(label2) + ) + ); + + /// + /// Metadata to be used when serializing to JSON, allowing code + /// in other languages to determine what representation is used + /// for this state. + /// + [JsonProperty("diagnostic_kind")] + private string DiagnosticKind => "state-vector"; + + /// + /// The indexes of each qubit on which this state is defined, or + /// null if these indexes are not known. + /// + [JsonProperty("qubit_ids")] + public IEnumerable? QubitIds { get; set; } + + /// + /// The number of qubits on which this state is defined. + /// + [JsonProperty("n_qubits")] + public int NQubits { get; set; } + + /// + /// These amplitudes represent the computational basis states + /// labeled in little-endian order, as per the behavior of + /// . + /// + [JsonProperty("amplitudes")] + public IDictionary? Amplitudes { get; set; } + + /// + /// An enumerable source of the significant amplitudes of this state + /// vector and their labels. + /// + /// + /// The convention to be used in labeling each computational basis state. + /// + /// + /// Whether to truncate small amplitudes. + /// + /// + /// If is true, + /// then amplitudes whose absolute value squared are below this + /// threshold are suppressed. + /// + public IEnumerable<(Complex, string)> SignificantAmplitudes( + BasisStateLabelingConvention convention, + bool truncateSmallAmplitudes, double truncationThreshold + ) => + ( + truncateSmallAmplitudes + ? Amplitudes + .Where(item => + System.Math.Pow(item.Value.Magnitude, 2.0) >= truncationThreshold + ) + : Amplitudes + ) + .Select( + item => (item.Value, BasisStateLabel(convention, item.Key)) + ) + .OrderBy( + item => item.Item2, + // If a basis state label is numeric, we want to compare + // numerically rather than lexographically. + convention switch { + BasisStateLabelingConvention.BigEndian => ToIntComparer, + BasisStateLabelingConvention.LittleEndian => ToIntComparer, + _ => Comparer.Default + } + ); + + /// + /// Using the given labeling convention, returns the label for a + /// computational basis state described by its bit string as encoded + /// into an integer index in the little-endian encoding. + /// + public string BasisStateLabel( + BasisStateLabelingConvention convention, int index + ) => convention switch + { + BasisStateLabelingConvention.Bitstring => + String.Concat( + System + .Convert + .ToString(index, 2) + .PadLeft(NQubits, '0') + .Reverse() + ), + BasisStateLabelingConvention.BigEndian => + System.Convert.ToInt64( + String.Concat( + System.Convert.ToString(index, 2).PadLeft(NQubits, '0').Reverse() + ), + fromBase: 2 + ) + .ToString(), + BasisStateLabelingConvention.LittleEndian => + index.ToString(), + _ => throw new ArgumentException($"Invalid basis state labeling convention {convention}.") + }; + + /// + /// Returns a string that represents the magnitude of the amplitude. + /// + public virtual string FormatMagnitude(double magnitude, double phase) => + (new String('*', (int)System.Math.Ceiling(20.0 * magnitude))).PadRight(20) + $" [ {magnitude:F6} ]"; + + /// + /// Returns a string that represents the phase of the amplitude. + /// + public virtual string FormatAngle(double magnitude, double angle) + { + var PI = System.Math.PI; + var offset = PI / 16.0; + if (magnitude == 0.0) + { + return " "; + } + + var chart = " ---"; + if (angle > 0) + { + if (angle >= (0 * PI / 8) + offset && angle < ((1 * PI / 8) + offset)) { chart = " /-"; } + if (angle >= (1 * PI / 8) + offset && angle < ((2 * PI / 8) + offset)) { chart = " / "; } + if (angle >= (2 * PI / 8) + offset && angle < ((3 * PI / 8) + offset)) { chart = " +/ "; } + if (angle >= (3 * PI / 8) + offset && angle < ((4 * PI / 8) + offset)) { chart = " ↑ "; } + if (angle >= (4 * PI / 8) + offset && angle < ((5 * PI / 8) + offset)) { chart = " \\- "; } + if (angle >= (5 * PI / 8) + offset && angle < ((6 * PI / 8) + offset)) { chart = " \\ "; } + if (angle >= (6 * PI / 8) + offset && angle < ((7 * PI / 8) + offset)) { chart = "+\\ "; } + if (angle >= (7 * PI / 8) + offset) { chart = "--- "; } + } + else if (angle < 0) + { + var abs_angle = System.Math.Abs(angle); + if (abs_angle >= (0 * PI / 8) + offset && abs_angle < ((1 * PI / 8) + offset)) { chart = " \\+"; } + if (abs_angle >= (1 * PI / 8) + offset && abs_angle < ((2 * PI / 8) + offset)) { chart = " \\ "; } + if (abs_angle >= (2 * PI / 8) + offset && abs_angle < ((3 * PI / 8) + offset)) { chart = " -\\ "; } + if (abs_angle >= (3 * PI / 8) + offset && abs_angle < ((4 * PI / 8) + offset)) { chart = " ↓ "; } + if (abs_angle >= (4 * PI / 8) + offset && abs_angle < ((5 * PI / 8) + offset)) { chart = " /+ "; } + if (abs_angle >= (5 * PI / 8) + offset && abs_angle < ((6 * PI / 8) + offset)) { chart = " / "; } + if (abs_angle >= (6 * PI / 8) + offset && abs_angle < ((7 * PI / 8) + offset)) { chart = "-/ "; } + } + + return $" {chart} [ {angle,8:F5} rad ]"; + } + + /// + /// Returns a string for the amplitude's polar representation (magnitude/angle). + /// + public virtual string FormatPolar(double magnitude, double angle) => + $"{FormatMagnitude(magnitude, angle)}{FormatAngle(magnitude, angle)}"; + + /// + /// Returns a string for the amplitude's cartesian representation (real + imagnary). + /// + public virtual string FormatCartesian(double real, double img) => + $"{real,9:F6} + {img,9:F6} i"; + + public string ToString(BasisStateLabelingConvention convention, // Non-override. Parameterized. + bool truncateSmallAmplitudes, + double truncationThreshold) + { + return string.Join('\n', + SignificantAmplitudes(convention, truncateSmallAmplitudes, truncationThreshold) + .Select( + item => + { + var (cmplx, basisLabel) = item; + var amplitude = (cmplx.Real * cmplx.Real) + (cmplx.Imaginary * cmplx.Imaginary); + var angle = System.Math.Atan2(cmplx.Imaginary, cmplx.Real); + return $"|{basisLabel}⟩\t{FormatCartesian(cmplx.Real, cmplx.Imaginary)}\t == \t" + + $"{FormatPolar(amplitude, angle)}"; + })); + } + + public override string ToString() => // An override of the `object.ToString()`. + ToString(BasisStateLabelingConvention.LittleEndian, false, 0.0); + + } + + } +} diff --git a/src/Simulation/Simulators/CommonNativeSimulator/Dump.cs b/src/Simulation/Simulators/CommonNativeSimulator/Dump.cs index 51fa1c153fa..ce3bcf38f63 100644 --- a/src/Simulation/Simulators/CommonNativeSimulator/Dump.cs +++ b/src/Simulation/Simulators/CommonNativeSimulator/Dump.cs @@ -2,19 +2,18 @@ // Licensed under the MIT License. using System; +using System.Collections.Generic; using System.IO; using System.Linq; +using System.Numerics; using Microsoft.Quantum.Simulation.Core; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; namespace Microsoft.Quantum.Simulation.Simulators { public partial class CommonNativeSimulator { - protected virtual QVoid process(Action channel, IQArray? qubits) - { - return QVoid.Instance; - } - /// /// Dumps the wave function for the given qubits into the given target. /// If the target is QVoid or an empty string, it dumps it to the console @@ -26,30 +25,27 @@ protected virtual QVoid process(Action channel, IQArray? qubits) /// protected virtual QVoid Dump(T target, IQArray? qubits = null) { - var filename = (target is QVoid) ? "" : target.ToString(); - var logMessage = this.Get, Microsoft.Quantum.Intrinsic.Message>(); + var filename = ((target == null) || (target is QVoid)) ? "" : target.ToString(); - // If no file provided, use `Message` to generate the message into the console; + // If no file provided, output to the console; if (string.IsNullOrWhiteSpace(filename)) { - var op = this.Get, Microsoft.Quantum.Intrinsic.Message>(); - return process((msg) => op.Apply(msg), qubits); + new DisplayableStateDumper(this).Dump(qubits); } else { try { - using (var file = new StreamWriter(filename)) - { - return process(file.WriteLine, qubits); - } + using var file = new StreamWriter(filename); + new DisplayableStateDumper(this, file.WriteLine).Dump(qubits); } catch (Exception e) { + var logMessage = this.Get, Microsoft.Quantum.Intrinsic.Message>(); logMessage.Apply($"[warning] Unable to write state to '{filename}' ({e.Message})"); - return QVoid.Instance; } } + return QVoid.Instance; } // `QsimDumpMachine` makes an impression that it is never used, @@ -96,5 +92,135 @@ public QSimDumpRegister(CommonNativeSimulator m) : base(m) return Simulator.Dump(location, qubits); }; } + + /// + /// This class allows you to dump the state (wave function) + /// of the native simulator into a callback function. + /// The callback function is triggered for every state basis + /// vector in the wavefunction. + /// + public abstract class StateDumper + { + /// + /// Basic constructor. Takes the simulator to probe. + /// + public StateDumper(CommonNativeSimulator qsim) + { + this.Simulator = qsim; + } + + /// + /// The callback method that will be used to report the amplitude + /// of each basis vector of the wave function. + /// The method should return 'true' if the simulator should + /// continue reporting the state of the remaining basis vectors. + /// + /// The index of the basis state vector being reported. + /// The real portion of the amplitude of the given basis state vector. + /// The imaginary portion of the amplitude of the given basis state vector. + /// true if dumping should continue, false to stop dumping. + public abstract bool Callback(uint idx, double real, double img); + + /// + /// The Simulator being reported. + /// + public CommonNativeSimulator Simulator { get; } + + /// + /// Entry method to get the dump of the wave function. + /// + public virtual bool Dump(IQArray? qubits = null) + { + if (qubits == null) + { + this.Simulator.sim_Dump(Callback); + return true; + } + else + { + var ids = qubits.GetIds(); + return this.Simulator.sim_DumpQubits((uint)ids.Length, ids, Callback); + } + } + } + + /// + /// A state dumper that encodes dumped states into displayable + /// objects. + /// + public class DisplayableStateDumper : StateDumper + { + private long _count = -1; + private IDictionary? _data = null; + + /// + /// A method to call to output a string representation. + /// + public virtual Action? FileWriter { get; } + + /// + /// Constructs a new display dumper for a given simulator. + /// + public DisplayableStateDumper(CommonNativeSimulator sim, Action? fileWriter = null) : base(sim) + { + this.FileWriter = fileWriter; + } + + /// + /// Used by the simulator to provide states when dumping. + /// Not intended to be called directly. + /// + public override bool Callback(uint idx, double real, double img) + { + if (_data == null) throw new Exception("Expected data buffer to be initialized before callback, but it was null."); + _data[(int)idx] = new Complex(real, img); + return true; + } + + /// + /// Dumps the state of a register of qubits as a displayable object. + /// + public override bool Dump(IQArray? qubits = null) + { + System.Diagnostics.Debug.Assert(this.Simulator.QubitManager != null, + "Internal logic error, QubitManager must be assigned"); + + _count = qubits == null + ? this.Simulator.QubitManager.AllocatedQubitsCount + : qubits.Length; + _data = new Dictionary(); // If 0 qubits are allocated then the array has + // a single element. The Hilbert space of the system is + // ℂ¹ (that is, complex-valued scalars). + var result = base.Dump(qubits); + + // At this point, _data should be filled with the full state + // vector, so let's display it, counting on the right display + // encoder to be there to pack it into a table. + + var state = new DisplayableState + { + // We cast here as we don't support a large enough number + // of qubits to saturate an int. + QubitIds = qubits?.Select(q => q.Id) ?? Simulator.QubitIds.Select(q => (int)q) ?? Enumerable.Empty(), + NQubits = (int)_count, + Amplitudes = _data, + }; + + if (this.FileWriter != null) + { + this.FileWriter(state.ToString()); + } + else + { + Simulator.MaybeDisplayDiagnostic(state); + } + + // Clean up the state vector buffer. + _data = null; + + return result; + } + + } } } diff --git a/src/Simulation/Simulators/CommonNativeSimulator/NativeWrappers.cs b/src/Simulation/Simulators/CommonNativeSimulator/NativeWrappers.cs index 7e33cea1441..42bfca58c8d 100644 --- a/src/Simulation/Simulators/CommonNativeSimulator/NativeWrappers.cs +++ b/src/Simulation/Simulators/CommonNativeSimulator/NativeWrappers.cs @@ -29,5 +29,9 @@ public partial class CommonNativeSimulator protected abstract void MCY(uint count, uint[] ctrls, uint qubit); protected abstract void Z(uint qubit); protected abstract void MCZ(uint count, uint[] ctrls, uint qubit); + + protected delegate bool DumpCallback(uint idx, double real, double img); + protected abstract void sim_Dump(DumpCallback callback); + protected abstract bool sim_DumpQubits(uint count, uint[] ids, DumpCallback callback); } } diff --git a/src/Simulation/Simulators/Microsoft.Quantum.Simulators.csproj b/src/Simulation/Simulators/Microsoft.Quantum.Simulators.csproj index 0869cee10f5..094318529d2 100644 --- a/src/Simulation/Simulators/Microsoft.Quantum.Simulators.csproj +++ b/src/Simulation/Simulators/Microsoft.Quantum.Simulators.csproj @@ -44,6 +44,7 @@ PreserveNewest false + diff --git a/src/Simulation/Simulators/QuantumSimulator/Dump.cs b/src/Simulation/Simulators/QuantumSimulator/Dump.cs index 3e414204905..9d0d4887300 100644 --- a/src/Simulation/Simulators/QuantumSimulator/Dump.cs +++ b/src/Simulation/Simulators/QuantumSimulator/Dump.cs @@ -14,7 +14,7 @@ public partial class QuantumSimulator /// /// Returns the list of the qubits' ids currently allocated in the simulator. /// - public uint[] QubitIds + public override uint[] QubitIds { get { @@ -25,20 +25,5 @@ public uint[] QubitIds return ids.ToArray(); } } - - protected override QVoid process(Action channel, IQArray? qubits) - { - var ids = qubits?.Select(q => (uint)q.Id).ToArray() ?? QubitIds; - - var dumper = new SimpleDumper(this, channel); - channel($"# wave function for qubits with ids (least to most significant): {string.Join(";", ids)}"); - - if (!dumper.Dump(qubits)) - { - channel("## Qubits were entangled with an external qubit. Cannot dump corresponding wave function. ##"); - } - - return QVoid.Instance; - } } } diff --git a/src/Simulation/Simulators/QuantumSimulator/NativeImports.cs b/src/Simulation/Simulators/QuantumSimulator/NativeImports.cs index dd77a4299d0..3562c661487 100644 --- a/src/Simulation/Simulators/QuantumSimulator/NativeImports.cs +++ b/src/Simulation/Simulators/QuantumSimulator/NativeImports.cs @@ -14,6 +14,9 @@ public partial class QuantumSimulator // Preparation\Arbitrary.cs(23,41): error CS0117: 'QuantumSimulator' does not contain a definition for // 'QSIM_DLL_NAME' [D:\a\1\s\submodules\QuantumLibraries\Standard\src\Standard.csproj] + [DllImport("libomp", ExactSpelling = true, CallingConvention = CallingConvention.Cdecl, EntryPoint = "omp_get_num_threads")] + private static extern int OmpGetNumberOfThreadsNative(); + private delegate void IdsCallback(uint id); [DllImport(QSIM_DLL_NAME, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl, EntryPoint = "DumpIds")] private static extern void sim_QubitsIdsNative(uint id, IdsCallback callback); diff --git a/src/Simulation/Simulators/QuantumSimulator/NativeWrappers.cs b/src/Simulation/Simulators/QuantumSimulator/NativeWrappers.cs index b185f287771..4ad08dc2a3d 100644 --- a/src/Simulation/Simulators/QuantumSimulator/NativeWrappers.cs +++ b/src/Simulation/Simulators/QuantumSimulator/NativeWrappers.cs @@ -107,12 +107,12 @@ protected override void MCAdjS(uint count, uint[] ctrls, uint qubit) MCAdjSNative(this.Id, count, ctrls, qubit); } - protected virtual void sim_Dump(DumpCallback callback) + protected override void sim_Dump(DumpCallback callback) { sim_DumpNative(this.Id, callback); } - protected virtual bool sim_DumpQubits(uint count, uint[] ids, DumpCallback callback) + protected override bool sim_DumpQubits(uint count, uint[] ids, DumpCallback callback) { return sim_DumpQubitsNative(this.Id, count, ids, callback); } diff --git a/src/Simulation/Simulators/QuantumSimulator/QuantumSimulator.cs b/src/Simulation/Simulators/QuantumSimulator/QuantumSimulator.cs index 58bceb2903f..c012d569b40 100644 --- a/src/Simulation/Simulators/QuantumSimulator/QuantumSimulator.cs +++ b/src/Simulation/Simulators/QuantumSimulator/QuantumSimulator.cs @@ -28,6 +28,14 @@ public QuantumSimulator( randomNumberGeneratorSeed, disableBorrowing) { + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + // We don't need this value, but explicitly calling an OMP function should trigger the load of libomp + // by .NET from the runtimes folder for the current platform, such that the later library load by the + // simulator does not need to know where to search for it. + var threadCount = OmpGetNumberOfThreadsNative(); + } + Id = InitNative(); // Make sure that the same seed used by the built-in System.Random // instance is also used by the native simulator itself. diff --git a/src/Simulation/Simulators/QuantumSimulator/StateDumper.cs b/src/Simulation/Simulators/QuantumSimulator/StateDumper.cs deleted file mode 100644 index 22c42a05f6e..00000000000 --- a/src/Simulation/Simulators/QuantumSimulator/StateDumper.cs +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -using System.Diagnostics; -using Microsoft.Quantum.Simulation.Core; - -namespace Microsoft.Quantum.Simulation.Simulators -{ - public partial class QuantumSimulator - { - protected delegate bool DumpCallback(uint idx, double real, double img); - - /// - /// This class allows you to dump the state (wave function) - /// of the QuantumSimulator into a callback function. - /// The callback function is triggered for every state basis - /// vector in the wavefunction. - /// - public abstract class StateDumper // Is used by "iqsharp\src\Jupyter\Visualization\StateDisplayOperations.cs". - { - /// - /// Basic constructor. Takes the simulator to probe. - /// - public StateDumper(QuantumSimulator qsim) - { - this.Simulator = qsim; - } - - /// - /// The callback method that will be used to report the amplitude - /// of each basis vector of the wave function. - /// The method should return 'true' if the QuantumSimulator should - /// continue reporting the state of the remaining basis vectors. - /// - /// The index of the basis state vector being reported. - /// The real portion of the amplitude of the given basis state vector. - /// The imaginary portion of the amplitude of the given basis state vector. - /// true if dumping should continue, false to stop dumping. - public abstract bool Callback(uint idx, double real, double img); - - /// - /// The QuantumSimulator being reported. - /// - public QuantumSimulator Simulator { get; } - - /// - /// Entry method to get the dump of the wave function. - /// - public virtual bool Dump(IQArray? qubits = null) - { - if (qubits == null) - { - this.Simulator.sim_Dump(Callback); - return true; - } - else - { - var ids = qubits.GetIds(); - return this.Simulator.sim_DumpQubits((uint)ids.Length, ids, Callback); - } - } - } - - /// - /// A simple implementation of a . It outputs the - /// a string representation of the state to the given channel. - /// - public class SimpleDumper : StateDumper - { - private int _maxCharsStateId; - - public SimpleDumper(QuantumSimulator qsim, Action channel) : base(qsim) - { - this.Channel = channel; - } - - /// - /// A method to call to output a string representation of the amplitude of each - /// state basis vector. - /// - public virtual Action Channel { get; } - - /// - /// Returns a string that represents the label for the given base state. - /// - public virtual string FormatBaseState(uint idx) => - $"∣{idx.ToString().PadLeft(_maxCharsStateId, ' ')}❭"; - - /// - /// Returns a string that represents the magnitude of the amplitude. - /// - public virtual string FormatMagnitude(double magnitude, double phase) => - (new String('*', (int)System.Math.Ceiling(20.0 * magnitude))).PadRight(20) + $" [ {magnitude:F6} ]"; - - /// - /// Returns a string that represents the phase of the amplitude. - /// - public virtual string FormatAngle(double magnitude, double angle) - { - var PI = System.Math.PI; - var offset = PI / 16.0; - if (magnitude == 0.0) - { - return " "; - } - - var chart = " ---"; - if (angle > 0) - { - if (angle >= (0 * PI / 8) + offset && angle < ((1 * PI / 8) + offset)) { chart = " /-"; } - if (angle >= (1 * PI / 8) + offset && angle < ((2 * PI / 8) + offset)) { chart = " / "; } - if (angle >= (2 * PI / 8) + offset && angle < ((3 * PI / 8) + offset)) { chart = " +/ "; } - if (angle >= (3 * PI / 8) + offset && angle < ((4 * PI / 8) + offset)) { chart = " ↑ "; } - if (angle >= (4 * PI / 8) + offset && angle < ((5 * PI / 8) + offset)) { chart = " \\- "; } - if (angle >= (5 * PI / 8) + offset && angle < ((6 * PI / 8) + offset)) { chart = " \\ "; } - if (angle >= (6 * PI / 8) + offset && angle < ((7 * PI / 8) + offset)) { chart = "+\\ "; } - if (angle >= (7 * PI / 8) + offset) { chart = "--- "; } - } - else if (angle < 0) - { - var abs_angle = System.Math.Abs(angle); - if (abs_angle >= (0 * PI / 8) + offset && abs_angle < ((1 * PI / 8) + offset)) { chart = " \\+"; } - if (abs_angle >= (1 * PI / 8) + offset && abs_angle < ((2 * PI / 8) + offset)) { chart = " \\ "; } - if (abs_angle >= (2 * PI / 8) + offset && abs_angle < ((3 * PI / 8) + offset)) { chart = " -\\ "; } - if (abs_angle >= (3 * PI / 8) + offset && abs_angle < ((4 * PI / 8) + offset)) { chart = " ↓ "; } - if (abs_angle >= (4 * PI / 8) + offset && abs_angle < ((5 * PI / 8) + offset)) { chart = " /+ "; } - if (abs_angle >= (5 * PI / 8) + offset && abs_angle < ((6 * PI / 8) + offset)) { chart = " / "; } - if (abs_angle >= (6 * PI / 8) + offset && abs_angle < ((7 * PI / 8) + offset)) { chart = "-/ "; } - } - - return $" {chart} [ {angle,8:F5} rad ]"; - } - - /// - /// Returns a string for the amplitude's polar representation (magnitude/angle). - /// - public virtual string FormatPolar(double magnitude, double angle) => - $"{FormatMagnitude(magnitude, angle)}{FormatAngle(magnitude, angle)}"; - - /// - /// Returns a string for the amplitude's cartesian representation (real + imagnary). - /// - public virtual string FormatCartesian(double real, double img) => - $"{real,9:F6} + {img,9:F6} i"; - - /// - /// The method to use to format the amplitude into a string. - /// - public virtual string Format(uint idx, double real, double img) - { - var amplitude = (real * real) + (img * img); - var angle = System.Math.Atan2(img, real); - - return $"{FormatBaseState(idx)}:\t" + - $"{FormatCartesian(real, img)}\t == \t" + - $"{FormatPolar(amplitude, angle)}"; - - } - - /// - /// The callback method. Formats the given state and invokes the - /// - /// True, so the entire wave function is dumped. - public override bool Callback(uint idx, double real, double img) - { - Channel(Format(idx, real, img)); - return true; - } - - public override bool Dump(IQArray? qubits = null) - { - Debug.Assert(this.Simulator.QubitManager != null); - - var count = qubits == null - ? this.Simulator.QubitManager.AllocatedQubitsCount - : qubits.Length; - this._maxCharsStateId = ((1 << (int)count) - 1).ToString().Length; - - return base.Dump(qubits); - } - } - } -} diff --git a/src/Simulation/TargetDefinitions/Decompositions/CCNOTFromCCZ.qs b/src/Simulation/TargetDefinitions/Decompositions/CCNOTFromCCZ.qs index fcc55c6aaa6..f9082d9e2ee 100644 --- a/src/Simulation/TargetDefinitions/Decompositions/CCNOTFromCCZ.qs +++ b/src/Simulation/TargetDefinitions/Decompositions/CCNOTFromCCZ.qs @@ -26,7 +26,7 @@ namespace Microsoft.Quantum.Intrinsic { H(target); } apply { - Controlled Z([control1, control2], target); + CCZ(control1, control2, target); } } controlled (ctls, ...) { diff --git a/src/Simulation/TargetDefinitions/Decompositions/CX.qs b/src/Simulation/TargetDefinitions/Decompositions/CX.qs new file mode 100644 index 00000000000..f212bb3eced --- /dev/null +++ b/src/Simulation/TargetDefinitions/Decompositions/CX.qs @@ -0,0 +1,42 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Canon { + open Microsoft.Quantum.Intrinsic; + + /// # Summary + /// Applies the controlled-X (CX) gate to a pair of qubits. + /// + /// # Description + /// This operation can be simulated by the unitary matrix + /// $$ + /// \begin{align} + /// \left(\begin{matrix} + /// 1 & 0 & 0 & 0 \\\\ + /// 0 & 1 & 0 & 0 \\\\ + /// 0 & 0 & 0 & 1 \\\\ + /// 0 & 0 & 1 & 0 + /// \end{matrix}\right) + /// \end{align}, + /// $$ + /// where rows and columns are organized as in the quantum concepts guide. + /// + /// # Input + /// ## control + /// Control qubit for the CX gate. + /// ## target + /// Target qubit for the CX gate. + /// + /// # Remarks + /// Equivalent to: + /// ```qsharp + /// Controlled X([control], target); + /// ``` + /// and to: + /// ```qsharp + /// CNOT(control, target); + /// ``` + operation CX(control : Qubit, target : Qubit) : Unit is Adj + Ctl{ + CNOT(control, target); + } +} \ No newline at end of file diff --git a/src/Simulation/TargetDefinitions/Decompositions/CYFromCNOT.qs b/src/Simulation/TargetDefinitions/Decompositions/CYFromCNOT.qs new file mode 100644 index 00000000000..364b4d2c573 --- /dev/null +++ b/src/Simulation/TargetDefinitions/Decompositions/CYFromCNOT.qs @@ -0,0 +1,46 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Canon { + open Microsoft.Quantum.Intrinsic; + + /// # Summary + /// Applies the controlled-Y (CY) gate to a pair of qubits. + /// + /// # Description + /// This operation can be simulated by the unitary matrix + /// $$ + /// \begin{align} + /// 1 & 0 & 0 & 0 \\\\ + /// 0 & 1 & 0 & 0 \\\\ + /// 0 & 0 & 0 & -i \\\\ + /// 0 & 0 & i & 0 + /// \end{align}, + /// $$ + /// where rows and columns are organized as in the quantum concepts guide. + /// + /// # Input + /// ## control + /// Control qubit for the CY gate. + /// ## target + /// Target qubit for the CY gate. + /// + /// # Remarks + /// Equivalent to: + /// ```qsharp + /// Controlled Y([control], target); + /// ``` + operation CY(control : Qubit, target : Qubit) : Unit { + body (...) { + within { + MapPauli(target, PauliX, PauliY); + } + apply { + CNOT(control, target); + } + } + adjoint self; + controlled distribute; + controlled adjoint self; + } +} \ No newline at end of file diff --git a/src/Simulation/TargetDefinitions/Decompositions/CZFromSinglyControlled.qs b/src/Simulation/TargetDefinitions/Decompositions/CZFromSinglyControlled.qs new file mode 100644 index 00000000000..80d6000368e --- /dev/null +++ b/src/Simulation/TargetDefinitions/Decompositions/CZFromSinglyControlled.qs @@ -0,0 +1,50 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Canon { + open Microsoft.Quantum.Intrinsic; + + /// # Summary + /// Applies the controlled-Z (CZ) gate to a pair of qubits. + /// + /// # Description + /// This operation can be simulated by the unitary matrix + /// $$ + /// \begin{align} + /// 1 & 0 & 0 & 0 \\\\ + /// 0 & 1 & 0 & 0 \\\\ + /// 0 & 0 & 1 & 0 \\\\ + /// 0 & 0 & 0 & -1 + /// \end{align}, + /// $$ + /// where rows and columns are organized as in the quantum concepts guide. + /// + /// # Input + /// ## control + /// Control qubit for the CZ gate. + /// ## target + /// Target qubit for the CZ gate. + /// + /// # Remarks + /// Equivalent to: + /// ```qsharp + /// Controlled Z([control], target); + /// ``` + operation CZ(control : Qubit, target : Qubit) : Unit { + body (...) { + ApplyControlledZ(control, target); + } + controlled (ctls, ...) { + if Length(ctls) == 0 { + ApplyControlledZ(control, target); + } + elif Length(ctls) == 1 { + CCZ(ctls[0], control, target); + } + else { + ApplyWithLessControlsA(Controlled CZ, (ctls, (control, target))); + } + } + adjoint self; + } +} \ No newline at end of file diff --git a/src/Simulation/TargetDefinitions/Decompositions/Utils.qs b/src/Simulation/TargetDefinitions/Decompositions/Utils.qs index 32c31472a42..3275be341a0 100644 --- a/src/Simulation/TargetDefinitions/Decompositions/Utils.qs +++ b/src/Simulation/TargetDefinitions/Decompositions/Utils.qs @@ -99,6 +99,23 @@ namespace Microsoft.Quantum.Intrinsic { H(target); } + internal operation CCZ (control1 : Qubit, control2 : Qubit, target : Qubit) : Unit is Adj { + // [Page 15 of arXiv:1206.0758v3](https://arxiv.org/pdf/1206.0758v3.pdf#page=15) + Adjoint T(control1); + Adjoint T(control2); + CNOT(target, control1); + T(control1); + CNOT(control2, target); + CNOT(control2, control1); + T(target); + Adjoint T(control1); + CNOT(control2, target); + CNOT(target, control1); + Adjoint T(target); + T(control1); + CNOT(control2, control1); + } + internal function ReducedDyadicFraction (numerator : Int, denominatorPowerOfTwo : Int) : (Int, Int) { if (numerator == 0) { return (0,0); } mutable num = numerator; diff --git a/src/Simulation/TargetDefinitions/Decompositions/YFromSinglyControlled.qs b/src/Simulation/TargetDefinitions/Decompositions/YFromSinglyControlled.qs index 71499ff03ac..95e0cb96740 100644 --- a/src/Simulation/TargetDefinitions/Decompositions/YFromSinglyControlled.qs +++ b/src/Simulation/TargetDefinitions/Decompositions/YFromSinglyControlled.qs @@ -2,6 +2,7 @@ // Licensed under the MIT License. namespace Microsoft.Quantum.Intrinsic { + open Microsoft.Quantum.Canon; /// # Summary /// Applies the Pauli $Y$ gate. @@ -27,19 +28,14 @@ namespace Microsoft.Quantum.Intrinsic { ApplyUncontrolledY(qubit); } elif (Length(ctls) == 1) { - within { - MapPauli(qubit, PauliX, PauliY); - } - apply { - CNOT(ctls[0], qubit); - } + CY(ctls[0], qubit); } elif (Length(ctls) == 2) { within { MapPauli(qubit, PauliZ, PauliY); } apply { - Controlled Z(ctls, qubit); + CCZ(ctls[0], ctls[1], qubit); } } else { diff --git a/src/Simulation/TargetDefinitions/Decompositions/ZFromSinglyControlled.qs b/src/Simulation/TargetDefinitions/Decompositions/ZFromSinglyControlled.qs index 7072a4f17c9..52b8f7d7b00 100644 --- a/src/Simulation/TargetDefinitions/Decompositions/ZFromSinglyControlled.qs +++ b/src/Simulation/TargetDefinitions/Decompositions/ZFromSinglyControlled.qs @@ -2,6 +2,7 @@ // Licensed under the MIT License. namespace Microsoft.Quantum.Intrinsic { + open Microsoft.Quantum.Canon; /// # Summary /// Applies the Pauli $Z$ gate. @@ -30,20 +31,7 @@ namespace Microsoft.Quantum.Intrinsic { ApplyControlledZ(ctls[0], qubit); } elif (Length(ctls) == 2) { - // [Page 15 of arXiv:1206.0758v3](https://arxiv.org/pdf/1206.0758v3.pdf#page=15) - Adjoint T(ctls[0]); - Adjoint T(ctls[1]); - CNOT(qubit, ctls[0]); - T(ctls[0]); - CNOT(ctls[1], qubit); - CNOT(ctls[1], ctls[0]); - T(qubit); - Adjoint T(ctls[0]); - CNOT(ctls[1], qubit); - CNOT(qubit, ctls[0]); - Adjoint T(qubit); - T(ctls[0]); - CNOT(ctls[1], ctls[0]); + CCZ(ctls[0], ctls[1], qubit); } else { ApplyWithLessControlsA(Controlled Z, (ctls, qubit)); diff --git a/src/Simulation/TargetDefinitions/TargetPackages/Type1.Package.props b/src/Simulation/TargetDefinitions/TargetPackages/Type1.Package.props index 866fd1f0391..a66eb655be5 100644 --- a/src/Simulation/TargetDefinitions/TargetPackages/Type1.Package.props +++ b/src/Simulation/TargetDefinitions/TargetPackages/Type1.Package.props @@ -26,6 +26,9 @@ + + + diff --git a/src/Simulation/TargetDefinitions/TargetPackages/Type3.Package.props b/src/Simulation/TargetDefinitions/TargetPackages/Type3.Package.props index b0d5d34c908..3dd8eee8145 100644 --- a/src/Simulation/TargetDefinitions/TargetPackages/Type3.Package.props +++ b/src/Simulation/TargetDefinitions/TargetPackages/Type3.Package.props @@ -27,6 +27,9 @@ + + + diff --git a/src/Simulation/qdk_sim_rs/src/common_matrices.rs b/src/Simulation/qdk_sim_rs/src/common_matrices.rs index 4247b1d6234..60d562ee0bc 100644 --- a/src/Simulation/qdk_sim_rs/src/common_matrices.rs +++ b/src/Simulation/qdk_sim_rs/src/common_matrices.rs @@ -24,7 +24,7 @@ pub fn x() -> Array2 { /// Returns a unitary matrix representing the `Y` operation. pub fn y() -> Array2 { - array![[ZERO_C, I_C], [-I_C, ZERO_C]] + array![[ZERO_C, -I_C], [I_C, ZERO_C]] } /// Returns a unitary matrix representing the `Z` operation. diff --git a/src/Simulation/qdk_sim_rs/tests/data/ideal-noise-model.json b/src/Simulation/qdk_sim_rs/tests/data/ideal-noise-model.json index 33c2d3089bb..19778ad8793 100644 --- a/src/Simulation/qdk_sim_rs/tests/data/ideal-noise-model.json +++ b/src/Simulation/qdk_sim_rs/tests/data/ideal-noise-model.json @@ -1 +1 @@ -{"initial_state":{"n_qubits":1,"data":{"Mixed":{"v":1,"dim":[2,2],"data":[[1,0],[0,0],[0,0],[0,0]]}}},"cnot":{"n_qubits":2,"data":{"Unitary":{"v":1,"dim":[4,4],"data":[[1,0],[0,0],[0,0],[0,0],[0,0],[1,0],[0,0],[0,0],[0,0],[0,0],[0,0],[1,0],[0,0],[0,0],[1,0],[0,0]]}}},"i":{"n_qubits":1,"data":{"Unitary":{"v":1,"dim":[2,2],"data":[[1,0],[0,0],[0,0],[1,0]]}}},"s":{"n_qubits":1,"data":{"Unitary":{"v":1,"dim":[2,2],"data":[[1,0],[0,0],[0,0],[0,1]]}}},"s_adj":{"n_qubits":1,"data":{"Unitary":{"v":1,"dim":[2,2],"data":[[1,-0],[0,-0],[0,-0],[0,-1]]}}},"t":{"n_qubits":1,"data":{"Unitary":{"v":1,"dim":[2,2],"data":[[1,0],[0,0],[0,0],[0.7071067811865476,0.7071067811865476]]}}},"t_adj":{"n_qubits":1,"data":{"Unitary":{"v":1,"dim":[2,2],"data":[[1,-0],[0,-0],[0,-0],[0.7071067811865476,-0.7071067811865476]]}}},"h":{"n_qubits":1,"data":{"Unitary":{"v":1,"dim":[2,2],"data":[[0.7071067811865476,0],[0.7071067811865476,0],[0.7071067811865476,0],[-0.7071067811865476,-0]]}}},"x":{"n_qubits":1,"data":{"Unitary":{"v":1,"dim":[2,2],"data":[[0,0],[1,0],[1,0],[0,0]]}}},"y":{"n_qubits":1,"data":{"Unitary":{"v":1,"dim":[2,2],"data":[[0,0],[0,1],[-0,-1],[0,0]]}}},"z":{"n_qubits":1,"data":{"Unitary":{"v":1,"dim":[2,2],"data":[[1,0],[0,0],[0,0],[-1,-0]]}}},"z_meas":{"Effects":[{"n_qubits":1,"data":{"KrausDecomposition":{"v":1,"dim":[1,2,2],"data":[[1,0],[0,0],[0,0],[0,0]]}}},{"n_qubits":1,"data":{"KrausDecomposition":{"v":1,"dim":[1,2,2],"data":[[0,0],[0,0],[0,0],[1,0]]}}}]}} \ No newline at end of file +{"initial_state":{"n_qubits":1,"data":{"Mixed":{"v":1,"dim":[2,2],"data":[[1,0],[0,0],[0,0],[0,0]]}}},"cnot":{"n_qubits":2,"data":{"Unitary":{"v":1,"dim":[4,4],"data":[[1,0],[0,0],[0,0],[0,0],[0,0],[1,0],[0,0],[0,0],[0,0],[0,0],[0,0],[1,0],[0,0],[0,0],[1,0],[0,0]]}}},"i":{"n_qubits":1,"data":{"Unitary":{"v":1,"dim":[2,2],"data":[[1,0],[0,0],[0,0],[1,0]]}}},"s":{"n_qubits":1,"data":{"Unitary":{"v":1,"dim":[2,2],"data":[[1,0],[0,0],[0,0],[0,1]]}}},"s_adj":{"n_qubits":1,"data":{"Unitary":{"v":1,"dim":[2,2],"data":[[1,-0],[0,-0],[0,-0],[0,-1]]}}},"t":{"n_qubits":1,"data":{"Unitary":{"v":1,"dim":[2,2],"data":[[1,0],[0,0],[0,0],[0.7071067811865476,0.7071067811865476]]}}},"t_adj":{"n_qubits":1,"data":{"Unitary":{"v":1,"dim":[2,2],"data":[[1,-0],[0,-0],[0,-0],[0.7071067811865476,-0.7071067811865476]]}}},"h":{"n_qubits":1,"data":{"Unitary":{"v":1,"dim":[2,2],"data":[[0.7071067811865476,0],[0.7071067811865476,0],[0.7071067811865476,0],[-0.7071067811865476,-0]]}}},"x":{"n_qubits":1,"data":{"Unitary":{"v":1,"dim":[2,2],"data":[[0,0],[1,0],[1,0],[0,0]]}}},"y":{"n_qubits":1,"data":{"Unitary":{"v":1,"dim":[2,2],"data":[[0,0],[-0,-1],[0,1],[0,0]]}}},"z":{"n_qubits":1,"data":{"Unitary":{"v":1,"dim":[2,2],"data":[[1,0],[0,0],[0,0],[-1,-0]]}}},"z_meas":{"Effects":[{"n_qubits":1,"data":{"KrausDecomposition":{"v":1,"dim":[1,2,2],"data":[[1,0],[0,0],[0,0],[0,0]]}}},{"n_qubits":1,"data":{"KrausDecomposition":{"v":1,"dim":[1,2,2],"data":[[0,0],[0,0],[0,0],[1,0]]}}}]}}