diff --git a/.github/workflows/create-jira-issues-for-community-activities.yml b/.github/workflows/create-jira-issues-for-community-activities.yml index e24ed025..0e146dc0 100644 --- a/.github/workflows/create-jira-issues-for-community-activities.yml +++ b/.github/workflows/create-jira-issues-for-community-activities.yml @@ -5,7 +5,7 @@ on: types: [created] issues: types: [opened] - pull_request: + pull_request_target: types: [opened] jobs: diff --git a/Docs/GettingStarted.md b/Docs/GettingStarted.md index 2e6d2474..fbb6baa4 100644 --- a/Docs/GettingStarted.md +++ b/Docs/GettingStarted.md @@ -7,7 +7,7 @@ To begin working with Hastlayer you'll need the following: - A .NET project that requires some hardware acceleration. - A compatible FPGA board. You have the following options here: - For production-level commercial workloads: - - Using [Xilinx Alveo U50, U200, U250 or U280 Data Center Accelerator Cards](https://www.xilinx.com/products/boards-and-kits/alveo.html) on-premises or in the cloud. In the cloud you can use them on Azure. + - Using [Xilinx Alveo U50, U200, U250 or U280 Data Center Accelerator Cards](https://www.xilinx.com/products/boards-and-kits/alveo.html) on-premises or in the cloud. In the cloud you can use them on Azure in [NP-series virtual machines](https://learn.microsoft.com/en-us/azure/virtual-machines/np-series). - Using [AWS EC2 F1 instances](https://aws.amazon.com/ec2/instance-types/f1/). - For embedded workloads: Using single board/module computers with Xilinx Zynq-7000 series SoC. We officially support the [Trenz Electronic TE0715-04-30-1C](https://shop.trenz-electronic.de/en/TE0715-04-30-1C-SoC-Module-with-Xilinx-Zynq-XC7Z030-1SBG485C-1-GByte-DDR3L-SDRAM-4-x-5-cm) module, but the codebase isn't highly specific to it and you can make your own manifest provider and device driver by inheriting from the same base classes. - For simpler workloads and testing: The [Nexys A7 (formerly known as Nexys 4 DDR)](https://store.digilentinc.com/nexys-a7-fpga-trainer-board-recommended-for-ece-curriculum/) board (which is **NOT** the same as the non-DDR Nexys 4, be sure to purchase the linked board!) is suitable. The **Nexys A7-100T** version is required. Note that this is a relatively low-end development board that can't fit huge algorithms and it only supports slow communication channels. So with this board Hastlayer is only suitable for simpler algorithms that only need to exchange small amount of data. Note that to work with Nexys cards, you need to use the Hastlayer SDK from source. diff --git a/Docs/WorkingWithHastlayer.md b/Docs/WorkingWithHastlayer.md index 02eda4ff..a1223f47 100644 --- a/Docs/WorkingWithHastlayer.md +++ b/Docs/WorkingWithHastlayer.md @@ -4,7 +4,7 @@ You can add Hastlayer to your app from NuGet, and then get going, see the steps below. You can also check out a sample solution right away, in [the _NuGetTest_ folder of this repo](../NuGetTest). -1. Install the latest version of the `Hast.Layer` NuGet package. +1. Install the latest version of the [`Hast.Layer` NuGet package](https://www.nuget.org/packages/Hast.Layer/). 2. You'll need a hardware framework too; currently, there's only one, so also install the latest version of the `Hast.Vitis.HardwareFramework` NuGet package. 3. In the project where you want to use Hastlayer add the necessary initialization code (as shown in the samples). 4. You're ready to start working with Hastlayer! We suggest starting with the included samples then taking your first Hastlayer steps by writing some small algorithm, then gradually stepping up to more complex applications. You can check out all the samples in the _Samples_ solution folder of the SDK. diff --git a/NuGetTest/Hast.NuGet.Console/Hast.NuGet.Console.csproj b/NuGetTest/Hast.NuGet.Console/Hast.NuGet.Console.csproj index f4c49234..221916f9 100644 --- a/NuGetTest/Hast.NuGet.Console/Hast.NuGet.Console.csproj +++ b/NuGetTest/Hast.NuGet.Console/Hast.NuGet.Console.csproj @@ -8,8 +8,8 @@ - - + + diff --git a/src/Hastlayer/Hast.Transformer.Vhdl/Verifiers/HardwareEntryPointsVerifier.cs b/src/Hastlayer/Hast.Transformer.Vhdl/Verifiers/HardwareEntryPointsVerifier.cs index ba563347..78cc28d8 100644 --- a/src/Hastlayer/Hast.Transformer.Vhdl/Verifiers/HardwareEntryPointsVerifier.cs +++ b/src/Hastlayer/Hast.Transformer.Vhdl/Verifiers/HardwareEntryPointsVerifier.cs @@ -36,7 +36,9 @@ private void VerifyHardwareEntryPoints(SyntaxTree syntaxTree, ITypeDeclarationLo { var unsupportedMembers = type .Members - .Where(member => member is FieldDeclaration || member is PropertyDeclaration || member.GetFullName().IsConstructorName()); + .Where(member => + (member is FieldDeclaration or PropertyDeclaration && !member.HasModifier(Modifiers.Const)) || + member.GetFullName().IsConstructorName()); if (unsupportedMembers.Any()) { throw new NotSupportedException( diff --git a/src/Hastlayer/Hast.Transformer/Models/IArraySizeHolder.cs b/src/Hastlayer/Hast.Transformer/Models/IArraySizeHolder.cs index 93422200..90cfc447 100644 --- a/src/Hastlayer/Hast.Transformer/Models/IArraySizeHolder.cs +++ b/src/Hastlayer/Hast.Transformer/Models/IArraySizeHolder.cs @@ -49,10 +49,10 @@ public static IArraySize GetSizeOrThrow(this IArraySizeHolder arraySizeHolder, A if (size == null) { throw new NotSupportedException( - "The length of the array holder " + arrayHolder.GetFullName() + - " couldn't be statically determined. Only arrays with dimensions defined at compile-time are " + - "supported. If the array size is actually static just Hastlayer can't figure it out for some " + - "reason then you can configure it manually via TransformerConfiguration."); + "The length of the array holder \"" + arrayHolder.GetFullName() + "\" couldn't be statically " + + "determined. Only arrays with dimensions defined at compile-time are supported. If the array size is " + + "actually static just Hastlayer can't figure it out for some reason then you can configure it " + + "manually via TransformerConfiguration by using the quoted full name."); } return size; diff --git a/src/Hastlayer/Hast.Transformer/Services/ConstantValuesSubstitution/ConstantValuesMarkingVisitor.cs b/src/Hastlayer/Hast.Transformer/Services/ConstantValuesSubstitution/ConstantValuesMarkingVisitor.cs index 4f303fe1..10ac37f4 100644 --- a/src/Hastlayer/Hast.Transformer/Services/ConstantValuesSubstitution/ConstantValuesMarkingVisitor.cs +++ b/src/Hastlayer/Hast.Transformer/Services/ConstantValuesSubstitution/ConstantValuesMarkingVisitor.cs @@ -215,6 +215,16 @@ private void PassLengthOfArrayHolderToParent(AstNode arrayHolder, int arrayLengt { AssignmentHandler = assignmentExpression => { + // Only assignments where an array is assigned to another member/variable matters, not just any + // assignment where arrayHolder is on the right (excluding cases where e.g. the right side is a + // method call with an array as an argument). + if (assignmentExpression.Right != arrayHolder && + assignmentExpression.Right is InvocationExpression invocationExpression && + invocationExpression.Target != arrayHolder) + { + return; + } + if (assignmentExpression.Left is MemberReferenceExpression memberReferenceExpression) { _arraySizeHolder.SetSize( diff --git a/src/Hastlayer/Hast.Transformer/Services/ConstantValuesSubstitution/ConstantValuesSubstitutingVisitor.cs b/src/Hastlayer/Hast.Transformer/Services/ConstantValuesSubstitution/ConstantValuesSubstitutingVisitor.cs index 03ead263..c3776ccd 100644 --- a/src/Hastlayer/Hast.Transformer/Services/ConstantValuesSubstitution/ConstantValuesSubstitutingVisitor.cs +++ b/src/Hastlayer/Hast.Transformer/Services/ConstantValuesSubstitution/ConstantValuesSubstitutingVisitor.cs @@ -256,9 +256,10 @@ protected override void VisitChildren(AstNode node) } } - // Is this a const? Then we can just substitute it directly. + // Is this a const expression? Then we can just substitute it directly. var resolveResult = node.GetResolveResult(); - if (resolveResult?.IsCompileTimeConstant == true && + if (node is Expression && + resolveResult?.IsCompileTimeConstant == true && resolveResult.ConstantValue != null && node is not PrimitiveExpression) { diff --git a/src/Hastlayer/Hast.Vitis/Docs/AzureReadme.md b/src/Hastlayer/Hast.Vitis/Docs/AzureReadme.md index 59a9ae13..8e21f76f 100644 --- a/src/Hastlayer/Hast.Vitis/Docs/AzureReadme.md +++ b/src/Hastlayer/Hast.Vitis/Docs/AzureReadme.md @@ -1,6 +1,6 @@ # Using Hastlayer with Vitis boards on Azure NP Servers -If you want work with an Alveo card on an Azure VM, you need to pick the Azure-specific device (currently only `Azure Alveo U250`). This alters some of the automatic compilation steps. After compilation it submits your binary to an attestation server (via Azure Blob Storage) for automatic approval. +If you want work with an Alveo card on an [Azure NP-series VM](https://learn.microsoft.com/en-us/azure/virtual-machines/np-series), you need to pick the Azure-specific device (currently only `Azure Alveo U250`). This alters some of the automatic compilation steps. After compilation it submits your binary to an attestation server (via Azure Blob Storage) for automatic approval. ## Preparation diff --git a/src/Hastlayer/Hast.Vitis/Readme.md b/src/Hastlayer/Hast.Vitis/Readme.md index 908edfdf..39af52cb 100644 --- a/src/Hastlayer/Hast.Vitis/Readme.md +++ b/src/Hastlayer/Hast.Vitis/Readme.md @@ -4,7 +4,7 @@ ## Overview -This project contains the communication service used to connect with Xilinx's [Vitis Unified Software Platform](https://www.xilinx.com/products/design-tools/vitis/vitis-platform.html) devices, such as the [Xilinx Alveo U250](https://www.xilinx.com/products/boards-and-kits/alveo/u250.html) FPGA accelerator card via the [OpenCL](https://www.khronos.org/opencl/) library. +This project contains the communication service used to connect with Xilinx's [Vitis Unified Software Platform](https://www.xilinx.com/products/design-tools/vitis/vitis-platform.html) devices, such as the [Xilinx Alveo U250](https://www.xilinx.com/products/boards-and-kits/alveo/u250.html) FPGA accelerator card via the [OpenCL](https://www.khronos.org/opencl/) library. This includes [Azure NP-series virtual machines](https://learn.microsoft.com/en-us/azure/virtual-machines/np-series). Note that the SH scripts in this project should use LF line endings! You'll get errors such as `-bash: $'\r': command not found` otherwise. diff --git a/src/Samples/Hast.Samples.SampleAssembly/Hast.Samples.SampleAssembly.csproj b/src/Samples/Hast.Samples.SampleAssembly/Hast.Samples.SampleAssembly.csproj index e6d70928..2455902f 100644 --- a/src/Samples/Hast.Samples.SampleAssembly/Hast.Samples.SampleAssembly.csproj +++ b/src/Samples/Hast.Samples.SampleAssembly/Hast.Samples.SampleAssembly.csproj @@ -12,8 +12,8 @@ - - + + diff --git a/test/Hast.Transformer.Vhdl.Tests/VerificationTests/StaticTestInputAssembliesVerificationTests.cs b/test/Hast.Transformer.Vhdl.Tests/VerificationTests/StaticTestInputAssembliesVerificationTests.cs index 152671c1..59e6934b 100644 --- a/test/Hast.Transformer.Vhdl.Tests/VerificationTests/StaticTestInputAssembliesVerificationTests.cs +++ b/test/Hast.Transformer.Vhdl.Tests/VerificationTests/StaticTestInputAssembliesVerificationTests.cs @@ -30,7 +30,12 @@ public Task StaticTestInputAssemblyMatchesApproved() => new[] { typeof(ArrayUsingCases).Assembly }, configuration => { - configuration.TransformerConfiguration().UseSimpleMemory = false; + var transformerConfiguration = configuration.TransformerConfiguration(); + transformerConfiguration.UseSimpleMemory = false; + // This shouldn't be necessary: https://github.com/Lombiq/Hastlayer-SDK/issues/112. + transformerConfiguration.ArrayLengths.Add( + "System.Int32 Hast.TestInputs.Static.ArrayUsingCases+<>c::b__1_0(System.Object).arrayObject", + ArrayUsingCases.TaskArrayLength); configuration .TransformerConfiguration() diff --git a/test/Hast.Transformer.Vhdl.Tests/VerificationTests/VerificationSources/StaticTestInputAssembliesVerificationTests.StaticTestInputAssemblyMatchesApproved.approved.vhdl b/test/Hast.Transformer.Vhdl.Tests/VerificationTests/VerificationSources/StaticTestInputAssembliesVerificationTests.StaticTestInputAssemblyMatchesApproved.approved.vhdl index 5c7c2e10..81a06fb8 100644 --- a/test/Hast.Transformer.Vhdl.Tests/VerificationTests/VerificationSources/StaticTestInputAssembliesVerificationTests.StaticTestInputAssemblyMatchesApproved.approved.vhdl +++ b/test/Hast.Transformer.Vhdl.Tests/VerificationTests/VerificationSources/StaticTestInputAssembliesVerificationTests.StaticTestInputAssemblyMatchesApproved.approved.vhdl @@ -1,4 +1,5 @@ -- Generated by Hastlayer (hastlayer.com) at for the following hardware entry points: +-- * System.Void Hast.TestInputs.Static.ArrayUsingCases::PassArrayToTask() -- * System.Void Hast.TestInputs.Static.ArrayUsingCases::PassArrayToConstructor() -- * System.Void Hast.TestInputs.Static.ArrayUsingCases::PassArrayFromMethod() -- * System.Void Hast.TestInputs.Static.ConstantsUsingCases::ConstantValuedVariables(System.Int32) @@ -117,9 +118,9 @@ architecture Imp of Hast_IP is -- * The InternalInvocationProxy processes dispatch invocations between state machines. -- Custom inter-dependent type declarations start + type \unsigned8_Array\ is array (integer range <>) of unsigned(7 downto 0); type \signed32_Array\ is array (integer range <>) of signed(31 downto 0); type \unsigned32_Array\ is array (integer range <>) of unsigned(31 downto 0); - type \unsigned8_Array\ is array (integer range <>) of unsigned(7 downto 0); type \boolean_Array\ is array (integer range <>) of boolean; type \Hast.TestInputs.Static.ArrayUsingCases+ArrayHolder\ is record \IsNull\: boolean; @@ -167,6 +168,36 @@ architecture Imp of Hast_IP is -- System.Void Hast.TestInputs.Static.ArrayUsingCases+ArrayHolder::.ctor(System.Int32[]).0 declarations end + -- System.Int32 Hast.TestInputs.Static.ArrayUsingCases+<>c::b__1_0(System.Object).0 declarations start + -- State machine states: + type \ArrayUsingCases+<>c::b__1_0(Object).0._States\ is ( + \ArrayUsingCases+<>c::b__1_0(Object).0._State_0\, + \ArrayUsingCases+<>c::b__1_0(Object).0._State_1\, + \ArrayUsingCases+<>c::b__1_0(Object).0._State_2\); + -- Signals: + Signal \ArrayUsingCases+<>c::b__1_0(Object).0._Finished\: boolean := false; + Signal \ArrayUsingCases+<>c::b__1_0(Object).0.return\: signed(31 downto 0) := to_signed(0, 32); + Signal \ArrayUsingCases+<>c::b__1_0(Object).0.arrayObject.parameter.Out\: \signed32_Array\(0 to 9) := (others => to_signed(0, 32)); + Signal \ArrayUsingCases+<>c::b__1_0(Object).0._Started\: boolean := false; + Signal \ArrayUsingCases+<>c::b__1_0(Object).0.arrayObject.parameter.In\: \signed32_Array\(0 to 9) := (others => to_signed(0, 32)); + -- System.Int32 Hast.TestInputs.Static.ArrayUsingCases+<>c::b__1_0(System.Object).0 declarations end + + + -- System.Void Hast.TestInputs.Static.ArrayUsingCases::PassArrayToTask().0 declarations start + -- State machine states: + type \ArrayUsingCases::PassArrayToTask().0._States\ is ( + \ArrayUsingCases::PassArrayToTask().0._State_0\, + \ArrayUsingCases::PassArrayToTask().0._State_1\, + \ArrayUsingCases::PassArrayToTask().0._State_2\); + -- Signals: + Signal \ArrayUsingCases::PassArrayToTask().0._Finished\: boolean := false; + Signal \ArrayUsingCases::PassArrayToTask().0.ArrayUsingCases+<>c::b__1_0(Object).arrayObject.parameter.Out.0\: \signed32_Array\(0 to 9) := (others => to_signed(0, 32)); + Signal \ArrayUsingCases::PassArrayToTask().0.ArrayUsingCases+<>c::b__1_0(Object)._Started.0\: boolean := false; + Signal \ArrayUsingCases::PassArrayToTask().0._Started\: boolean := false; + Signal \ArrayUsingCases::PassArrayToTask().0.ArrayUsingCases+<>c::b__1_0(Object).arrayObject.parameter.In.0\: \signed32_Array\(0 to 9) := (others => to_signed(0, 32)); + -- System.Void Hast.TestInputs.Static.ArrayUsingCases::PassArrayToTask().0 declarations end + + -- System.Void Hast.TestInputs.Static.ArrayUsingCases::PassArrayToConstructor().0 declarations start -- State machine states: type \ArrayUsingCases::PassArrayToConstructor().0._States\ is ( @@ -786,6 +817,7 @@ architecture Imp of Hast_IP is -- System.Void Hast::ExternalInvocationProxy() declarations start -- Signals: Signal \FinishedInternal\: boolean := false; + Signal \Hast::ExternalInvocationProxy().ArrayUsingCases::PassArrayToTask()._Started.0\: boolean := false; Signal \Hast::ExternalInvocationProxy().ArrayUsingCases::PassArrayToConstructor()._Started.0\: boolean := false; Signal \Hast::ExternalInvocationProxy().ArrayUsingCases::PassArrayFromMethod()._Started.0\: boolean := false; Signal \Hast::ExternalInvocationProxy().ConstantsUsingCases::ConstantValuedVariables(Int32)._Started.0\: boolean := false; @@ -800,6 +832,7 @@ architecture Imp of Hast_IP is Signal \Hast::ExternalInvocationProxy().ParallelCases::WhenAllWhenAnyAwaitedTasks(UInt32)._Started.0\: boolean := false; Signal \Hast::ExternalInvocationProxy().ParallelCases::ObjectUsingTasks(UInt32)._Started.0\: boolean := false; Signal \Hast::ExternalInvocationProxy().UnaryCases::IncrementDecrement(Int32)._Started.0\: boolean := false; + Signal \Hast::ExternalInvocationProxy().ArrayUsingCases::PassArrayToTask()._Finished.0\: boolean := false; Signal \Hast::ExternalInvocationProxy().ArrayUsingCases::PassArrayToConstructor()._Finished.0\: boolean := false; Signal \Hast::ExternalInvocationProxy().ArrayUsingCases::PassArrayFromMethod()._Finished.0\: boolean := false; Signal \Hast::ExternalInvocationProxy().ConstantsUsingCases::ConstantValuedVariables(Int32)._Finished.0\: boolean := false; @@ -878,6 +911,123 @@ begin -- System.Void Hast.TestInputs.Static.ArrayUsingCases+ArrayHolder::.ctor(System.Int32[]).0 state machine end + -- System.Int32 Hast.TestInputs.Static.ArrayUsingCases+<>c::b__1_0(System.Object).0 state machine start + \ArrayUsingCases+<>c::b__1_0(Object).0._StateMachine\: process (\Clock\) + Variable \ArrayUsingCases+<>c::b__1_0(Object).0._State\: \ArrayUsingCases+<>c::b__1_0(Object).0._States\ := \ArrayUsingCases+<>c::b__1_0(Object).0._State_0\; + Variable \ArrayUsingCases+<>c::b__1_0(Object).0.arrayObject\: \signed32_Array\(0 to 9) := (others => to_signed(0, 32)); + begin + if (rising_edge(\Clock\)) then + if (\Reset\ = '1') then + -- Synchronous reset + \ArrayUsingCases+<>c::b__1_0(Object).0._Finished\ <= false; + \ArrayUsingCases+<>c::b__1_0(Object).0.return\ <= to_signed(0, 32); + \ArrayUsingCases+<>c::b__1_0(Object).0.arrayObject.parameter.Out\ <= (others => to_signed(0, 32)); + \ArrayUsingCases+<>c::b__1_0(Object).0._State\ := \ArrayUsingCases+<>c::b__1_0(Object).0._State_0\; + \ArrayUsingCases+<>c::b__1_0(Object).0.arrayObject\ := (others => to_signed(0, 32)); + else + case \ArrayUsingCases+<>c::b__1_0(Object).0._State\ is + when \ArrayUsingCases+<>c::b__1_0(Object).0._State_0\ => + -- Start state + -- Waiting for the start signal. + if (\ArrayUsingCases+<>c::b__1_0(Object).0._Started\ = true) then + \ArrayUsingCases+<>c::b__1_0(Object).0._State\ := \ArrayUsingCases+<>c::b__1_0(Object).0._State_2\; + end if; + -- Clock cycles needed to complete this state (approximation): 0 + when \ArrayUsingCases+<>c::b__1_0(Object).0._State_1\ => + -- Final state + -- Signaling finished until Started is pulled back to false, then returning to the start state. + if (\ArrayUsingCases+<>c::b__1_0(Object).0._Started\ = true) then + \ArrayUsingCases+<>c::b__1_0(Object).0._Finished\ <= true; + else + \ArrayUsingCases+<>c::b__1_0(Object).0._Finished\ <= false; + \ArrayUsingCases+<>c::b__1_0(Object).0._State\ := \ArrayUsingCases+<>c::b__1_0(Object).0._State_0\; + end if; + -- Writing back out-flowing parameters so any changes made in this state machine will be reflected in the invoking one too. + \ArrayUsingCases+<>c::b__1_0(Object).0.arrayObject.parameter.Out\ <= \ArrayUsingCases+<>c::b__1_0(Object).0.arrayObject\; + -- Clock cycles needed to complete this state (approximation): 0 + when \ArrayUsingCases+<>c::b__1_0(Object).0._State_2\ => + \ArrayUsingCases+<>c::b__1_0(Object).0.arrayObject\ := \ArrayUsingCases+<>c::b__1_0(Object).0.arrayObject.parameter.In\; + -- The following section was transformed from the .NET statement below: + -- arrayObject [0] = 123; + -- + \ArrayUsingCases+<>c::b__1_0(Object).0.arrayObject\(to_integer(to_signed(0, 32))) := to_signed(123, 32); + -- The following section was transformed from the .NET statement below: + -- return arrayObject [0]; + -- + \ArrayUsingCases+<>c::b__1_0(Object).0.return\ <= \ArrayUsingCases+<>c::b__1_0(Object).0.arrayObject\(to_integer(to_signed(0, 32))); + \ArrayUsingCases+<>c::b__1_0(Object).0._State\ := \ArrayUsingCases+<>c::b__1_0(Object).0._State_1\; + -- Clock cycles needed to complete this state (approximation): 0 + end case; + end if; + end if; + end process; + -- System.Int32 Hast.TestInputs.Static.ArrayUsingCases+<>c::b__1_0(System.Object).0 state machine end + + + -- System.Void Hast.TestInputs.Static.ArrayUsingCases::PassArrayToTask().0 state machine start + \ArrayUsingCases::PassArrayToTask().0._StateMachine\: process (\Clock\) + Variable \ArrayUsingCases::PassArrayToTask().0._State\: \ArrayUsingCases::PassArrayToTask().0._States\ := \ArrayUsingCases::PassArrayToTask().0._State_0\; + Variable \ArrayUsingCases::PassArrayToTask().0.state\: \signed32_Array\(0 to 9) := (others => to_signed(0, 32)); + Variable \ArrayUsingCases::PassArrayToTask().0.array\: \signed32_Array\(0 to 14) := (others => to_signed(0, 32)); + begin + if (rising_edge(\Clock\)) then + if (\Reset\ = '1') then + -- Synchronous reset + \ArrayUsingCases::PassArrayToTask().0._Finished\ <= false; + \ArrayUsingCases::PassArrayToTask().0.ArrayUsingCases+<>c::b__1_0(Object).arrayObject.parameter.Out.0\ <= (others => to_signed(0, 32)); + \ArrayUsingCases::PassArrayToTask().0.ArrayUsingCases+<>c::b__1_0(Object)._Started.0\ <= false; + \ArrayUsingCases::PassArrayToTask().0._State\ := \ArrayUsingCases::PassArrayToTask().0._State_0\; + \ArrayUsingCases::PassArrayToTask().0.state\ := (others => to_signed(0, 32)); + \ArrayUsingCases::PassArrayToTask().0.array\ := (others => to_signed(0, 32)); + else + case \ArrayUsingCases::PassArrayToTask().0._State\ is + when \ArrayUsingCases::PassArrayToTask().0._State_0\ => + -- Start state + -- Waiting for the start signal. + if (\ArrayUsingCases::PassArrayToTask().0._Started\ = true) then + \ArrayUsingCases::PassArrayToTask().0._State\ := \ArrayUsingCases::PassArrayToTask().0._State_2\; + end if; + -- Clock cycles needed to complete this state (approximation): 0 + when \ArrayUsingCases::PassArrayToTask().0._State_1\ => + -- Final state + -- Signaling finished until Started is pulled back to false, then returning to the start state. + if (\ArrayUsingCases::PassArrayToTask().0._Started\ = true) then + \ArrayUsingCases::PassArrayToTask().0._Finished\ <= true; + else + \ArrayUsingCases::PassArrayToTask().0._Finished\ <= false; + \ArrayUsingCases::PassArrayToTask().0._State\ := \ArrayUsingCases::PassArrayToTask().0._State_0\; + end if; + -- Clock cycles needed to complete this state (approximation): 0 + when \ArrayUsingCases::PassArrayToTask().0._State_2\ => + -- The following section was transformed from the .NET statement below: + -- int[] state; + -- + -- The following section was transformed from the .NET statement below: + -- state = new int[10]; + -- + \ArrayUsingCases::PassArrayToTask().0.state\ := (others => to_signed(0, 32)); + -- The following section was transformed from the .NET statement below: + -- Task[] array; + -- + -- The following section was transformed from the .NET statement below: + -- array = new Task[15]; + -- + \ArrayUsingCases::PassArrayToTask().0.array\ := (others => to_signed(0, 32)); + -- The following section was transformed from the .NET statement below: + -- array [0] = Task.Factory.StartNew (<>c.<>9__1_0 ?? (<>c.<>9__1_0 = <>c.<>9.b__1_0), state); + -- + -- Starting state machine invocation for the following method: System.Int32 Hast.TestInputs.Static.ArrayUsingCases+<>c::b__1_0(System.Object) + \ArrayUsingCases::PassArrayToTask().0.ArrayUsingCases+<>c::b__1_0(Object).arrayObject.parameter.Out.0\ <= \ArrayUsingCases::PassArrayToTask().0.state\; + \ArrayUsingCases::PassArrayToTask().0.ArrayUsingCases+<>c::b__1_0(Object)._Started.0\ <= true; + \ArrayUsingCases::PassArrayToTask().0._State\ := \ArrayUsingCases::PassArrayToTask().0._State_1\; + -- Clock cycles needed to complete this state (approximation): 0 + end case; + end if; + end if; + end process; + -- System.Void Hast.TestInputs.Static.ArrayUsingCases::PassArrayToTask().0 state machine end + + -- System.Void Hast.TestInputs.Static.ArrayUsingCases::PassArrayToConstructor().0 state machine start \ArrayUsingCases::PassArrayToConstructor().0._StateMachine\: process (\Clock\) Variable \ArrayUsingCases::PassArrayToConstructor().0._State\: \ArrayUsingCases::PassArrayToConstructor().0._States\ := \ArrayUsingCases::PassArrayToConstructor().0._State_0\; @@ -4197,6 +4347,7 @@ begin if (\Reset\ = '1') then -- Synchronous reset \FinishedInternal\ <= false; + \Hast::ExternalInvocationProxy().ArrayUsingCases::PassArrayToTask()._Started.0\ <= false; \Hast::ExternalInvocationProxy().ArrayUsingCases::PassArrayToConstructor()._Started.0\ <= false; \Hast::ExternalInvocationProxy().ArrayUsingCases::PassArrayFromMethod()._Started.0\ <= false; \Hast::ExternalInvocationProxy().ConstantsUsingCases::ConstantValuedVariables(Int32)._Started.0\ <= false; @@ -4216,97 +4367,104 @@ begin -- Starting the state machine corresponding to the given member ID. case \MemberId\ is when 0 => + if (\Hast::ExternalInvocationProxy().ArrayUsingCases::PassArrayToTask()._Started.0\ = false) then + \Hast::ExternalInvocationProxy().ArrayUsingCases::PassArrayToTask()._Started.0\ <= true; + elsif (\Hast::ExternalInvocationProxy().ArrayUsingCases::PassArrayToTask()._Started.0\ = \Hast::ExternalInvocationProxy().ArrayUsingCases::PassArrayToTask()._Finished.0\) then + \Hast::ExternalInvocationProxy().ArrayUsingCases::PassArrayToTask()._Started.0\ <= false; + \FinishedInternal\ <= true; + end if; + when 1 => if (\Hast::ExternalInvocationProxy().ArrayUsingCases::PassArrayToConstructor()._Started.0\ = false) then \Hast::ExternalInvocationProxy().ArrayUsingCases::PassArrayToConstructor()._Started.0\ <= true; elsif (\Hast::ExternalInvocationProxy().ArrayUsingCases::PassArrayToConstructor()._Started.0\ = \Hast::ExternalInvocationProxy().ArrayUsingCases::PassArrayToConstructor()._Finished.0\) then \Hast::ExternalInvocationProxy().ArrayUsingCases::PassArrayToConstructor()._Started.0\ <= false; \FinishedInternal\ <= true; end if; - when 1 => + when 2 => if (\Hast::ExternalInvocationProxy().ArrayUsingCases::PassArrayFromMethod()._Started.0\ = false) then \Hast::ExternalInvocationProxy().ArrayUsingCases::PassArrayFromMethod()._Started.0\ <= true; elsif (\Hast::ExternalInvocationProxy().ArrayUsingCases::PassArrayFromMethod()._Started.0\ = \Hast::ExternalInvocationProxy().ArrayUsingCases::PassArrayFromMethod()._Finished.0\) then \Hast::ExternalInvocationProxy().ArrayUsingCases::PassArrayFromMethod()._Started.0\ <= false; \FinishedInternal\ <= true; end if; - when 2 => + when 3 => if (\Hast::ExternalInvocationProxy().ConstantsUsingCases::ConstantValuedVariables(Int32)._Started.0\ = false) then \Hast::ExternalInvocationProxy().ConstantsUsingCases::ConstantValuedVariables(Int32)._Started.0\ <= true; elsif (\Hast::ExternalInvocationProxy().ConstantsUsingCases::ConstantValuedVariables(Int32)._Started.0\ = \Hast::ExternalInvocationProxy().ConstantsUsingCases::ConstantValuedVariables(Int32)._Finished.0\) then \Hast::ExternalInvocationProxy().ConstantsUsingCases::ConstantValuedVariables(Int32)._Started.0\ <= false; \FinishedInternal\ <= true; end if; - when 3 => + when 4 => if (\Hast::ExternalInvocationProxy().ConstantsUsingCases::ConstantPassingToMethod(Int32)._Started.0\ = false) then \Hast::ExternalInvocationProxy().ConstantsUsingCases::ConstantPassingToMethod(Int32)._Started.0\ <= true; elsif (\Hast::ExternalInvocationProxy().ConstantsUsingCases::ConstantPassingToMethod(Int32)._Started.0\ = \Hast::ExternalInvocationProxy().ConstantsUsingCases::ConstantPassingToMethod(Int32)._Finished.0\) then \Hast::ExternalInvocationProxy().ConstantsUsingCases::ConstantPassingToMethod(Int32)._Started.0\ <= false; \FinishedInternal\ <= true; end if; - when 4 => + when 5 => if (\Hast::ExternalInvocationProxy().ConstantsUsingCases::ConstantPassingToObject()._Started.0\ = false) then \Hast::ExternalInvocationProxy().ConstantsUsingCases::ConstantPassingToObject()._Started.0\ <= true; elsif (\Hast::ExternalInvocationProxy().ConstantsUsingCases::ConstantPassingToObject()._Started.0\ = \Hast::ExternalInvocationProxy().ConstantsUsingCases::ConstantPassingToObject()._Finished.0\) then \Hast::ExternalInvocationProxy().ConstantsUsingCases::ConstantPassingToObject()._Started.0\ <= false; \FinishedInternal\ <= true; end if; - when 5 => + when 6 => if (\Hast::ExternalInvocationProxy().LoopCases::BreakInLoop(Int32)._Started.0\ = false) then \Hast::ExternalInvocationProxy().LoopCases::BreakInLoop(Int32)._Started.0\ <= true; elsif (\Hast::ExternalInvocationProxy().LoopCases::BreakInLoop(Int32)._Started.0\ = \Hast::ExternalInvocationProxy().LoopCases::BreakInLoop(Int32)._Finished.0\) then \Hast::ExternalInvocationProxy().LoopCases::BreakInLoop(Int32)._Started.0\ <= false; \FinishedInternal\ <= true; end if; - when 6 => + when 7 => if (\Hast::ExternalInvocationProxy().LoopCases::BreakInLoopInLoop(Int32)._Started.0\ = false) then \Hast::ExternalInvocationProxy().LoopCases::BreakInLoopInLoop(Int32)._Started.0\ <= true; elsif (\Hast::ExternalInvocationProxy().LoopCases::BreakInLoopInLoop(Int32)._Started.0\ = \Hast::ExternalInvocationProxy().LoopCases::BreakInLoopInLoop(Int32)._Finished.0\) then \Hast::ExternalInvocationProxy().LoopCases::BreakInLoopInLoop(Int32)._Started.0\ <= false; \FinishedInternal\ <= true; end if; - when 7 => + when 8 => if (\Hast::ExternalInvocationProxy().ObjectUsingCases::NullUsage()._Started.0\ = false) then \Hast::ExternalInvocationProxy().ObjectUsingCases::NullUsage()._Started.0\ <= true; elsif (\Hast::ExternalInvocationProxy().ObjectUsingCases::NullUsage()._Started.0\ = \Hast::ExternalInvocationProxy().ObjectUsingCases::NullUsage()._Finished.0\) then \Hast::ExternalInvocationProxy().ObjectUsingCases::NullUsage()._Started.0\ <= false; \FinishedInternal\ <= true; end if; - when 8 => + when 9 => if (\Hast::ExternalInvocationProxy().ObjectUsingCases::VoidReturn(Int32)._Started.0\ = false) then \Hast::ExternalInvocationProxy().ObjectUsingCases::VoidReturn(Int32)._Started.0\ <= true; elsif (\Hast::ExternalInvocationProxy().ObjectUsingCases::VoidReturn(Int32)._Started.0\ = \Hast::ExternalInvocationProxy().ObjectUsingCases::VoidReturn(Int32)._Finished.0\) then \Hast::ExternalInvocationProxy().ObjectUsingCases::VoidReturn(Int32)._Started.0\ <= false; \FinishedInternal\ <= true; end if; - when 9 => + when 10 => if (\Hast::ExternalInvocationProxy().ObjectUsingCases::ReferenceAssignment(Int32)._Started.0\ = false) then \Hast::ExternalInvocationProxy().ObjectUsingCases::ReferenceAssignment(Int32)._Started.0\ <= true; elsif (\Hast::ExternalInvocationProxy().ObjectUsingCases::ReferenceAssignment(Int32)._Started.0\ = \Hast::ExternalInvocationProxy().ObjectUsingCases::ReferenceAssignment(Int32)._Finished.0\) then \Hast::ExternalInvocationProxy().ObjectUsingCases::ReferenceAssignment(Int32)._Started.0\ <= false; \FinishedInternal\ <= true; end if; - when 10 => + when 11 => if (\Hast::ExternalInvocationProxy().OptionaParametersCases::OmittedOptionalParameters(Int32)._Started.0\ = false) then \Hast::ExternalInvocationProxy().OptionaParametersCases::OmittedOptionalParameters(Int32)._Started.0\ <= true; elsif (\Hast::ExternalInvocationProxy().OptionaParametersCases::OmittedOptionalParameters(Int32)._Started.0\ = \Hast::ExternalInvocationProxy().OptionaParametersCases::OmittedOptionalParameters(Int32)._Finished.0\) then \Hast::ExternalInvocationProxy().OptionaParametersCases::OmittedOptionalParameters(Int32)._Started.0\ <= false; \FinishedInternal\ <= true; end if; - when 11 => + when 12 => if (\Hast::ExternalInvocationProxy().ParallelCases::WhenAllWhenAnyAwaitedTasks(UInt32)._Started.0\ = false) then \Hast::ExternalInvocationProxy().ParallelCases::WhenAllWhenAnyAwaitedTasks(UInt32)._Started.0\ <= true; elsif (\Hast::ExternalInvocationProxy().ParallelCases::WhenAllWhenAnyAwaitedTasks(UInt32)._Started.0\ = \Hast::ExternalInvocationProxy().ParallelCases::WhenAllWhenAnyAwaitedTasks(UInt32)._Finished.0\) then \Hast::ExternalInvocationProxy().ParallelCases::WhenAllWhenAnyAwaitedTasks(UInt32)._Started.0\ <= false; \FinishedInternal\ <= true; end if; - when 12 => + when 13 => if (\Hast::ExternalInvocationProxy().ParallelCases::ObjectUsingTasks(UInt32)._Started.0\ = false) then \Hast::ExternalInvocationProxy().ParallelCases::ObjectUsingTasks(UInt32)._Started.0\ <= true; elsif (\Hast::ExternalInvocationProxy().ParallelCases::ObjectUsingTasks(UInt32)._Started.0\ = \Hast::ExternalInvocationProxy().ParallelCases::ObjectUsingTasks(UInt32)._Finished.0\) then \Hast::ExternalInvocationProxy().ParallelCases::ObjectUsingTasks(UInt32)._Started.0\ <= false; \FinishedInternal\ <= true; end if; - when 13 => + when 14 => if (\Hast::ExternalInvocationProxy().UnaryCases::IncrementDecrement(Int32)._Started.0\ = false) then \Hast::ExternalInvocationProxy().UnaryCases::IncrementDecrement(Int32)._Started.0\ <= true; elsif (\Hast::ExternalInvocationProxy().UnaryCases::IncrementDecrement(Int32)._Started.0\ = \Hast::ExternalInvocationProxy().UnaryCases::IncrementDecrement(Int32)._Finished.0\) then @@ -4328,6 +4486,16 @@ begin -- System.Void Hast::ExternalInvocationProxy() end + -- System.Void Hast::InternalInvocationProxy().System.Int32 Hast.TestInputs.Static.ArrayUsingCases+<>c::b__1_0(System.Object) start + -- Signal connections for System.Void Hast.TestInputs.Static.ArrayUsingCases::PassArrayToTask().0 (#0): + \ArrayUsingCases+<>c::b__1_0(Object).0._Started\ <= \ArrayUsingCases::PassArrayToTask().0.ArrayUsingCases+<>c::b__1_0(Object)._Started.0\; + \ArrayUsingCases+<>c::b__1_0(Object).0.arrayObject.parameter.In\ <= \ArrayUsingCases::PassArrayToTask().0.ArrayUsingCases+<>c::b__1_0(Object).arrayObject.parameter.Out.0\; + \ArrayUsingCases::PassArrayToTask().0.ArrayUsingCases+<>c::b__1_0(Object)._Finished.0\ <= \ArrayUsingCases+<>c::b__1_0(Object).0._Finished\; + \ArrayUsingCases::PassArrayToTask().0.ArrayUsingCases+<>c::b__1_0(Object).return.0\ <= \ArrayUsingCases+<>c::b__1_0(Object).0.return\; + \ArrayUsingCases::PassArrayToTask().0.ArrayUsingCases+<>c::b__1_0(Object).arrayObject.parameter.In.0\ <= \ArrayUsingCases+<>c::b__1_0(Object).0.arrayObject.parameter.Out\; + -- System.Void Hast::InternalInvocationProxy().System.Int32 Hast.TestInputs.Static.ArrayUsingCases+<>c::b__1_0(System.Object) end + + -- System.Void Hast::InternalInvocationProxy().System.Void Hast.TestInputs.Static.ArrayUsingCases+ArrayHolder::.ctor(System.Int32[]) start -- Signal connections for System.Void Hast.TestInputs.Static.ArrayUsingCases::PassArrayToConstructor().0 (#0): \ArrayUsingCases+ArrayHolder::.ctor(Int32[]).0._Started\ <= \ArrayUsingCases::PassArrayToConstructor().0.ArrayUsingCases+ArrayHolder::.ctor(Int32[])._Started.0\; @@ -4565,6 +4733,13 @@ begin -- System.Void Hast::InternalInvocationProxy().System.Boolean Hast.TestInputs.Static.ParallelCases+<>c__DisplayClass1_0::b__0(System.Object) end + -- System.Void Hast::InternalInvocationProxy().System.Void Hast.TestInputs.Static.ArrayUsingCases::PassArrayToTask() start + -- Signal connections for System.Void Hast::ExternalInvocationProxy() (#0): + \ArrayUsingCases::PassArrayToTask().0._Started\ <= \Hast::ExternalInvocationProxy().ArrayUsingCases::PassArrayToTask()._Started.0\; + \Hast::ExternalInvocationProxy().ArrayUsingCases::PassArrayToTask()._Finished.0\ <= \ArrayUsingCases::PassArrayToTask().0._Finished\; + -- System.Void Hast::InternalInvocationProxy().System.Void Hast.TestInputs.Static.ArrayUsingCases::PassArrayToTask() end + + -- System.Void Hast::InternalInvocationProxy().System.Void Hast.TestInputs.Static.ArrayUsingCases::PassArrayToConstructor() start -- Signal connections for System.Void Hast::ExternalInvocationProxy() (#0): \ArrayUsingCases::PassArrayToConstructor().0._Started\ <= \Hast::ExternalInvocationProxy().ArrayUsingCases::PassArrayToConstructor()._Started.0\; diff --git a/test/TestInputAssemblies/Hast.TestInputs.Static/ArrayUsingCases.cs b/test/TestInputAssemblies/Hast.TestInputs.Static/ArrayUsingCases.cs index 2f3952ab..095a9421 100644 --- a/test/TestInputAssemblies/Hast.TestInputs.Static/ArrayUsingCases.cs +++ b/test/TestInputAssemblies/Hast.TestInputs.Static/ArrayUsingCases.cs @@ -1,7 +1,26 @@ +using System.Threading.Tasks; + namespace Hast.TestInputs.Static; public class ArrayUsingCases { + public const int TaskArrayLength = 10; + + public void PassArrayToTask() + { + var array = new int[TaskArrayLength]; + var tasks = new Task[15]; + + tasks[0] = Task.Factory.StartNew( + arrayObject => + { + var localArray = (int[])arrayObject; + localArray[0] = 123; + return localArray[0]; + }, + array); + } + public void PassArrayToConstructor() { var array = new int[5]; diff --git a/test/TestInputAssemblies/Hast.TestInputs.Static/GlobalSuppressions.cs b/test/TestInputAssemblies/Hast.TestInputs.Static/GlobalSuppressions.cs index 534de752..80ec9e8e 100644 --- a/test/TestInputAssemblies/Hast.TestInputs.Static/GlobalSuppressions.cs +++ b/test/TestInputAssemblies/Hast.TestInputs.Static/GlobalSuppressions.cs @@ -35,3 +35,11 @@ "S3353:Unchanged local variables should be \"const\"", Justification = ThatsThePoint, Scope = "module")] +[assembly: SuppressMessage( + "Reliability", + "CA2008:Do not create tasks without passing a TaskScheduler", + Justification = "Can't do it without passing CancellationToken which is not supported.")] +[assembly: SuppressMessage( + "Usage", + "VSTHRD105:Avoid method overloads that assume TaskScheduler.Current", + Justification = "Can't do it without passing CancellationToken which is not supported.")] diff --git a/test/TestInputAssemblies/Hast.TestInputs.Static/ParallelCases.cs b/test/TestInputAssemblies/Hast.TestInputs.Static/ParallelCases.cs index 50fbec5c..31d7940b 100644 --- a/test/TestInputAssemblies/Hast.TestInputs.Static/ParallelCases.cs +++ b/test/TestInputAssemblies/Hast.TestInputs.Static/ParallelCases.cs @@ -10,9 +10,6 @@ public void WhenAllWhenAnyAwaitedTasks(uint input) for (uint i = 0; i < 3; i++) { - // Can't do it without passing CancellationToken which is not supported. -#pragma warning disable CA2008 // Do not create tasks without passing a TaskScheduler -#pragma warning disable VSTHRD105 // Avoid method overloads that assume TaskScheduler.Current tasks[i] = Task.Factory.StartNew( indexObject => { @@ -21,8 +18,6 @@ public void WhenAllWhenAnyAwaitedTasks(uint input) return index % 2 == 0; }, i); -#pragma warning restore VSTHRD105 // Avoid method overloads that assume TaskScheduler.Current -#pragma warning restore CA2008 // Do not create tasks without passing a TaskScheduler } // These two after each other don't make sense, but the test result will be still usable just for static @@ -37,9 +32,6 @@ public void ObjectUsingTasks(uint input) for (uint i = 0; i < 3; i++) { - // Can't do it without passing CancellationToken which is not supported. -#pragma warning disable CA2008 // Do not create tasks without passing a TaskScheduler -#pragma warning disable VSTHRD105 // Avoid method overloads that assume TaskScheduler.Current tasks[i] = Task.Factory.StartNew( indexObject => { @@ -48,8 +40,6 @@ public void ObjectUsingTasks(uint input) return new Calculator { Number = index }.IsEven(); }, i); -#pragma warning restore VSTHRD105 // Avoid method overloads that assume TaskScheduler.Current -#pragma warning restore CA2008 // Do not create tasks without passing a TaskScheduler } Task.WhenAll(tasks).Wait();