示例#1
0
        static void Main(string[] args)
        {
            Task.Run(async() =>
            {
                using (var hastlayer = await Hastlayer.Create())
                {
                    #region Configuration
                    var configuration = new HardwareGenerationConfiguration("Nexys4 DDR");

                    configuration.AddHardwareEntryPointType <ParallelAlgorithm>();

                    configuration.TransformerConfiguration().AddMemberInvocationInstanceCountConfiguration(
                        new MemberInvocationInstanceCountConfigurationForMethod <ParallelAlgorithm>(p => p.Run(null), 0)
                    {
                        MaxDegreeOfParallelism = ParallelAlgorithm.MaxDegreeOfParallelism
                    });

                    configuration.VhdlTransformerConfiguration().VhdlGenerationMode = VhdlGenerationMode.Debug;

                    hastlayer.ExecutedOnHardware += (sender, e) =>
                    {
                        Console.WriteLine(
                            "Executing " +
                            e.MemberFullName +
                            " on hardware took " +
                            e.HardwareExecutionInformation.HardwareExecutionTimeMilliseconds +
                            "ms (net) " +
                            e.HardwareExecutionInformation.FullExecutionTimeMilliseconds +
                            " milliseconds (all together)");
                    };
                    #endregion

                    #region HardwareGeneration
                    var hardwareRepresentation = await hastlayer.GenerateHardware(
                        new[]
                    {
                        typeof(Program).Assembly
                    },
                        configuration);

                    await hardwareRepresentation.HardwareDescription.WriteSource("Hast_IP.vhd");
                    #endregion

                    #region Execution
                    var parallelAlgorithm = await hastlayer.GenerateProxy(hardwareRepresentation, new ParallelAlgorithm());

                    var output1 = parallelAlgorithm.Run(234234);
                    var output2 = parallelAlgorithm.Run(123);
                    var output3 = parallelAlgorithm.Run(9999);

                    var sw        = System.Diagnostics.Stopwatch.StartNew();
                    var cpuOutput = new ParallelAlgorithm().Run(234234);
                    sw.Stop();
                    Console.WriteLine("On CPU it took " + sw.ElapsedMilliseconds + "ms.");
                    #endregion
                }
            }).Wait();

            Console.ReadKey();
        }
示例#2
0
        public async Task <IHastlayer> InitializeHastlayer(bool verifyOutput, bool randomSeedEnable)
        {
            _verifyOutput     = verifyOutput;
            _randomSeedEnable = randomSeedEnable;

            LogItFunction("Creating Hastlayer Factory...");

            var hastlayer = await Hastlayer.Create();

            hastlayer.ExecutedOnHardware += (sender, e) =>
            {
                LogItFunction("Hastlayer timer: " +
                              e.HardwareExecutionInformation.HardwareExecutionTimeMilliseconds + "ms (net) / " +
                              e.HardwareExecutionInformation.FullExecutionTimeMilliseconds + " ms (total)"
                              );
            };

            var configuration = new HardwareGenerationConfiguration((await hastlayer.GetSupportedDevices()).First().Name);

            configuration.VhdlTransformerConfiguration().VhdlGenerationConfiguration = VhdlGenerationConfiguration.Debug;
            configuration.EnableCaching = false;

            LogItFunction("Generating hardware...");

            if (_kpzTarget.HastlayerParallelizedAlgorithm())
            {
                configuration.AddHardwareEntryPointType <KpzKernelsParallelizedInterface>();
                configuration.TransformerConfiguration().AddAdditionalInlinableMethod <RandomMwc64X>(r => r.NextUInt32());
            }
            else if (_kpzTarget.HastlayerPlainAlgorithm())
            {
                configuration.AddHardwareEntryPointType <KpzKernelsInterface>();
            }
            else // if (kpzTarget == KpzTarget.PrngTest)
            {
                configuration.AddHardwareEntryPointType <PrngTestInterface>();
            }


            var hardwareRepresentation = await hastlayer.GenerateHardware(new[] {
                typeof(KpzKernelsParallelizedInterface).Assembly,
                typeof(RandomMwc64X).Assembly
            }, configuration);

            await hardwareRepresentation.HardwareDescription.WriteSource(VhdlOutputFilePath);

            LogItFunction("Generating proxy...");

            if (_kpzTarget.HastlayerOnFpga())
            {
                var proxyConf = new ProxyGenerationConfiguration
                {
                    VerifyHardwareResults = _verifyOutput
                };

                if (_kpzTarget == KpzTarget.Fpga)
                {
                    Kernels = await hastlayer.GenerateProxy(
                        hardwareRepresentation,
                        new KpzKernelsInterface(),
                        proxyConf);
                }
                else if (_kpzTarget == KpzTarget.FpgaParallelized)
                {
                    KernelsParallelized = await hastlayer.GenerateProxy(
                        hardwareRepresentation,
                        new KpzKernelsParallelizedInterface(),
                        proxyConf);
                }
                else //if(kpzTarget == KpzTarget.PrngTest)
                {
                    KernelsP = await hastlayer.GenerateProxy(
                        hardwareRepresentation,
                        new PrngTestInterface(),
                        proxyConf);
                }

                LogItFunction("FPGA target detected");
            }
            else //if (kpzTarget == KpzTarget.HastlayerSimulation())
            {
                Kernels             = new KpzKernelsInterface();
                KernelsParallelized = new KpzKernelsParallelizedInterface();
                LogItFunction("Simulation target detected");
            }

            if (_kpzTarget.HastlayerPlainAlgorithm())
            {
                LogItFunction("Running TestAdd...");
                uint resultFpga = Kernels.TestAddWrapper(4313, 123);
                uint resultCpu  = 4313 + 123;
                if (resultCpu == resultFpga)
                {
                    LogItFunction(string.Format("Success: {0} == {1}", resultFpga, resultCpu));
                }
                else
                {
                    LogItFunction(string.Format("Fail: {0} != {1}", resultFpga, resultCpu));
                }
            }

            if (_kpzTarget == KpzTarget.PrngTest)
            {
                LogItFunction("Running TestPrng...");

                var   kernelsCpu = new PrngTestInterface();
                ulong randomSeed = 0x37a92d76a96ef210UL;
                var   smCpu      = kernelsCpu.PushRandomSeed(randomSeed);
                var   smFpga     = KernelsP.PushRandomSeed(randomSeed);
                LogItFunction("PRNG results:");
                bool success = true;

                for (int PrngTestIndex = 0; PrngTestIndex < 10; PrngTestIndex++)
                {
                    uint prngCpuResult  = kernelsCpu.GetNextRandom(smCpu);
                    uint prngFpgaResult = KernelsP.GetNextRandom(smFpga);
                    if (prngCpuResult != prngFpgaResult)
                    {
                        success = false;
                    }
                    LogItFunction(String.Format("{0}, {1}", prngCpuResult, prngFpgaResult));
                }

                if (success)
                {
                    LogItFunction("TestPrng succeeded!");
                }
                else
                {
                    LogItFunction("TestPrng failed!");
                }
            }
            return(hastlayer);
        }
        static void Main(string[] args)
        {
            // Wrapping the whole program into Task.Run() is a workaround for async just to be able to run all this from
            // inside a console app.
            Task.Run(async() =>
            {
                /*
                 * On a high level these are the steps to use Hastlayer:
                 * 1. Create the Hastlayer shell.
                 * 2. Configure hardware generation and generate FPGA hardware representation of the given .NET code.
                 * 3. Generate proxies for hardware-transformed types and use these proxies to utilize hardware
                 *    implementations. (You can see this inside the SampleRunners.)
                 */

                // Configuring the Hastlayer shell. Which flavor should we use? If you're unsure then you'll need
                // the Client flavor: This will let you connect to a remote Hastlayer service to run the software
                // to hardware transformation.
                var hastlayerConfiguration = new HastlayerConfiguration {
                    Flavor = HastlayerFlavor.Developer
                };

                // Initializing a Hastlayer shell. Since this is non-trivial to do you can cache this shell object
                // while the program runs and re-use it continuously. No need to always wrap it into a using() like
                // here, just make sure to Dispose() it before the program terminates.
                using (var hastlayer = await Hastlayer.Create(hastlayerConfiguration))
                {
                    // Hooking into an event of Hastlayer so some execution information can be made visible on the
                    // console.
                    hastlayer.ExecutedOnHardware += (sender, e) =>
                    {
                        Console.WriteLine(
                            "Executing " +
                            e.MemberFullName +
                            " on hardware took " +
                            e.HardwareExecutionInformation.HardwareExecutionTimeMilliseconds +
                            " milliseconds (net) " +
                            e.HardwareExecutionInformation.FullExecutionTimeMilliseconds +
                            " milliseconds (all together)");
                    };


                    // We need to set what kind of device (FPGA/FPGA board) to generate the hardware for.
                    var devices = await hastlayer.GetSupportedDevices();
                    // Let's just use the first one that is available. However you might want to use a specific
                    // device, not just any first one.
                    var configuration = new HardwareGenerationConfiguration(devices.First().Name);

                    // If you're running Hastlayer in the Client flavor, you also need to configure some credentials
                    // here:
                    var remoteClientConfiguration       = configuration.RemoteClientConfiguration();
                    remoteClientConfiguration.AppName   = "TestApp";
                    remoteClientConfiguration.AppSecret = "appsecret";
                    if (hastlayerConfiguration.Flavor == HastlayerFlavor.Client &&
                        remoteClientConfiguration.AppSecret == "appsecret")
                    {
                        throw new InvalidOperationException(
                            "You haven't changed the default remote credentials! Write to [email protected] to receive access if you don't have yet.");
                    }


                    // Letting the configuration of samples run. Check out those methods too!
                    switch (Configuration.SampleToRun)
                    {
                    case Sample.Fix64Calculator:
                        Fix64CalculatorSampleRunner.Configure(configuration);
                        break;

                    case Sample.GenomeMatcher:
                        GenomeMatcherSampleRunner.Configure(configuration);
                        break;

                    case Sample.ParallelAlgorithm:
                        ParallelAlgorithmSampleRunner.Configure(configuration);
                        break;

                    case Sample.ImageProcessingAlgorithms:
                        ImageProcessingAlgorithmsSampleRunner.Configure(configuration);
                        break;

                    case Sample.Loopback:
                        LoopbackSampleRunner.Configure(configuration);
                        break;

                    case Sample.MonteCarloAlgorithm:
                        MonteCarloAlgorithmSampleRunner.Configure(configuration);
                        break;

                    case Sample.ObjectOrientedShowcase:
                        ObjectOrientedShowcaseSampleRunner.Configure(configuration);
                        break;

                    case Sample.PrimeCalculator:
                        PrimeCalculatorSampleRunner.Configure(configuration);
                        break;

                    case Sample.RecursiveAlgorithms:
                        RecursiveAlgorithmsSampleRunner.Configure(configuration);
                        break;

                    case Sample.SimdCalculator:
                        SimdCalculatorSampleRunner.Configure(configuration);
                        break;

                    default:
                        break;
                    }

                    // The generated VHDL code will contain debug-level information, though it will be slower to
                    // create.
                    configuration.VhdlTransformerConfiguration().VhdlGenerationConfiguration = VhdlGenerationConfiguration.Debug;

                    Console.WriteLine("Hardware generation starts.");

                    // Generating hardware from the sample assembly with the given configuration.
                    var hardwareRepresentation = await hastlayer.GenerateHardware(
                        new[]
                    {
                        // Selecting any type from the sample assembly here just to get its Assembly object.
                        typeof(PrimeCalculator).Assembly,
                        typeof(Fix64).Assembly
                    },
                        configuration);

                    Console.WriteLine("Hardware generation finished, writing VHDL source to file.");

                    if (!string.IsNullOrEmpty(Configuration.VhdlOutputFilePath))
                    {
                        await hardwareRepresentation.HardwareDescription.WriteSource(Configuration.VhdlOutputFilePath);
                    }

                    Console.WriteLine("VHDL source written to file, starting hardware execution.");

                    // Running samples.
                    switch (Configuration.SampleToRun)
                    {
                    case Sample.Fix64Calculator:
                        await Fix64CalculatorSampleRunner.Run(hastlayer, hardwareRepresentation);
                        break;

                    case Sample.GenomeMatcher:
                        await GenomeMatcherSampleRunner.Run(hastlayer, hardwareRepresentation);
                        break;

                    case Sample.ParallelAlgorithm:
                        await ParallelAlgorithmSampleRunner.Run(hastlayer, hardwareRepresentation);
                        break;

                    case Sample.ImageProcessingAlgorithms:
                        await ImageProcessingAlgorithmsSampleRunner.Run(hastlayer, hardwareRepresentation);
                        break;

                    case Sample.Loopback:
                        await LoopbackSampleRunner.Run(hastlayer, hardwareRepresentation);
                        break;

                    case Sample.MonteCarloAlgorithm:
                        await MonteCarloAlgorithmSampleRunner.Run(hastlayer, hardwareRepresentation);
                        break;

                    case Sample.ObjectOrientedShowcase:
                        await ObjectOrientedShowcaseSampleRunner.Run(hastlayer, hardwareRepresentation);
                        break;

                    case Sample.PrimeCalculator:
                        await PrimeCalculatorSampleRunner.Run(hastlayer, hardwareRepresentation);
                        break;

                    case Sample.RecursiveAlgorithms:
                        await RecursiveAlgorithmsSampleRunner.Run(hastlayer, hardwareRepresentation);
                        break;

                    case Sample.SimdCalculator:
                        await SimdCalculatorSampleRunner.Run(hastlayer, hardwareRepresentation);
                        break;

                    default:
                        break;
                    }
                }
            }).Wait();

            Console.WriteLine("Press any key to exit.");
            Console.ReadKey();
        }
示例#4
0
        private static async Task MainTask(Options configuration)
        {
            using (var hastlayer = await Hastlayer.Create(new HastlayerConfiguration {
                Flavor = HastlayerFlavor.Developer
            }))
            {
                // Get devices and if asked exit with the device list.
                var devices = await hastlayer.GetSupportedDevices();

                if (devices == null || !devices.Any())
                {
                    throw new Exception("No devices are available!");
                }

                if (configuration.ListDevices)
                {
                    foreach (var d in devices)
                    {
                        Console.WriteLine(d.Name);
                    }
                    return;
                }


                // If there is an output file name, then the file type can not be None.
                if (configuration.OutputFileType == OutputFileType.None && !string.IsNullOrEmpty(configuration.OutputFileName))
                {
                    configuration.OutputFileType = OutputFileType.Hexdump;
                }


                // Try to load selected device or pick the first available if none were selected.
                if (string.IsNullOrEmpty(configuration.DeviceName))
                {
                    configuration.DeviceName = devices.First().Name;
                }
                var selectedDevice = devices.FirstOrDefault(device => device.Name == configuration.DeviceName);
                if (selectedDevice == null)
                {
                    throw new Exception($"Target device '{configuration.DeviceName}' not found!");
                }
                var channelName = selectedDevice.DefaultCommunicationChannelName;


                var(memory, accessor) = GenerateMemory(configuration.PayloadType,
                                                       configuration.PayloadLengthCells, configuration.InputFileName);


                // Save input to file using the format of the output file type.
                SaveFile(configuration.OutputFileType, configuration.PayloadType, configuration.InputFileName, true, memory);

                // Create reference copy of input to compare against output.
                var referenceMemory = configuration.NoCheck ? null : SimpleMemoryAccessor.Create(accessor.Get());

                Console.WriteLine("Starting hardware execution.");
                var communicationService = await hastlayer.GetCommunicationService(channelName);

                communicationService.TesterOutput = Console.Out;
                var executionContext = new BasicExecutionContext(hastlayer, selectedDevice.Name,
                                                                 selectedDevice.DefaultCommunicationChannelName);
                var info = await communicationService.Execute(memory, configuration.MemberId, executionContext);

                Console.WriteLine("Executing test on hardware took {0:0.##}ms (net) {1:0.##}ms (all together)",
                                  info.HardwareExecutionTimeMilliseconds, info.FullExecutionTimeMilliseconds);

                // Save output to file.
                SaveFile(configuration.OutputFileType, configuration.PayloadType, configuration.OutputFileName, false, memory);

                if (!string.IsNullOrWhiteSpace(configuration?.JsonOutputFileName))
                {
                    var json = JsonConvert.SerializeObject(new { Success = true, Result = info });
                    File.WriteAllText(configuration.JsonOutputFileName, json);
                }


                // Verify results if wanted.
                if (!configuration.NoCheck)
                {
                    Verify(memory, referenceMemory);
                }
            }
        }
示例#5
0
        static async Task MainTask(string[] args)
        {
            /*
             * On a high level these are the steps to use Hastlayer:
             * 1. Create the Hastlayer shell.
             * 2. Configure hardware generation and generate FPGA hardware representation of the given .NET code.
             * 3. Generate proxies for hardware-transformed types and use these proxies to utilize hardware
             *    implementations. (You can see this inside the SampleRunners.)
             */

            // Configuring the Hastlayer shell. Which flavor should we use? If you're unsure then you'll need
            // the Client flavor: This will let you connect to a remote Hastlayer service to run the software
            // to hardware transformation.
            var hastlayerConfiguration = new HastlayerConfiguration {
                Flavor = HastlayerFlavor.Developer
            };

            // Initializing a Hastlayer shell. Since this is non-trivial to do you can cache this shell object
            // while the program runs and re-use it continuously. No need to always wrap it into a using() like
            // here, just make sure to Dispose() it before the program terminates.
            using (var hastlayer = await Hastlayer.Create(hastlayerConfiguration))
            {
                // Hooking into an event of Hastlayer so some execution information can be made visible on the
                // console.
                hastlayer.ExecutedOnHardware += (sender, e) =>
                {
                    Console.WriteLine(
                        "Executing " +
                        e.MemberFullName +
                        " on hardware took " +
                        e.HardwareExecutionInformation.HardwareExecutionTimeMilliseconds +
                        " milliseconds (net) " +
                        e.HardwareExecutionInformation.FullExecutionTimeMilliseconds +
                        " milliseconds (all together)");
                };


                // A little helper for later.
                var argsList = (IList <string>)args;
                string GetArgument(string name)
                {
                    name = "-" + name;
                    return(args.Contains(name) ? args[argsList.IndexOf(name) + 1] : null);
                }

                // We need to set what kind of device (FPGA/FPGA board) to generate the hardware for.
                var devices = await hastlayer.GetSupportedDevices();

                if (devices == null || !devices.Any())
                {
                    throw new Exception("No devices are available!");
                }

                // Let's just use the first one that is available unless it's specified.
                if (string.IsNullOrEmpty(Configuration.DeviceName))
                {
                    Configuration.DeviceName = devices.First().Name;
                }
                var targetDeviceName = GetArgument("device") ?? Configuration.DeviceName;
                var selectedDevice   = devices.FirstOrDefault(device => device.Name == targetDeviceName);
                if (selectedDevice == null)
                {
                    throw new Exception($"Target device '{targetDeviceName}' not found!");
                }

                var configuration = new HardwareGenerationConfiguration(selectedDevice.Name);

                // If you're running Hastlayer in the Client flavor, you also need to configure some credentials:
                var remoteClientConfiguration = configuration.RemoteClientConfiguration();
                remoteClientConfiguration.AppName   = GetArgument("appname") ?? Configuration.AppName;
                remoteClientConfiguration.AppSecret = GetArgument("appsecret") ?? Configuration.AppSecret;
                if (hastlayerConfiguration.Flavor == HastlayerFlavor.Client &&
                    remoteClientConfiguration.AppSecret == "appsecret")
                {
                    throw new InvalidOperationException(
                              "You haven't changed the default remote credentials! Write to [email protected] to receive access if you don't have yet.");
                }

                // If the sample was selected in the command line use that, or otherwise the default.
                Configuration.SampleToRun = (Sample)Enum.Parse(typeof(Sample), GetArgument("sample") ?? Configuration.SampleToRun.ToString(), true);

                // Letting the configuration of samples run. Check out those methods too!
                switch (Configuration.SampleToRun)
                {
                case Sample.Fix64Calculator:
                    Fix64CalculatorSampleRunner.Configure(configuration);
                    break;

                case Sample.FSharpParallelAlgorithm:
                    FSharpParallelAlgorithmSampleRunner.Configure(configuration);
                    break;

                case Sample.GenomeMatcher:
                    GenomeMatcherSampleRunner.Configure(configuration);
                    break;

                case Sample.ParallelAlgorithm:
                    ParallelAlgorithmSampleRunner.Configure(configuration);
                    break;

                case Sample.ImageProcessingAlgorithms:
                    ImageProcessingAlgorithmsSampleRunner.Configure(configuration);
                    break;

                case Sample.Loopback:
                    LoopbackSampleRunner.Configure(configuration);
                    break;

                case Sample.MemoryTest:
                    MemoryTestSampleRunner.Configure(configuration);
                    break;

                case Sample.MonteCarloPiEstimator:
                    MonteCarloPiEstimatorSampleRunner.Configure(configuration);
                    break;

                case Sample.ObjectOrientedShowcase:
                    ObjectOrientedShowcaseSampleRunner.Configure(configuration);
                    break;

                case Sample.PrimeCalculator:
                    PrimeCalculatorSampleRunner.Configure(configuration);
                    break;

                case Sample.RecursiveAlgorithms:
                    RecursiveAlgorithmsSampleRunner.Configure(configuration);
                    break;

                case Sample.SimdCalculator:
                    SimdCalculatorSampleRunner.Configure(configuration);
                    break;

                default:
                    break;
                }

                // The generated VHDL code will contain debug-level information, though it will be slower to create.
                configuration.VhdlTransformerConfiguration().VhdlGenerationConfiguration = VhdlGenerationConfiguration.Debug;

                Console.WriteLine("Hardware generation starts.");

                // Generating hardware from the sample assembly with the given configuration.
                var hardwareRepresentation = await hastlayer.GenerateHardware(
                    new[]
                {
                    // Selecting any type from the sample assembly here just to get its Assembly object.
                    typeof(PrimeCalculator).Assembly,
                    typeof(Fix64).Assembly,
                    typeof(FSharpSampleAssembly.FSharpParallelAlgorithmContainer).Assembly
                },
                    configuration);

                Console.WriteLine("Hardware generation finished.");
                Console.WriteLine();

                // Be sure to check out transformation warnings. Most of the time the issues noticed shouldn't cause
                // any problems, but sometimes they can.
                if (hardwareRepresentation.HardwareDescription.Warnings.Any())
                {
                    Console.WriteLine(
                        "There were the following transformation warnings, which may hint on issues that can cause the hardware implementation to produce incorrect results:" +
                        Environment.NewLine +
                        string.Join(Environment.NewLine, hardwareRepresentation.HardwareDescription.Warnings.Select(warning => "* " + warning.ToString())));
                    Console.WriteLine();
                }

                if (!string.IsNullOrEmpty(Configuration.VhdlOutputFilePath))
                {
                    Console.WriteLine("Writing VHDL source to file.");

                    await hardwareRepresentation.HardwareDescription.WriteSource(Configuration.VhdlOutputFilePath);

                    Console.WriteLine("VHDL source written to file.");
                    Console.WriteLine();
                }

                Console.WriteLine("Starting hardware execution.");

                // Running samples.
                try
                {
                    switch (Configuration.SampleToRun)
                    {
                    case Sample.Fix64Calculator:
                        await Fix64CalculatorSampleRunner.Run(hastlayer, hardwareRepresentation);

                        break;

                    case Sample.FSharpParallelAlgorithm:
                        await FSharpParallelAlgorithmSampleRunner.Run(hastlayer, hardwareRepresentation);

                        break;

                    case Sample.GenomeMatcher:
                        await GenomeMatcherSampleRunner.Run(hastlayer, hardwareRepresentation);

                        break;

                    case Sample.ParallelAlgorithm:
                        await ParallelAlgorithmSampleRunner.Run(hastlayer, hardwareRepresentation);

                        break;

                    case Sample.ImageProcessingAlgorithms:
                        await ImageProcessingAlgorithmsSampleRunner.Run(hastlayer, hardwareRepresentation);

                        break;

                    case Sample.Loopback:
                        await LoopbackSampleRunner.Run(hastlayer, hardwareRepresentation);

                        break;

                    case Sample.MemoryTest:
                        await MemoryTestSampleRunner.Run(hastlayer, hardwareRepresentation);

                        break;

                    case Sample.MonteCarloPiEstimator:
                        await MonteCarloPiEstimatorSampleRunner.Run(hastlayer, hardwareRepresentation);

                        break;

                    case Sample.ObjectOrientedShowcase:
                        await ObjectOrientedShowcaseSampleRunner.Run(hastlayer, hardwareRepresentation);

                        break;

                    case Sample.PrimeCalculator:
                        await PrimeCalculatorSampleRunner.Run(hastlayer, hardwareRepresentation);

                        break;

                    case Sample.RecursiveAlgorithms:
                        await RecursiveAlgorithmsSampleRunner.Run(hastlayer, hardwareRepresentation);

                        break;

                    case Sample.SimdCalculator:
                        await SimdCalculatorSampleRunner.Run(hastlayer, hardwareRepresentation);

                        break;

                    default:
                        break;
                    }
                }
                catch (AggregateException ex) when(ex.InnerException is HardwareExecutionResultMismatchException)
                {
                    // If you set ProxyGenerationConfiguration.VerifyHardwareResults to true (when calling
                    // GenerateProxy()) then everything will be computed in software as well to check the hardware.
                    // You'll get such an exception if there is any mismatch. This shouldn't normally happen, but it's
                    // not impossible in corner cases.
                    var mismatches    = ((HardwareExecutionResultMismatchException)ex.InnerException).Mismatches;
                    var mismatchCount = mismatches.Count();

                    Console.WriteLine($"There {(mismatchCount == 1 ? "was a mismatch" : $"were {mismatchCount} mismatches")} between the software and hardware execution's results! Mismatch{(mismatchCount == 1 ? string.Empty : $"es")}:");